SCIP Doxygen Documentation
Loading...
Searching...
No Matches
var.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file var.c
26 * @ingroup OTHER_CFILES
27 * @brief methods for problem variables
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Gerald Gamrath
31 * @author Stefan Heinz
32 * @author Marc Pfetsch
33 * @author Michael Winkler
34 * @author Kati Wolter
35 * @author Stefan Vigerske
36 *
37 * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
38 * corresponding linear constraint if it exists. This seems to require some work, since the linear
39 * constraint has to be stored. Moreover, it has even to be created in case the original constraint
40 * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
41 * changed. This has to be done with care in order to not loose the performance gains of
42 * multi-aggregation.
43 */
44
45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46#include "scip/cons.h"
47#include "scip/certificate.h"
48#include "scip/event.h"
49#include "scip/history.h"
50#include "scip/implics.h"
51#include "scip/lp.h"
52#include "scip/lpexact.h"
53#include "scip/primal.h"
54#include "scip/prob.h"
55#include "scip/pub_cons.h"
56#include "scip/pub_history.h"
57#include "scip/pub_implics.h"
58#include "scip/pub_lp.h"
59#include "scip/pub_message.h"
60#include "scip/pub_misc.h"
61#include "scip/pub_misc_sort.h"
62#include "scip/pub_prop.h"
63#include "scip/pub_var.h"
64#include "scip/relax.h"
66#include "scip/scip_exact.h"
67#include "scip/scip_prob.h"
68#include "scip/scip_probing.h"
69#include "scip/set.h"
70#include "scip/sol.h"
71#include "scip/stat.h"
72#include "scip/struct_event.h"
73#include "scip/struct_lp.h"
74#include "scip/struct_lpexact.h"
75#include "scip/struct_prob.h"
76#include "scip/struct_set.h"
77#include "scip/struct_stat.h"
78#include "scip/struct_var.h"
79#include "scip/tree.h"
80#include "scip/var.h"
81#include <string.h>
82
83#define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
84 * in implication graph */
85#define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
86
87
88/*
89 * Debugging variable release and capture
90 *
91 * Define DEBUGUSES_VARNAME to the name of the variable for which to print
92 * a backtrace when it is captured and released.
93 * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
94 * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
95 */
96/* #define DEBUGUSES_VARNAME "t_t_b7" */
97/* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
98/* #define DEBUGUSES_NOADDR2LINE */
99
100#ifdef DEBUGUSES_VARNAME
101#include <execinfo.h>
102#include <stdio.h>
103#include <stdlib.h>
104#include "scip/struct_scip.h"
105
106/** obtains a backtrace and prints it to stdout. */
107static
108void print_backtrace(void)
109{
110 void* array[10];
111 char** strings;
112 int size;
113 int i;
114
115 size = backtrace(array, 10);
116 strings = backtrace_symbols(array, size);
117 if( strings == NULL )
118 return;
119
120 /* skip first entry, which is the print_backtrace function */
121 for( i = 1; i < size; ++i )
122 {
123 /* if string is something like
124 * /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
125 * (that is, no function name because it is a inlined function), then call
126 * addr2line -e <libname> <addr> to get func and code line
127 * dladdr() may be an alternative
128 */
129 char* openpar;
130 char* closepar = NULL;
131#ifndef DEBUGUSES_NOADDR2LINE
132 openpar = strchr(strings[i], '(');
133 if( openpar != NULL && openpar[1] == '+' )
134 closepar = strchr(openpar+2, ')');
135#endif
136 if( closepar != NULL )
137 {
138 char cmd[SCIP_MAXSTRLEN];
139 (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
140 printf(" ");
141 fflush(stdout);
142 system(cmd);
143 }
144 else
145 printf(" %s\n", strings[i]);
146 }
147
148 free(strings);
149}
150#endif
151
152/*
153 * hole, holelist, and domain methods
154 */
155
156/** creates a new holelist element */
157static
159 SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
160 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
161 SCIP_SET* set, /**< global SCIP settings */
162 SCIP_Real left, /**< left bound of open interval in new hole */
163 SCIP_Real right /**< right bound of open interval in new hole */
164 )
165{
166 assert(holelist != NULL);
167 assert(blkmem != NULL);
168 assert(SCIPsetIsLT(set, left, right));
169
170 SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
171
172 SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
173 (*holelist)->hole.left = left;
174 (*holelist)->hole.right = right;
175 (*holelist)->next = NULL;
176
177 return SCIP_OKAY;
178}
179
180/** frees all elements in the holelist */
181static
183 SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
184 BMS_BLKMEM* blkmem /**< block memory for target holelist */
185 )
186{
187 assert(holelist != NULL);
188 assert(blkmem != NULL);
189
190 while( *holelist != NULL )
191 {
192 SCIP_HOLELIST* next;
193
194 SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
195 (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
196
197 next = (*holelist)->next;
198 BMSfreeBlockMemory(blkmem, holelist);
199 assert(*holelist == NULL);
200
201 *holelist = next;
202 }
203 assert(*holelist == NULL);
204}
205
206/** duplicates a list of holes */
207static
209 SCIP_HOLELIST** target, /**< pointer to target holelist */
210 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
211 SCIP_SET* set, /**< global SCIP settings */
212 SCIP_HOLELIST* source /**< holelist to duplicate */
213 )
214{
215 assert(target != NULL);
216
217 while( source != NULL )
218 {
219 assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
220 SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
221 source = source->next;
222 target = &(*target)->next;
223 }
224
225 return SCIP_OKAY;
226}
227
228/** adds a hole to the domain */
229static
231 SCIP_DOM* dom, /**< domain to add hole to */
232 BMS_BLKMEM* blkmem, /**< block memory */
233 SCIP_SET* set, /**< global SCIP settings */
234 SCIP_Real left, /**< left bound of open interval in new hole */
235 SCIP_Real right, /**< right bound of open interval in new hole */
236 SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
237 )
238{
239 SCIP_HOLELIST** insertpos;
240 SCIP_HOLELIST* next;
241
242 assert(dom != NULL);
243 assert(added != NULL);
244
245 /* search for the position of the new hole */
246 insertpos = &dom->holelist;
247 while( *insertpos != NULL && (*insertpos)->hole.left < left )
248 insertpos = &(*insertpos)->next;
249
250 /* check if new hole already exists in the hole list or is a sub hole of an existing one */
251 if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
252 {
253 SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
254 left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
255 *added = FALSE;
256 return SCIP_OKAY;
257 }
258
259 /* add hole */
260 *added = TRUE;
261
262 next = *insertpos;
263 SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
264 (*insertpos)->next = next;
265
266 return SCIP_OKAY;
267}
268
269/** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
270/**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
271 * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
272 * merge */
273static
275 SCIP_DOM* dom, /**< domain to merge */
276 BMS_BLKMEM* blkmem, /**< block memory */
277 SCIP_SET* set, /**< global SCIP settings */
278 SCIP_Real* newlb, /**< pointer to store new lower bound */
279 SCIP_Real* newub /**< pointer to store new upper bound */
280 )
281{
282 SCIP_HOLELIST** holelistptr;
283 SCIP_HOLELIST** lastnextptr;
284 SCIP_Real* lastrightptr;
285
286 assert(dom != NULL);
287 assert(SCIPsetIsLE(set, dom->lb, dom->ub));
288
289#ifndef NDEBUG
290 {
291 /* check if the holelist is sorted w.r.t. to the left interval bounds */
292 SCIP_Real lastleft;
293
294 holelistptr = &dom->holelist;
295
296 lastleft = -SCIPsetInfinity(set);
297
298 while( *holelistptr != NULL )
299 {
300 if( (*holelistptr)->next != NULL )
301 {
302 assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
303 lastleft = (*holelistptr)->hole.left;
304 }
305
306 holelistptr = &(*holelistptr)->next;
307 }
308 }
309#endif
310
311 SCIPsetDebugMsg(set, "merge hole list\n");
312
313 holelistptr = &dom->holelist;
314 lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
315 lastnextptr = holelistptr;
316
317 while( *holelistptr != NULL )
318 {
319 SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
320
321 /* check that the hole is not empty */
322 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
323
324 if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
325 {
326 /* the remaining holes start behind the upper bound: remove them */
327 SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
328 holelistFree(holelistptr, blkmem);
329 assert(*holelistptr == NULL);
330
331 /* unlink this hole from the previous hole */
332 *lastnextptr = NULL;
333 }
334 else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
335 {
336 /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
337 SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
338
339 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
340
341 /* adjust upper bound */
342 dom->ub = (*holelistptr)->hole.left;
343
344 if(newub != NULL )
345 *newub = (*holelistptr)->hole.left;
346
347 /* remove remaining hole list */
348 holelistFree(holelistptr, blkmem);
349 assert(*holelistptr == NULL);
350
351 /* unlink this hole from the previous hole */
352 *lastnextptr = NULL;
353 }
354 else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
355 {
356 /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
357 * the last hole, delete this hole */
358 SCIP_HOLELIST* nextholelist;
359
360 if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
361 {
362 /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
363 * the lower bound */
364 SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
365 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
366
367 /* adjust lower bound */
368 dom->lb = *lastrightptr;
369
370 if(newlb != NULL )
371 *newlb = *lastrightptr;
372 }
373 else
374 {
375 SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
376 *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
377 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
378 }
379 nextholelist = (*holelistptr)->next;
380 (*holelistptr)->next = NULL;
381 holelistFree(holelistptr, blkmem);
382
383 /* connect the linked list after removing the hole */
384 *lastnextptr = nextholelist;
385
386 /* get next hole */
387 *holelistptr = nextholelist;
388 }
389 else
390 {
391 /* the holes do not overlap: update lastholelist and lastrightptr */
392 lastrightptr = &(*holelistptr)->hole.right;
393 lastnextptr = &(*holelistptr)->next;
394
395 /* get next hole */
396 holelistptr = &(*holelistptr)->next;
397 }
398 }
399
400#ifndef NDEBUG
401 {
402 /* check that holes are merged */
403 SCIP_Real lastright;
404
405 lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
406 holelistptr = &dom->holelist;
407
408 while( *holelistptr != NULL )
409 {
410 /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
411 assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
412
413 /* check the hole property (check that the hole is not empty) */
414 assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
415 lastright = (*holelistptr)->hole.right;
416
417 /* get next hole */
418 holelistptr = &(*holelistptr)->next;
419 }
420
421 /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
422 assert( SCIPsetIsLE(set, lastright, dom->ub) );
423 }
424#endif
425}
426
427/*
428 * domain change methods
429 */
430
431/** ensures, that bound change info array for lower bound changes can store at least num entries */
432static
434 SCIP_VAR* var, /**< problem variable */
435 BMS_BLKMEM* blkmem, /**< block memory */
436 SCIP_SET* set, /**< global SCIP settings */
437 int num /**< minimum number of entries to store */
438 )
439{
440 assert(var != NULL);
441 assert(var->nlbchginfos <= var->lbchginfossize);
443
444 if( num > var->lbchginfossize )
445 {
446 int newsize;
447
448 newsize = SCIPsetCalcMemGrowSize(set, num);
449 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
450 var->lbchginfossize = newsize;
451 }
452 assert(num <= var->lbchginfossize);
453
454 return SCIP_OKAY;
455}
456
457/** ensures, that bound change info array for upper bound changes can store at least num entries */
458static
460 SCIP_VAR* var, /**< problem variable */
461 BMS_BLKMEM* blkmem, /**< block memory */
462 SCIP_SET* set, /**< global SCIP settings */
463 int num /**< minimum number of entries to store */
464 )
465{
466 assert(var != NULL);
467 assert(var->nubchginfos <= var->ubchginfossize);
469
470 if( num > var->ubchginfossize )
471 {
472 int newsize;
473
474 newsize = SCIPsetCalcMemGrowSize(set, num);
475 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
476 var->ubchginfossize = newsize;
477 }
478 assert(num <= var->ubchginfossize);
479
480 return SCIP_OKAY;
481}
482
483/** adds domain change info to the variable's lower bound change info array */
484static
486 SCIP_VAR* var, /**< problem variable */
487 BMS_BLKMEM* blkmem, /**< block memory */
488 SCIP_SET* set, /**< global SCIP settings */
489 SCIP_Real oldbound, /**< old value for bound */
490 SCIP_Real newbound, /**< new value for bound */
491 int depth, /**< depth in the tree, where the bound change takes place */
492 int pos, /**< position of the bound change in its bound change array */
493 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
494 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
495 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
496 int inferinfo, /**< user information for inference to help resolving the conflict */
497 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
498 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
499 )
500{
501 assert(var != NULL);
502 assert(SCIPsetIsLT(set, oldbound, newbound));
505 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
506 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
507 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
508 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
509 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
510
511 SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
512 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
513 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
514 oldbound, newbound);
515
516 SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
517 var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
518 var->lbchginfos[var->nlbchginfos].newbound = newbound;
519 var->lbchginfos[var->nlbchginfos].var = var;
520 var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
521 var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
522 var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
523 var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
524 var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
525 var->lbchginfos[var->nlbchginfos].redundant = FALSE;
526 var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
527 var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
528 var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
529
530 /**@note The "pos" data member of the bound change info has a size of 27 bits */
531 assert(var->nlbchginfos < 1 << 27);
532
533 switch( boundchgtype )
534 {
536 break;
538 assert(infercons != NULL);
539 var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
540 break;
542 var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
543 break;
544 default:
545 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
546 return SCIP_INVALIDDATA;
547 }
548
549 var->nlbchginfos++;
550
551 assert(var->nlbchginfos < 2
552 || SCIPbdchgidxIsEarlier(&var->lbchginfos[var->nlbchginfos-2].bdchgidx,
553 &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
554
555 return SCIP_OKAY;
556}
557
558/** adds domain change info to the variable's upper bound change info array */
559static
561 SCIP_VAR* var, /**< problem variable */
562 BMS_BLKMEM* blkmem, /**< block memory */
563 SCIP_SET* set, /**< global SCIP settings */
564 SCIP_Real oldbound, /**< old value for bound */
565 SCIP_Real newbound, /**< new value for bound */
566 int depth, /**< depth in the tree, where the bound change takes place */
567 int pos, /**< position of the bound change in its bound change array */
568 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
569 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
570 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
571 int inferinfo, /**< user information for inference to help resolving the conflict */
572 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
573 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
574 )
575{
576 assert(var != NULL);
577 assert(SCIPsetIsGT(set, oldbound, newbound));
580 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
581 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
582 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
583 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
584 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
585
586 SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
587 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
588 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
589 oldbound, newbound);
590
591 SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
592 var->ubchginfos[var->nubchginfos].oldbound = oldbound;
593 var->ubchginfos[var->nubchginfos].newbound = newbound;
594 var->ubchginfos[var->nubchginfos].var = var;
595 var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
596 var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
597 var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
598 var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
599 var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
600 var->ubchginfos[var->nubchginfos].redundant = FALSE;
601 var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
602 var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
603 var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
604
605 /**@note The "pos" data member of the bound change info has a size of 27 bits */
606 assert(var->nubchginfos < 1 << 27);
607
608 switch( boundchgtype )
609 {
611 break;
613 assert(infercons != NULL);
614 var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
615 break;
617 var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
618 break;
619 default:
620 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
621 return SCIP_INVALIDDATA;
622 }
623
624 var->nubchginfos++;
625
626 assert(var->nubchginfos < 2
627 || SCIPbdchgidxIsEarlier(&var->ubchginfos[var->nubchginfos-2].bdchgidx,
628 &var->ubchginfos[var->nubchginfos-1].bdchgidx));
629
630 return SCIP_OKAY;
631}
632
633/** applies single bound change */
634static
636 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
637 BMS_BLKMEM* blkmem, /**< block memory */
638 SCIP_SET* set, /**< global SCIP settings */
639 SCIP_STAT* stat, /**< problem statistics */
640 SCIP_LP* lp, /**< current LP data */
641 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
642 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
643 int depth, /**< depth in the tree, where the bound change takes place */
644 int pos, /**< position of the bound change in its bound change array */
645 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
646 )
647{
648 SCIP_VAR* var;
649
650 assert(boundchg != NULL);
651 assert(stat != NULL);
652 assert(depth > 0);
653 assert(pos >= 0);
654 assert(cutoff != NULL);
655 assert(boundchg->newboundexact != NULL);
656
657 *cutoff = FALSE;
658
659 /* ignore redundant bound changes */
660 if( boundchg->redundant )
661 return SCIP_OKAY;
662
663 var = boundchg->var;
664 assert(var != NULL);
667
668 /* apply bound change */
669 switch( boundchg->boundtype )
670 {
672 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
674 {
676 {
677 /* add the bound change info to the variable's bound change info array */
678 switch( boundchg->boundchgtype )
679 {
681 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
682 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
683 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
685 stat->lastbranchvar = var;
687 stat->lastbranchvalue = boundchg->newbound;
688 break;
689
691 assert(boundchg->data.inferencedata.reason.cons != NULL);
692 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
693 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
694 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
695 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
696 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
697 boundchg->data.inferencedata.info,
699 break;
700
702 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
703 boundchg->data.inferencedata.reason.prop != NULL
704 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
705 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
706 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
707 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
708 boundchg->data.inferencedata.info,
710 break;
711
712 default:
713 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
714 return SCIP_INVALIDDATA;
715 }
717 {
718 assert( var->exactdata->locdom.lbcertificateidx != -1 || SCIPsetIsInfinity(set, -var->locdom.lb) );
719 var->lbchginfos[var->nlbchginfos - 1].oldcertificateindex = var->exactdata->locdom.lbcertificateidx;
721 }
722 /* change local bound of variable */
723 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, boundchg->newboundexact) );
724 }
725 else
726 {
727 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
728 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
729 *cutoff = TRUE;
730 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
731 }
732 }
733 else
734 {
735 /* mark bound change to be inactive */
736 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
737 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
738 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
739 boundchg->redundant = TRUE;
740 }
741 break;
742
744 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
746 {
748 {
749 /* add the bound change info to the variable's bound change info array */
750 switch( boundchg->boundchgtype )
751 {
753 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
754 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
755 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
757 stat->lastbranchvar = var;
759 stat->lastbranchvalue = boundchg->newbound;
760 break;
761
763 assert(boundchg->data.inferencedata.reason.cons != NULL);
764 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
765 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
766 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
767 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
768 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
769 boundchg->data.inferencedata.info,
771 break;
772
774 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
775 boundchg->data.inferencedata.reason.prop != NULL
776 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
777 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
778 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
779 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
780 boundchg->data.inferencedata.info,
782 break;
783
784 default:
785 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
786 return SCIP_INVALIDDATA;
787 }
788
790 {
791 assert( var->exactdata->locdom.ubcertificateidx != -1 || SCIPsetIsInfinity(set, var->locdom.ub) );
792 var->ubchginfos[var->nubchginfos - 1].oldcertificateindex = var->exactdata->locdom.ubcertificateidx;
794 }
795 /* change local bound of variable */
796 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, boundchg->newboundexact) );
797 }
798 else
799 {
800 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
801 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
802 *cutoff = TRUE;
803 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
804 }
805 }
806 else
807 {
808 /* mark bound change to be inactive */
809 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
810 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
811 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
812 boundchg->redundant = TRUE;
813 }
814 break;
815
816 default:
817 SCIPerrorMessage("unknown bound type\n");
818 return SCIP_INVALIDDATA;
819 }
820
821 /* update the branching and inference history */
822 if( !boundchg->applied && !boundchg->redundant )
823 {
824 assert(var == boundchg->var);
825
827 {
828 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
831 }
832 else if( stat->lastbranchvar != NULL )
833 {
834 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
835 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
836 }
837 boundchg->applied = TRUE;
838 }
839
840 return SCIP_OKAY;
841}
842
843
844/** applies single bound change */
846 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
847 BMS_BLKMEM* blkmem, /**< block memory */
848 SCIP_SET* set, /**< global SCIP settings */
849 SCIP_STAT* stat, /**< problem statistics */
850 SCIP_LP* lp, /**< current LP data */
851 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
852 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
853 int depth, /**< depth in the tree, where the bound change takes place */
854 int pos, /**< position of the bound change in its bound change array */
855 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
856 )
857{
858 SCIP_VAR* var;
859
860 assert(boundchg != NULL);
861 assert(stat != NULL);
862 assert(depth > 0);
863 assert(pos >= 0);
864 assert(cutoff != NULL);
865
866 *cutoff = FALSE;
867
868 /* ignore redundant bound changes */
869 if( boundchg->redundant )
870 return SCIP_OKAY;
871
872 if( boundchg->newboundexact != NULL)
873 return boundchgApplyExact(boundchg, blkmem, set, stat, lp, branchcand, eventqueue, depth, pos, cutoff);
874
875 var = boundchg->var;
876 assert(var != NULL);
879
880 /* apply bound change */
881 switch( boundchg->boundtype )
882 {
884 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
885 if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
886 {
887 if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
888 {
889 /* add the bound change info to the variable's bound change info array */
890 switch( boundchg->boundchgtype )
891 {
893 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
894 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
895 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
897 stat->lastbranchvar = var;
899 stat->lastbranchvalue = boundchg->newbound;
900 break;
901
903 assert(boundchg->data.inferencedata.reason.cons != NULL);
904 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
905 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
906 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
907 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
908 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
909 boundchg->data.inferencedata.info,
911 break;
912
914 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
915 boundchg->data.inferencedata.reason.prop != NULL
916 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
917 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
918 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
919 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
920 boundchg->data.inferencedata.info,
922 break;
923
924 default:
925 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
926 return SCIP_INVALIDDATA;
927 }
928
930 {
931 assert( var->exactdata->locdom.lbcertificateidx != -1 || SCIPsetIsInfinity(set, -var->locdom.lb) );
932 var->lbchginfos[var->nlbchginfos - 1].oldcertificateindex = var->exactdata->locdom.lbcertificateidx;
934 }
935
936 /* change local bound of variable */
937 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
938 }
939 else
940 {
941 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
942 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
943 *cutoff = TRUE;
944 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
945 }
946 }
947 else
948 {
949 /* mark bound change to be inactive */
950 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
951 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
952 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
953 boundchg->redundant = TRUE;
954 }
955 break;
956
958 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
959 if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
960 {
961 if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
962 {
963 /* add the bound change info to the variable's bound change info array */
964 switch( boundchg->boundchgtype )
965 {
967 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
968 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
969 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
971 stat->lastbranchvar = var;
973 stat->lastbranchvalue = boundchg->newbound;
974 break;
975
977 assert(boundchg->data.inferencedata.reason.cons != NULL);
978 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
979 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
980 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
981 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
982 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
983 boundchg->data.inferencedata.info,
985 break;
986
988 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
989 boundchg->data.inferencedata.reason.prop != NULL
990 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
991 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
992 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
993 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
994 boundchg->data.inferencedata.info,
996 break;
997
998 default:
999 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
1000 return SCIP_INVALIDDATA;
1001 }
1002
1004 {
1005 assert( var->exactdata->locdom.ubcertificateidx != -1 || SCIPsetIsInfinity(set, var->locdom.ub) );
1006 var->ubchginfos[var->nubchginfos - 1].oldcertificateindex = var->exactdata->locdom.ubcertificateidx;
1008 }
1009
1010 /* change local bound of variable */
1011 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
1012 }
1013 else
1014 {
1015 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
1016 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
1017 *cutoff = TRUE;
1018 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
1019 }
1020 }
1021 else
1022 {
1023 /* mark bound change to be inactive */
1024 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
1025 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1026 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
1027 boundchg->redundant = TRUE;
1028 }
1029 break;
1030
1031 default:
1032 SCIPerrorMessage("unknown bound type\n");
1033 return SCIP_INVALIDDATA;
1034 }
1035
1036 /* update the branching and inference history */
1037 if( !boundchg->applied && !boundchg->redundant )
1038 {
1039 assert(var == boundchg->var);
1040
1042 {
1043 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
1046 }
1047 else if( stat->lastbranchvar != NULL )
1048 {
1049 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
1050 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
1051 }
1052 boundchg->applied = TRUE;
1053 }
1054
1055 return SCIP_OKAY;
1056}
1057
1058/** undoes single bound change */
1060 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1061 BMS_BLKMEM* blkmem, /**< block memory */
1062 SCIP_SET* set, /**< global SCIP settings */
1063 SCIP_STAT* stat, /**< problem statistics */
1064 SCIP_LP* lp, /**< current LP data */
1065 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1066 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1067 )
1068{
1069 SCIP_VAR* var;
1070
1071 assert(boundchg != NULL);
1072 assert(stat != NULL);
1073
1074 /* ignore redundant bound changes */
1075 if( boundchg->redundant )
1076 return SCIP_OKAY;
1077
1078 var = boundchg->var;
1079 assert(var != NULL);
1081
1082 /* undo bound change: apply the previous bound change of variable */
1083 switch( boundchg->boundtype )
1084 {
1086 var->nlbchginfos--;
1087 assert(var->nlbchginfos >= 0);
1088 assert(var->lbchginfos != NULL);
1089 assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
1090 assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
1091
1092 SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
1093 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
1094 var->lbchginfos[var->nlbchginfos].bdchgidx.depth, var->lbchginfos[var->nlbchginfos].bdchgidx.pos,
1095 var->lbchginfos[var->nlbchginfos].oldbound, var->lbchginfos[var->nlbchginfos].newbound);
1096
1097 /* in case certificate is used, set back the certificate line index */
1099 && !SCIPsetIsInfinity(set, -var->lbchginfos[var->nlbchginfos].oldbound) )
1100 {
1102 var->lbchginfos[var->nlbchginfos].oldcertificateindex) );
1103 }
1104
1105 if( set->exact_enable && !SCIPrationalIsFpRepresentable(SCIPvarGetLbGlobalExact(boundchg->var))
1106 && SCIPsetIsEQ(set, var->lbchginfos[var->nlbchginfos].oldbound, SCIPvarGetLbGlobal(boundchg->var) ) )
1107 {
1108 /* reinstall the exact global bound, if necessary */
1109 SCIP_CALL( SCIPvarChgLbLocalExact(boundchg->var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue,
1110 SCIPvarGetLbGlobalExact(boundchg->var)) );
1111 }
1112 else
1113 {
1114 /* reinstall the previous local bound */
1115 SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
1116 var->lbchginfos[var->nlbchginfos].oldbound) );
1117 }
1118
1119 /* in case all bound changes are removed the local bound should match the global bound */
1120 assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
1121
1122 break;
1123
1125 var->nubchginfos--;
1126 assert(var->nubchginfos >= 0);
1127 assert(var->ubchginfos != NULL);
1128 assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
1129 assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
1130
1131 SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
1132 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
1133 var->ubchginfos[var->nubchginfos].bdchgidx.depth, var->ubchginfos[var->nubchginfos].bdchgidx.pos,
1134 var->ubchginfos[var->nubchginfos].oldbound, var->ubchginfos[var->nubchginfos].newbound);
1135
1137 && !SCIPsetIsInfinity(set, var->ubchginfos[var->nubchginfos].oldbound) )
1138 {
1140 var->ubchginfos[var->nubchginfos].oldcertificateindex) );
1141 }
1142
1143 if( set->exact_enable && !SCIPrationalIsFpRepresentable(SCIPvarGetUbGlobalExact(boundchg->var))
1144 && SCIPsetIsEQ(set, var->ubchginfos[var->nubchginfos].oldbound, SCIPvarGetUbGlobal(boundchg->var) ) )
1145 {
1146 /* reinstall the exact global bound, if necessary */
1147 SCIP_CALL( SCIPvarChgUbLocalExact(boundchg->var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue,
1148 SCIPvarGetUbGlobalExact(boundchg->var)) );
1149 }
1150 else
1151 {
1152 /* reinstall the previous local bound */
1153 SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
1154 var->ubchginfos[var->nubchginfos].oldbound) );
1155 }
1156
1157 /* in case all bound changes are removed the local bound should match the global bound */
1158 assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
1159
1160 /* in case certificate is used, set back the certificate line index */
1161
1162 break;
1163
1164 default:
1165 SCIPerrorMessage("unknown bound type\n");
1166 return SCIP_INVALIDDATA;
1167 }
1168
1169 /* update last branching variable */
1171 {
1172 stat->lastbranchvar = NULL;
1174 }
1175
1176 return SCIP_OKAY;
1177}
1178
1179/** applies single bound change to the global problem by changing the global bound of the corresponding variable */
1180static
1182 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
1183 BMS_BLKMEM* blkmem, /**< block memory */
1184 SCIP_SET* set, /**< global SCIP settings */
1185 SCIP_STAT* stat, /**< problem statistics */
1186 SCIP_LP* lp, /**< current LP data */
1187 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1188 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1189 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1190 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
1191 )
1192{
1193 SCIP_VAR* var;
1194 SCIP_Real newbound;
1195 SCIP_BOUNDTYPE boundtype;
1196
1197 assert(boundchg != NULL);
1198 assert(cutoff != NULL);
1199
1200 *cutoff = FALSE;
1201
1202 /* ignore redundant bound changes */
1203 if( boundchg->redundant )
1204 return SCIP_OKAY;
1205
1206 var = SCIPboundchgGetVar(boundchg);
1207 newbound = SCIPboundchgGetNewbound(boundchg);
1208 boundtype = SCIPboundchgGetBoundtype(boundchg);
1209
1210 /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
1211 * after that bound change was applied
1212 *
1213 * @note a global bound change is not captured by the redundant member of the bound change data structure
1214 */
1215 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
1216 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
1217 {
1218 return SCIP_OKAY;
1219 }
1220
1221 SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
1223 boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
1224
1225 /* check for cutoff */
1226 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
1227 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
1228 {
1229 *cutoff = TRUE;
1230 return SCIP_OKAY;
1231 }
1232
1233 if( SCIPisCertified(set->scip) )
1234 {
1235 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1236 {
1237 var->exactdata->glbdom.lbcertificateidx = boundchg->certificateindex;
1238 var->exactdata->locdom.lbcertificateidx = boundchg->certificateindex;
1239 }
1240 else if( boundtype == SCIP_BOUNDTYPE_UPPER )
1241 {
1242 var->exactdata->glbdom.ubcertificateidx = boundchg->certificateindex;
1243 var->exactdata->locdom.ubcertificateidx = boundchg->certificateindex;
1244 }
1245#ifndef NDEBUG
1247#endif
1248 }
1249
1250 /* apply bound change */
1251 SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
1252
1253 return SCIP_OKAY;
1254}
1255
1256/** captures branching and inference data of bound change */
1257static
1259 SCIP_BOUNDCHG* boundchg /**< bound change to remove */
1260 )
1261{
1262 assert(boundchg != NULL);
1263
1264 /* capture variable associated with the bound change */
1265 assert(boundchg->var != NULL);
1266 SCIPvarCapture(boundchg->var);
1267
1268 switch( boundchg->boundchgtype )
1269 {
1272 break;
1273
1275 assert(boundchg->data.inferencedata.var != NULL);
1276 assert(boundchg->data.inferencedata.reason.cons != NULL);
1277 SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
1278 break;
1279
1280 default:
1281 SCIPerrorMessage("invalid bound change type\n");
1282 return SCIP_INVALIDDATA;
1283 }
1284
1285 return SCIP_OKAY;
1286}
1287
1288/** releases branching and inference data of bound change */
1289static
1291 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1292 BMS_BLKMEM* blkmem, /**< block memory */
1293 SCIP_SET* set, /**< global SCIP settings */
1294 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1295 SCIP_LP* lp /**< current LP data */
1296
1297 )
1298{
1299 assert(boundchg != NULL);
1300
1301 switch( boundchg->boundchgtype )
1302 {
1305 break;
1306
1308 assert(boundchg->data.inferencedata.var != NULL);
1309 assert(boundchg->data.inferencedata.reason.cons != NULL);
1310 SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1311 break;
1312
1313 default:
1314 SCIPerrorMessage("invalid bound change type\n");
1315 return SCIP_INVALIDDATA;
1316 }
1317
1318 /* release variable */
1319 assert(boundchg->var != NULL);
1320 SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1321
1322 return SCIP_OKAY;
1323}
1324
1325/** creates empty domain change data with dynamic arrays */
1326static
1328 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1329 BMS_BLKMEM* blkmem /**< block memory */
1330 )
1331{
1332 assert(domchg != NULL);
1333 assert(blkmem != NULL);
1334
1335 SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1336 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1337 (*domchg)->domchgdyn.nboundchgs = 0;
1338 (*domchg)->domchgdyn.boundchgs = NULL;
1339 (*domchg)->domchgdyn.nholechgs = 0;
1340 (*domchg)->domchgdyn.holechgs = NULL;
1341 (*domchg)->domchgdyn.boundchgssize = 0;
1342 (*domchg)->domchgdyn.holechgssize = 0;
1343
1344 return SCIP_OKAY;
1345}
1346
1347/** frees domain change data */
1349 SCIP_DOMCHG** domchg, /**< pointer to domain change */
1350 BMS_BLKMEM* blkmem, /**< block memory */
1351 SCIP_SET* set, /**< global SCIP settings */
1352 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1353 SCIP_LP* lp /**< current LP data */
1354 )
1355{
1356 assert(domchg != NULL);
1357 assert(blkmem != NULL);
1358
1359 if( *domchg != NULL )
1360 {
1361 int i;
1362
1363 /* release variables, branching and inference data associated with the bound changes */
1364 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1365 {
1366 SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1367 if( (*domchg)->domchgbound.boundchgs[i].newboundexact != NULL )
1368 SCIPrationalFreeBlock(blkmem, &(*domchg)->domchgbound.boundchgs[i].newboundexact);
1369 }
1370
1371 /* free memory for bound and hole changes */
1372 switch( (*domchg)->domchgdyn.domchgtype )
1373 {
1375 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1376 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1377 break;
1379 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1380 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1381 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1382 break;
1384 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1385 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1386 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1387 break;
1388 default:
1389 SCIPerrorMessage("invalid domain change type\n");
1390 return SCIP_INVALIDDATA;
1391 }
1392 }
1393
1394 return SCIP_OKAY;
1395}
1396
1397/** converts a static domain change data into a dynamic one */
1398static
1400 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1401 BMS_BLKMEM* blkmem /**< block memory */
1402 )
1403{
1404 assert(domchg != NULL);
1405 assert(blkmem != NULL);
1406
1407 SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1408
1409 if( *domchg == NULL )
1410 {
1411 SCIP_CALL( domchgCreate(domchg, blkmem) );
1412 }
1413 else
1414 {
1415 switch( (*domchg)->domchgdyn.domchgtype )
1416 {
1418 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1419 (*domchg)->domchgdyn.nholechgs = 0;
1420 (*domchg)->domchgdyn.holechgs = NULL;
1421 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1422 (*domchg)->domchgdyn.holechgssize = 0;
1423 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1424 break;
1426 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1427 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1428 (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1429 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1430 break;
1432 break;
1433 default:
1434 SCIPerrorMessage("invalid domain change type\n");
1435 return SCIP_INVALIDDATA;
1436 }
1437 }
1438#ifndef NDEBUG
1439 {
1440 int i;
1441 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1442 assert(!SCIPvarIsIntegral((*domchg)->domchgbound.boundchgs[i].var)
1443 || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1444 }
1445#endif
1446
1447 return SCIP_OKAY;
1448}
1449
1450/** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1452 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1453 BMS_BLKMEM* blkmem, /**< block memory */
1454 SCIP_SET* set, /**< global SCIP settings */
1455 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1456 SCIP_LP* lp /**< current LP data */
1457 )
1458{
1459 assert(domchg != NULL);
1460 assert(blkmem != NULL);
1461
1462 SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1463
1464 if( *domchg != NULL )
1465 {
1466 switch( (*domchg)->domchgdyn.domchgtype )
1467 {
1469 if( (*domchg)->domchgbound.nboundchgs == 0 )
1470 {
1471 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1472 }
1473 break;
1475 if( (*domchg)->domchgboth.nholechgs == 0 )
1476 {
1477 if( (*domchg)->domchgbound.nboundchgs == 0 )
1478 {
1479 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1480 }
1481 else
1482 {
1483 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1484 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1485 }
1486 }
1487 break;
1489 if( (*domchg)->domchgboth.nholechgs == 0 )
1490 {
1491 if( (*domchg)->domchgbound.nboundchgs == 0 )
1492 {
1493 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1494 }
1495 else
1496 {
1497 /* shrink dynamic size arrays to their minimal sizes */
1498 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1499 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1500 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1501
1502 /* convert into static domain change */
1503 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1504 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1505 }
1506 }
1507 else
1508 {
1509 /* shrink dynamic size arrays to their minimal sizes */
1510 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1511 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1512 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1513 (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1514
1515 /* convert into static domain change */
1516 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1517 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1518 }
1519 break;
1520 default:
1521 SCIPerrorMessage("invalid domain change type\n");
1522 return SCIP_INVALIDDATA;
1523 }
1524#ifndef NDEBUG
1525 if( *domchg != NULL )
1526 {
1527 int i;
1528 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1529 assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1530 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1531 }
1532#endif
1533 }
1534
1535 return SCIP_OKAY;
1536}
1537
1538/** ensures, that boundchgs array can store at least num entries */
1539static
1541 SCIP_DOMCHG* domchg, /**< domain change data structure */
1542 BMS_BLKMEM* blkmem, /**< block memory */
1543 SCIP_SET* set, /**< global SCIP settings */
1544 int num /**< minimum number of entries to store */
1545 )
1546{
1547 assert(domchg != NULL);
1548 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1549
1550 if( num > domchg->domchgdyn.boundchgssize )
1551 {
1552 int newsize;
1553
1554 newsize = SCIPsetCalcMemGrowSize(set, num);
1555 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1556 for( int i = domchg->domchgdyn.boundchgssize; i < newsize; ++i)
1558 domchg->domchgdyn.boundchgssize = newsize;
1559 }
1560 assert(num <= domchg->domchgdyn.boundchgssize);
1561
1562 return SCIP_OKAY;
1563}
1564
1565/** ensures, that holechgs array can store at least num additional entries */
1566static
1568 SCIP_DOMCHG* domchg, /**< domain change data structure */
1569 BMS_BLKMEM* blkmem, /**< block memory */
1570 SCIP_SET* set, /**< global SCIP settings */
1571 int num /**< minimum number of additional entries to store */
1572 )
1573{
1574 assert(domchg != NULL);
1575 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1576
1577 if( num > domchg->domchgdyn.holechgssize )
1578 {
1579 int newsize;
1580
1581 newsize = SCIPsetCalcMemGrowSize(set, num);
1582 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1583 domchg->domchgdyn.holechgssize = newsize;
1584 }
1585 assert(num <= domchg->domchgdyn.holechgssize);
1586
1587 return SCIP_OKAY;
1588}
1589
1590/** applies domain change */
1592 SCIP_DOMCHG* domchg, /**< domain change to apply */
1593 BMS_BLKMEM* blkmem, /**< block memory */
1594 SCIP_SET* set, /**< global SCIP settings */
1595 SCIP_STAT* stat, /**< problem statistics */
1596 SCIP_LP* lp, /**< current LP data */
1597 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1598 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1599 int depth, /**< depth in the tree, where the domain change takes place */
1600 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1601 )
1602{
1603 int i;
1604
1605 assert(cutoff != NULL);
1606
1607 *cutoff = FALSE;
1608
1609 SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1610
1611 if( domchg == NULL )
1612 return SCIP_OKAY;
1613
1614 /* apply bound changes */
1615 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1616 {
1617 SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1618 branchcand, eventqueue, depth, i, cutoff) );
1619 if( *cutoff )
1620 break;
1621 }
1622 SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1623
1624 /* mark all bound changes after a cutoff redundant */
1625 for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1627
1628 /* apply holelist changes */
1629 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1630 {
1631 for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1632 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1633 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1634 }
1635
1636 return SCIP_OKAY;
1637}
1638
1639/** undoes domain change */
1641 SCIP_DOMCHG* domchg, /**< domain change to remove */
1642 BMS_BLKMEM* blkmem, /**< block memory */
1643 SCIP_SET* set, /**< global SCIP settings */
1644 SCIP_STAT* stat, /**< problem statistics */
1645 SCIP_LP* lp, /**< current LP data */
1646 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1647 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1648 )
1649{
1650 int i;
1651
1652 SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1653 if( domchg == NULL )
1654 return SCIP_OKAY;
1655
1656 /* undo holelist changes */
1657 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1658 {
1659 for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1660 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1661 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1662 }
1663
1664 /* undo bound changes */
1665 for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1666 {
1667 SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1668 }
1669 SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1670
1671 return SCIP_OKAY;
1672}
1673
1674/** applies domain change to the global problem */
1676 SCIP_DOMCHG* domchg, /**< domain change to apply */
1677 BMS_BLKMEM* blkmem, /**< block memory */
1678 SCIP_SET* set, /**< global SCIP settings */
1679 SCIP_STAT* stat, /**< problem statistics */
1680 SCIP_LP* lp, /**< current LP data */
1681 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1682 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1683 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1684 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1685 )
1686{
1687 int i;
1688
1689 assert(cutoff != NULL);
1690
1691 *cutoff = FALSE;
1692
1693 if( domchg == NULL )
1694 return SCIP_OKAY;
1695
1696 SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1697
1698 /* apply bound changes */
1699 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1700 {
1701 SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1702 branchcand, eventqueue, cliquetable, cutoff) );
1703 if( *cutoff )
1704 break;
1705 }
1706 SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1707
1708 /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1709
1710 return SCIP_OKAY;
1711}
1712
1713/** adds certificate line number to domain changes */
1715 SCIP_DOMCHG* domchg, /**< pointer to domain change data structure */
1716 SCIP_CERTIFICATE* certificate /**< certificate information */
1717 )
1718{
1719 SCIP_BOUNDCHG* change;
1720
1721 if( !SCIPcertificateIsEnabled(certificate) )
1722 return;
1723
1724 change = &(domchg->domchgdyn.boundchgs[domchg->domchgdyn.nboundchgs - 1]);
1725
1726#ifndef NDEBUG
1728#endif
1729
1730 change->certificateindex = SCIPcertificateGetCurrentIndex(certificate) - 1;
1731}
1732
1733/** adds bound change to domain changes */
1735 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1736 BMS_BLKMEM* blkmem, /**< block memory */
1737 SCIP_SET* set, /**< global SCIP settings */
1738 SCIP_VAR* var, /**< variable to change the bounds for */
1739 SCIP_Real newbound, /**< new value for bound */
1740 SCIP_RATIONAL* newboundexact, /**< new value for exact bound, or NULL if not needed */
1741 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1742 SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1743 SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1744 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1745 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1746 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1747 int inferinfo, /**< user information for inference to help resolving the conflict */
1748 SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1749 )
1750{
1751 SCIP_BOUNDCHG* boundchg;
1752
1753 assert(domchg != NULL);
1754 assert(var != NULL);
1756 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1758 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1759 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1760 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1761
1762 SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1763 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1764 newbound, var->name, (void*)domchg, (void*)*domchg);
1765
1766 /* if domain change data doesn't exist, create it;
1767 * if domain change is static, convert it into dynamic change
1768 */
1769 if( *domchg == NULL )
1770 {
1771 SCIP_CALL( domchgCreate(domchg, blkmem) );
1772 }
1773 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1774 {
1775 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1776 }
1777 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1778
1779 /* get memory for additional bound change */
1780 SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1781
1782 /* fill in the bound change data */
1783 boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1784 boundchg->var = var;
1785 switch( boundchgtype )
1786 {
1788 boundchg->data.branchingdata.lpsolval = lpsolval;
1789 break;
1791 assert(infercons != NULL);
1792 boundchg->data.inferencedata.var = infervar;
1793 boundchg->data.inferencedata.reason.cons = infercons;
1794 boundchg->data.inferencedata.info = inferinfo;
1795 break;
1797 boundchg->data.inferencedata.var = infervar;
1798 boundchg->data.inferencedata.reason.prop = inferprop;
1799 boundchg->data.inferencedata.info = inferinfo;
1800 break;
1801 default:
1802 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1803 return SCIP_INVALIDDATA;
1804 }
1805
1806 boundchg->newbound = newbound;
1807 boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1808 boundchg->boundtype = boundtype; /*lint !e641*/
1809 boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1810 boundchg->applied = FALSE;
1811 boundchg->redundant = FALSE;
1812 (*domchg)->domchgdyn.nboundchgs++;
1813 if( newboundexact != NULL )
1814 {
1815 if( boundchg->newboundexact == NULL )
1816 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &boundchg->newboundexact, newboundexact) );
1817 else
1818 SCIPrationalSetRational(boundchg->newboundexact, newboundexact);
1819 }
1820
1821 /* capture branching and inference data associated with the bound changes */
1822 SCIP_CALL( boundchgCaptureData(boundchg) );
1823
1824#ifdef SCIP_DISABLED_CODE /* expensive debug check */
1825#ifdef SCIP_MORE_DEBUG
1826 {
1827 int i;
1828 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1829 assert(!SCIPvarIsIntegral((*domchg)->domchgbound.boundchgs[i].var)
1830 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1831 }
1832#endif
1833#endif
1834
1835 return SCIP_OKAY;
1836}
1837
1838/** adds hole change to domain changes */
1840 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1841 BMS_BLKMEM* blkmem, /**< block memory */
1842 SCIP_SET* set, /**< global SCIP settings */
1843 SCIP_HOLELIST** ptr, /**< changed list pointer */
1844 SCIP_HOLELIST* newlist, /**< new value of list pointer */
1845 SCIP_HOLELIST* oldlist /**< old value of list pointer */
1846 )
1847{
1848 SCIP_HOLECHG* holechg;
1849
1850 assert(domchg != NULL);
1851 assert(ptr != NULL);
1852
1853 /* if domain change data doesn't exist, create it;
1854 * if domain change is static, convert it into dynamic change
1855 */
1856 if( *domchg == NULL )
1857 {
1858 SCIP_CALL( domchgCreate(domchg, blkmem) );
1859 }
1860 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1861 {
1862 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1863 }
1864 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1865
1866 /* get memory for additional hole change */
1867 SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1868
1869 /* fill in the hole change data */
1870 holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1871 holechg->ptr = ptr;
1872 holechg->newlist = newlist;
1873 holechg->oldlist = oldlist;
1874 (*domchg)->domchgdyn.nholechgs++;
1875
1876 return SCIP_OKAY;
1877}
1878
1879
1880
1881
1882/*
1883 * methods for variables
1884 */
1885
1886/** returns adjusted lower bound value, which is rounded for integral variable types */
1887static
1889 SCIP_SET* set, /**< global SCIP settings */
1890 SCIP_Bool isintegral, /**< is variable integral? */
1891 SCIP_Real lb /**< lower bound to adjust */
1892 )
1893{
1894 if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1895 return -SCIPsetInfinity(set);
1896 else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1897 return SCIPsetInfinity(set);
1898 else if( isintegral )
1899 return SCIPsetFeasCeil(set, lb);
1900 else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1901 return 0.0;
1902 else
1903 return lb;
1904}
1905
1906/** returns adjusted lower bound value, which is rounded for integral variable types */
1907static
1909 SCIP_Bool isintegral, /**< is variable integral? */
1910 SCIP_Real lb /**< lower bound to adjust */
1911 )
1912{
1913 if( isintegral )
1914 return ceil(lb);
1915 else
1916 return lb;
1917}
1918
1919/** returns adjusted lower bound value, which is rounded for integral variable types */
1920static
1922 SCIP_SET* set, /**< global SCIP settings */
1923 SCIP_Bool isintegral, /**< is variable integral? */
1924 SCIP_RATIONAL* lb /**< lower bound to adjust */
1925 )
1926{
1931 else if( isintegral )
1933}
1934
1935/** returns adjusted upper bound value, which is rounded for integral variable types */
1936static
1938 SCIP_SET* set, /**< global SCIP settings */
1939 SCIP_Bool isintegral, /**< is variable integral? */
1940 SCIP_Real ub /**< upper bound to adjust */
1941 )
1942{
1943 if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1944 return SCIPsetInfinity(set);
1945 else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1946 return -SCIPsetInfinity(set);
1947 else if( isintegral )
1948 return SCIPsetFeasFloor(set, ub);
1949 else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1950 return 0.0;
1951 else
1952 return ub;
1953}
1954
1955/** returns adjusted upperbound value, which is rounded for integral variable types */
1956static
1958 SCIP_Bool isintegral, /**< is variable integral? */
1959 SCIP_Real lb /**< lower bound to adjust */
1960 )
1961{
1962 if( isintegral )
1963 return floor(lb);
1964 else
1965 return lb;
1966}
1967
1968/** returns adjusted lower bound value, which is rounded for integral variable types */
1969static
1971 SCIP_SET* set, /**< global SCIP settings */
1972 SCIP_Bool isintegral, /**< is variable integral? */
1973 SCIP_RATIONAL* ub /**< lower bound to adjust */
1974 )
1975{
1980 else if( isintegral )
1982}
1983
1984/** writes the approximate exact multi-aggregate data in the floating-point structs */
1985static
1987 SCIP_SET* set, /**< global SCIP settings */
1988 SCIP_VAR* var /**< SCIP variable */
1989 )
1990{
1991 int i;
1992
1993 if( !set->exact_enable || SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
1994 return;
1995
1996 var->data.multaggr.constant = SCIPrationalGetReal(var->exactdata->multaggr.constant);
1997 for( i = 0; i < var->data.multaggr.nvars; i++ )
1998 {
1999 var->data.multaggr.scalars[i] = SCIPrationalGetReal(var->exactdata->multaggr.scalars[i]);
2000 }
2001}
2002
2003/** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
2004 * bounds arrays, and optionally removes them also from the variable itself
2005 */
2007 SCIP_VAR* var, /**< problem variable */
2008 BMS_BLKMEM* blkmem, /**< block memory */
2009 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2010 SCIP_SET* set, /**< global SCIP settings */
2011 SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
2012 SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
2013 SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
2014 )
2015{
2016 SCIP_Real lb;
2017 SCIP_Real ub;
2018
2019 assert(var != NULL);
2022
2023 lb = SCIPvarGetLbGlobal(var);
2024 ub = SCIPvarGetUbGlobal(var);
2025
2026 SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
2027 onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
2028
2029 /* remove implications of (fixed) binary variable */
2030 if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
2031 {
2032 SCIP_Bool varfixing;
2033
2035
2036 varfixing = FALSE;
2037 do
2038 {
2039 SCIP_VAR** implvars;
2040 SCIP_BOUNDTYPE* impltypes;
2041 int nimpls;
2042 int i;
2043
2044 nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
2045 implvars = SCIPimplicsGetVars(var->implics, varfixing);
2046 impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
2047
2048 for( i = 0; i < nimpls; i++ )
2049 {
2050 SCIP_VAR* implvar;
2051 SCIP_BOUNDTYPE impltype;
2052
2053 implvar = implvars[i];
2054 impltype = impltypes[i];
2055 assert(implvar != var);
2056
2057 /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
2058 * the following variable bound from x's variable bounds
2059 * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
2060 * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
2061 */
2062 if( impltype == SCIP_BOUNDTYPE_UPPER )
2063 {
2064 if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2065 {
2066 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
2067 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
2068 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
2069 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
2070 implvar->closestvblpcount = -1;
2071 var->closestvblpcount = -1;
2072 }
2073 }
2074 else
2075 {
2076 if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2077 {
2078 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
2079 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
2080 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
2081 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
2082 implvar->closestvblpcount = -1;
2083 var->closestvblpcount = -1;
2084 }
2085 }
2086 }
2087 varfixing = !varfixing;
2088 }
2089 while( varfixing == TRUE );
2090
2091 if( removefromvar )
2092 {
2093 /* free the implications data structures */
2094 SCIPimplicsFree(&var->implics, blkmem);
2095 }
2096 }
2097
2098 /* remove the (redundant) variable lower bounds */
2099 if( var->vlbs != NULL )
2100 {
2101 SCIP_VAR** vars;
2102 SCIP_Real* coefs;
2103 SCIP_Real* constants;
2104 int nvbds;
2105 int newnvbds;
2106 int i;
2107
2108 nvbds = SCIPvboundsGetNVbds(var->vlbs);
2109 vars = SCIPvboundsGetVars(var->vlbs);
2110 coefs = SCIPvboundsGetCoefs(var->vlbs);
2111 constants = SCIPvboundsGetConstants(var->vlbs);
2112
2113 /* remove for all variable bounds x >= b*z+d the following implication from z's implications
2114 * z == ub ==> x >= b*ub + d , if b > 0
2115 * z == lb ==> x >= b*lb + d , if b < 0
2116 */
2117 newnvbds = 0;
2118 for( i = 0; i < nvbds; i++ )
2119 {
2120 SCIP_VAR* implvar;
2121 SCIP_Real coef;
2122
2123 assert(newnvbds <= i);
2124
2125 implvar = vars[i];
2126 assert(implvar != NULL);
2127
2128 coef = coefs[i];
2129 assert(!SCIPsetIsZero(set, coef));
2130
2131 /* check, if we want to remove the variable bound */
2132 if( onlyredundant )
2133 {
2134 SCIP_Real vbound;
2135
2136 vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
2137 if( SCIPsetIsFeasGT(set, vbound, lb) )
2138 {
2139 /* the variable bound is not redundant: keep it */
2140 if( removefromvar )
2141 {
2142 if( newnvbds < i )
2143 {
2144 vars[newnvbds] = implvar;
2145 coefs[newnvbds] = coef;
2146 constants[newnvbds] = constants[i];
2147 }
2148 newnvbds++;
2149 }
2150 continue;
2151 }
2152 }
2153
2154 /* remove the corresponding implication */
2155 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
2156 {
2157 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
2158 SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
2159 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
2160 }
2161 if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2162 {
2163 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
2164 SCIPvarGetName(implvar), SCIPvarGetName(var));
2165 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
2166 implvar->closestvblpcount = -1;
2167 var->closestvblpcount = -1;
2168 }
2169 else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2170 {
2171 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
2172 SCIPvarGetName(implvar), SCIPvarGetName(var));
2173 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
2174 implvar->closestvblpcount = -1;
2175 var->closestvblpcount = -1;
2176 }
2177 }
2178
2179 if( removefromvar )
2180 {
2181 /* update the number of variable bounds */
2182 SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
2183 var->closestvblpcount = -1;
2184 }
2185 }
2186
2187 /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
2188 * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
2189 * cannot remove such variables x from z's implications.
2190 */
2191
2192 /* remove the (redundant) variable upper bounds */
2193 if( var->vubs != NULL )
2194 {
2195 SCIP_VAR** vars;
2196 SCIP_Real* coefs;
2197 SCIP_Real* constants;
2198 int nvbds;
2199 int newnvbds;
2200 int i;
2201
2202 nvbds = SCIPvboundsGetNVbds(var->vubs);
2203 vars = SCIPvboundsGetVars(var->vubs);
2204 coefs = SCIPvboundsGetCoefs(var->vubs);
2205 constants = SCIPvboundsGetConstants(var->vubs);
2206
2207 /* remove for all variable bounds x <= b*z+d the following implication from z's implications
2208 * z == lb ==> x <= b*lb + d , if b > 0
2209 * z == ub ==> x <= b*ub + d , if b < 0
2210 */
2211 newnvbds = 0;
2212 for( i = 0; i < nvbds; i++ )
2213 {
2214 SCIP_VAR* implvar;
2215 SCIP_Real coef;
2216
2217 assert(newnvbds <= i);
2218
2219 implvar = vars[i];
2220 assert(implvar != NULL);
2221
2222 coef = coefs[i];
2223 assert(!SCIPsetIsZero(set, coef));
2224
2225 /* check, if we want to remove the variable bound */
2226 if( onlyredundant )
2227 {
2228 SCIP_Real vbound;
2229
2230 vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
2231 if( SCIPsetIsFeasLT(set, vbound, ub) )
2232 {
2233 /* the variable bound is not redundant: keep it */
2234 if( removefromvar )
2235 {
2236 if( newnvbds < i )
2237 {
2238 vars[newnvbds] = implvar;
2239 coefs[newnvbds] = coefs[i];
2240 constants[newnvbds] = constants[i];
2241 }
2242 newnvbds++;
2243 }
2244 continue;
2245 }
2246 }
2247
2248 /* remove the corresponding implication */
2249 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
2250 {
2251 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
2252 SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
2253 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
2254 }
2255 if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2256 {
2257 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
2258 SCIPvarGetName(implvar), SCIPvarGetName(var));
2259 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
2260 implvar->closestvblpcount = -1;
2261 var->closestvblpcount = -1;
2262 }
2263 else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2264 {
2265 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
2266 SCIPvarGetName(implvar), SCIPvarGetName(var));
2267 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
2268 implvar->closestvblpcount = -1;
2269 var->closestvblpcount = -1;
2270 }
2271 }
2272
2273 if( removefromvar )
2274 {
2275 /* update the number of variable bounds */
2276 SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
2277 var->closestvblpcount = -1;
2278 }
2279 }
2280
2281 /* remove the variable from all cliques */
2282 if( SCIPvarIsBinary(var) )
2283 SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
2284
2285 /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
2286 * z has no link (like in the binary case) to x
2287 */
2288
2289 return SCIP_OKAY;
2290}
2291
2292/** sets the variable name */
2293static
2295 SCIP_VAR* var, /**< problem variable */
2296 BMS_BLKMEM* blkmem, /**< block memory */
2297 SCIP_STAT* stat, /**< problem statistics, or NULL */
2298 const char* name /**< name of variable, or NULL for automatic name creation */
2299 )
2300{
2301 assert(blkmem != NULL);
2302 assert(var != NULL);
2303
2304 if( name == NULL )
2305 {
2306 char s[SCIP_MAXSTRLEN];
2307
2308 assert(stat != NULL);
2309
2310 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
2311 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
2312 }
2313 else
2314 {
2315 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
2316 }
2317
2318 return SCIP_OKAY;
2319}
2320
2321/** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
2322 * with bounds zero and one is automatically converted into a binary variable
2323 */
2324static
2326 SCIP_VAR** var, /**< pointer to variable data */
2327 BMS_BLKMEM* blkmem, /**< block memory */
2328 SCIP_SET* set, /**< global SCIP settings */
2329 SCIP_STAT* stat, /**< problem statistics */
2330 const char* name, /**< name of variable, or NULL for automatic name creation */
2331 SCIP_Real lb, /**< lower bound of variable */
2332 SCIP_Real ub, /**< upper bound of variable */
2333 SCIP_Real obj, /**< objective function value */
2334 SCIP_VARTYPE vartype, /**< type of variable */
2335 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2336 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2337 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2338 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2339 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2340 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2341 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2342 SCIP_VARDATA* vardata /**< user data for this specific variable */
2343 )
2344{
2345 SCIP_Bool integral;
2346 int i;
2347
2348 assert(var != NULL);
2349 assert(blkmem != NULL);
2350 assert(stat != NULL);
2352
2353 /* forbid infinite objective values */
2355 {
2356 SCIPerrorMessage("invalid objective coefficient: value is infinite\n");
2357 return SCIP_INVALIDDATA;
2358 }
2359
2360 /* exact bounds may follow later */
2361 if( !set->exact_enable )
2362 {
2363 /* adjust bounds of variable */
2364 integral = vartype != SCIP_VARTYPE_CONTINUOUS || impltype != SCIP_IMPLINTTYPE_NONE;
2365 lb = adjustedLb(set, integral, lb);
2366 ub = adjustedUb(set, integral, ub);
2367
2368 /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
2369 if( ( lb == 0.0 || lb == 1.0 ) && ( ub == 0.0 || ub == 1.0 ) ) /*lint !e777*/
2370 {
2371 if( vartype == SCIP_VARTYPE_INTEGER )
2372 vartype = SCIP_VARTYPE_BINARY;
2373 }
2374 else
2375 {
2376 if( vartype == SCIP_VARTYPE_BINARY )
2377 {
2378 SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
2379 return SCIP_INVALIDDATA;
2380 }
2381 }
2382
2383 assert(vartype != SCIP_VARTYPE_BINARY || lb == 0.0 || lb == 1.0); /*lint !e777*/
2384 assert(vartype != SCIP_VARTYPE_BINARY || ub == 0.0 || ub == 1.0); /*lint !e777*/
2386 }
2387
2389
2390 /* set variable's name */
2391 SCIP_CALL( varSetName(*var, blkmem, stat, name) );
2392
2393#ifndef NDEBUG
2394 (*var)->scip = set->scip;
2395#endif
2396 (*var)->obj = obj;
2397 (*var)->unchangedobj = obj;
2398 (*var)->branchfactor = 1.0;
2399 (*var)->rootsol = 0.0;
2400 (*var)->bestrootsol = 0.0;
2401 (*var)->bestrootredcost = 0.0;
2402 (*var)->bestrootlpobjval = SCIP_INVALID;
2403 (*var)->relaxsol = 0.0;
2404 (*var)->nlpsol = 0.0;
2405 (*var)->primsolavg = 0.5 * (lb + ub);
2406 (*var)->conflictlb = SCIP_REAL_MIN;
2407 (*var)->conflictub = SCIP_REAL_MAX;
2408 (*var)->conflictrelaxedlb = (*var)->conflictlb;
2409 (*var)->conflictrelaxedub = (*var)->conflictub;
2410 (*var)->lazylb = -SCIPsetInfinity(set);
2411 (*var)->lazyub = SCIPsetInfinity(set);
2412 (*var)->glbdom.holelist = NULL;
2413 (*var)->glbdom.lb = lb;
2414 (*var)->glbdom.ub = ub;
2415 (*var)->locdom.holelist = NULL;
2416 (*var)->locdom.lb = lb;
2417 (*var)->locdom.ub = ub;
2418 (*var)->varcopy = varcopy;
2419 (*var)->vardelorig = vardelorig;
2420 (*var)->vartrans = vartrans;
2421 (*var)->vardeltrans = vardeltrans;
2422 (*var)->vardata = vardata;
2423 (*var)->parentvars = NULL;
2424 (*var)->negatedvar = NULL;
2425 (*var)->vlbs = NULL;
2426 (*var)->vubs = NULL;
2427 (*var)->implics = NULL;
2428 (*var)->cliquelist = NULL;
2429 (*var)->eventfilter = NULL;
2430 (*var)->lbchginfos = NULL;
2431 (*var)->ubchginfos = NULL;
2432 (*var)->index = stat->nvaridx;
2433 (*var)->probindex = -1;
2434 (*var)->pseudocandindex = -1;
2435 (*var)->eventqueueindexobj = -1;
2436 (*var)->eventqueueindexlb = -1;
2437 (*var)->eventqueueindexub = -1;
2438 (*var)->parentvarssize = 0;
2439 (*var)->nparentvars = 0;
2440 (*var)->nuses = 0;
2441 (*var)->branchpriority = 0;
2442 (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2443 (*var)->lbchginfossize = 0;
2444 (*var)->nlbchginfos = 0;
2445 (*var)->ubchginfossize = 0;
2446 (*var)->nubchginfos = 0;
2447 (*var)->conflictlbcount = 0;
2448 (*var)->conflictubcount = 0;
2449 (*var)->closestvlbidx = -1;
2450 (*var)->closestvubidx = -1;
2451 (*var)->closestvblpcount = -1;
2452 (*var)->initial = initial;
2453 (*var)->removable = removable;
2454 (*var)->deleted = FALSE;
2455 (*var)->donotaggr = FALSE;
2456 (*var)->donotmultaggr = FALSE;
2457 (*var)->vartype = (unsigned int)vartype;
2458 (*var)->varimpltype = (unsigned int)impltype;
2459 (*var)->pseudocostflag = FALSE;
2460 (*var)->eventqueueimpl = FALSE;
2461 (*var)->deletable = FALSE;
2462 (*var)->delglobalstructs = FALSE;
2463 (*var)->exactdata = NULL;
2464 (*var)->relaxationonly = FALSE;
2465
2466 for( i = 0; i < NLOCKTYPES; i++ )
2467 {
2468 (*var)->nlocksdown[i] = 0;
2469 (*var)->nlocksup[i] = 0;
2470 }
2471
2472 stat->nvaridx++;
2473
2474 /* create branching and inference history entries */
2475 SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2476 SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2477
2478 /* the value based history is only created on demand */
2479 (*var)->valuehistory = NULL;
2480
2481 return SCIP_OKAY;
2482}
2483
2484/** creates and captures an original problem variable; an integer variable with bounds
2485 * zero and one is automatically converted into a binary variable
2486 */
2488 SCIP_VAR** var, /**< pointer to variable data */
2489 BMS_BLKMEM* blkmem, /**< block memory */
2490 SCIP_SET* set, /**< global SCIP settings */
2491 SCIP_STAT* stat, /**< problem statistics */
2492 const char* name, /**< name of variable, or NULL for automatic name creation */
2493 SCIP_Real lb, /**< lower bound of variable */
2494 SCIP_Real ub, /**< upper bound of variable */
2495 SCIP_Real obj, /**< objective function value */
2496 SCIP_VARTYPE vartype, /**< type of variable */
2497 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2498 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2499 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2500 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2501 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2502 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2503 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2504 SCIP_VARDATA* vardata /**< user data for this specific variable */
2505 )
2506{
2507 assert(var != NULL);
2508 assert(blkmem != NULL);
2509 assert(stat != NULL);
2510
2511 /* create variable */
2512 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
2513 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2514
2515 /* set variable status and data */
2516 (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2517 (*var)->data.original.origdom.holelist = NULL;
2518 (*var)->data.original.origdom.lb = lb;
2519 (*var)->data.original.origdom.ub = ub;
2520 (*var)->data.original.transvar = NULL;
2521
2522 /* capture variable */
2524
2525 return SCIP_OKAY;
2526}
2527
2528/** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2529 * zero and one is automatically converted into a binary variable
2530 */
2532 SCIP_VAR** var, /**< pointer to variable data */
2533 BMS_BLKMEM* blkmem, /**< block memory */
2534 SCIP_SET* set, /**< global SCIP settings */
2535 SCIP_STAT* stat, /**< problem statistics */
2536 const char* name, /**< name of variable, or NULL for automatic name creation */
2537 SCIP_Real lb, /**< lower bound of variable */
2538 SCIP_Real ub, /**< upper bound of variable */
2539 SCIP_Real obj, /**< objective function value */
2540 SCIP_VARTYPE vartype, /**< type of variable */
2541 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2542 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2543 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2544 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2545 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2546 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2547 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2548 SCIP_VARDATA* vardata /**< user data for this specific variable */
2549 )
2550{
2551 assert(var != NULL);
2552 assert(blkmem != NULL);
2553
2554 /* create variable */
2555 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
2556 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2557
2558 /* create event filter for transformed variable */
2559 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2560
2561 /* set variable status and data */
2562 (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2563 (*var)->data.loose.minaggrcoef = 1.0;
2564 (*var)->data.loose.maxaggrcoef = 1.0;
2565
2566 /* capture variable */
2568
2569 return SCIP_OKAY;
2570}
2571
2572/** creates and sets the exact variable bounds and objective value (using floating-point data if value pointer is NULL)
2573 *
2574 * @note an inactive integer variable with bounds zero and one is automatically converted into a binary variable
2575 *
2576 * @note if exact data is provided, the corresponding floating-point data is overwritten
2577 */
2579 SCIP_VAR* var, /**< pointer to variable data */
2580 BMS_BLKMEM* blkmem, /**< block memory */
2581 SCIP_RATIONAL* lb, /**< lower bound of variable, or NULL to use floating-point data */
2582 SCIP_RATIONAL* ub, /**< upper bound of variable, or NULL to use floating-point data */
2583 SCIP_RATIONAL* obj /**< objective function value, or NULL to use floating-point data */
2584 )
2585{
2586 assert(var != NULL);
2587 assert(blkmem != NULL);
2588
2589 assert(var->exactdata == NULL);
2590 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &(var->exactdata)) );
2591
2592 if( lb != NULL )
2593 {
2594 var->data.original.origdom.lb = SCIPrationalRoundReal(lb, SCIP_R_ROUND_DOWNWARDS);
2595 var->glbdom.lb = var->data.original.origdom.lb;
2596 var->locdom.lb = var->data.original.origdom.lb;
2597
2598 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->origdom.lb, lb) );
2599 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->glbdom.lb, lb) );
2600 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->locdom.lb, lb) );
2601 }
2602 else
2603 {
2604 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->origdom.lb) );
2605 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->glbdom.lb) );
2606 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->locdom.lb) );
2607
2608 SCIPrationalSetReal(var->exactdata->origdom.lb, var->data.original.origdom.lb);
2609 SCIPrationalSetReal(var->exactdata->glbdom.lb, var->glbdom.lb);
2610 SCIPrationalSetReal(var->exactdata->locdom.lb, var->locdom.lb);
2611 }
2612
2613 if( ub != NULL )
2614 {
2615 var->data.original.origdom.ub = SCIPrationalRoundReal(ub, SCIP_R_ROUND_UPWARDS);
2616 var->glbdom.ub = var->data.original.origdom.ub;
2617 var->locdom.ub = var->data.original.origdom.ub;
2618
2619 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->origdom.ub, ub) );
2620 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->glbdom.ub, ub) );
2621 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->locdom.ub, ub) );
2622 }
2623 else
2624 {
2625 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->origdom.ub) );
2626 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->glbdom.ub) );
2627 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->locdom.ub) );
2628
2629 SCIPrationalSetReal(var->exactdata->origdom.ub, var->data.original.origdom.ub);
2630 SCIPrationalSetReal(var->exactdata->glbdom.ub, var->glbdom.ub);
2631 SCIPrationalSetReal(var->exactdata->locdom.ub, var->locdom.ub);
2632 }
2633
2634 if( obj != NULL )
2635 {
2636 var->unchangedobj = SCIPrationalGetReal(obj);
2637 var->obj = var->unchangedobj;
2638
2639 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->obj, obj) );
2640 SCIPintervalSetRational(&var->exactdata->objinterval, obj);
2641 }
2642 else
2643 {
2644 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->obj) );
2645
2646 SCIPrationalSetReal(var->exactdata->obj, var->obj);
2647 SCIPintervalSet(&var->exactdata->objinterval, var->obj);
2648 }
2649
2650 var->exactdata->glbdom.lbcertificateidx = -1;
2651 var->exactdata->glbdom.ubcertificateidx = -1;
2652 var->exactdata->locdom.lbcertificateidx = -1;
2653 var->exactdata->locdom.ubcertificateidx = -1;
2654 var->exactdata->colexact = NULL;
2655 var->exactdata->varstatusexact = SCIPvarGetStatus(var);
2656 var->exactdata->certificateindex = -1;
2657 var->exactdata->multaggr.scalars = NULL;
2658 var->exactdata->multaggr.constant = NULL;
2659 var->exactdata->aggregate.constant = NULL;
2660 var->exactdata->aggregate.scalar = NULL;
2661 var->primsolavg = 0.5 * (var->data.original.origdom.lb + var->data.original.origdom.ub);
2662
2663 /* convert inactive [0,1]-integers into binary variables and check that binary variables have correct bounds */
2664 if( ( SCIPrationalIsZero(var->exactdata->origdom.lb) || SCIPrationalIsEQReal(var->exactdata->origdom.lb, 1.0) )
2665 && ( SCIPrationalIsZero(var->exactdata->origdom.ub) || SCIPrationalIsEQReal(var->exactdata->origdom.ub, 1.0) ) )
2666 {
2667 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && var->probindex == -1 )
2668 var->vartype = (unsigned int)SCIP_VARTYPE_BINARY;
2669 }
2670 else
2671 {
2672 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_BINARY )
2673 {
2674 SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", var->data.original.origdom.lb,
2675 var->data.original.origdom.ub, var->name);
2676 return SCIP_INVALIDDATA;
2677 }
2678 }
2679
2680 return SCIP_OKAY;
2681}
2682
2683/** copies exact variable data from one variable to another
2684 *
2685 * @note This method cannot be integrated into SCIPvarCopy() because it is needed, e.g., when transforming vars.
2686 */
2688 BMS_BLKMEM* blkmem, /**< block memory */
2689 SCIP_VAR* targetvar, /**< variable that gets the exact data */
2690 SCIP_VAR* sourcevar, /**< variable the data gets copied from */
2691 SCIP_Bool negateobj /**< should the objective be negated */
2692 )
2693{
2694 assert(blkmem != NULL);
2695 assert(targetvar != NULL);
2696 assert(sourcevar != NULL);
2697
2698 if( sourcevar->exactdata == NULL )
2699 return SCIP_OKAY;
2700
2701 assert(sourcevar->exactdata != NULL);
2702
2703 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &(targetvar->exactdata)) );
2704 targetvar->exactdata->glbdom = sourcevar->exactdata->glbdom;
2705 targetvar->exactdata->locdom = sourcevar->exactdata->locdom;
2706 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->glbdom.lb, sourcevar->exactdata->glbdom.lb) );
2707 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->glbdom.ub, sourcevar->exactdata->glbdom.ub) );
2708 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->locdom.lb, sourcevar->exactdata->locdom.lb) );
2709 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->locdom.ub, sourcevar->exactdata->locdom.ub) );
2710 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->origdom.lb, sourcevar->exactdata->origdom.lb) );
2711 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->origdom.ub, sourcevar->exactdata->origdom.ub) );
2712
2713 if( sourcevar->exactdata->aggregate.scalar != NULL )
2714 {
2715 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->aggregate.scalar, sourcevar->exactdata->aggregate.scalar) );
2717 }
2718 else
2719 {
2720 targetvar->exactdata->aggregate.constant = NULL;
2721 targetvar->exactdata->aggregate.scalar = NULL;
2722 }
2723
2724 if( sourcevar->exactdata->multaggr.scalars != NULL )
2725 {
2728 sourcevar->exactdata->multaggr.scalars, sourcevar->data.multaggr.nvars) );
2729 }
2730 else
2731 {
2732 targetvar->exactdata->multaggr.constant = NULL;
2733 targetvar->exactdata->multaggr.scalars = NULL;
2734 }
2735
2736 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->obj, sourcevar->exactdata->obj) );
2737 if( negateobj )
2738 {
2739 SCIPrationalNegate(targetvar->exactdata->obj, targetvar->exactdata->obj);
2740 }
2741 SCIPintervalSetRational(&(targetvar->exactdata->objinterval), targetvar->exactdata->obj);
2742 targetvar->exactdata->colexact = NULL;
2744 targetvar->exactdata->certificateindex = sourcevar->exactdata->certificateindex;
2745
2746 return SCIP_OKAY;
2747}
2748
2749/** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2750 * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2751 * copied at all
2752 */
2754 SCIP_VAR** var, /**< pointer to store the target variable */
2755 BMS_BLKMEM* blkmem, /**< block memory */
2756 SCIP_SET* set, /**< global SCIP settings */
2757 SCIP_STAT* stat, /**< problem statistics */
2758 SCIP* sourcescip, /**< source SCIP data structure */
2759 SCIP_VAR* sourcevar, /**< source variable */
2760 SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2761 * target variables */
2762 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2763 * target constraints */
2764 SCIP_Bool global /**< should global or local bounds be used? */
2765 )
2766{
2767 SCIP_VARDATA* targetdata;
2769 SCIP_Real lb;
2770 SCIP_Real ub;
2771
2772 assert(set != NULL);
2773 assert(blkmem != NULL);
2774 assert(stat != NULL);
2775 assert(sourcescip != NULL);
2776 assert(sourcevar != NULL);
2777 assert(var != NULL);
2778 assert(set->stage == SCIP_STAGE_PROBLEM);
2779 assert(varmap != NULL);
2780 assert(consmap != NULL);
2781
2782 /** @todo copy hole lists */
2783 assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2784 assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2785
2787 targetdata = NULL;
2788
2789 if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2790 {
2791 lb = SCIPvarGetLbOriginal(sourcevar);
2792 ub = SCIPvarGetUbOriginal(sourcevar);
2793 }
2794 else
2795 {
2796 lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2797 ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2798 }
2799
2800 /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2801 SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2802 lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar), SCIPvarGetImplType(sourcevar),
2803 SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2804 NULL, NULL, NULL, NULL, NULL) );
2805 assert(*var != NULL);
2806
2807 /* directly copy donot(mult)aggr flag */
2808 (*var)->donotaggr = sourcevar->donotaggr;
2809 (*var)->donotmultaggr = sourcevar->donotmultaggr;
2810
2811 /* insert variable into mapping between source SCIP and the target SCIP */
2812 assert(!SCIPhashmapExists(varmap, sourcevar));
2813 SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2814
2815 /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2816 if( sourcevar->vardata != NULL )
2817 {
2818 if( sourcevar->varcopy != NULL )
2819 {
2820 SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2821 varmap, consmap, (*var), &targetdata, &result) );
2822
2823 /* evaluate result */
2825 {
2826 SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2827 return SCIP_INVALIDRESULT;
2828 }
2829
2830 assert(targetdata == NULL || result == SCIP_SUCCESS);
2831
2832 /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2833 if( result == SCIP_SUCCESS )
2834 {
2835 (*var)->varcopy = sourcevar->varcopy;
2836 (*var)->vardelorig = sourcevar->vardelorig;
2837 (*var)->vartrans = sourcevar->vartrans;
2838 (*var)->vardeltrans = sourcevar->vardeltrans;
2839 (*var)->vardata = targetdata;
2840 }
2841 }
2842 else
2843 {
2844 /* if there is no copy callback, just copy data pointers */
2845 (*var)->vardata = sourcevar->vardata;
2846 }
2847 }
2848
2849 /* we initialize histories of the variables by copying the source variable-information */
2850 if( set->history_allowtransfer )
2851 {
2852 SCIPvarMergeHistories((*var), sourcevar, stat);
2853 }
2854
2855 /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2856 * methods
2857 */
2858 if( result == SCIP_SUCCESS )
2859 {
2860 (*var)->varcopy = sourcevar->varcopy;
2861 (*var)->vardelorig = sourcevar->vardelorig;
2862 (*var)->vartrans = sourcevar->vartrans;
2863 (*var)->vardeltrans = sourcevar->vardeltrans;
2864 (*var)->vardata = targetdata;
2865 }
2866
2867 SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2868
2869 return SCIP_OKAY;
2870}
2871
2872/** parse given string for a value */
2873static
2875 SCIP_SET* set, /**< global SCIP settings */
2876 const char* str, /**< string to parse */
2877 SCIP_Real* value, /**< pointer to store the parsed value */
2878 SCIP_RATIONAL* valueexact /**< pointer to store the parsed exact value */
2879 )
2880{
2881 assert(value == NULL || valueexact == NULL);
2882
2883 /* parse exact value */
2884 if( valueexact != NULL )
2885 {
2886 /* check for rationality */
2887 if( SCIPrationalIsString(str) )
2888 {
2889 SCIPrationalSetString(valueexact, str);
2890 SCIPrationalCanonicalize(valueexact);
2891 }
2892 else
2893 {
2894 SCIPerrorMessage("expected exact value: %s\n", str);
2895 return SCIP_READERROR;
2896 }
2897
2898 SCIPrationalDebugMessage("parsed exact value: %q\n", valueexact);
2899 }
2900 /* parse real value */
2901 else if( value != NULL )
2902 {
2903 char* endptr;
2904
2905 /* check for infinity */
2906 if( strncmp(str, "+inf", 4) == 0 )
2907 {
2908 *value = SCIPsetInfinity(set);
2909 }
2910 else if( strncmp(str, "-inf", 4) == 0 )
2911 {
2912 *value = -SCIPsetInfinity(set);
2913 }
2914 else if( !SCIPstrToRealValue(str, value, &endptr) || *endptr != '\0' )
2915 {
2916 SCIPerrorMessage("expected real value: %s\n", str);
2917 return SCIP_READERROR;
2918 }
2919
2920 SCIPsetDebugMsg(set, "parsed real value: %g\n", *value);
2921 }
2922
2923 return SCIP_OKAY;
2924}
2925
2926/** parse the characters as bounds */
2927static
2929 SCIP_SET* set, /**< global SCIP settings */
2930 const char* str, /**< string to parse */
2931 char* type, /**< bound type (global, local, or lazy) */
2932 SCIP_Real* lb, /**< pointer to store the lower bound */
2933 SCIP_Real* ub, /**< pointer to store the upper bound */
2934 SCIP_RATIONAL* lbexact, /**< pointer to store the exact lower bound */
2935 SCIP_RATIONAL* ubexact, /**< pointer to store the exact upper bound */
2936 char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occurred) */
2937 )
2938{
2939 char token[SCIP_MAXSTRLEN];
2940
2941 SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2942
2943 /* get bound type */
2944 SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2945 if ( *endptr == str
2946 || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2947 {
2948 SCIPsetDebugMsg(set, "unkown bound type\n");
2949 *endptr = NULL;
2950 return SCIP_OKAY;
2951 }
2952
2953 SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2954
2955 /* get lower bound */
2956 SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2957 SCIP_CALL( parseValue(set, token, lb, lbexact) );
2958
2959 str = *endptr - 1;
2960
2961 /* get upper bound */
2962 SCIPstrCopySection(str, ',', ']', token, SCIP_MAXSTRLEN, endptr);
2963 SCIP_CALL( parseValue(set, token, ub, ubexact) );
2964
2965 /* skip end of bounds */
2966 if( **endptr == ',' )
2967 ++(*endptr);
2968
2969 return SCIP_OKAY;
2970}
2971
2972/** parses a given string for a variable informations */
2973static
2975 SCIP_SET* set, /**< global SCIP settings */
2976 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2977 const char* str, /**< string to parse */
2978 char* name, /**< pointer to store the variable name */
2979 SCIP_Real* lb, /**< pointer to store the lower bound */
2980 SCIP_Real* ub, /**< pointer to store the upper bound */
2981 SCIP_Real* obj, /**< pointer to store the objective coefficient */
2982 SCIP_RATIONAL* lbexact, /**< pointer to store the exact lower bound */
2983 SCIP_RATIONAL* ubexact, /**< pointer to store the exact upper bound */
2984 SCIP_RATIONAL* objexact, /**< pointer to store the exact objective coefficient */
2985 SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2986 SCIP_IMPLINTTYPE* impltype, /**< pointer to store the implied integral type */
2987 SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2988 SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2989 SCIP_RATIONAL* lazylbexact, /**< pointer to store if the exact lower bound is lazy */
2990 SCIP_RATIONAL* lazyubexact, /**< pointer to store if the exact upper bound is lazy */
2991 SCIP_Bool local, /**< should the local bound be applied */
2992 char** endptr, /**< pointer to store the final string position if successfully */
2993 SCIP_Bool* success /**< pointer store if the paring process was successful */
2994 )
2995{
2996 SCIP_Bool lazyread = FALSE;
2997 char token[SCIP_MAXSTRLEN];
2998 char* strptr;
2999 int i;
3000
3001 assert(vartype != NULL);
3002 assert(success != NULL);
3003
3004 (*success) = TRUE;
3005
3006 /* copy variable type */
3007 SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
3008 assert(*endptr != str);
3009 SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
3010
3011 (*impltype) = SCIP_IMPLINTTYPE_NONE;
3012 /* get variable type */
3013 if( strncmp(token, "binary", 3) == 0 )
3014 (*vartype) = SCIP_VARTYPE_BINARY;
3015 else if( strncmp(token, "integer", 3) == 0 )
3016 (*vartype) = SCIP_VARTYPE_INTEGER;
3017 else if( strncmp(token, "implicit", 3) == 0 )
3018 {
3019 (*vartype) = SCIP_VARTYPE_CONTINUOUS;
3020 (*impltype) = SCIP_IMPLINTTYPE_WEAK;
3021 }
3022 else if( strncmp(token, "continuous", 3) == 0 )
3023 (*vartype) = SCIP_VARTYPE_CONTINUOUS;
3024 else
3025 {
3026 SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
3027 (*success) = FALSE;
3028 return SCIP_OKAY;
3029 }
3030
3031 /* move string pointer behind variable type */
3032 str = *endptr;
3033
3034 /* get variable name */
3035 SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
3036 assert(*endptr != str);
3037 SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
3038
3039 /* move string pointer behind variable name */
3040 str = *endptr;
3041
3042 /* get objective coefficient */
3043 SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
3044 SCIP_CALL( parseValue(set, token, obj, objexact) );
3045
3046 /* move string pointer behind objective coefficient */
3047 str = *endptr;
3048
3049 /* parse global/original bounds */
3050 SCIP_CALL( parseBounds(set, str, token, lb, ub, lbexact, ubexact, endptr) );
3051 if( *endptr == NULL )
3052 {
3053 SCIPerrorMessage("Expected bound type: %s.\n", token);
3054 return SCIP_READERROR;
3055 }
3056 assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
3057
3058 /* store pointer */
3059 strptr = *endptr;
3060
3061 /* possibly parse optional local and lazy bounds */
3062 for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
3063 {
3064 /* start after previous bounds */
3065 strptr = *endptr;
3066
3067 /* parse variable bounds */
3068 SCIP_CALL( parseBounds(set, strptr, token, lazylb, lazyub, lazylbexact, lazyubexact, endptr) );
3069
3070 /* set local bounds */
3071 if( strncmp(token, "local", 5) == 0 )
3072 {
3073 if( local )
3074 {
3075 if( lb != NULL )
3076 {
3077 assert(lazylb != NULL);
3078 *lb = *lazylb;
3079 }
3080
3081 if( ub != NULL )
3082 {
3083 assert(lazyub != NULL);
3084 *ub = *lazyub;
3085 }
3086
3087 if( lbexact != NULL )
3088 {
3089 assert(lazylbexact != NULL);
3090 SCIPrationalSetRational(lbexact, lazylbexact);
3091 }
3092
3093 if( ubexact != NULL )
3094 {
3095 assert(lazyubexact != NULL);
3096 SCIPrationalSetRational(ubexact, lazyubexact);
3097 }
3098 }
3099 }
3100 /* set lazy bounds */
3101 else if( strncmp(token, "lazy", 4) == 0 )
3102 {
3103 lazyread = TRUE;
3104 break;
3105 }
3106
3107 /* stop if parsing of bounds failed */
3108 if( *endptr == NULL )
3109 break;
3110 }
3111
3112 /* reset lazy bounds */
3113 if( !lazyread )
3114 {
3115 if( lazylb != NULL )
3116 *lazylb = -SCIPsetInfinity(set);
3117
3118 if( lazyub != NULL )
3119 *lazyub = SCIPsetInfinity(set);
3120
3121 if( lazylbexact != NULL )
3122 SCIPrationalSetNegInfinity(lazylbexact);
3123
3124 if( lazyubexact != NULL )
3125 SCIPrationalSetInfinity(lazyubexact);
3126 }
3127
3128 /* check bounds for binary variables */
3129 if( (*vartype) == SCIP_VARTYPE_BINARY )
3130 {
3131 if( lb != NULL && *lb < 0.0 )
3132 {
3133 SCIPerrorMessage("Parsed invalid lower bound for binary variable <%s>: %f.\n", name, *lb);
3134 return SCIP_READERROR;
3135 }
3136
3137 if( ub != NULL && *ub > 1.0 )
3138 {
3139 SCIPerrorMessage("Parsed invalid upper bound for binary variable <%s>: %f.\n", name, *ub);
3140 return SCIP_READERROR;
3141 }
3142
3143 if( lbexact != NULL && SCIPrationalIsNegative(lbexact) )
3144 {
3145 SCIPerrorMessage("Parsed invalid exact lower bound for binary variable <%s>: %f.\n",
3147 return SCIP_READERROR;
3148 }
3149
3150 if( ubexact != NULL && SCIPrationalIsGTReal(ubexact, 1.0) )
3151 {
3152 SCIPerrorMessage("Parsed invalid exact upper bound for binary variable <%s>: %f.\n",
3154 return SCIP_READERROR;
3155 }
3156
3157 if( lazyread )
3158 {
3159 if( lazylb != NULL && *lazylb < 0.0 )
3160 {
3161 SCIPerrorMessage("Parsed invalid lazy lower bound for binary variable <%s>: %f.\n", name, *lazylb);
3162 return SCIP_READERROR;
3163 }
3164
3165 if( lazyub != NULL && *lazyub > 1.0 )
3166 {
3167 SCIPerrorMessage("Parsed invalid lazy upper bound for binary variable <%s>: %f.\n", name, *lazyub);
3168 return SCIP_READERROR;
3169 }
3170
3171 if( lazylbexact != NULL && SCIPrationalIsNegative(lazylbexact) )
3172 {
3173 SCIPerrorMessage("Parsed invalid exact lazy lower bound for binary variable <%s>: %f.\n",
3174 name, SCIPrationalRoundReal(lazylbexact, SCIP_R_ROUND_DOWNWARDS));
3175 return SCIP_READERROR;
3176 }
3177
3178 if( lazyubexact != NULL && SCIPrationalIsGTReal(lazyubexact, 1.0) )
3179 {
3180 SCIPerrorMessage("Parsed invalid exact lazy upper bound for binary variable <%s>: %f.\n",
3181 name, SCIPrationalRoundReal(lazyubexact, SCIP_R_ROUND_UPWARDS));
3182 return SCIP_READERROR;
3183 }
3184 }
3185 }
3186
3187 /* update string pointer */
3188 if( *endptr != NULL )
3189 strptr = *endptr;
3190
3191 /* detect implied declaration */
3192 SCIPstrCopySection(strptr, ' ', ':', token, SCIP_MAXSTRLEN, endptr);
3193
3194 /* no further declaration */
3195 if( *endptr == strptr )
3196 return SCIP_OKAY;
3197
3198 /* get implied type */
3199 if( strncmp(token, "implied", 7) == 0 )
3200 {
3201 strptr = *endptr;
3202 SCIP_CALL( SCIPskipSpace(&strptr) );
3203
3204 if( strncmp(strptr, "strong", 6) == 0 )
3205 {
3206 (*impltype) = SCIP_IMPLINTTYPE_STRONG;
3207 *endptr = strptr + 6;
3208 }
3209 else if( strncmp(strptr, "weak", 4) == 0 )
3210 {
3211 (*impltype) = SCIP_IMPLINTTYPE_WEAK;
3212 *endptr = strptr + 4;
3213 }
3214 else if( strncmp(strptr, "none", 4) == 0 )
3215 {
3216 (*impltype) = SCIP_IMPLINTTYPE_NONE;
3217 *endptr = strptr + 4;
3218 }
3219 else
3220 {
3221 SCIPerrorMessage("Expected implied integral type 'none', 'weak', or 'strong', got: '%s'.\n", strptr);
3222 return SCIP_READERROR;
3223 }
3224 }
3225 /* keep other declarations */
3226 else
3227 *endptr = strptr;
3228
3229 return SCIP_OKAY;
3230}
3231
3232/** parses variable information (in cip format) out of a string; if the parsing process was successful an original
3233 * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
3234 * integer variable with bounds zero and one is automatically converted into a binary variable
3235 */
3237 SCIP_VAR** var, /**< pointer to variable data */
3238 BMS_BLKMEM* blkmem, /**< block memory */
3239 SCIP_SET* set, /**< global SCIP settings */
3240 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3241 SCIP_STAT* stat, /**< problem statistics */
3242 const char* str, /**< string to parse */
3243 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
3244 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
3245 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
3246 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
3247 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
3248 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
3249 SCIP_VARDATA* vardata, /**< user data for this specific variable */
3250 char** endptr, /**< pointer to store the final string position if successfully */
3251 SCIP_Bool* success /**< pointer store if the paring process was successful */
3252 )
3253{
3254 char name[SCIP_MAXSTRLEN];
3255 SCIP_VARTYPE vartype;
3256 SCIP_IMPLINTTYPE impltype;
3257
3258 assert(var != NULL);
3259 assert(blkmem != NULL);
3260 assert(stat != NULL);
3261 assert(endptr != NULL);
3262 assert(success != NULL);
3263
3264 /* parse exact variable */
3265 if( set->exact_enable )
3266 {
3267 SCIP_RATIONAL* lb;
3268 SCIP_RATIONAL* ub;
3270 SCIP_RATIONAL* lazylb;
3271 SCIP_RATIONAL* lazyub;
3272
3273 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lb) );
3274 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &ub) );
3276 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazylb) );
3277 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazyub) );
3278
3279 /* parse string in cip format for exact variable information */
3280 SCIP_CALL( varParse(set, messagehdlr, str, name, NULL, NULL, NULL, lb, ub, obj, &vartype, &impltype,
3281 NULL, NULL, lazylb, lazyub, FALSE, endptr, success) );
3282
3283 if( *success ) /*lint !e774*/
3284 {
3285 /* create variable */
3286 SCIP_CALL( varCreate(var, blkmem, set, stat, name, 0.0, 0.0, 0.0, vartype, impltype, initial, removable,
3287 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3288
3289 /* set variable status */
3292 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_ORIGINAL;
3293 (*var)->data.original.origdom.holelist = NULL;
3294 (*var)->data.original.transvar = NULL;
3295
3296 /* add exact data */
3297 SCIP_CALL( SCIPvarAddExactData(*var, blkmem, lb, ub, obj) );
3298
3299 /**@todo implement lazy bounds in exact solving mode (and adjust values before setting them) */
3300 if( !SCIPrationalIsNegInfinity(lazylb) || !SCIPrationalIsInfinity(lazyub) )
3301 {
3302 SCIPerrorMessage("exact lazy bounds not supported yet\n");
3303 return SCIP_READERROR;
3304 }
3305
3306 /* capture variable */
3308 }
3309
3310 SCIPrationalFreeBlock(blkmem, &lazyub);
3311 SCIPrationalFreeBlock(blkmem, &lazylb);
3312 SCIPrationalFreeBlock(blkmem, &obj);
3313 SCIPrationalFreeBlock(blkmem, &ub);
3314 SCIPrationalFreeBlock(blkmem, &lb);
3315 }
3316 else
3317 {
3318 SCIP_Real lb;
3319 SCIP_Real ub;
3320 SCIP_Real obj;
3321 SCIP_Real lazylb;
3322 SCIP_Real lazyub;
3323
3324 /* parse string in cip format for variable information */
3325 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, NULL, NULL, NULL, &vartype, &impltype,
3326 &lazylb, &lazyub, NULL, NULL, FALSE, endptr, success) );
3327
3328 if( *success ) /*lint !e774*/
3329 {
3330 /* create variable */
3331 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
3332 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3333
3334 /* set variable status */
3335 assert(*var != NULL);
3336 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_ORIGINAL;
3337 (*var)->data.original.origdom.holelist = NULL;
3338 (*var)->data.original.origdom.lb = (*var)->glbdom.lb;
3339 (*var)->data.original.origdom.ub = (*var)->glbdom.ub;
3340 (*var)->data.original.transvar = NULL;
3341 SCIPvarAdjustLb(*var, set, &lazylb);
3342 SCIPvarAdjustUb(*var, set, &lazyub);
3343 (*var)->lazylb = lazylb;
3344 (*var)->lazyub = lazyub;
3345
3346 /* capture variable */
3348 }
3349 }
3350
3351 return SCIP_OKAY;
3352}
3353
3354/** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
3355 * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
3356 * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
3357 * variable
3358 */
3360 SCIP_VAR** var, /**< pointer to variable data */
3361 BMS_BLKMEM* blkmem, /**< block memory */
3362 SCIP_SET* set, /**< global SCIP settings */
3363 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3364 SCIP_STAT* stat, /**< problem statistics */
3365 const char* str, /**< string to parse */
3366 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
3367 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
3368 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
3369 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
3370 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
3371 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
3372 SCIP_VARDATA* vardata, /**< user data for this specific variable */
3373 char** endptr, /**< pointer to store the final string position if successfully */
3374 SCIP_Bool* success /**< pointer store if the paring process was successful */
3375 )
3376{
3377 char name[SCIP_MAXSTRLEN];
3378 SCIP_VARTYPE vartype;
3379 SCIP_IMPLINTTYPE impltype;
3380
3381 assert(var != NULL);
3382 assert(blkmem != NULL);
3383 assert(endptr != NULL);
3384 assert(success != NULL);
3385
3386 /* parse exact variable */
3387 if( set->exact_enable )
3388 {
3389 SCIP_RATIONAL* lb;
3390 SCIP_RATIONAL* ub;
3392 SCIP_RATIONAL* lazylb;
3393 SCIP_RATIONAL* lazyub;
3394
3395 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lb) );
3396 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &ub) );
3398 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazylb) );
3399 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazyub) );
3400
3401 /* parse string in cip format for exact variable information */
3402 SCIP_CALL( varParse(set, messagehdlr, str, name, NULL, NULL, NULL, lb, ub, obj, &vartype, &impltype,
3403 NULL, NULL, lazylb, lazyub, TRUE, endptr, success) );
3404
3405 if( *success ) /*lint !e774*/
3406 {
3407 /* create variable */
3408 SCIP_CALL( varCreate(var, blkmem, set, stat, name, 0.0, 0.0, 0.0, vartype, impltype, initial, removable,
3409 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3410
3411 /* set variable status */
3414 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_LOOSE;
3415 (*var)->data.loose.minaggrcoef = 1.0;
3416 (*var)->data.loose.maxaggrcoef = 1.0;
3417
3418 /* add exact data */
3419 SCIP_CALL( SCIPvarAddExactData(*var, blkmem, lb, ub, obj) );
3420
3421 /**@todo implement lazy bounds in exact solving mode */
3422 if( !SCIPrationalIsNegInfinity(lazylb) || !SCIPrationalIsInfinity(lazyub) )
3423 {
3424 SCIPerrorMessage("exact lazy bounds not supported yet\n");
3425 return SCIP_READERROR;
3426 }
3427
3428 /* create event filter for transformed variable */
3429 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
3430
3431 /* capture variable */
3433 }
3434
3435 SCIPrationalFreeBlock(blkmem, &lazyub);
3436 SCIPrationalFreeBlock(blkmem, &lazylb);
3437 SCIPrationalFreeBlock(blkmem, &obj);
3438 SCIPrationalFreeBlock(blkmem, &ub);
3439 SCIPrationalFreeBlock(blkmem, &lb);
3440 }
3441 /* parse real variable */
3442 else
3443 {
3444 SCIP_Real lb;
3445 SCIP_Real ub;
3446 SCIP_Real obj;
3447 SCIP_Real lazylb;
3448 SCIP_Real lazyub;
3449
3450 /* parse string in cip format for variable information */
3451 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, NULL, NULL, NULL, &vartype, &impltype,
3452 &lazylb, &lazyub, NULL, NULL, TRUE, endptr, success) );
3453
3454 if( *success ) /*lint !e774*/
3455 {
3456 /* create variable */
3457 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
3458 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3459
3460 /* set variable status */
3461 assert(*var != NULL);
3462 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_LOOSE;
3463 (*var)->data.loose.minaggrcoef = 1.0;
3464 (*var)->data.loose.maxaggrcoef = 1.0;
3465 (*var)->lazylb = lazylb;
3466 (*var)->lazyub = lazyub;
3467
3468 /* create event filter for transformed variable */
3469 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
3470
3471 /* capture variable */
3473 }
3474 }
3475
3476 return SCIP_OKAY;
3477}
3478
3479/** ensures, that parentvars array of var can store at least num entries */
3480static
3482 SCIP_VAR* var, /**< problem variable */
3483 BMS_BLKMEM* blkmem, /**< block memory */
3484 SCIP_SET* set, /**< global SCIP settings */
3485 int num /**< minimum number of entries to store */
3486 )
3487{
3488 assert(var->nparentvars <= var->parentvarssize);
3489
3490 if( num > var->parentvarssize )
3491 {
3492 int newsize;
3493
3494 newsize = SCIPsetCalcMemGrowSize(set, num);
3495 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
3496 var->parentvarssize = newsize;
3497 }
3498 assert(num <= var->parentvarssize);
3499
3500 return SCIP_OKAY;
3501}
3502
3503/** adds variable to parent list of a variable and captures parent variable */
3504static
3506 SCIP_VAR* var, /**< variable to add parent to */
3507 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3508 SCIP_SET* set, /**< global SCIP settings */
3509 SCIP_VAR* parentvar /**< parent variable to add */
3510 )
3511{
3512 assert(var != NULL);
3513 assert(parentvar != NULL);
3514
3515 /* the direct original counterpart must be stored as first parent */
3516 assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
3517
3518 SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
3519 parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
3520
3521 SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
3522
3523 var->parentvars[var->nparentvars] = parentvar;
3524 var->nparentvars++;
3525
3526 SCIPvarCapture(parentvar);
3527
3528 return SCIP_OKAY;
3529}
3530
3531/** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
3532static
3534 SCIP_VAR** var, /**< pointer to variable */
3535 BMS_BLKMEM* blkmem, /**< block memory */
3536 SCIP_SET* set, /**< global SCIP settings */
3537 SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
3538 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
3539 )
3540{
3541 SCIP_VAR* parentvar;
3542 int i;
3543
3544 SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
3545
3546 /* release the parent variables and remove the link from the parent variable to the child */
3547 for( i = 0; i < (*var)->nparentvars; ++i )
3548 {
3549 assert((*var)->parentvars != NULL);
3550 parentvar = (*var)->parentvars[i];
3551 assert(parentvar != NULL);
3552
3553 switch( SCIPvarGetStatus(parentvar) )
3554 {
3556 assert(parentvar->data.original.transvar == *var);
3557 assert(&parentvar->data.original.transvar != var);
3558 parentvar->data.original.transvar = NULL;
3559 break;
3560
3562 assert(parentvar->data.aggregate.var == *var);
3563 assert(&parentvar->data.aggregate.var != var);
3564 parentvar->data.aggregate.var = NULL;
3565 break;
3566
3567#ifdef SCIP_DISABLED_CODE
3568 /* The following code is unclear: should the current variable be removed from its parents? */
3570 assert(parentvar->data.multaggr.vars != NULL);
3571 for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
3572 {}
3573 assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
3574 if( v < parentvar->data.multaggr.nvars-1 )
3575 {
3576 parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
3577 parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
3578 }
3579 parentvar->data.multaggr.nvars--;
3580 break;
3581#endif
3582
3584 assert(parentvar->negatedvar == *var);
3585 assert((*var)->negatedvar == parentvar);
3586 parentvar->negatedvar = NULL;
3587 (*var)->negatedvar = NULL;
3588 break;
3589
3590 default:
3591 SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
3592 return SCIP_INVALIDDATA;
3593 } /*lint !e788*/
3594
3595 SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
3596 }
3597
3598 /* free parentvars array */
3599 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
3600
3601 return SCIP_OKAY;
3602}
3603
3604/** free exact variable data, if it exists */
3605static
3607 SCIP_VAR* var, /**< variable */
3608 BMS_BLKMEM* blkmem, /**< block memory */
3609 SCIP_SET* set /**< global SCIP settings */
3610 )
3611{
3612 assert(blkmem != NULL);
3613 assert(var != NULL);
3614
3615 if( !set->exact_enable )
3616 {
3617 assert( var->exactdata == NULL );
3618 return SCIP_OKAY;
3619 }
3620
3621 /* free exact variable data if it was created */
3622 if( var->exactdata != NULL )
3623 {
3625 {
3626 SCIP_CALL( SCIPcolExactFree(&(var->exactdata->colexact), blkmem) );
3627 }
3628
3629 if( var->exactdata->aggregate.scalar != NULL )
3630 {
3631 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->aggregate.constant);
3632 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->aggregate.scalar);
3633 }
3634
3635 if( var->exactdata->multaggr.scalars != NULL )
3636 {
3637 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->multaggr.constant);
3638 SCIPrationalFreeBlockArray(blkmem, &(var)->exactdata->multaggr.scalars, var->data.multaggr.varssize);
3639 }
3640
3641 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->glbdom.lb);
3642 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->glbdom.ub);
3643 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->locdom.lb);
3644 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->locdom.ub);
3645 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->origdom.lb);
3646 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->origdom.ub);
3647 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->obj );
3648
3649 BMSfreeBlockMemory(blkmem, &(var)->exactdata);
3650 assert((var)->exactdata == NULL);
3651 }
3652
3653 return SCIP_OKAY;
3654}
3655
3656/** frees a variable */
3657static
3659 SCIP_VAR** var, /**< pointer to variable */
3660 BMS_BLKMEM* blkmem, /**< block memory */
3661 SCIP_SET* set, /**< global SCIP settings */
3662 SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
3663 SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
3664 )
3665{
3666 assert(var != NULL);
3667 assert(*var != NULL);
3668 assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
3669 assert((*var)->nuses == 0);
3670 assert((*var)->probindex == -1);
3671 assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
3672 assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
3673
3674 SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
3675
3676 switch( SCIPvarGetStatus(*var) )
3677 {
3679 assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
3680 holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
3681 assert((*var)->data.original.origdom.holelist == NULL);
3682 break;
3684 break;
3686 SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
3687 break;
3690 break;
3692 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
3693 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
3694 break;
3696 break;
3697 default:
3698 SCIPerrorMessage("unknown variable status\n");
3699 return SCIP_INVALIDDATA;
3700 }
3701
3702 /* release all parent variables and free the parentvars array */
3703 SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
3704
3705 /* free user data */
3707 {
3708 if( (*var)->vardelorig != NULL )
3709 {
3710 SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
3711 }
3712 }
3713 else
3714 {
3715 if( (*var)->vardeltrans != NULL )
3716 {
3717 SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
3718 }
3719 }
3720
3721 /* free event filter */
3722 if( (*var)->eventfilter != NULL )
3723 {
3724 SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
3725 }
3726 assert((*var)->eventfilter == NULL);
3727
3728 /* free hole lists */
3729 holelistFree(&(*var)->glbdom.holelist, blkmem);
3730 holelistFree(&(*var)->locdom.holelist, blkmem);
3731 assert((*var)->glbdom.holelist == NULL);
3732 assert((*var)->locdom.holelist == NULL);
3733
3734 /* free variable bounds data structures */
3735 SCIPvboundsFree(&(*var)->vlbs, blkmem);
3736 SCIPvboundsFree(&(*var)->vubs, blkmem);
3737
3738 /* free implications data structures */
3739 SCIPimplicsFree(&(*var)->implics, blkmem);
3740
3741 /* free clique list data structures */
3742 SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
3743
3744 /* free bound change information arrays */
3745 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
3746 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
3747
3748 /* free branching and inference history entries */
3749 SCIPhistoryFree(&(*var)->history, blkmem);
3750 SCIPhistoryFree(&(*var)->historycrun, blkmem);
3751 SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
3752
3753 /* free exact data if it exists */
3754 SCIP_CALL( varFreeExactData(*var, blkmem, set) );
3755
3756 /* free variable data structure */
3757 BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
3758 BMSfreeBlockMemory(blkmem, var);
3759
3760 return SCIP_OKAY;
3761}
3762
3763/** increases usage counter of variable */
3765 SCIP_VAR* var /**< variable */
3766 )
3767{
3768 assert(var != NULL);
3769 assert(var->nuses >= 0);
3770
3771 SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
3772 var->nuses++;
3773
3774#ifdef DEBUGUSES_VARNAME
3775 if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
3776#ifdef DEBUGUSES_PROBNAME
3777 && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
3778 strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
3779#endif
3780 )
3781 {
3782 printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses);
3783 print_backtrace();
3784 }
3785#endif
3786}
3787
3788/** decreases usage counter of variable, and frees memory if necessary */
3790 SCIP_VAR** var, /**< pointer to variable */
3791 BMS_BLKMEM* blkmem, /**< block memory */
3792 SCIP_SET* set, /**< global SCIP settings */
3793 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3794 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
3795 )
3796{
3797 assert(var != NULL);
3798 assert(*var != NULL);
3799 assert((*var)->nuses >= 1);
3800 assert(blkmem != NULL);
3801 assert((*var)->scip == set->scip);
3802
3803 SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
3804 (*var)->nuses--;
3805
3806#ifdef DEBUGUSES_VARNAME
3807 if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
3808#ifdef DEBUGUSES_PROBNAME
3809 && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
3810 strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
3811#endif
3812 )
3813 {
3814 printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
3815 print_backtrace();
3816 }
3817#endif
3818
3819 if( (*var)->nuses == 0 )
3820 {
3821 SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
3822 }
3823
3824 *var = NULL;
3825
3826 return SCIP_OKAY;
3827}
3828
3829/** change variable name */
3831 SCIP_VAR* var, /**< problem variable */
3832 BMS_BLKMEM* blkmem, /**< block memory */
3833 const char* name /**< name of variable */
3834 )
3835{
3836 assert(name != NULL);
3837
3838 /* remove old variable name */
3839 BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
3840
3841 /* set new variable name */
3842 SCIP_CALL( varSetName(var, blkmem, NULL, name) );
3843
3844 return SCIP_OKAY;
3845}
3846
3847/** initializes variable data structure for solving */
3849 SCIP_VAR* var /**< problem variable */
3850 )
3851{
3852 assert(var != NULL);
3853
3854 SCIPhistoryReset(var->historycrun);
3855 var->conflictlbcount = 0;
3856 var->conflictubcount = 0;
3857}
3858
3859/** outputs the given bounds into the file stream */
3860static
3862 SCIP_SET* set, /**< global SCIP settings */
3863 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3864 FILE* file, /**< output file (or NULL for standard output) */
3865 SCIP_Real lb, /**< lower bound */
3866 SCIP_Real ub, /**< upper bound */
3867 const char* name /**< bound type name */
3868 )
3869{
3870 assert(set != NULL);
3871
3872 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=[", name);
3873 if( SCIPsetIsInfinity(set, lb) )
3874 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3875 else if( SCIPsetIsInfinity(set, -lb) )
3876 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3877 else
3878 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", lb);
3879 SCIPmessageFPrintInfo(messagehdlr, file, ",");
3880 if( SCIPsetIsInfinity(set, ub) )
3881 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3882 else if( SCIPsetIsInfinity(set, -ub) )
3883 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3884 else
3885 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", ub);
3886 SCIPmessageFPrintInfo(messagehdlr, file, "]");
3887}
3888
3889/** outputs the given exact bounds into the file stream */
3890static
3892 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3893 FILE* file, /**< output file (or NULL for standard output) */
3894 SCIP_RATIONAL* lb, /**< exact lower bound */
3895 SCIP_RATIONAL* ub, /**< exact upper bound */
3896 const char* name /**< bound type name */
3897 )
3898{
3899 assert(lb != NULL);
3900 assert(ub != NULL);
3901
3902 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=[", name);
3903 if( SCIPrationalIsInfinity(lb) )
3904 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3905 else if( SCIPrationalIsNegInfinity(lb) )
3906 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3907 else
3908 SCIPrationalMessage(messagehdlr, file, lb);
3909 SCIPmessageFPrintInfo(messagehdlr, file, ",");
3910 if( SCIPrationalIsInfinity(ub) )
3911 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3912 else if( SCIPrationalIsNegInfinity(ub) )
3913 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3914 else
3915 SCIPrationalMessage(messagehdlr, file, ub);
3916 SCIPmessageFPrintInfo(messagehdlr, file, "]");
3917}
3918
3919/** prints hole list to file stream */
3920static
3922 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3923 FILE* file, /**< output file (or NULL for standard output) */
3924 SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
3925 const char* name /**< hole type name */
3926 )
3927{ /*lint --e{715}*/
3928 SCIP_Real left;
3929 SCIP_Real right;
3930
3931 if( holelist == NULL )
3932 return;
3933
3934 left = SCIPholelistGetLeft(holelist);
3935 right = SCIPholelistGetRight(holelist);
3936
3937 /* display first hole */
3938 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
3939 holelist = SCIPholelistGetNext(holelist);
3940
3941 while(holelist != NULL )
3942 {
3943 left = SCIPholelistGetLeft(holelist);
3944 right = SCIPholelistGetRight(holelist);
3945
3946 /* display hole */
3947 SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
3948
3949 /* get next hole */
3950 holelist = SCIPholelistGetNext(holelist);
3951 }
3952}
3953
3954/** outputs variable information into file stream */
3956 SCIP_VAR* var, /**< problem variable */
3957 SCIP_SET* set, /**< global SCIP settings */
3958 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3959 FILE* file /**< output file (or NULL for standard output) */
3960 )
3961{
3962 assert(var != NULL);
3963 assert(var->scip == set->scip);
3964 assert(set != NULL);
3965 assert(set->write_implintlevel >= -2);
3966 assert(set->write_implintlevel <= 2);
3967
3968 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3970 int i;
3971
3972 /* change integrality constraints of implied integral variables based on the writing settings */
3973 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3974 {
3975 if( (int)impltype > 2 - set->write_implintlevel )
3976 vartype = SCIP_VARTYPE_INTEGER;
3977 }
3978 else
3979 {
3980 if( (int)impltype > 2 + set->write_implintlevel )
3981 vartype = SCIP_VARTYPE_CONTINUOUS;
3982 }
3983
3984 /* type of variable */
3985 switch( vartype )
3986 {
3988 SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3989 break;
3991 SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3992 break;
3994 SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3995 break;
3997 default:
3998 SCIPerrorMessage("unknown variable type\n");
3999 return SCIP_INVALIDDATA;
4000 } /*lint !e788*/
4001
4002 /* name */
4003 SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
4004
4005 if( var->exactdata != NULL )
4006 {
4007 assert(set->exact_enable);
4008
4009 SCIP_RATIONAL* lb;
4010 SCIP_RATIONAL* ub;
4011
4012 /* exact objective value */
4013 assert(var->exactdata->obj != NULL);
4014 SCIPmessageFPrintInfo(messagehdlr, file, " obj=");
4015 SCIPrationalMessage(messagehdlr, file, var->exactdata->obj);
4016
4017 /* exact bounds (global bounds for transformed variables, original bounds for original variables) */
4019 {
4020 /* output exact original bounds */
4023 printBoundsExact(messagehdlr, file, lb, ub, "original bounds");
4024
4025 /**@todo get exact lazy bounds */
4026 /**@todo output exact lazy bounds */
4028 {
4029 SCIPerrorMessage("exact lazy bounds not supported yet\n");
4030 return SCIP_INVALIDDATA;
4031 }
4032
4034 }
4035 else
4036 {
4037 /* output exact global bounds */
4040 printBoundsExact(messagehdlr, file, lb, ub, "global bounds");
4041
4042 /* output exact local bounds */
4045 printBoundsExact(messagehdlr, file, lb, ub, "local bounds");
4046
4047 /**@todo get exact lazy bounds */
4048 /**@todo output exact lazy bounds */
4050 {
4051 SCIPerrorMessage("exact lazy bounds not supported yet\n");
4052 return SCIP_INVALIDDATA;
4053 }
4054
4057 }
4058 }
4059 else
4060 {
4061 assert(!set->exact_enable);
4062
4063 SCIP_Real lb;
4064 SCIP_Real ub;
4065
4066 /* objective value */
4067 SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
4068
4069 /* bounds (global bounds for transformed variables, original bounds for original variables) */
4071 {
4072 /* output original bounds */
4075 printBounds(set, messagehdlr, file, lb, ub, "original bounds");
4076
4077 /* output lazy bounds */
4078 lb = SCIPvarGetLbLazy(var);
4079 ub = SCIPvarGetUbLazy(var);
4080
4081 /* only display the lazy bounds if they are different from [-infinity,infinity] */
4082 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
4083 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
4084
4085 /* original hole list */
4086 printHolelist(messagehdlr, file, SCIPvarGetHolelistOriginal(var), "original holes");
4087 }
4088 else
4089 {
4090 /* output global bounds */
4091 lb = SCIPvarGetLbGlobal(var);
4092 ub = SCIPvarGetUbGlobal(var);
4093 printBounds(set, messagehdlr, file, lb, ub, "global bounds");
4094
4095 /* output local bounds */
4096 lb = SCIPvarGetLbLocal(var);
4097 ub = SCIPvarGetUbLocal(var);
4098 printBounds(set, messagehdlr, file, lb, ub, "local bounds");
4099
4100 /* output lazy bounds */
4101 lb = SCIPvarGetLbLazy(var);
4102 ub = SCIPvarGetUbLazy(var);
4103
4104 /* only display the lazy bounds if they are different from [-infinity,infinity] */
4105 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
4106 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
4107
4108 /* global hole list */
4109 printHolelist(messagehdlr, file, SCIPvarGetHolelistGlobal(var), "global holes");
4110
4111 /* local hole list */
4112 printHolelist(messagehdlr, file, SCIPvarGetHolelistLocal(var), "local holes");
4113 }
4114 }
4115
4116 /* implication of variable */
4117 switch( impltype )
4118 {
4120 break;
4122 SCIPmessageFPrintInfo(messagehdlr, file, ", implied: weak");
4123 break;
4125 SCIPmessageFPrintInfo(messagehdlr, file, ", implied: strong");
4126 break;
4127 default:
4128 SCIPerrorMessage("unknown implied type\n");
4129 return SCIP_INVALIDDATA;
4130 }
4131
4132 /* fixings and aggregations */
4133 switch( SCIPvarGetStatus(var) )
4134 {
4138 break;
4139
4141 SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
4142 if( SCIPsetIsInfinity(set, var->glbdom.lb) )
4143 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
4144 else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4145 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
4146 else
4147 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
4148 break;
4149
4151 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
4152 if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
4153 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
4154 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
4155 break;
4156
4158 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
4159 if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
4160 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
4161 for( i = 0; i < var->data.multaggr.nvars; ++i )
4162 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
4163 break;
4164
4166 SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
4167 break;
4168
4169 default:
4170 SCIPerrorMessage("unknown variable status\n");
4171 return SCIP_INVALIDDATA;
4172 }
4173
4174 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
4175
4176 return SCIP_OKAY;
4177}
4178
4179/** issues a VARUNLOCKED event on the given variable */
4180static
4182 SCIP_VAR* var, /**< problem variable to change */
4183 BMS_BLKMEM* blkmem, /**< block memory */
4184 SCIP_SET* set, /**< global SCIP settings */
4185 SCIP_EVENTQUEUE* eventqueue /**< event queue */
4186 )
4187{
4188 SCIP_EVENT* event;
4189
4190 assert(var != NULL);
4191 assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
4192 assert(var->scip == set->scip);
4193
4194 /* issue VARUNLOCKED event on variable */
4195 SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
4196 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
4197
4198 return SCIP_OKAY;
4199}
4200
4201/** modifies lock numbers for rounding */
4203 SCIP_VAR* var, /**< problem variable */
4204 BMS_BLKMEM* blkmem, /**< block memory */
4205 SCIP_SET* set, /**< global SCIP settings */
4206 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4207 SCIP_LOCKTYPE locktype, /**< type of the variable locks */
4208 int addnlocksdown, /**< increase in number of rounding down locks */
4209 int addnlocksup /**< increase in number of rounding up locks */
4210 )
4211{
4212 SCIP_VAR* lockvar;
4213
4214 assert(var != NULL);
4215 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4216 assert(var->nlocksup[locktype] >= 0);
4217 assert(var->nlocksdown[locktype] >= 0);
4218 assert(var->scip == set->scip);
4219
4220 if( addnlocksdown == 0 && addnlocksup == 0 )
4221 return SCIP_OKAY;
4222
4223#ifdef SCIP_DEBUG
4224 SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
4225 addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
4226#endif
4227
4228 lockvar = var;
4229
4230 while( TRUE ) /*lint !e716 */
4231 {
4232 assert(lockvar != NULL);
4233
4234 switch( SCIPvarGetStatus(lockvar) )
4235 {
4237 if( lockvar->data.original.transvar != NULL )
4238 {
4239 lockvar = lockvar->data.original.transvar;
4240 break;
4241 }
4242 else
4243 {
4244 lockvar->nlocksdown[locktype] += addnlocksdown;
4245 lockvar->nlocksup[locktype] += addnlocksup;
4246
4247 assert(lockvar->nlocksdown[locktype] >= 0);
4248 assert(lockvar->nlocksup[locktype] >= 0);
4249
4250 return SCIP_OKAY;
4251 }
4255 lockvar->nlocksdown[locktype] += addnlocksdown;
4256 lockvar->nlocksup[locktype] += addnlocksup;
4257
4258 assert(lockvar->nlocksdown[locktype] >= 0);
4259 assert(lockvar->nlocksup[locktype] >= 0);
4260
4261 if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
4262 && lockvar->nlocksup[locktype] <= 1 )
4263 {
4264 SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
4265 }
4266
4267 return SCIP_OKAY;
4269 assert(!lockvar->donotaggr);
4270
4271 if( lockvar->data.aggregate.scalar < 0.0 )
4272 SCIPswapInts(&addnlocksup, &addnlocksdown);
4273
4274 lockvar = lockvar->data.aggregate.var;
4275 break;
4277 {
4278 int v;
4279
4280 assert(!lockvar->donotmultaggr);
4281
4282 lockvar->nlocksdown[locktype] += addnlocksdown;
4283 lockvar->nlocksup[locktype] += addnlocksup;
4284
4285 assert(lockvar->nlocksdown[locktype] >= 0);
4286 assert(lockvar->nlocksup[locktype] >= 0);
4287
4288 for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
4289 {
4290 if( lockvar->data.multaggr.scalars[v] > 0.0 )
4291 {
4292 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
4293 addnlocksup) );
4294 }
4295 else
4296 {
4297 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
4298 addnlocksdown) );
4299 }
4300 }
4301 return SCIP_OKAY;
4302 }
4304 {
4305 assert(lockvar->negatedvar != NULL);
4307 assert(lockvar->negatedvar->negatedvar == lockvar);
4308
4309 SCIPswapInts(&addnlocksup, &addnlocksdown);
4310
4311 lockvar = lockvar->negatedvar;
4312 break;
4313 }
4314 default:
4315 SCIPerrorMessage("unknown variable status\n");
4316 return SCIP_INVALIDDATA;
4317 }
4318 }
4319}
4320
4321/** gets number of locks for rounding down of a special type */
4323 SCIP_VAR* var, /**< problem variable */
4324 SCIP_LOCKTYPE locktype /**< type of variable locks */
4325 )
4326{
4327 int nlocks;
4328 int i;
4329
4330 assert(var != NULL);
4331 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4332 assert(var->nlocksdown[locktype] >= 0);
4333
4334 switch( SCIPvarGetStatus(var) )
4335 {
4337 if( var->data.original.transvar != NULL )
4338 return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
4339 else
4340 return var->nlocksdown[locktype];
4341
4345 return var->nlocksdown[locktype];
4346
4348 assert(!var->donotaggr);
4349 if( var->data.aggregate.scalar > 0.0 )
4350 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
4351 else
4352 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
4353
4355 assert(!var->donotmultaggr);
4356 nlocks = 0;
4357 for( i = 0; i < var->data.multaggr.nvars; ++i )
4358 {
4359 if( var->data.multaggr.scalars[i] > 0.0 )
4360 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
4361 else
4362 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
4363 }
4364 return nlocks;
4365
4367 assert(var->negatedvar != NULL);
4369 assert(var->negatedvar->negatedvar == var);
4370 return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
4371
4372 default:
4373 SCIPerrorMessage("unknown variable status\n");
4374 SCIPABORT();
4375 return INT_MAX; /*lint !e527*/
4376 }
4377}
4378
4379/** gets number of locks for rounding up of a special type */
4381 SCIP_VAR* var, /**< problem variable */
4382 SCIP_LOCKTYPE locktype /**< type of variable locks */
4383 )
4384{
4385 int nlocks;
4386 int i;
4387
4388 assert(var != NULL);
4389 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4390 assert(var->nlocksup[locktype] >= 0);
4391
4392 switch( SCIPvarGetStatus(var) )
4393 {
4395 if( var->data.original.transvar != NULL )
4396 return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
4397 else
4398 return var->nlocksup[locktype];
4399
4403 return var->nlocksup[locktype];
4404
4406 assert(!var->donotaggr);
4407 if( var->data.aggregate.scalar > 0.0 )
4408 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
4409 else
4410 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
4411
4413 assert(!var->donotmultaggr);
4414 nlocks = 0;
4415 for( i = 0; i < var->data.multaggr.nvars; ++i )
4416 {
4417 if( var->data.multaggr.scalars[i] > 0.0 )
4418 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
4419 else
4420 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
4421 }
4422 return nlocks;
4423
4425 assert(var->negatedvar != NULL);
4427 assert(var->negatedvar->negatedvar == var);
4428 return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
4429
4430 default:
4431 SCIPerrorMessage("unknown variable status\n");
4432 SCIPABORT();
4433 return INT_MAX; /*lint !e527*/
4434 }
4435}
4436
4437/** gets number of locks for rounding down
4438 *
4439 * @note This method will always return variable locks of type model
4440 *
4441 * @note It is recommented to use SCIPvarGetNLocksDownType()
4442 */
4444 SCIP_VAR* var /**< problem variable */
4445 )
4446{
4448}
4449
4450/** gets number of locks for rounding up
4451 *
4452 * @note This method will always return variable locks of type model
4453 *
4454 * @note It is recommented to use SCIPvarGetNLocksUpType()
4455 */
4457 SCIP_VAR* var /**< problem variable */
4458 )
4459{
4461}
4462
4463/** is it possible, to round variable down and stay feasible?
4464 *
4465 * @note This method will always check w.r.t variable locks of type model
4466 */
4468 SCIP_VAR* var /**< problem variable */
4469 )
4470{
4472}
4473
4474/** is it possible, to round variable up and stay feasible?
4475 *
4476 * @note This method will always check w.r.t. variable locks of type model
4477 */
4479 SCIP_VAR* var /**< problem variable */
4480 )
4481{
4483}
4484
4485/** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
4486 * a new transformed variable for this variable is created
4487 */
4489 SCIP_VAR* origvar, /**< original problem variable */
4490 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4491 SCIP_SET* set, /**< global SCIP settings */
4492 SCIP_STAT* stat, /**< problem statistics */
4493 SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
4494 SCIP_VAR** transvar /**< pointer to store the transformed variable */
4495 )
4496{
4497 char name[SCIP_MAXSTRLEN];
4498
4499 assert(origvar != NULL);
4500 assert(origvar->scip == set->scip);
4502 assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
4503 assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
4504 assert(origvar->vlbs == NULL);
4505 assert(origvar->vubs == NULL);
4506 assert(transvar != NULL);
4507
4508 /* check if variable is already transformed */
4509 if( origvar->data.original.transvar != NULL )
4510 {
4511 *transvar = origvar->data.original.transvar;
4512 SCIPvarCapture(*transvar);
4513 }
4514 else
4515 {
4516 int i;
4517
4518 /* create transformed variable */
4519 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
4520 SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
4521 origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
4522 SCIPvarGetType(origvar), SCIPvarGetImplType(origvar), origvar->initial, origvar->removable,
4523 origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
4524
4525 /* copy the branch factor and priority */
4526 (*transvar)->branchfactor = origvar->branchfactor;
4527 (*transvar)->branchpriority = origvar->branchpriority;
4528 (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
4529
4530 /* duplicate hole lists */
4531 SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
4532 SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
4533
4534 /* link original and transformed variable */
4535 origvar->data.original.transvar = *transvar;
4536 SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
4537
4538 /* copy rounding locks */
4539 for( i = 0; i < NLOCKTYPES; i++ )
4540 {
4541 (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
4542 (*transvar)->nlocksup[i] = origvar->nlocksup[i];
4543 assert((*transvar)->nlocksdown[i] >= 0);
4544 assert((*transvar)->nlocksup[i] >= 0);
4545 }
4546
4547 /* copy donot(mult)aggr status */
4548 (*transvar)->donotaggr = origvar->donotaggr;
4549 (*transvar)->donotmultaggr = origvar->donotmultaggr;
4550
4551 /* copy lazy bounds */
4552 (*transvar)->lazylb = origvar->lazylb;
4553 (*transvar)->lazyub = origvar->lazyub;
4554
4555 /* transfer eventual variable statistics; do not update global statistics, because this has been done
4556 * when original variable was created
4557 */
4558 SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
4559
4560 /* transform user data */
4561 if( origvar->vartrans != NULL )
4562 {
4563 SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
4564 }
4565 else
4566 (*transvar)->vardata = origvar->vardata;
4567 }
4568
4569 SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
4570
4571 return SCIP_OKAY;
4572}
4573
4574/** gets corresponding transformed variable of an original or negated original variable */
4576 SCIP_VAR* origvar, /**< original problem variable */
4577 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4578 SCIP_SET* set, /**< global SCIP settings */
4579 SCIP_STAT* stat, /**< problem statistics */
4580 SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
4581 )
4582{
4583 assert(origvar != NULL);
4585 assert(origvar->scip == set->scip);
4586
4588 {
4589 assert(origvar->negatedvar != NULL);
4591
4592 if( origvar->negatedvar->data.original.transvar == NULL )
4593 *transvar = NULL;
4594 else
4595 {
4596 SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
4597 }
4598 }
4599 else
4600 *transvar = origvar->data.original.transvar;
4601
4602 return SCIP_OKAY;
4603}
4604
4605/** converts loose transformed variable into column variable, creates LP column */
4607 SCIP_VAR* var, /**< problem variable */
4608 BMS_BLKMEM* blkmem, /**< block memory */
4609 SCIP_SET* set, /**< global SCIP settings */
4610 SCIP_STAT* stat, /**< problem statistics */
4611 SCIP_PROB* prob, /**< problem data */
4612 SCIP_LP* lp /**< current LP data */
4613 )
4614{
4615 assert(var != NULL);
4617 assert(var->scip == set->scip);
4618
4619 SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
4620
4621 /* switch variable status */
4622 var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
4623
4624 /* create column of variable */
4625 SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
4626
4627 if( var->probindex != -1 )
4628 {
4629 /* inform problem about the variable's status change */
4630 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
4631
4632 /* inform LP, that problem variable is now a column variable and no longer loose */
4634 }
4635
4636 return SCIP_OKAY;
4637}
4638
4639/** converts loose transformed variable into column variable, creates LP column */
4641 SCIP_VAR* var, /**< problem variable */
4642 BMS_BLKMEM* blkmem, /**< block memory */
4643 SCIP_SET* set, /**< global SCIP settings */
4644 SCIP_STAT* stat, /**< problem statistics */
4645 SCIP_LPEXACT* lp /**< current LP data */
4646 )
4647{
4648 if( !set->exact_enable )
4649 return SCIP_OKAY;
4650
4651 assert(var != NULL);
4652 assert(var->exactdata->colexact == NULL);
4653 assert(var->scip == set->scip);
4654 assert(var->exactdata != NULL);
4655
4656 SCIPsetDebugMsg(set, "creating exact column for variable <%s>\n", var->name);
4657
4658 /* switch variable status */
4659 var->exactdata->varstatusexact = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
4660
4661 /* create column of variable */
4662 SCIP_CALL( SCIPcolExactCreate(&(var->exactdata->colexact), SCIPvarGetCol(var), blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
4663
4664 if( var->probindex != -1 )
4665 {
4666 /* inform LP, that problem variable is now a column variable and no longer loose */
4668 }
4669
4670 return SCIP_OKAY;
4671}
4672
4673/** converts column transformed variable back into loose variable, frees LP column */
4675 SCIP_VAR* var, /**< problem variable */
4676 BMS_BLKMEM* blkmem, /**< block memory */
4677 SCIP_SET* set, /**< global SCIP settings */
4678 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4679 SCIP_PROB* prob, /**< problem data */
4680 SCIP_LP* lp /**< current LP data */
4681 )
4682{
4683 assert(var != NULL);
4685 assert(var->scip == set->scip);
4686 assert(var->data.col != NULL);
4687 assert(var->data.col->lppos == -1);
4688 assert(var->data.col->lpipos == -1);
4689
4690 SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
4691
4692 /* free column of variable */
4693 SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
4694
4695 /* switch variable status */
4696 var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
4697
4698 if( var->probindex != -1 )
4699 {
4700 /* inform problem about the variable's status change */
4701 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
4702
4703 /* inform LP, that problem variable is now a loose variable and no longer a column */
4705 }
4706
4707 /* initialize variable data */
4708 var->data.loose.minaggrcoef = 1.0;
4709 var->data.loose.maxaggrcoef = 1.0;
4710
4711 return SCIP_OKAY;
4712}
4713
4714/** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
4715 * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
4716 * are not informed about a fixing of an active variable they are pointing to
4717 */
4718static
4720 SCIP_VAR* var, /**< problem variable to change */
4721 BMS_BLKMEM* blkmem, /**< block memory */
4722 SCIP_SET* set, /**< global SCIP settings */
4723 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4724 int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
4725 * multi-aggregation(2)
4726 */
4727 )
4728{
4729 SCIP_EVENT* event;
4730 SCIP_VARSTATUS varstatus;
4731 int i;
4732
4733 assert(var != NULL);
4734 assert(var->scip == set->scip);
4735 assert(0 <= fixeventtype && fixeventtype <= 2);
4736
4737 /* issue VARFIXED event on variable */
4738 SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
4739 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
4740
4741#ifndef NDEBUG
4742 for( i = var->nparentvars -1; i >= 0; --i )
4743 {
4745 }
4746#endif
4747
4748 switch( fixeventtype )
4749 {
4750 case 0:
4751 /* process all parents of a fixed variable */
4752 for( i = var->nparentvars - 1; i >= 0; --i )
4753 {
4754 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4755
4756 assert(varstatus != SCIP_VARSTATUS_FIXED);
4757
4758 /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
4759 * one
4760 */
4761 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4762 {
4763 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4764 }
4765 }
4766 break;
4767 case 1:
4768 /* process all parents of a aggregated variable */
4769 for( i = var->nparentvars - 1; i >= 0; --i )
4770 {
4771 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4772
4773 assert(varstatus != SCIP_VARSTATUS_FIXED);
4774
4775 /* issue event for not aggregated parent variable, because for these and its parents the var event was already
4776 * issued(, except the original one)
4777 *
4778 * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
4779 * yet issued
4780 */
4781 if( varstatus == SCIP_VARSTATUS_AGGREGATED )
4782 continue;
4783
4784 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4785 {
4786 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4787 }
4788 }
4789 break;
4790 case 2:
4791 /* process all parents of a aggregated variable */
4792 for( i = var->nparentvars - 1; i >= 0; --i )
4793 {
4794 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4795
4796 assert(varstatus != SCIP_VARSTATUS_FIXED);
4797
4798 /* issue event on all parent variables except the original one */
4799 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4800 {
4801 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4802 }
4803 }
4804 break;
4805 default:
4806 SCIPerrorMessage("unknown variable fixation event origin\n");
4807 return SCIP_INVALIDDATA;
4808 }
4809
4810 return SCIP_OKAY;
4811}
4812
4813/** converts variable into fixed variable */
4815 SCIP_VAR* var, /**< problem variable */
4816 BMS_BLKMEM* blkmem, /**< block memory */
4817 SCIP_SET* set, /**< global SCIP settings */
4818 SCIP_STAT* stat, /**< problem statistics */
4819 SCIP_PROB* transprob, /**< tranformed problem data */
4820 SCIP_PROB* origprob, /**< original problem data */
4821 SCIP_PRIMAL* primal, /**< primal data */
4822 SCIP_TREE* tree, /**< branch and bound tree */
4823 SCIP_REOPT* reopt, /**< reoptimization data structure */
4824 SCIP_LP* lp, /**< current LP data */
4825 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4826 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4827 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
4828 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4829 SCIP_Real fixedval, /**< value to fix variable at */
4830 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
4831 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
4832 )
4833{
4834 SCIP_Real obj;
4835 SCIP_Real childfixedval;
4836
4837 assert(var != NULL);
4838 assert(var->scip == set->scip);
4839 assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
4840 assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
4841 assert(!SCIPsetIsInfinity(set, REALABS(fixedval)));
4842 assert(infeasible != NULL);
4843 assert(fixed != NULL);
4844
4845 SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
4846
4847 *infeasible = FALSE;
4848 *fixed = FALSE;
4849
4851 {
4852 *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
4853 SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
4854 return SCIP_OKAY;
4855 }
4856 else if( ( SCIPvarIsIntegral(var) && !SCIPsetIsFeasIntegral(set, fixedval) )
4857 || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
4858 || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
4859 {
4860 SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
4861 *infeasible = TRUE;
4862 return SCIP_OKAY;
4863 }
4864
4865 switch( SCIPvarGetStatus(var) )
4866 {
4868 if( var->data.original.transvar == NULL )
4869 {
4870 SCIPerrorMessage("cannot fix an untransformed original variable\n");
4871 return SCIP_INVALIDDATA;
4872 }
4873 SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
4874 lp, branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
4875 break;
4876
4878 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4879
4880 /* set the fixed variable's objective value to 0.0 */
4881 obj = var->obj;
4882 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4883
4884 /* since we change the variable type form loose to fixed, we have to adjust the number of loose
4885 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
4886 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
4887 * objective of this variable is set to zero
4888 */
4890
4891 /* free hole lists */
4892 holelistFree(&var->glbdom.holelist, blkmem);
4893 holelistFree(&var->locdom.holelist, blkmem);
4894
4895 /* adjust fixed value */
4896 if( SCIPvarIsIntegral(var) )
4897 fixedval = SCIPsetRound(set, fixedval);
4898
4899 /* change variable bounds to fixed value */
4900 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
4901 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
4902
4903 /* explicitly set variable's bounds if the fixed value was in epsilon range of the old bound (so above call didn't set bound) */
4904 var->glbdom.lb = fixedval;
4905 var->glbdom.ub = fixedval;
4906
4907 /* ensure local domain is fixed to same value as global domain */
4908 var->locdom.lb = fixedval;
4909 var->locdom.ub = fixedval;
4910
4911 /* delete implications and variable bounds information */
4912 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
4913 assert(var->vlbs == NULL);
4914 assert(var->vubs == NULL);
4915 assert(var->implics == NULL);
4916
4917 /* clear the history of the variable */
4918 SCIPhistoryReset(var->history);
4919 SCIPhistoryReset(var->historycrun);
4920
4921 /* convert variable into fixed variable */
4922 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
4923
4924 /* inform problem about the variable's status change */
4925 if( var->probindex != -1 )
4926 {
4927 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4928 }
4929
4930 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
4931 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
4932
4933 /* issue VARFIXED event */
4934 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
4935
4936 *fixed = TRUE;
4937 break;
4938
4940 SCIPerrorMessage("cannot fix a column variable\n");
4941 return SCIP_INVALIDDATA;
4942
4944 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
4945 SCIPABORT(); /* case is already handled in earlier if condition */
4946 return SCIP_INVALIDDATA; /*lint !e527*/
4947
4949 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
4950 assert(SCIPsetIsZero(set, var->obj));
4951 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
4952 childfixedval = (fixedval - var->data.aggregate.constant) / var->data.aggregate.scalar;
4953 SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4954 branchcand, eventqueue, eventfilter, cliquetable, childfixedval, infeasible, fixed) );
4955 break;
4956
4958 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
4959 SCIPABORT();
4960 return SCIP_INVALIDDATA; /*lint !e527*/
4961
4963 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
4964 assert(SCIPsetIsZero(set, var->obj));
4965 assert(var->negatedvar != NULL);
4967 assert(var->negatedvar->negatedvar == var);
4968 SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4969 branchcand, eventqueue, eventfilter, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
4970 break;
4971
4972 default:
4973 SCIPerrorMessage("unknown variable status\n");
4974 return SCIP_INVALIDDATA;
4975 }
4976
4977 return SCIP_OKAY;
4978}
4979
4980/** converts variable into fixed variable */
4982 SCIP_VAR* var, /**< problem variable */
4983 BMS_BLKMEM* blkmem, /**< block memory */
4984 SCIP_SET* set, /**< global SCIP settings */
4985 SCIP_STAT* stat, /**< problem statistics */
4986 SCIP_PROB* transprob, /**< tranformed problem data */
4987 SCIP_PROB* origprob, /**< original problem data */
4988 SCIP_PRIMAL* primal, /**< primal data */
4989 SCIP_TREE* tree, /**< branch and bound tree */
4990 SCIP_REOPT* reopt, /**< reoptimization data structure */
4991 SCIP_LP* lp, /**< current LP data */
4992 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4993 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4994 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
4995 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4996 SCIP_RATIONAL* fixedval, /**< value to fix variable at */
4997 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
4998 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
4999 )
5000{
5002 SCIP_RATIONAL* childfixedval;
5003 SCIP_RATIONAL* tmpval;
5004
5005 assert(var != NULL);
5006 assert(var->scip == set->scip);
5007 assert(set->exact_enable);
5008
5009 *infeasible = FALSE;
5010 *fixed = FALSE;
5011
5012 if( !set->exact_enable )
5013 return SCIP_OKAY;
5014
5015 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
5016 assert(SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub));
5017 assert(infeasible != NULL);
5018 assert(fixed != NULL);
5019
5020 SCIPrationalDebugMessage("fix variable <%s>[%g,%g] to %q\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
5021
5023 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childfixedval) );
5024 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
5025
5027
5029 {
5030 *infeasible = !SCIPrationalIsEQ(fixedval, var->exactdata->locdom.lb);
5031 SCIPrationalDebugMessage(" -> variable already fixed to %q (fixedval=%q): infeasible=%u\n", var->exactdata->locdom.lb, fixedval, *infeasible);
5032 goto terminate;
5033 }
5034 else if( (SCIPvarIsIntegral(var) && !SCIPrationalIsIntegral(fixedval))
5035 || SCIPrationalIsLT(fixedval, var->exactdata->locdom.lb)
5036 || SCIPrationalIsGT(fixedval, var->exactdata->locdom.ub) )
5037 {
5038 SCIPrationalDebugMessage(" -> fixing infeasible: locdom=[%q,%q], fixedval=%q\n", var->exactdata->locdom.lb, var->exactdata->locdom.ub, fixedval);
5039 *infeasible = TRUE;
5040 goto terminate;
5041 }
5042
5043 switch( SCIPvarGetStatusExact(var) )
5044 {
5046 if( var->data.original.transvar == NULL )
5047 {
5048 SCIPerrorMessage("cannot fix an untransformed original variable\n");
5049 return SCIP_INVALIDDATA;
5050 }
5051 SCIP_CALL( SCIPvarFixExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
5052 lp, branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
5053 break;
5054
5056 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5057
5058 /* set the fixed variable's objective value to 0.0 */
5059 SCIPrationalSetRational(obj, var->exactdata->obj);
5060 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lp->lpexact, eventqueue, tmpval) );
5061
5062 /* since we change the variable type form loose to fixed, we have to adjust the number of loose
5063 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5064 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5065 * objective of this variable is set to zero
5066 */
5068
5069 /* free fole lists */
5070 holelistFree(&var->glbdom.holelist, blkmem);
5071 holelistFree(&var->locdom.holelist, blkmem);
5072
5073 /* no need to adjust fixed value as in floating-point code */
5075
5076 /* change variable bounds to fixed value */
5077 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, fixedval) );
5078 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, fixedval) );
5079
5080 /* delete implications and variable bounds information */
5081 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5082 assert(var->vlbs == NULL);
5083 assert(var->vubs == NULL);
5084 assert(var->implics == NULL);
5085 assert(var->cliquelist == NULL);
5086
5087 /* clear the history of the variable */
5088 SCIPhistoryReset(var->history);
5089 SCIPhistoryReset(var->historycrun);
5090
5091 /* convert variable into fixed variable */
5092 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
5093 var->exactdata->varstatusexact = SCIP_VARSTATUS_FIXED; /*lint !e641*/
5094
5095 /* inform problem about the variable's status change */
5096 if( var->probindex != -1 )
5097 {
5098 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5099 }
5100
5101 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
5102 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
5103
5104 /* issue VARFIXED event */
5105 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
5106
5107 *fixed = TRUE;
5108 break;
5109
5111 SCIPerrorMessage("cannot fix a column variable\n");
5112 return SCIP_INVALIDDATA;
5113
5115 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
5116 SCIPABORT(); /* case is already handled in earlier if condition */
5117 return SCIP_INVALIDDATA; /*lint !e527*/
5118
5120 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
5121 assert(SCIPsetIsZero(set, var->obj));
5122 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
5123 if( SCIPrationalIsInfinity(fixedval) || SCIPrationalIsNegInfinity(fixedval) )
5124 SCIPrationalIsNegative(var->exactdata->aggregate.scalar) ? SCIPrationalNegate(childfixedval, fixedval) : SCIPrationalSetRational(childfixedval, fixedval);
5125 else
5126 {
5127 SCIPrationalDiff(tmpval, fixedval, var->exactdata->aggregate.constant);
5128 SCIPrationalDiv(childfixedval, tmpval, var->exactdata->aggregate.scalar);
5129 }
5130 SCIP_CALL( SCIPvarFixExact(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5131 branchcand, eventqueue, eventfilter, cliquetable, childfixedval, infeasible, fixed) );
5132 break;
5133
5135 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
5136 SCIPABORT();
5137 return SCIP_INVALIDDATA; /*lint !e527*/
5138
5140 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
5141 assert(SCIPrationalIsZero(var->exactdata->obj));
5142 assert(var->negatedvar != NULL);
5144 assert(var->negatedvar->negatedvar == var);
5145 SCIPrationalDiffReal(fixedval, fixedval, var->data.negate.constant);
5146 SCIPrationalNegate(fixedval, fixedval);
5147 SCIP_CALL( SCIPvarFixExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5148 branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
5149 break;
5150
5151 default:
5152 SCIPerrorMessage("unknown variable status\n");
5153 return SCIP_INVALIDDATA;
5154 }
5155
5156terminate:
5157 SCIPrationalFreeBuffer(set->buffer, &tmpval);
5158 SCIPrationalFreeBuffer(set->buffer, &childfixedval);
5159 SCIPrationalFreeBuffer(set->buffer, &obj);
5160
5161 return SCIP_OKAY;
5162}
5163
5164/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
5165 *
5166 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens
5167 * except that an upper bound on the required size is stored in the variable requiredsize; otherwise, the active
5168 * variable representation is stored in the arrays.
5169 *
5170 * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been
5171 * allocated (e.g., by a C++ 'new' or SCIP functions). Note that requiredsize is an upper bound due to possible
5172 * cancelations.
5173 */
5175 SCIP_SET* set, /**< global SCIP settings */
5176 SCIP_VAR** vars, /**< variable array to get active variables */
5177 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
5178 int* nvars, /**< pointer to number of variables and values in vars and scalars array */
5179 int varssize, /**< available slots in vars and scalars array */
5180 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
5181 int* requiredsize /**< pointer to store an uppper bound on the required size for the active variables */
5182 )
5183{
5184 SCIP_VAR** activevars;
5185 SCIP_Real activeconstant;
5186 SCIP_Bool activeconstantinf;
5187 int activevarssize;
5188 int nactivevars;
5189
5190 SCIP_VAR* var;
5191 SCIP_Real scalar;
5192 int v;
5193
5194 SCIP_VAR** tmpvars;
5195 SCIP_VAR** multvars;
5196 SCIP_Real* tmpscalars;
5197 SCIP_Real* multscalars;
5198 int tmpvarssize;
5199 int ntmpvars;
5200 int nmultvars;
5201
5202 SCIP_VAR* multvar;
5203 SCIP_Real multscalar;
5204 SCIP_Real multconstant;
5205 SCIP_VARSTATUS varstatus;
5206 int ntotalvars;
5207
5208 assert(set != NULL);
5209 assert(nvars != NULL);
5210 assert(constant != NULL);
5211 assert(requiredsize != NULL);
5212 assert(*nvars <= varssize);
5213
5214 *requiredsize = 0;
5215
5216 if( *nvars == 0 )
5217 return SCIP_OKAY;
5218
5219 assert(vars != NULL);
5220 assert(scalars != NULL);
5221
5222 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
5223 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
5224 {
5225 *requiredsize = 1;
5226
5227 return SCIP_OKAY;
5228 }
5229
5230 /* allocate temporary list of variables */
5231 tmpvarssize = *nvars;
5232 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars, tmpvarssize) );
5233
5234 /* allocate memory for list of active variables */
5235 activevarssize = MAX(10, 2 * (*nvars)); /* take the maximum to avoid small reallocations */
5236 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
5237
5238 /* allocate dense array for storing scalars (to avoid checking for duplicate variables) */
5239 ntotalvars = SCIPgetNTotalVars(set->scip);
5240 SCIP_CALL( SCIPsetAllocCleanBufferArray(set, &tmpscalars, ntotalvars) );
5241
5242 /* perform one round of replacing variables by their active, fixed or multi-aggregated counterparts */
5243 activeconstant = 0.0;
5244 nactivevars = 0;
5245 ntmpvars = 0;
5246 for( v = 0; v < *nvars; ++v )
5247 {
5248 var = vars[v];
5249 assert(var != NULL);
5250 scalar = scalars[v];
5251
5252 /* Transforms variable, scalar and constant to corresponding active, fixed, or multi-aggregated variable, scalar
5253 * and constant; activeconstant collects the sum of all constants (even for variables with scalar == 0.0). */
5254 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
5255 assert(var != NULL);
5256
5257 assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
5258 assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
5259
5260 varstatus = SCIPvarGetStatus(var);
5261 assert( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN
5262 || varstatus == SCIP_VARSTATUS_MULTAGGR || varstatus == SCIP_VARSTATUS_FIXED);
5263
5264 /* enter nonzero scalars into dense array and list */
5265 if( scalar != 0.0 )
5266 {
5267 assert(0 <= var->index && var->index < ntotalvars);
5268 if( tmpscalars[var->index] == 0.0 )
5269 {
5270 if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN )
5271 activevars[nactivevars++] = var; /* store active variables */
5272 else if( varstatus == SCIP_VARSTATUS_MULTAGGR )
5273 tmpvars[ntmpvars++] = var; /* enter mutli-aggregated variables in list to be processed below */
5274 }
5275 tmpscalars[var->index] += scalar;
5276 }
5277 }
5278 assert(ntmpvars <= *nvars);
5279 assert(nactivevars <= *nvars);
5280
5281 /* store whether the constant is infinite */
5282 activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
5283
5284 /* collect for each variable the representation in active variables */
5285 while( ntmpvars >= 1 )
5286 {
5287 --ntmpvars;
5288
5289 var = tmpvars[ntmpvars];
5290 assert(var != NULL);
5291 assert(0 <= var->index && var->index < ntotalvars);
5293
5294 scalar = tmpscalars[var->index];
5295 /* the scalar can be 0 if the variable has been treated before and is zeroed below */
5296 if( scalar == 0.0 )
5297 continue;
5298
5299 /* x = a_1*y_1 + ... + a_n*y_n + c */
5300 nmultvars = var->data.multaggr.nvars;
5301 multvars = var->data.multaggr.vars;
5302 multscalars = var->data.multaggr.scalars;
5303
5304 /* mark variable as treated */
5305 tmpscalars[var->index] = 0.0;
5306
5307 /* loop through variables of multi-aggregation */
5308 for( v = 0; v < nmultvars; ++v )
5309 {
5310 multvar = multvars[v];
5311 multscalar = multscalars[v];
5312 multconstant = 0.0;
5313
5314 assert(multvar != NULL);
5315 SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
5316 assert(multvar != NULL);
5317
5318 /* handle constant */
5319 if( !activeconstantinf )
5320 {
5321 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
5322
5323 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
5324 {
5325 assert(scalar != 0.0);
5326 if( scalar * multconstant > 0.0 )
5327 {
5328 activeconstant = SCIPsetInfinity(set);
5329 activeconstantinf = TRUE;
5330 }
5331 else
5332 {
5333 activeconstant = -SCIPsetInfinity(set);
5334 activeconstantinf = TRUE;
5335 }
5336 }
5337 else
5338 activeconstant += scalar * multconstant;
5339 }
5340#ifndef NDEBUG
5341 else
5342 {
5343 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
5344 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5345 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
5346 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5347 }
5348#endif
5349
5350 /* Note that the variable can have a nonzero constant but 0 scalar. */
5351 if( multscalar == 0.0 )
5352 continue;
5353
5354 /* enter variable into list if not already present */
5355 assert(0 <= multvar->index && multvar->index < ntotalvars);
5356 if( tmpscalars[multvar->index] == 0.0 )
5357 {
5358 varstatus = SCIPvarGetStatus(multvar);
5359 if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN )
5360 {
5361 /* store active variables */
5362 if( nactivevars >= activevarssize )
5363 {
5364 activevarssize *= 2;
5365 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
5366 assert(nactivevars < activevarssize);
5367 }
5368 activevars[nactivevars++] = multvar;
5369 }
5370 else if( varstatus == SCIP_VARSTATUS_MULTAGGR )
5371 {
5372 /* ensure storage */
5373 if( ntmpvars >= tmpvarssize )
5374 {
5375 tmpvarssize *= 2;
5376 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
5377 assert(ntmpvars <= tmpvarssize);
5378 }
5379 tmpvars[ntmpvars++] = multvar;
5380 }
5381 }
5382
5383 /* transfer new scalar to dense array in any case */
5384 tmpscalars[multvar->index] += scalar * multscalar;
5385 assert(scalar * multscalar != 0.0);
5386 }
5387
5388 /* handle constant of multi-aggregation */
5389 if( !activeconstantinf )
5390 {
5391 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
5392
5393 multconstant = SCIPvarGetMultaggrConstant(var);
5394
5395 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
5396 {
5397 assert(scalar != 0.0);
5398 if( scalar * multconstant > 0.0 )
5399 {
5400 activeconstant = SCIPsetInfinity(set);
5401 activeconstantinf = TRUE;
5402 }
5403 else
5404 {
5405 activeconstant = -SCIPsetInfinity(set);
5406 activeconstantinf = TRUE;
5407 }
5408 }
5409 else
5410 activeconstant += scalar * multconstant;
5411 }
5412#ifndef NDEBUG
5413 else
5414 {
5415 multconstant = SCIPvarGetMultaggrConstant(var);
5416 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
5417 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5418 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
5419 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5420 }
5421#endif
5422 }
5423
5424 /* Here, nactivevars is an upper bound on the required size, because of possible cancellation. We could compute the
5425 * actual size, but this would need another loop through the active variables. We therefore take the upper bound. */
5426
5427 /* return results */
5428 if( varssize >= nactivevars )
5429 {
5430 assert(vars != NULL);
5431
5432 if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
5433 {
5434 /* if activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
5435 if( activeconstantinf )
5436 *constant = activeconstant;
5437 else
5438 *constant += activeconstant;
5439 }
5440#ifndef NDEBUG
5441 else
5442 {
5443 assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
5444 assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
5445 }
5446#endif
5447
5448 /* copy active variable and scalar array to the given arrays */
5449 *nvars = 0;
5450 for( v = 0; v < nactivevars; ++v )
5451 {
5452 var = activevars[v];
5453
5455 assert(0 <= var->index && var->index < ntotalvars);
5456
5457 /* due to cancelation, the scalar could become 0 */
5458 if( ! SCIPsetIsZero(set, tmpscalars[var->index]) )
5459 {
5460 vars[*nvars] = var;
5461 scalars[*nvars] = tmpscalars[var->index];
5462 assert(scalars[*nvars] != 0.0);
5463 ++(*nvars);
5464 }
5465
5466 /* clean buffer again */
5467 tmpscalars[var->index] = 0.0;
5468 }
5469 /* set requiredsize to space actually needed */
5470 *requiredsize = *nvars;
5471 }
5472 else
5473 {
5474 /* clean buffer again */
5475 for( v = 0; v < nactivevars; ++v )
5476 {
5477 var = activevars[v];
5478 assert( 0 <= var->index && var->index < ntotalvars );
5479 tmpscalars[var->index] = 0.0;
5480 }
5481 *requiredsize = nactivevars;
5482 }
5483
5484 assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
5485 assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
5486
5487 SCIPsetFreeCleanBufferArray(set, &tmpscalars);
5488 SCIPsetFreeBufferArray(set, &activevars);
5489 SCIPsetFreeBufferArray(set, &tmpvars);
5490
5491 return SCIP_OKAY;
5492}
5493
5494/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
5495 *
5496 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
5497 * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
5498 * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
5499 *
5500 * The reason for this approach is that we cannot reallocate memory, since we do not know how the
5501 * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
5502 *
5503 * @todo Reimplement this method as was done with SCIPvarGetActiveRepresentatives() using a clean buffer array for rationals.
5504 */
5506 SCIP_SET* set, /**< global SCIP settings */
5507 SCIP_VAR** vars, /**< variable array to get active variables */
5508 SCIP_RATIONAL** scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
5509 int* nvars, /**< pointer to number of variables and values in vars and vals array */
5510 int varssize, /**< available slots in vars and scalars array */
5511 SCIP_RATIONAL* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
5512 int* requiredsize, /**< pointer to store the required array size for the active variables */
5513 SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
5514 )
5515{
5516 SCIP_VAR** activevars;
5517 SCIP_RATIONAL** activescalars;
5518 int nactivevars;
5519 SCIP_RATIONAL* activeconstant;
5520 SCIP_Bool activeconstantinf;
5521 int activevarssize;
5522
5523 SCIP_VAR* var;
5524 SCIP_RATIONAL* scalar;
5525 int v;
5526 int k;
5527
5528 SCIP_VAR** tmpvars;
5529 SCIP_VAR** multvars;
5530 SCIP_RATIONAL** tmpscalars;
5531 SCIP_RATIONAL** multscalars;
5532 int tmpvarssize;
5533 int ntmpvars;
5534 int nmultvars;
5535 int ntmpvarsnew;
5536
5537 SCIP_VAR* multvar;
5538 SCIP_RATIONAL* multscalar;
5539 SCIP_RATIONAL* multconstant;
5540 int pos;
5541
5542 int noldtmpvars;
5543
5544 SCIP_VAR** tmpvars2;
5545 SCIP_RATIONAL** tmpscalars2;
5546 int tmpvarssize2;
5547 int ntmpvars2;
5548
5549 SCIP_Bool sortagain = FALSE;
5550
5551 assert(set != NULL);
5552 assert(nvars != NULL);
5553 assert(scalars != NULL || *nvars == 0);
5554 assert(constant != NULL);
5555 assert(requiredsize != NULL);
5556 assert(*nvars <= varssize);
5557
5558 *requiredsize = 0;
5559
5560 if( *nvars == 0 )
5561 return SCIP_OKAY;
5562
5563 assert(vars != NULL);
5564
5565 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
5566 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
5567 {
5568 *requiredsize = 1;
5569
5570 return SCIP_OKAY;
5571 }
5572
5573 nactivevars = 0;
5574 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &scalar) );
5575 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &activeconstant) );
5576 activeconstantinf = FALSE;
5577 activevarssize = (*nvars) * 2;
5578 ntmpvars = *nvars;
5579 tmpvarssize = *nvars;
5580
5581 tmpvarssize2 = 1;
5582
5583 /* allocate temporary memory */
5584 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
5585 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &tmpscalars2, tmpvarssize2) );
5586 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
5587 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &activescalars, activevarssize) );
5588 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
5589 SCIP_CALL( SCIPrationalCopyBufferArray(set->buffer, &tmpscalars, scalars, *nvars) );
5590
5591 /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
5592 * first, first get all corresponding variables with status loose, column, multaggr or fixed
5593 */
5594 for( v = ntmpvars - 1; v >= 0; --v )
5595 {
5596 var = tmpvars[v];
5597 SCIPrationalSetRational(scalar, tmpscalars[v]);
5598
5599 assert(var != NULL);
5600 /* transforms given variable, scalar and constant to the corresponding active, fixed, or
5601 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
5602 * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
5603 */
5604 SCIP_CALL( SCIPvarGetProbvarSumExact(&var, scalar, activeconstant) );
5605 assert(var != NULL);
5606
5607 activeconstantinf = SCIPrationalIsInfinity(activeconstant) || SCIPrationalIsNegInfinity(activeconstant);
5608
5613
5614 tmpvars[v] = var;
5615 SCIPrationalSetRational(tmpscalars[v], scalar);
5616 }
5617 noldtmpvars = ntmpvars;
5618
5619 /* sort all variables to combine equal variables easily */
5620 SCIPsortPtrPtr((void**)tmpvars, (void**)tmpscalars, SCIPvarComp, noldtmpvars);
5621 ntmpvars = 0;
5622 for( v = 1; v < noldtmpvars; ++v )
5623 {
5624 /* combine same variables */
5625 if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
5626 {
5627 SCIPrationalAdd(tmpscalars[ntmpvars], tmpscalars[ntmpvars], tmpscalars[v]);
5628 }
5629 else
5630 {
5631 ++ntmpvars;
5632 if( v > ntmpvars )
5633 {
5634 SCIPrationalSetRational(tmpscalars[ntmpvars], tmpscalars[v]);
5635 tmpvars[ntmpvars] = tmpvars[v];
5636 }
5637 }
5638 }
5639 ++ntmpvars;
5640
5641#ifdef SCIP_MORE_DEBUG
5642 for( v = 1; v < ntmpvars; ++v )
5643 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5644#endif
5645
5646 /* collect for each variable the representation in active variables */
5647 while( ntmpvars >= 1 )
5648 {
5649 --ntmpvars;
5650 ntmpvars2 = 0;
5651 var = tmpvars[ntmpvars];
5652 SCIPrationalSetRational(scalar, tmpscalars[ntmpvars]);
5653
5654 assert(var != NULL);
5655
5656 /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
5657 if( SCIPrationalIsZero(scalar) )
5658 continue;
5659
5664
5665 switch( SCIPvarGetStatus(var) )
5666 {
5669 /* x = a*y + c */
5670 if( nactivevars >= activevarssize )
5671 {
5672 int newactivevarssize = activevarssize * 2;
5673 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, newactivevarssize) );
5674 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &activescalars, activevarssize, newactivevarssize) );
5675 activevarssize = newactivevarssize;
5676 assert(nactivevars < activevarssize);
5677 }
5678 activevars[nactivevars] = var;
5679 SCIPrationalSetRational(activescalars[nactivevars], scalar);
5680 nactivevars++;
5681 break;
5682
5684 /* x = a_1*y_1 + ... + a_n*y_n + c */
5685 nmultvars = var->data.multaggr.nvars;
5686 multvars = var->data.multaggr.vars;
5687 multscalars = var->exactdata->multaggr.scalars;
5688 sortagain = TRUE;
5689
5690 if( nmultvars + ntmpvars > tmpvarssize )
5691 {
5692 ntmpvarsnew = tmpvarssize;
5693 while( nmultvars + ntmpvars > ntmpvarsnew )
5694 ntmpvarsnew *= 2;
5695 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, ntmpvarsnew) );
5696 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &tmpscalars, tmpvarssize, ntmpvarsnew) );
5697 assert(nmultvars + ntmpvars <= ntmpvarsnew);
5698 tmpvarssize = ntmpvarsnew;
5699 }
5700
5701 if( nmultvars > tmpvarssize2 )
5702 {
5703 ntmpvarsnew = tmpvarssize2;
5704 while( nmultvars > ntmpvarsnew )
5705 ntmpvarsnew *= 2;
5706 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, ntmpvarsnew) );
5707 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &tmpscalars2, tmpvarssize2, ntmpvarsnew) );
5708 assert(nmultvars <= ntmpvarsnew);
5709 tmpvarssize2 = ntmpvarsnew;
5710 }
5711
5712 --nmultvars;
5713
5714 for( ; nmultvars >= 0; --nmultvars )
5715 {
5716 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multconstant) );
5717 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multscalar) );
5718
5719 multvar = multvars[nmultvars];
5720 SCIPrationalSetRational(multscalar, multscalars[nmultvars]);
5721
5722 assert(multvar != NULL);
5723 SCIP_CALL( SCIPvarGetProbvarSumExact(&multvar, multscalar, multconstant) );
5724 assert(multvar != NULL);
5725
5730
5731 if( !activeconstantinf )
5732 {
5734
5735 if( SCIPrationalIsAbsInfinity(multconstant) )
5736 {
5737 assert(!SCIPrationalIsZero(scalar));
5738 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign(multconstant) && !SCIPrationalIsZero(scalar) )
5739 {
5740 SCIPrationalSetInfinity(activeconstant);
5741 activeconstantinf = TRUE;
5742 }
5743 else
5744 {
5745 SCIPrationalSetNegInfinity(activeconstant);
5746 activeconstantinf = TRUE;
5747 }
5748 }
5749 else
5750 SCIPrationalAddProd(activeconstant, scalar, multconstant);
5751 }
5752
5753 if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
5754 {
5755 assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
5756 SCIPrationalAddProd(tmpscalars[pos], scalar, multscalar);
5757 }
5758 else
5759 {
5760 tmpvars2[ntmpvars2] = multvar;
5761 SCIPrationalMult(tmpscalars2[ntmpvars2], scalar, multscalar);
5762 ++(ntmpvars2);
5763 assert(ntmpvars2 <= tmpvarssize2);
5764 }
5765
5766 SCIPrationalFreeBuffer(set->buffer, &multscalar);
5767 SCIPrationalFreeBuffer(set->buffer, &multconstant);
5768 }
5769
5770 if( ntmpvars2 > 0 )
5771 {
5772 /* sort all variables to combine equal variables easily */
5773 SCIPsortPtrPtr((void**)tmpvars2, (void**)tmpscalars2, SCIPvarComp, ntmpvars2);
5774 pos = 0;
5775 for( v = 1; v < ntmpvars2; ++v )
5776 {
5777 /* combine same variables */
5778 if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
5779 {
5780 SCIPrationalAdd(tmpscalars2[pos], tmpscalars2[pos], tmpscalars2[v]);
5781 }
5782 else
5783 {
5784 ++pos;
5785 if( v > pos )
5786 {
5787 SCIPrationalSetRational(tmpscalars2[pos], tmpscalars2[v]);
5788 tmpvars2[pos] = tmpvars2[v];
5789 }
5790 }
5791 }
5792 ntmpvars2 = pos + 1;
5793#ifdef SCIP_MORE_DEBUG
5794 for( v = 1; v < ntmpvars2; ++v )
5795 {
5796 assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
5797 }
5798 for( v = 1; v < ntmpvars; ++v )
5799 {
5800 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5801 }
5802#endif
5803 v = ntmpvars - 1;
5804 k = ntmpvars2 - 1;
5805 pos = ntmpvars + ntmpvars2 - 1;
5806 ntmpvars += ntmpvars2;
5807
5808 while( v >= 0 && k >= 0 )
5809 {
5810 assert(pos >= 0);
5811 assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
5812 if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
5813 {
5814 tmpvars[pos] = tmpvars[v];
5815 SCIPrationalSetRational(tmpscalars[pos], tmpscalars[v]);
5816 --v;
5817 }
5818 else
5819 {
5820 tmpvars[pos] = tmpvars2[k];
5821 SCIPrationalSetRational(tmpscalars[pos], tmpscalars2[k]);
5822 --k;
5823 }
5824 --pos;
5825 assert(pos >= 0);
5826 }
5827 while( v >= 0 )
5828 {
5829 assert(pos >= 0);
5830 tmpvars[pos] = tmpvars[v];
5831 SCIPrationalSetRational(tmpscalars[pos], tmpscalars[v]);
5832 --v;
5833 --pos;
5834 }
5835 while( k >= 0 )
5836 {
5837 assert(pos >= 0);
5838 tmpvars[pos] = tmpvars2[k];
5839 SCIPrationalSetRational(tmpscalars[pos], tmpscalars2[k]);
5840 --k;
5841 --pos;
5842 }
5843 }
5844#ifdef SCIP_MORE_DEBUG
5845 for( v = 1; v < ntmpvars; ++v )
5846 {
5847 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5848 }
5849#endif
5850
5851 if( !activeconstantinf )
5852 {
5854
5855 multconstant = SCIPvarGetMultaggrConstantExact(var);
5856
5857 if( SCIPrationalIsAbsInfinity(multconstant) )
5858 {
5859 assert(!SCIPrationalIsZero(scalar));
5860 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign(multconstant) && !SCIPrationalIsZero(scalar) )
5861 {
5862 SCIPrationalSetInfinity(activeconstant);
5863 activeconstantinf = TRUE;
5864 }
5865 else
5866 {
5867 SCIPrationalSetNegInfinity(activeconstant);
5868 activeconstantinf = TRUE;
5869 }
5870 }
5871 else
5872 SCIPrationalAddProd(activeconstant, scalar, multconstant);
5873 }
5874
5875 break;
5876
5881 default:
5882 /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
5883 * fixed variables and is handled already
5884 */
5886 assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
5887 }
5888 }
5889
5890 if( mergemultiples )
5891 {
5892 if( sortagain )
5893 {
5894 /* sort variable and scalar array by variable index */
5895 SCIPsortPtrPtr((void**)activevars, (void**)activescalars, SCIPvarComp, nactivevars);
5896
5897 /* eliminate duplicates and count required size */
5898 v = nactivevars - 1;
5899 while( v > 0 )
5900 {
5901 /* combine both variable since they are the same */
5902 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
5903 {
5904 SCIPrationalNegate(scalar, activescalars[v]);
5905 if( !SCIPrationalIsEQ(activescalars[v - 1], scalar) )
5906 {
5907 SCIPrationalAdd(activescalars[v - 1], activescalars[v - 1], activescalars[v]);
5908 --nactivevars;
5909 activevars[v] = activevars[nactivevars];
5910 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5911 }
5912 else
5913 {
5914 --nactivevars;
5915 activevars[v] = activevars[nactivevars];
5916 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5917 --nactivevars;
5918 --v;
5919 activevars[v] = activevars[nactivevars];
5920 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5921 }
5922 }
5923 --v;
5924 }
5925 }
5926 /* the variables were added in reverse order, we revert the order now;
5927 * this should not be necessary, but not doing this changes the behavior sometimes
5928 */
5929 else
5930 {
5931 SCIP_VAR* tmpvar;
5932
5933 for( v = 0; v < nactivevars / 2; ++v )
5934 {
5935 tmpvar = activevars[v];
5936 SCIPrationalSetRational(scalar, activescalars[v]);
5937 activevars[v] = activevars[nactivevars - 1 - v];
5938 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars - 1 - v]);
5939 activevars[nactivevars - 1 - v] = tmpvar;
5940 SCIPrationalSetRational(activescalars[nactivevars - 1 - v], scalar);
5941 }
5942 }
5943 }
5944 *requiredsize = nactivevars;
5945
5946 if( varssize >= *requiredsize )
5947 {
5948 assert(vars != NULL);
5949
5950 *nvars = *requiredsize;
5951
5952 if( !SCIPrationalIsAbsInfinity(constant) )
5953 {
5954 /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
5955 if( activeconstantinf )
5956 SCIPrationalSetRational(constant, activeconstant);
5957 else
5958 SCIPrationalAdd(constant, constant, activeconstant);
5959 }
5960
5961 /* copy active variable and scalar array to the given arrays */
5962 for( v = 0; v < *nvars; ++v )
5963 {
5964 vars[v] = activevars[v];
5965 SCIPrationalSetRational(scalars[v], activescalars[v]); /*lint !e613*/
5966 }
5967 }
5968
5969 SCIPrationalFreeBufferArray(set->buffer, &tmpscalars, tmpvarssize);
5970 SCIPsetFreeBufferArray(set, &tmpvars);
5971 SCIPrationalFreeBufferArray(set->buffer, &activescalars, activevarssize);
5972 SCIPsetFreeBufferArray(set, &activevars);
5973 SCIPrationalFreeBufferArray(set->buffer, &tmpscalars2, tmpvarssize2);
5974 SCIPsetFreeBufferArray(set, &tmpvars2);
5975
5976 SCIPrationalFreeBuffer(set->buffer, &activeconstant);
5977 SCIPrationalFreeBuffer(set->buffer, &scalar);
5978
5979 return SCIP_OKAY;
5980}
5981
5982/** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
5984 SCIP_VAR* var, /**< problem variable */
5985 BMS_BLKMEM* blkmem, /**< block memory */
5986 SCIP_SET* set, /**< global SCIP settings */
5987 SCIP_EVENTQUEUE* eventqueue /**< event queue */
5988 )
5989{
5990 int nlocksup[NLOCKTYPES];
5991 int nlocksdown[NLOCKTYPES];
5992 SCIP_Real multconstant;
5993 int multvarssize;
5994 int nmultvars;
5995 int multrequiredsize;
5996 int i;
5997
5998 assert( var != NULL );
6000 assert(var->scip == set->scip);
6001
6002 /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
6003 * on the current representation now and re-add the locks once the variable graph has been flattened, which
6004 * may lead to duplicate occurences of the same variable being merged
6005 *
6006 * Here is an example. Assume we have the multi-aggregation z = x + y.
6007 * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
6008 * When the multi-aggregation is performed, all locks are added to the active representation,
6009 * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
6010 * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
6011 * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
6012 * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
6013 * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
6014 * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
6015 * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
6016 * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
6017 * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
6018 * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
6019 * By removing the locks here, based on the old representation and adding them again after flattening,
6020 * we ensure that the locks are correct afterwards if coefficients were merged.
6021 */
6022 for( i = 0; i < NLOCKTYPES; ++i )
6023 {
6024 nlocksup[i] = var->nlocksup[i];
6025 nlocksdown[i] = var->nlocksdown[i];
6026
6027 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
6028 }
6029
6030 multconstant = var->data.multaggr.constant;
6031 nmultvars = var->data.multaggr.nvars;
6032 multvarssize = var->data.multaggr.varssize;
6033
6034 if( !set->exact_enable )
6035 {
6036 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars,
6037 multvarssize, &multconstant, &multrequiredsize) );
6038
6039 if( multrequiredsize > multvarssize )
6040 {
6041 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
6042 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
6043 multvarssize = multrequiredsize;
6044 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars,
6045 multvarssize, &multconstant, &multrequiredsize) );
6046
6047 assert( multrequiredsize <= multvarssize );
6048 }
6049
6050 /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
6051 * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
6052 * may loose performance hereby, since aggregated variables are easier to handle.
6053 *
6054 * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
6055 * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
6056 * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
6057 * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
6058 *
6059 * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
6060 *
6061 * The same issue appears in the SCIPvarGetProbvar...() methods.
6062 */
6063
6064 var->data.multaggr.constant = multconstant;
6065 }
6066 else
6067 {
6068 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, var->data.multaggr.vars, var->exactdata->multaggr.scalars,
6069 &nmultvars, multvarssize, var->exactdata->multaggr.constant, &multrequiredsize, TRUE) );
6070
6071 var->data.multaggr.nvars = nmultvars;
6072 var->data.multaggr.varssize = multvarssize;
6074
6075 if( multrequiredsize > multvarssize )
6076 {
6077 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
6078 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
6079 SCIP_CALL( SCIPrationalReallocBlockArray(blkmem, &(var->exactdata->multaggr.scalars), multvarssize, multrequiredsize) );
6080 multvarssize = multrequiredsize;
6081 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, var->data.multaggr.vars, var->exactdata->multaggr.scalars,
6082 &nmultvars, multvarssize, var->exactdata->multaggr.constant, &multrequiredsize, TRUE) );
6083
6084 var->data.multaggr.nvars = nmultvars;
6085 var->data.multaggr.varssize = multvarssize;
6086
6088
6089 assert( multrequiredsize <= multvarssize );
6090 }
6091 }
6092
6093 var->data.multaggr.nvars = nmultvars;
6094 var->data.multaggr.varssize = multvarssize;
6095
6096 for( i = 0; i < NLOCKTYPES; ++i )
6097 {
6098 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
6099 }
6100
6101 return SCIP_OKAY;
6102}
6103
6104/** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
6105 * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
6106 * the history merge is reasonable
6107 *
6108 * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
6109 * this corrupts the variable pseudo costs
6110 * @note Apply with care; no internal checks are performed if the two variables should be merged
6111 */
6113 SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
6114 SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
6115 SCIP_STAT* stat /**< problem statistics */
6116 )
6117{
6118 /* merge only the history of the current run into the target history */
6119 SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
6120
6121 /* apply the changes also to the global history */
6122 SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
6123}
6124
6125/** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
6126 * history over several iterations
6127 */
6129 SCIP_VAR* var, /**< variable */
6130 SCIP_HISTORY* history, /**< the history which is to set */
6131 SCIP_STAT* stat /**< problem statistics */
6132 )
6133{
6134 /* merge only the history of the current run into the target history */
6135 SCIPhistoryUnite(var->history, history, FALSE);
6136
6137 /* apply the changes also to the global history */
6138 SCIPhistoryUnite(stat->glbhistory, history, FALSE);
6139}
6140
6141/** update min/maxaggrcoef of a loose variable */
6142static
6144 SCIP_VAR* var, /**< problem variable that is used in aggregation */
6145 SCIP_VAR* aggvar, /**< variable that is aggregated */
6146 SCIP_Real aggscalar /**< coefficient that is used for var in the aggregation of aggvar */
6147 )
6148{
6149 SCIP_Real minscalar;
6150 SCIP_Real maxscalar;
6151
6152 assert(var != NULL);
6154 assert(aggvar != NULL);
6156 assert(aggscalar != 0.0); /*lint !e777*/
6157
6158 maxscalar = minscalar = REALABS(aggscalar);
6159 minscalar *= aggvar->data.loose.minaggrcoef;
6160 maxscalar *= aggvar->data.loose.maxaggrcoef;
6161 if( var->data.loose.minaggrcoef > minscalar )
6162 var->data.loose.minaggrcoef = minscalar;
6163 if( var->data.loose.maxaggrcoef < maxscalar )
6164 var->data.loose.maxaggrcoef = maxscalar;
6165}
6166
6167
6168/** tightens the bounds of both variables in aggregation x = a*y + c */
6169static
6171 SCIP_VAR* var, /**< problem variable */
6172 BMS_BLKMEM* blkmem, /**< block memory */
6173 SCIP_SET* set, /**< global SCIP settings */
6174 SCIP_STAT* stat, /**< problem statistics */
6175 SCIP_PROB* transprob, /**< tranformed problem data */
6176 SCIP_PROB* origprob, /**< original problem data */
6177 SCIP_PRIMAL* primal, /**< primal data */
6178 SCIP_TREE* tree, /**< branch and bound tree */
6179 SCIP_REOPT* reopt, /**< reoptimization data structure */
6180 SCIP_LP* lp, /**< current LP data */
6181 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6182 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6183 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6184 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6185 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
6186 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
6187 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
6188 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6189 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
6190 )
6191{
6192 SCIP_Real varlb;
6193 SCIP_Real varub;
6194 SCIP_Real aggvarlb;
6195 SCIP_Real aggvarub;
6196 SCIP_Bool aggvarbdschanged;
6197
6198 assert(var != NULL);
6199 assert(var->scip == set->scip);
6200 assert(aggvar != NULL);
6201 assert(!SCIPsetIsZero(set, scalar));
6202 assert(infeasible != NULL);
6203 assert(fixed != NULL);
6204
6205 *infeasible = FALSE;
6206 *fixed = FALSE;
6207
6208 SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
6209 SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
6210 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
6211
6212 /* loop as long additional changes may be found */
6213 do
6214 {
6215 aggvarbdschanged = FALSE;
6216
6217 /* update the bounds of the aggregated variable x in x = a*y + c */
6218 if( scalar > 0.0 )
6219 {
6220 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
6221 varlb = -SCIPsetInfinity(set);
6222 else
6223 varlb = aggvar->glbdom.lb * scalar + constant;
6224 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
6225 varub = SCIPsetInfinity(set);
6226 else
6227 varub = aggvar->glbdom.ub * scalar + constant;
6228 }
6229 else
6230 {
6231 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
6232 varub = SCIPsetInfinity(set);
6233 else
6234 varub = aggvar->glbdom.lb * scalar + constant;
6235 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
6236 varlb = -SCIPsetInfinity(set);
6237 else
6238 varlb = aggvar->glbdom.ub * scalar + constant;
6239 }
6240 varlb = MAX(varlb, var->glbdom.lb);
6241 varub = MIN(varub, var->glbdom.ub);
6242 SCIPvarAdjustLb(var, set, &varlb);
6243 SCIPvarAdjustUb(var, set, &varub);
6244
6245 /* check the new bounds */
6246 if( SCIPsetIsGT(set, varlb, varub) )
6247 {
6248 /* the aggregation is infeasible */
6249 *infeasible = TRUE;
6250 return SCIP_OKAY;
6251 }
6252 else if( SCIPsetIsEQ(set, varlb, varub) )
6253 {
6254 /* the aggregated variable is fixed -> fix both variables */
6255 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6256 eventqueue, eventfilter, cliquetable, varlb, infeasible, fixed) );
6257 if( !(*infeasible) )
6258 {
6259 SCIP_Bool aggfixed;
6260
6261 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6262 eventqueue, eventfilter, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
6263 assert(*fixed == aggfixed);
6264 }
6265 return SCIP_OKAY;
6266 }
6267 else
6268 {
6269 if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
6270 {
6271 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
6272 }
6273 if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
6274 {
6275 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
6276 }
6277
6278 /* update the hole list of the aggregation variable */
6279 /**@todo update hole list of aggregation variable */
6280 }
6281
6282 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
6283 if( scalar > 0.0 )
6284 {
6285 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
6286 aggvarlb = -SCIPsetInfinity(set);
6287 else
6288 aggvarlb = (var->glbdom.lb - constant) / scalar;
6289 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
6290 aggvarub = SCIPsetInfinity(set);
6291 else
6292 aggvarub = (var->glbdom.ub - constant) / scalar;
6293 }
6294 else
6295 {
6296 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
6297 aggvarub = SCIPsetInfinity(set);
6298 else
6299 aggvarub = (var->glbdom.lb - constant) / scalar;
6300 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
6301 aggvarlb = -SCIPsetInfinity(set);
6302 else
6303 aggvarlb = (var->glbdom.ub - constant) / scalar;
6304 }
6305 aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
6306 aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
6307 SCIPvarAdjustLb(aggvar, set, &aggvarlb);
6308 SCIPvarAdjustUb(aggvar, set, &aggvarub);
6309
6310 /* check the new bounds */
6311 if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
6312 {
6313 /* the aggregation is infeasible */
6314 *infeasible = TRUE;
6315 return SCIP_OKAY;
6316 }
6317 else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
6318 {
6319 /* the aggregation variable is fixed -> fix both variables */
6320 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6321 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, fixed) );
6322 if( !(*infeasible) )
6323 {
6324 SCIP_Bool varfixed;
6325
6326 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6327 eventqueue, eventfilter, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
6328 assert(*fixed == varfixed);
6329 }
6330 return SCIP_OKAY;
6331 }
6332 else
6333 {
6334 SCIP_Real oldbd;
6335 if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
6336 {
6337 oldbd = aggvar->glbdom.lb;
6338 SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
6339 aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
6340 }
6341 if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
6342 {
6343 oldbd = aggvar->glbdom.ub;
6344 SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
6345 aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
6346 }
6347
6348 /* update the hole list of the aggregation variable */
6349 /**@todo update hole list of aggregation variable */
6350 }
6351 }
6352 while( aggvarbdschanged );
6353
6354 SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
6355 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
6356
6357 return SCIP_OKAY;
6358}
6359
6360/** tightens the bounds of both variables in aggregation x = a*y + c */
6361static
6363 SCIP_VAR* var, /**< problem variable */
6364 BMS_BLKMEM* blkmem, /**< block memory */
6365 SCIP_SET* set, /**< global SCIP settings */
6366 SCIP_STAT* stat, /**< problem statistics */
6367 SCIP_PROB* transprob, /**< tranformed problem data */
6368 SCIP_PROB* origprob, /**< original problem data */
6369 SCIP_PRIMAL* primal, /**< primal data */
6370 SCIP_TREE* tree, /**< branch and bound tree */
6371 SCIP_REOPT* reopt, /**< reoptimization data structure */
6372 SCIP_LP* lp, /**< current LP data */
6373 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6374 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6375 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6376 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6377 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
6378 SCIP_RATIONAL* scalar, /**< multiplier a in aggregation x = a*y + c */
6379 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a*y + c */
6380 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6381 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
6382 )
6383{
6384 SCIP_RATIONAL* varlb;
6385 SCIP_RATIONAL* varub;
6386 SCIP_RATIONAL* aggvarlb;
6387 SCIP_RATIONAL* aggvarub;
6388 SCIP_Bool aggvarbdschanged;
6389
6390 assert(var != NULL);
6391 assert(var->scip == set->scip);
6392 assert(aggvar != NULL);
6393 assert(!SCIPrationalIsZero(scalar));
6394 assert(infeasible != NULL);
6395 assert(fixed != NULL);
6396
6397 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &varlb) );
6398 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &varub) );
6399 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &aggvarlb) );
6400 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &aggvarub) );
6401
6402 *infeasible = FALSE;
6403 *fixed = FALSE;
6404
6405 SCIPrationalDebugMessage("updating bounds of variables in aggregation <%s> == %q*<%s> %+q\n", var->name, scalar, aggvar->name, constant);
6406 SCIPrationalDebugMessage(" old bounds: <%s> [%q,%q] <%s> [%q,%q]\n",
6407 var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub);
6408
6409 /* loop as long additional changes may be found */
6410 do
6411 {
6412 aggvarbdschanged = FALSE;
6413
6414 /* update the bounds of the aggregated variable x in x = a*y + c */
6415 if( SCIPrationalIsPositive(scalar) )
6416 {
6419 else
6420 {
6421 SCIPrationalMult(varlb, aggvar->exactdata->glbdom.lb, scalar);
6422 SCIPrationalAdd(varlb, varlb, constant);
6423 }
6426 else
6427 {
6428 SCIPrationalMult(varub, aggvar->exactdata->glbdom.ub, scalar);
6429 SCIPrationalAdd(varub, varub, constant);
6430 }
6431 }
6432 else
6433 {
6436 else
6437 {
6438 SCIPrationalMult(varub, aggvar->exactdata->glbdom.lb, scalar);
6439 SCIPrationalAdd(varub, varub, constant);
6440 }
6443 else
6444 {
6445 SCIPrationalMult(varlb, aggvar->exactdata->glbdom.ub, scalar);
6446 SCIPrationalAdd(varlb, varlb, constant);
6447 }
6448 }
6449 SCIPrationalMax(varlb, varlb, var->exactdata->glbdom.lb);
6450 SCIPrationalMin(varub, varub, var->exactdata->glbdom.ub);
6451 SCIPvarAdjustLbExact(var, set, varlb);
6452 SCIPvarAdjustUbExact(var, set, varub);
6453
6454 /* check the new bounds */
6455 if( SCIPrationalIsGT(varlb, varub) )
6456 {
6457 /* the aggregation is infeasible */
6458 *infeasible = TRUE;
6459 break;
6460 }
6461 else if( SCIPrationalIsEQ(varlb, varub) )
6462 {
6463 /* the aggregated variable is fixed -> fix both variables */
6464 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6465 eventqueue, eventfilter, cliquetable, varlb, infeasible, fixed) );
6466
6467 if( !(*infeasible) )
6468 {
6469 SCIP_Bool aggfixed;
6470
6471 SCIPrationalDiff(varlb, varlb, constant);
6472 SCIPrationalDiv(varlb, varlb, scalar);
6473
6474 SCIP_CALL( SCIPvarFixExact(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6475 eventqueue, eventfilter, cliquetable, varlb, infeasible, &aggfixed) );
6476 assert(*fixed == aggfixed);
6477 }
6478 break;
6479 }
6480 else
6481 {
6482 if( SCIPrationalIsGT(varlb, var->exactdata->glbdom.lb) )
6483 {
6484 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, varlb) );
6485 }
6486 if( SCIPrationalIsLT(varub, var->exactdata->glbdom.ub) )
6487 {
6488 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, varub) );
6489 }
6490
6491 /* update the hole list of the aggregation variable */
6492 /**@todo update hole list of aggregation variable */
6493 }
6494
6495 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
6496 if( SCIPrationalIsPositive(scalar) )
6497 {
6498 if( SCIPrationalIsNegInfinity(var->exactdata->glbdom.lb) )
6500 else
6501 {
6502 SCIPrationalDiff(aggvarlb, var->exactdata->glbdom.lb, constant);
6503 SCIPrationalDiv(aggvarlb, aggvarlb, scalar);
6504 }
6505 if( SCIPrationalIsInfinity(var->exactdata->glbdom.ub) )
6506 SCIPrationalSetInfinity(aggvarub);
6507 else
6508 {
6509 SCIPrationalDiff(aggvarub, var->exactdata->glbdom.ub, constant);
6510 SCIPrationalDiv(aggvarub, aggvarub, scalar);
6511 }
6512 }
6513 else
6514 {
6515 if( SCIPrationalIsNegInfinity(var->exactdata->glbdom.lb) )
6516 SCIPrationalSetInfinity(aggvarub);
6517 else
6518 {
6519 SCIPrationalDiff(aggvarub, var->exactdata->glbdom.lb, constant);
6520 SCIPrationalDiv(aggvarub, aggvarub, scalar);
6521 }
6522 if( SCIPrationalIsInfinity(var->exactdata->glbdom.ub) )
6524 else
6525 {
6526 SCIPrationalDiff(aggvarlb, var->exactdata->glbdom.ub, constant);
6527 SCIPrationalDiv(aggvarlb, aggvarlb, scalar);
6528 }
6529 }
6530 SCIPrationalMax(aggvarlb, aggvarlb, aggvar->exactdata->glbdom.lb);
6531 SCIPrationalMin(aggvarub, aggvarub, aggvar->exactdata->glbdom.ub);
6532 SCIPvarAdjustLbExact(aggvar, set, aggvarlb);
6533 SCIPvarAdjustUbExact(aggvar, set, aggvarub);
6534
6535 /* check the new bounds */
6536 if( SCIPrationalIsGT(aggvarlb, aggvarub) )
6537 {
6538 /* the aggregation is infeasible */
6539 *infeasible = TRUE;
6540 break;
6541 }
6542 else if( SCIPrationalIsEQ(aggvarlb, aggvarub) )
6543 {
6544 /* the aggregation variable is fixed -> fix both variables */
6545 SCIP_CALL( SCIPvarFixExact(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6546 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, fixed) );
6547
6548 if( !(*infeasible) )
6549 {
6550 SCIP_Bool varfixed;
6551
6552 SCIPrationalMult(aggvarlb, aggvarlb, scalar);
6553 SCIPrationalAdd(aggvarlb, aggvarlb, constant);
6554
6555 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6556 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, &varfixed) );
6557 assert(*fixed == varfixed);
6558 }
6559 break;
6560 }
6561 else
6562 {
6563 if( SCIPrationalIsGT(aggvarlb, aggvar->exactdata->glbdom.lb) )
6564 {
6565 SCIPrationalSetRational(varlb, aggvar->exactdata->glbdom.lb);
6566 SCIP_CALL( SCIPvarChgLbGlobalExact(aggvar, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, aggvarlb) );
6567 aggvarbdschanged = !SCIPrationalIsEQ(varlb, aggvar->exactdata->glbdom.lb);
6568 }
6569
6570 if( SCIPrationalIsLT(aggvarub, aggvar->exactdata->glbdom.ub) )
6571 {
6572 SCIPrationalSetRational(varub, aggvar->exactdata->glbdom.ub);
6573 SCIP_CALL( SCIPvarChgUbGlobalExact(aggvar, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, aggvarub) );
6574 aggvarbdschanged = aggvarbdschanged || !SCIPrationalIsEQ(varub, aggvar->exactdata->glbdom.ub);
6575 }
6576
6577 /* update the hole list of the aggregation variable */
6578 /**@todo update hole list of aggregation variable */
6579 }
6580 }
6581 while( aggvarbdschanged );
6582
6583 SCIPrationalDebugMessage(" new bounds: <%s> [%q,%q] <%s> [%q,%q]\n",
6584 var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub);
6585
6586 SCIPrationalFreeBuffer(set->buffer, &aggvarub);
6587 SCIPrationalFreeBuffer(set->buffer, &aggvarlb);
6588 SCIPrationalFreeBuffer(set->buffer, &varub);
6589 SCIPrationalFreeBuffer(set->buffer, &varlb);
6590
6591 return SCIP_OKAY;
6592}
6593
6594/** converts loose variable into aggregated variable */
6596 SCIP_VAR* var, /**< loose problem variable */
6597 BMS_BLKMEM* blkmem, /**< block memory */
6598 SCIP_SET* set, /**< global SCIP settings */
6599 SCIP_STAT* stat, /**< problem statistics */
6600 SCIP_PROB* transprob, /**< tranformed problem data */
6601 SCIP_PROB* origprob, /**< original problem data */
6602 SCIP_PRIMAL* primal, /**< primal data */
6603 SCIP_TREE* tree, /**< branch and bound tree */
6604 SCIP_REOPT* reopt, /**< reoptimization data structure */
6605 SCIP_LP* lp, /**< current LP data */
6606 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6607 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6608 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6609 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6610 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
6611 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
6612 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
6613 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6614 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
6615 )
6616{
6617 SCIP_VAR** vars;
6618 SCIP_Real* coefs;
6619 SCIP_Real* constants;
6620 SCIP_Real obj;
6621 SCIP_Real branchfactor;
6622 SCIP_Bool fixed;
6623 int branchpriority;
6624 int nlocksdown[NLOCKTYPES];
6625 int nlocksup[NLOCKTYPES];
6626 int nvbds;
6627 int i;
6628 int j;
6629
6630 assert(var != NULL);
6631 assert(aggvar != NULL);
6632 assert(var->scip == set->scip);
6633 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
6634 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
6636 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
6637 assert(infeasible != NULL);
6638 assert(aggregated != NULL);
6639
6640 *infeasible = FALSE;
6641 *aggregated = FALSE;
6642
6643 /* get active problem variable of aggregation variable */
6644 SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
6645
6646 /* aggregation is a fixing, if the scalar is zero */
6647 if( SCIPsetIsZero(set, scalar) )
6648 {
6649 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
6650 eventfilter, cliquetable, constant, infeasible, aggregated) );
6651 goto TERMINATE;
6652 }
6653
6654 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
6656 return SCIP_OKAY;
6657
6658 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
6659 * should be changed in the future
6660 */
6662 return SCIP_OKAY;
6663
6664 /* if the variable is not allowed to be aggregated */
6665 if( SCIPvarDoNotAggr(var) )
6666 {
6667 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
6668 return SCIP_OKAY;
6669 }
6670
6671 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
6672 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
6674
6675 SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
6676 scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
6677
6678 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
6679 if( var == aggvar )
6680 {
6681 if( SCIPsetIsEQ(set, scalar, 1.0) )
6682 *infeasible = !SCIPsetIsZero(set, constant);
6683 else
6684 {
6685 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6686 eventqueue, eventfilter, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
6687 }
6688 goto TERMINATE;
6689 }
6690
6691 /* tighten the bounds of aggregated and aggregation variable */
6692 SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6693 branchcand, eventqueue, eventfilter, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
6694 if( *infeasible || fixed )
6695 {
6696 *aggregated = fixed;
6697 goto TERMINATE;
6698 }
6699
6700 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
6701 * aggregated variable
6702 */
6703 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
6704
6705 /* set the aggregated variable's objective value to 0.0 */
6706 obj = var->obj;
6707 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
6708
6709 /* unlock all locks */
6710 for( i = 0; i < NLOCKTYPES; i++ )
6711 {
6712 nlocksdown[i] = var->nlocksdown[i];
6713 nlocksup[i] = var->nlocksup[i];
6714
6715 var->nlocksdown[i] = 0;
6716 var->nlocksup[i] = 0;
6717 }
6718
6719 /* update aggregation bounds (argument names of varUpdateMinMaxAggrCoef are swapped) */
6720 varUpdateMinMaxAggrCoef(aggvar, var, scalar);
6721
6722 /* check, if variable should be used as NEGATED variable of the aggregation variable */
6723 if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
6724 && var->negatedvar == NULL && aggvar->negatedvar == NULL
6725 && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
6726 {
6727 /* link both variables as negation pair */
6728 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
6729 var->data.negate.constant = 1.0;
6730 var->negatedvar = aggvar;
6731 aggvar->negatedvar = var;
6732
6733 /* copy donot(mult)aggr status */
6734 aggvar->donotaggr |= var->donotaggr;
6735 aggvar->donotmultaggr |= var->donotmultaggr;
6736
6737 /* mark both variables to be non-deletable */
6740 }
6741 else
6742 {
6743 /* convert variable into aggregated variable */
6744 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
6745 var->data.aggregate.var = aggvar;
6746 var->data.aggregate.scalar = scalar;
6747 var->data.aggregate.constant = constant;
6748
6749 /* copy donot(mult)aggr status */
6750 aggvar->donotaggr |= var->donotaggr;
6751 aggvar->donotmultaggr |= var->donotmultaggr;
6752
6753 /* mark both variables to be non-deletable */
6756 }
6757
6758 /* make aggregated variable a parent of the aggregation variable */
6759 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
6760
6761 /* relock the variable, thus increasing the locks of the aggregation variable */
6762 for( i = 0; i < NLOCKTYPES; i++ )
6763 {
6764 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
6765 }
6766
6767 /* move the variable bounds to the aggregation variable:
6768 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
6769 * - free the variable bounds data structures
6770 */
6771 if( var->vlbs != NULL )
6772 {
6773 nvbds = SCIPvboundsGetNVbds(var->vlbs);
6774 vars = SCIPvboundsGetVars(var->vlbs);
6775 coefs = SCIPvboundsGetCoefs(var->vlbs);
6776 constants = SCIPvboundsGetConstants(var->vlbs);
6777 for( i = 0; i < nvbds && !(*infeasible); ++i )
6778 {
6779 SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
6780 eventqueue, eventfilter, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
6781 }
6782 }
6783 if( var->vubs != NULL )
6784 {
6785 nvbds = SCIPvboundsGetNVbds(var->vubs);
6786 vars = SCIPvboundsGetVars(var->vubs);
6787 coefs = SCIPvboundsGetCoefs(var->vubs);
6788 constants = SCIPvboundsGetConstants(var->vubs);
6789 for( i = 0; i < nvbds && !(*infeasible); ++i )
6790 {
6791 SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
6792 eventqueue, eventfilter, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
6793 }
6794 }
6795 SCIPvboundsFree(&var->vlbs, blkmem);
6796 SCIPvboundsFree(&var->vubs, blkmem);
6797
6798 /* move the implications to the aggregation variable:
6799 * - add all implications again to the variable, thus adding it to the aggregation variable
6800 * - free the implications data structures
6801 */
6802 if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(aggvar) )
6803 {
6805 for( i = 0; i < 2; ++i )
6806 {
6807 SCIP_VAR** implvars;
6808 SCIP_BOUNDTYPE* impltypes;
6809 SCIP_Real* implbounds;
6810 int nimpls;
6811
6812 nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
6813 implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
6814 impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
6815 implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
6816
6817 for( j = 0; j < nimpls && !(*infeasible); ++j )
6818 {
6819 /* @todo can't we omit transitive closure, because it should already have been done when adding the
6820 * implication to the aggregated variable?
6821 */
6822 SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
6823 branchcand, eventqueue, eventfilter, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE,
6824 infeasible, NULL) );
6825 assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
6826 }
6827 }
6828 }
6829 SCIPimplicsFree(&var->implics, blkmem);
6830
6831 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
6832 SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
6833 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
6834 SCIPhistoryReset(var->history);
6835 SCIPhistoryReset(var->historycrun);
6836
6837 /* update flags of aggregation variable */
6838 aggvar->removable &= var->removable;
6839
6840 /* update branching factors and priorities of both variables to be the maximum of both variables */
6841 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
6842 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
6843 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
6844 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
6845 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
6846 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
6847
6848 /* update branching direction of both variables to agree to a single direction */
6849 if( scalar >= 0.0 )
6850 {
6851 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
6852 {
6854 }
6856 {
6857 SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
6858 }
6859 else if( var->branchdirection != aggvar->branchdirection )
6860 {
6862 }
6863 }
6864 else
6865 {
6866 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
6867 {
6869 }
6871 {
6873 }
6874 else if( var->branchdirection != aggvar->branchdirection )
6875 {
6877 }
6878 }
6879
6880 if( var->probindex != -1 )
6881 {
6882 /* inform problem about the variable's status change */
6883 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
6884 }
6885
6886 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
6887 * variable and the problem's objective offset
6888 */
6889 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
6890
6891 /* issue VARFIXED event */
6892 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
6893
6894 *aggregated = TRUE;
6895
6896TERMINATE:
6897 /* check aggregation on debugging solution */
6898 if( *infeasible || *aggregated )
6899 SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
6900
6901 return SCIP_OKAY;
6902}
6903
6904/** converts loose variable into aggregated variable */
6906 SCIP_VAR* var, /**< loose problem variable */
6907 BMS_BLKMEM* blkmem, /**< block memory */
6908 SCIP_SET* set, /**< global SCIP settings */
6909 SCIP_STAT* stat, /**< problem statistics */
6910 SCIP_PROB* transprob, /**< tranformed problem data */
6911 SCIP_PROB* origprob, /**< original problem data */
6912 SCIP_PRIMAL* primal, /**< primal data */
6913 SCIP_TREE* tree, /**< branch and bound tree */
6914 SCIP_REOPT* reopt, /**< reoptimization data structure */
6915 SCIP_LP* lp, /**< current LP data */
6916 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6917 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6918 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6919 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6920 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
6921 SCIP_RATIONAL* scalar, /**< multiplier a in aggregation x = a*y + c */
6922 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a*y + c */
6923 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6924 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
6925 )
6926{
6928 SCIP_RATIONAL* tmpval;
6929 SCIP_Real branchfactor;
6930 SCIP_Bool fixed;
6931 int branchpriority;
6932 int nlocksdown[NLOCKTYPES];
6933 int nlocksup[NLOCKTYPES];
6934 int i;
6935
6936 assert(var != NULL);
6937 assert(aggvar != NULL);
6938 assert(var->scip == set->scip);
6939 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
6940 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
6942 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
6943 assert(infeasible != NULL);
6944 assert(aggregated != NULL);
6945
6946 *infeasible = FALSE;
6947 *aggregated = FALSE;
6948
6949 /* get active problem variable of aggregation variable */
6950 SCIP_CALL( SCIPvarGetProbvarSumExact(&aggvar, scalar, constant) );
6951
6952 /* aggregation is a fixing, if the scalar is zero */
6953 if( SCIPrationalIsZero(scalar) )
6954 {
6955 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6956 eventqueue, eventfilter, cliquetable, constant, infeasible, aggregated) );
6957 return SCIP_OKAY;
6958 }
6959
6960 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
6962 return SCIP_OKAY;
6963
6964 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
6965 * should be changed in the future
6966 */
6968 return SCIP_OKAY;
6969
6970 /* if the variable is not allowed to be aggregated */
6971 if( SCIPvarDoNotAggr(var) )
6972 {
6973 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
6974 return SCIP_OKAY;
6975 }
6976
6977 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
6978 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
6980
6981 SCIPrationalDebugMessage("aggregate variable <%s>[%q,%q] == %q*<%s>[%q,%q] +%q\n", var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub,
6982 scalar, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub, constant);
6983
6984 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
6985 if( var == aggvar )
6986 {
6987 if( SCIPrationalIsEQReal(scalar, 1.0) )
6988 *infeasible = !SCIPrationalIsZero(constant);
6989 else
6990 {
6991 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
6992 /* fix to constant/(1-scalar) */
6993 SCIPrationalDiffReal(tmpval, scalar, 1.0);
6994 SCIPrationalNegate(tmpval, tmpval);
6995 SCIPrationalDiv(tmpval, constant, tmpval);
6996 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6997 eventqueue, eventfilter, cliquetable, tmpval, infeasible, aggregated) );
6998
6999 SCIPrationalFreeBuffer(set->buffer, &tmpval);
7000 }
7001 return SCIP_OKAY;
7002 }
7003
7004 /* tighten the bounds of aggregated and aggregation variable */
7005 SCIP_CALL( varUpdateAggregationBoundsExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
7006 branchcand, eventqueue, eventfilter, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
7007 if( *infeasible || fixed )
7008 {
7009 *aggregated = fixed;
7010 return SCIP_OKAY;
7011 }
7012
7013 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
7014 * aggregated variable
7015 */
7016 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
7017 assert(var->cliquelist == NULL);
7018
7020 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
7021
7022 /* set the aggregated variable's objective value to 0.0 */
7023 SCIPrationalSetRational(obj, var->exactdata->obj);
7024 SCIPrationalSetReal(tmpval, 0.0);
7025 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lp->lpexact, eventqueue, tmpval) );
7026
7027 SCIPrationalFreeBuffer(set->buffer, &tmpval);
7028
7029 /* unlock all locks */
7030 for( i = 0; i < NLOCKTYPES; i++ )
7031 {
7032 nlocksdown[i] = var->nlocksdown[i];
7033 nlocksup[i] = var->nlocksup[i];
7034
7035 var->nlocksdown[i] = 0;
7036 var->nlocksup[i] = 0;
7037 }
7038
7039 /* check, if variable should be used as NEGATED variable of the aggregation variable */
7040 if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
7041 && var->negatedvar == NULL && aggvar->negatedvar == NULL
7042 && SCIPrationalIsEQReal(scalar, -1.0) && SCIPrationalIsEQReal(constant, 1.0) )
7043 {
7044 /* link both variables as negation pair */
7045 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
7046 var->exactdata->varstatusexact = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
7047 var->data.negate.constant = 1.0;
7048 var->negatedvar = aggvar;
7049 aggvar->negatedvar = var;
7050
7051 /* copy doNotMultiaggr status */
7052 aggvar->donotmultaggr |= var->donotmultaggr;
7053
7054 /* mark both variables to be non-deletable */
7057 }
7058 else
7059 {
7060 /* convert variable into aggregated variable */
7061 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
7062 var->exactdata->varstatusexact = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
7063 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->aggregate.scalar) );
7064 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->aggregate.constant) );
7065
7066 var->data.aggregate.var = aggvar;
7067 SCIPrationalSetRational(var->exactdata->aggregate.scalar, scalar);
7068 SCIPrationalSetRational(var->exactdata->aggregate.constant, constant);
7069 var->data.aggregate.scalar = SCIPrationalGetReal(scalar);
7070 var->data.aggregate.constant = SCIPrationalGetReal(constant);
7071
7072 /* copy doNotMultiaggr status */
7073 aggvar->donotmultaggr |= var->donotmultaggr;
7074
7075 /* mark both variables to be non-deletable */
7078 }
7079
7080 /* make aggregated variable a parent of the aggregation variable */
7081 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
7082
7083 /* relock the variable, thus increasing the locks of the aggregation variable */
7084 for( i = 0; i < NLOCKTYPES; i++ )
7085 {
7086 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
7087 }
7088
7089 /* move the variable bounds to the aggregation variable:
7090 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
7091 * - free the variable bounds data structures
7092 */
7093 assert(var->vlbs == NULL);
7094 assert(var->vubs == NULL);
7095
7096 /* move the implications to the aggregation variable:
7097 * - add all implications again to the variable, thus adding it to the aggregation variable
7098 * - free the implications data structures
7099 */
7100 assert(var->implics == NULL);
7101
7102 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
7103 SCIPhistoryUnite(aggvar->history, var->history, SCIPrationalIsNegative(scalar));
7104 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, SCIPrationalIsNegative(scalar));
7105 SCIPhistoryReset(var->history);
7106 SCIPhistoryReset(var->historycrun);
7107
7108 /* update flags of aggregation variable */
7109 aggvar->removable &= var->removable;
7110
7111 /* update branching factors and priorities of both variables to be the maximum of both variables */
7112 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
7113 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
7114 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
7115 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
7116 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
7117 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
7118
7119 /* update branching direction of both variables to agree to a single direction */
7120 if( !SCIPrationalIsNegative(scalar) )
7121 {
7122 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
7123 {
7125 }
7127 {
7128 SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
7129 }
7130 else if( var->branchdirection != aggvar->branchdirection )
7131 {
7133 }
7134 }
7135 else
7136 {
7137 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
7138 {
7140 }
7142 {
7144 }
7145 else if( var->branchdirection != aggvar->branchdirection )
7146 {
7148 }
7149 }
7150
7151 if( var->probindex != -1 )
7152 {
7153 /* inform problem about the variable's status change */
7154 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
7155 }
7156
7157 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
7158 * variable and the problem's objective offset
7159 */
7160 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
7161
7162 /* issue VARFIXED event */
7163 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
7164
7165 SCIPrationalFreeBuffer(set->buffer, &obj);
7166
7167 *aggregated = TRUE;
7168
7169 return SCIP_OKAY;
7170}
7171
7172/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
7173 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
7174 *
7175 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
7176 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7177 */
7178static
7180 SCIP_SET* set, /**< global SCIP settings */
7181 BMS_BLKMEM* blkmem, /**< block memory */
7182 SCIP_STAT* stat, /**< problem statistics */
7183 SCIP_PROB* transprob, /**< tranformed problem data */
7184 SCIP_PROB* origprob, /**< original problem data */
7185 SCIP_PRIMAL* primal, /**< primal data */
7186 SCIP_TREE* tree, /**< branch and bound tree */
7187 SCIP_REOPT* reopt, /**< reoptimization data structure */
7188 SCIP_LP* lp, /**< current LP data */
7189 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7190 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7191 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7192 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7193 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
7194 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
7195 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
7196 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
7197 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
7198 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7199 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7200 )
7201{
7202 SCIP_VAR* aggvar;
7203 char aggvarname[SCIP_MAXSTRLEN];
7204 SCIP_Longint scalarxn = 0;
7205 SCIP_Longint scalarxd = 0;
7206 SCIP_Longint scalaryn = 0;
7207 SCIP_Longint scalaryd = 0;
7211 SCIP_Longint scm;
7212 SCIP_Longint gcd;
7213 SCIP_Longint currentclass;
7214 SCIP_Longint classstep;
7215 SCIP_Longint xsol;
7216 SCIP_Longint ysol;
7217 SCIP_Bool success;
7218 SCIP_VARTYPE vartype;
7219 SCIP_IMPLINTTYPE impltypex;
7220 SCIP_IMPLINTTYPE impltypey;
7221 SCIP_IMPLINTTYPE impltype;
7222
7223#define MAXDNOM 1000000LL
7224
7225 assert(set != NULL);
7226 assert(blkmem != NULL);
7227 assert(stat != NULL);
7228 assert(transprob != NULL);
7229 assert(origprob != NULL);
7230 assert(tree != NULL);
7231 assert(lp != NULL);
7232 assert(cliquetable != NULL);
7233 assert(branchcand != NULL);
7234 assert(eventqueue != NULL);
7235 assert(varx != NULL);
7236 assert(vary != NULL);
7237 assert(varx != vary);
7238 assert(infeasible != NULL);
7239 assert(aggregated != NULL);
7245 assert(!SCIPsetIsZero(set, scalarx));
7246 assert(!SCIPsetIsZero(set, scalary));
7247
7248 *infeasible = FALSE;
7249 *aggregated = FALSE;
7250
7251 /* if the variable is not allowed to be aggregated */
7252 if( SCIPvarDoNotAggr(varx) )
7253 {
7254 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
7255 return SCIP_OKAY;
7256 }
7257
7258 /* get rational representation of coefficients */
7259 success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
7260 if( success )
7261 success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
7262 if( !success )
7263 return SCIP_OKAY;
7264 assert(scalarxd >= 1);
7265 assert(scalaryd >= 1);
7266
7267 /* multiply equality with smallest common denominator */
7268 scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
7269 a = (scm/scalarxd)*scalarxn;
7270 b = (scm/scalaryd)*scalaryn;
7271 rhs *= scm;
7272
7273 /* divide equality by the greatest common divisor of a and b */
7274 gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
7275 a /= gcd;
7276 b /= gcd;
7277 rhs /= gcd;
7278 assert(a != 0);
7279 assert(b != 0);
7280
7281 /* check, if right hand side is integral */
7282 if( !SCIPsetIsFeasIntegral(set, rhs) )
7283 {
7284 *infeasible = TRUE;
7285 return SCIP_OKAY;
7286 }
7288
7289 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
7290 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7291 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7292 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7293 {
7294 return SCIP_OKAY;
7295 }
7296
7297 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
7298 if( ( a == 1 || a == -1 ) && !SCIPvarIsImpliedIntegral(vary) )
7299 {
7300 /* aggregate x = - b/a*y + c/a */
7301 /*lint --e{653}*/
7302 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7303 branchcand, eventqueue, eventfilter, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
7304 assert(*aggregated);
7305 return SCIP_OKAY;
7306 }
7307 if( ( b == 1 || b == -1 ) && !SCIPvarIsImpliedIntegral(varx) )
7308 {
7309 /* aggregate y = - a/b*x + c/b */
7310 /*lint --e{653}*/
7311 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7312 branchcand, eventqueue, eventfilter, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
7313 assert(*aggregated);
7314 return SCIP_OKAY;
7315 }
7316
7317 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
7318 * common divisor. Let (x',y') be a solution of the equality
7319 * a*x + b*y == c -> a*x == c - b*y
7320 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
7321 */
7322
7323 /* find initial solution (x',y'):
7324 * - find y' such that c - b*y' is a multiple of a
7325 * - start in equivalence class c%a
7326 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
7327 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
7328 * - 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
7329 * - calculate x' with x' = (c - b*y')/a (which must be integral)
7330 *
7331 * Algorithm works for a > 0 only.
7332 */
7333 if( a < 0 )
7334 {
7335 a = -a;
7336 b = -b;
7337 c = -c;
7338 }
7339 assert(a > 0);
7340
7341 /* search upwards from ysol = 0 */
7342 ysol = 0;
7343 currentclass = c % a;
7344 if( currentclass < 0 )
7345 currentclass += a;
7346 assert(0 <= currentclass && currentclass < a);
7347
7348 classstep = (-b) % a;
7349
7350 if( classstep < 0 )
7351 classstep += a;
7352 assert(0 <= classstep && classstep < a);
7353
7354 while( currentclass != 0 )
7355 {
7356 assert(0 <= currentclass && currentclass < a);
7357 currentclass += classstep;
7358 if( currentclass >= a )
7359 currentclass -= a;
7360 ysol++;
7361 }
7362 assert(ysol < a);
7363 assert(((c - b*ysol) % a) == 0);
7364
7365 xsol = (c - b*ysol)/a;
7366
7367 /* determine variable type for new artificial variable:
7368 *
7369 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
7370 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
7371 * integral type
7372 */
7375 impltypex = SCIPvarGetImplType(varx);
7376 impltypey = SCIPvarGetImplType(vary);
7377 impltype = MIN(impltypex, impltypey);
7378
7379 /* feasible solutions are (x,y) = (x',y') + z * (-b,a)
7380 * - create new integer variable z with infinite bounds
7381 * - aggregate variable x = -b*z + x'
7382 * - aggregate variable y = a*z + y'
7383 * - the bounds of z are calculated automatically during aggregation
7384 */
7385 (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
7386 SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
7387 aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype, impltype,
7389 NULL, NULL, NULL, NULL, NULL) );
7390
7391 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventqueue, eventfilter, aggvar) );
7392
7393 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7394 branchcand, eventqueue, eventfilter, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
7395 assert(*aggregated || *infeasible);
7396
7397 if( !(*infeasible) )
7398 {
7399 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7400 branchcand, eventqueue, eventfilter, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
7401 assert(*aggregated || *infeasible);
7402 }
7403
7404 /* release z */
7405 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
7406
7407 return SCIP_OKAY; /*lint !e438*/
7408}
7409
7410/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
7411 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
7412 *
7413 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
7414 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7415 */
7416static
7418 SCIP_SET* set, /**< global SCIP settings */
7419 BMS_BLKMEM* blkmem, /**< block memory */
7420 SCIP_STAT* stat, /**< problem statistics */
7421 SCIP_PROB* transprob, /**< tranformed problem data */
7422 SCIP_PROB* origprob, /**< original problem data */
7423 SCIP_PRIMAL* primal, /**< primal data */
7424 SCIP_TREE* tree, /**< branch and bound tree */
7425 SCIP_REOPT* reopt, /**< reoptimization data structure */
7426 SCIP_LP* lp, /**< current LP data */
7427 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7428 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7429 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7430 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7431 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
7432 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
7433 SCIP_RATIONAL* scalarx, /**< multiplier a in equality a*x + b*y == c */
7434 SCIP_RATIONAL* scalary, /**< multiplier b in equality a*x + b*y == c */
7435 SCIP_RATIONAL* rhs, /**< right hand side c in equality a*x + b*y == c */
7436 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7437 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7438 )
7439{
7440 SCIP_VAR* aggvar;
7441 SCIP_RATIONAL* tmprat1;
7442 SCIP_RATIONAL* tmprat2;
7443 SCIP_RATIONAL* tmprat3;
7444 char aggvarname[SCIP_MAXSTRLEN];
7445 SCIP_Longint scalarxn;
7446 SCIP_Longint scalarxd;
7447 SCIP_Longint scalaryn;
7448 SCIP_Longint scalaryd;
7452 SCIP_Longint scm;
7453 SCIP_Longint gcd;
7454 SCIP_Longint currentclass;
7455 SCIP_Longint classstep;
7456 SCIP_Longint xsol;
7457 SCIP_Longint ysol;
7458 SCIP_VARTYPE vartype;
7459 SCIP_IMPLINTTYPE impltypex;
7460 SCIP_IMPLINTTYPE impltypey;
7461 SCIP_IMPLINTTYPE impltype;
7462
7463 assert(set != NULL);
7464 assert(blkmem != NULL);
7465 assert(stat != NULL);
7466 assert(transprob != NULL);
7467 assert(origprob != NULL);
7468 assert(tree != NULL);
7469 assert(lp != NULL);
7470 assert(cliquetable != NULL);
7471 assert(branchcand != NULL);
7472 assert(eventqueue != NULL);
7473 assert(varx != NULL);
7474 assert(vary != NULL);
7475 assert(varx != vary);
7476 assert(infeasible != NULL);
7477 assert(aggregated != NULL);
7483 assert(!SCIPrationalIsZero(scalarx));
7484 assert(!SCIPrationalIsZero(scalary));
7485
7486 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat1) );
7487 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat2) );
7488 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat3) );
7489
7490 *infeasible = FALSE;
7491 *aggregated = FALSE;
7492
7493 SCIPrationalCanonicalize(scalary);
7494 SCIPrationalCanonicalize(scalarx);
7495
7496 scalarxd = SCIPrationalDenominator(scalarx);
7497 scalaryd = SCIPrationalDenominator(scalary);
7498 scalarxn = SCIPrationalNumerator(scalarx);
7499 scalaryn = SCIPrationalNumerator(scalary);
7500
7501 /* multiply equality with smallest common denominator */
7502 scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
7503 a = (scm/scalarxd)*scalarxn;
7504 b = (scm/scalaryd)*scalaryn;
7505
7506 /* divide equality by the greatest common divisor of a and b */
7507 gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
7508 a /= gcd;
7509 b /= gcd;
7510 SCIPrationalSetFraction(tmprat1, scm, gcd);
7511 SCIPrationalMult(rhs, rhs, tmprat1);
7512 assert(a != 0);
7513 assert(b != 0);
7514
7515 /* check, if right hand side is integral */
7516 if( !SCIPrationalIsIntegral(rhs) )
7517 {
7518 *infeasible = TRUE;
7519 goto FREE;
7520 }
7521
7522 /* we know rhs is integral, so check if it is in integer range */
7524 {
7525 *infeasible = TRUE;
7526 goto FREE;
7527 }
7528
7529 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
7530 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7531 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7532 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7533 {
7534 goto FREE;
7535 }
7536
7537 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
7538 if( ( a == 1 || a == -1 ) && !SCIPvarIsImpliedIntegral(vary) )
7539 {
7540 /* aggregate x = - b/a*y + c/a */
7541 /*lint --e{653}*/
7542 SCIPrationalSetFraction(tmprat1, -b, a);
7543 SCIPrationalSetFraction(tmprat2, c, a);
7544 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7545 branchcand, eventqueue, eventfilter, vary, tmprat1, tmprat2, infeasible, aggregated) );
7546 assert(*aggregated);
7547 goto FREE;
7548 }
7549 if( ( b == 1 || b == -1 ) && !SCIPvarIsImpliedIntegral(varx) )
7550 {
7551 /* aggregate y = - a/b*x + c/b */
7552 /*lint --e{653}*/
7553 SCIPrationalSetFraction(tmprat1, -a, b);
7554 SCIPrationalSetFraction(tmprat2, c, b);
7555 SCIP_CALL( SCIPvarAggregateExact(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7556 branchcand, eventqueue, eventfilter, varx, tmprat1, tmprat2, infeasible, aggregated) );
7557 assert(*aggregated);
7558 goto FREE;
7559 }
7560
7561 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
7562 * common divisor. Let (x',y') be a solution of the equality
7563 * a*x + b*y == c -> a*x == c - b*y
7564 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
7565 */
7566
7567 /* find initial solution (x',y'):
7568 * - find y' such that c - b*y' is a multiple of a
7569 * - start in equivalence class c%a
7570 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
7571 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
7572 * - 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
7573 * - calculate x' with x' = (c - b*y')/a (which must be integral)
7574 *
7575 * Algorithm works for a > 0 only.
7576 */
7577 if( a < 0 )
7578 {
7579 a = -a;
7580 b = -b;
7581 c = -c;
7582 }
7583 assert(a > 0);
7584
7585 /* search upwards from ysol = 0 */
7586 ysol = 0;
7587 currentclass = c % a;
7588 if( currentclass < 0 )
7589 currentclass += a;
7590 assert(0 <= currentclass && currentclass < a);
7591
7592 classstep = (-b) % a;
7593
7594 if( classstep < 0 )
7595 classstep += a;
7596 assert(0 <= classstep && classstep < a);
7597
7598 while( currentclass != 0 )
7599 {
7600 assert(0 <= currentclass && currentclass < a);
7601 currentclass += classstep;
7602 if( currentclass >= a )
7603 currentclass -= a;
7604 ysol++;
7605 }
7606 assert(ysol < a);
7607 assert(((c - b*ysol) % a) == 0);
7608
7609 xsol = (c - b*ysol)/a;
7610
7611 /* determine variable type for new artificial variable:
7612 *
7613 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
7614 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
7615 * integral type
7616 */
7619 impltypex = SCIPvarGetImplType(varx);
7620 impltypey = SCIPvarGetImplType(vary);
7621 impltype = MIN(impltypex, impltypey);
7622
7623 /* feasible solutions are (x,y) = (x',y') + z * (-b,a)
7624 * - create new integer variable z with infinite bounds
7625 * - aggregate variable x = -b*z + x'
7626 * - aggregate variable y = a*z + y'
7627 * - the bounds of z are calculated automatically during aggregation
7628 */
7629 (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
7630 SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
7631 aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype, impltype,
7633 NULL, NULL, NULL, NULL, NULL) );
7634
7636 SCIPrationalSetInfinity(tmprat2);
7637 SCIPrationalSetFraction(tmprat3, 0LL, 0LL);
7638
7639 SCIP_CALL( SCIPvarAddExactData(aggvar, blkmem, tmprat1, tmprat2, tmprat3) );
7640
7641 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventqueue, eventfilter, aggvar) );
7642
7643 SCIPrationalSetFraction(tmprat1, -b, 1LL);
7644 SCIPrationalSetFraction(tmprat2, xsol, 1LL);
7645
7646 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7647 branchcand, eventqueue, eventfilter, aggvar, tmprat1, tmprat2, infeasible, aggregated) );
7648 assert(*aggregated || *infeasible);
7649
7650 if( !(*infeasible) )
7651 {
7652 SCIPrationalSetFraction(tmprat1, a, 1LL);
7653 SCIPrationalSetFraction(tmprat2, ysol, 1LL);
7654
7655 SCIP_CALL( SCIPvarAggregateExact(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7656 branchcand, eventqueue, eventfilter, aggvar, tmprat1, tmprat2, infeasible, aggregated) );
7657 assert(*aggregated || *infeasible);
7658 }
7659
7660 /* release z */
7661 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
7662
7663FREE:
7664 SCIPrationalFreeBuffer(set->buffer, &tmprat3);
7665 SCIPrationalFreeBuffer(set->buffer, &tmprat2);
7666 SCIPrationalFreeBuffer(set->buffer, &tmprat1);
7667
7668 return SCIP_OKAY; /*lint !e438*/
7669}
7670
7671/** performs second step of SCIPaggregateVars():
7672 * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
7673 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
7674 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
7675 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
7676 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
7677 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7678 *
7679 * @todo check for fixings, infeasibility, bound changes, or domain holes:
7680 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
7681 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
7682 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
7683 */
7685 SCIP_SET* set, /**< global SCIP settings */
7686 BMS_BLKMEM* blkmem, /**< block memory */
7687 SCIP_STAT* stat, /**< problem statistics */
7688 SCIP_PROB* transprob, /**< tranformed problem data */
7689 SCIP_PROB* origprob, /**< original problem data */
7690 SCIP_PRIMAL* primal, /**< primal data */
7691 SCIP_TREE* tree, /**< branch and bound tree */
7692 SCIP_REOPT* reopt, /**< reoptimization data structure */
7693 SCIP_LP* lp, /**< current LP data */
7694 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7695 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7696 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7697 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7698 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
7699 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
7700 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
7701 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
7702 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
7703 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7704 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7705 )
7706{
7707 SCIP_Real scalar;
7708 SCIP_Real constant;
7709 SCIP_Bool easyaggr;
7710 SCIP_VARTYPE typex;
7711 SCIP_VARTYPE typey;
7712
7713 assert(set != NULL);
7714 assert(blkmem != NULL);
7715 assert(stat != NULL);
7716 assert(transprob != NULL);
7717 assert(origprob != NULL);
7718 assert(tree != NULL);
7719 assert(lp != NULL);
7720 assert(cliquetable != NULL);
7721 assert(branchcand != NULL);
7722 assert(eventqueue != NULL);
7723 assert(varx != NULL);
7724 assert(vary != NULL);
7725 assert(varx != vary);
7726 assert(infeasible != NULL);
7727 assert(aggregated != NULL);
7731 assert(scalarx != 0.0); /*lint !e777*/
7732 assert(scalary != 0.0); /*lint !e777*/
7734
7735 *infeasible = FALSE;
7736 *aggregated = FALSE;
7737
7738 /**@todo simplify the following code once SCIP_DEPRECATED_VARTYPE_IMPLINT is removed */
7741
7742 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
7743 if( typex < typey ||
7744 ( typex == typey && SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
7745 {
7746 SCIP_VAR* var;
7747 SCIP_VARTYPE type;
7748
7749 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
7750 var = vary;
7751 vary = varx;
7752 varx = var;
7753 scalar = scalary;
7754 scalary = scalarx;
7755 scalarx = scalar;
7756 type = typey;
7757 typey = typex;
7758 typex = type;
7759 }
7760
7761 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
7762 if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
7763 return SCIP_OKAY;
7764
7765 assert(typex >= typey);
7766
7767 easyaggr = FALSE;
7768
7769 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
7770 scalar = -scalary / scalarx;
7771 constant = rhs / scalarx;
7772
7773 /* check if it is an easy aggregation */
7774 if( typex == SCIP_VARTYPE_CONTINUOUS )
7775 {
7776 easyaggr = TRUE;
7777 }
7778 else if( SCIPsetIsIntegral(set, scalar) )
7779 {
7780 if( SCIPsetIsFeasIntegral(set, constant) )
7781 constant = SCIPsetRound(set, constant);
7782 else
7783 {
7784 *infeasible = TRUE;
7785 return SCIP_OKAY;
7786 }
7787
7788 scalar = SCIPsetRound(set, scalar);
7789 easyaggr = TRUE;
7790 }
7791 else if( typex == typey && SCIPsetIsIntegral(set, scalarx / scalary) )
7792 {
7793 /* swap the variables, such that varx is the aggregated variable */
7794 SCIP_VAR* var;
7795
7796 constant = rhs / scalary;
7797
7798 if( SCIPsetIsFeasIntegral(set, constant) )
7799 constant = SCIPsetRound(set, constant);
7800 else
7801 {
7802 *infeasible = TRUE;
7803 return SCIP_OKAY;
7804 }
7805
7806 scalar = SCIPsetRound(set, -scalarx / scalary);
7807 var = varx;
7808 varx = vary;
7809 vary = var;
7810 easyaggr = TRUE;
7811 }
7812
7813 /* terminate if a bound on resolved aggregation scalar becomes too small or large so that numerical cancellation may be caused */
7814 if( !SCIPvarIsAggrCoefAcceptable(set, varx, scalar) )
7815 return SCIP_OKAY;
7816
7817 /* did we find an "easy" aggregation? */
7818 if( easyaggr )
7819 {
7820 assert(typex >= typey);
7821
7822 if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7823 return SCIP_OKAY;
7824
7825 /* if the aggregation scalar is fractional, we cannot aggregate integral variables,
7826 * since then we would loose the corresponding divisibility property
7827 */
7829
7830 /* aggregate the variable */
7831 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7832 branchcand, eventqueue, eventfilter, vary, scalar, constant, infeasible, aggregated) );
7833 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
7834 }
7835 else if( ( typex == SCIP_VARTYPE_INTEGER || typex == SCIP_DEPRECATED_VARTYPE_IMPLINT )
7836 && ( typey == SCIP_VARTYPE_INTEGER || typey == SCIP_DEPRECATED_VARTYPE_IMPLINT ) )
7837 {
7838 /* the variables are both integral: we have to try to find an integer aggregation */
7839 SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7840 branchcand, eventqueue, eventfilter, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
7841 }
7842
7843 return SCIP_OKAY;
7844}
7845
7846/** performs second step of SCIPaggregateVarsExact()
7847 *
7848 * The variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
7849 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
7850 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
7851 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
7852 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
7853 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7854 *
7855 * @todo check for fixings, infeasibility, bound changes, or domain holes:
7856 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
7857 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
7858 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
7859 */
7861 SCIP_SET* set, /**< global SCIP settings */
7862 BMS_BLKMEM* blkmem, /**< block memory */
7863 SCIP_STAT* stat, /**< problem statistics */
7864 SCIP_PROB* transprob, /**< tranformed problem data */
7865 SCIP_PROB* origprob, /**< original problem data */
7866 SCIP_PRIMAL* primal, /**< primal data */
7867 SCIP_TREE* tree, /**< branch and bound tree */
7868 SCIP_REOPT* reopt, /**< reoptimization data structure */
7869 SCIP_LP* lp, /**< current LP data */
7870 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7871 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7872 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7873 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7874 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
7875 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
7876 SCIP_RATIONAL* scalarx, /**< multiplier a in equality a*x + b*y == c */
7877 SCIP_RATIONAL* scalary, /**< multiplier b in equality a*x + b*y == c */
7878 SCIP_RATIONAL* rhs, /**< right hand side c in equality a*x + b*y == c */
7879 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7880 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7881 )
7882{
7883 SCIP_Bool easyaggr;
7884 SCIP_RATIONAL* quotxy;
7885 SCIP_RATIONAL* quotyx;
7886 SCIP_Real absquot;
7887 SCIP_Real maxscalar;
7888 SCIP_VARTYPE typex;
7889 SCIP_VARTYPE typey;
7890
7891 assert(set != NULL);
7892 assert(blkmem != NULL);
7893 assert(stat != NULL);
7894 assert(transprob != NULL);
7895 assert(origprob != NULL);
7896 assert(tree != NULL);
7897 assert(lp != NULL);
7898 assert(cliquetable != NULL);
7899 assert(branchcand != NULL);
7900 assert(eventqueue != NULL);
7901 assert(varx != NULL);
7902 assert(vary != NULL);
7903 assert(varx != vary);
7904 assert(infeasible != NULL);
7905 assert(aggregated != NULL);
7909 assert(!SCIPrationalIsZero(scalarx));
7910 assert(!SCIPrationalIsZero(scalary));
7911
7912 *infeasible = FALSE;
7913 *aggregated = FALSE;
7914
7915 absquot = REALABS(SCIPrationalGetReal(scalarx) / SCIPrationalGetReal(scalary));
7916 maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
7917 maxscalar = MAX(maxscalar, 1.0);
7918
7919 if( absquot > maxscalar || absquot < 1 / maxscalar )
7920 return SCIP_OKAY;
7921
7922 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &quotxy) );
7923 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &quotyx) );
7924
7925 SCIPrationalDiv(quotxy, scalarx, scalary);
7926 SCIPrationalInvert(quotyx, quotxy);
7927
7928 /**@todo simplify the following code once SCIP_DEPRECATED_VARTYPE_IMPLINT is removed */
7931
7932 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
7933 if( typex < typey ||
7934 ( typex == typey && SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
7935 {
7936 SCIP_VAR* var;
7937 SCIP_RATIONAL* scalar;
7938 SCIP_VARTYPE type;
7939
7940 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
7941 var = vary;
7942 vary = varx;
7943 varx = var;
7944 scalar = scalary;
7945 scalary = scalarx;
7946 scalarx = scalar;
7947 type = typey;
7948 typey = typex;
7949 typex = type;
7950 SCIPrationalInvert(quotyx, quotyx);
7951 SCIPrationalInvert(quotxy, quotxy);
7952 }
7953
7954 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
7955 if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
7956 return SCIP_OKAY;
7957
7958 assert(typex >= typey);
7959
7960 /* figure out, which variable should be aggregated */
7961 easyaggr = FALSE;
7962
7963 /* check if it is an easy aggregation that means:
7964 *
7965 * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
7966 */
7968 {
7969 if( typex == SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS )
7970 {
7971 easyaggr = TRUE;
7972 }
7973 else if( SCIPrationalIsIntegral(quotyx) )
7974 {
7975 easyaggr = TRUE;
7976 }
7977 else if( typex == typey && SCIPrationalIsIntegral(quotxy) )
7978 {
7979 /* we have an easy aggregation if we flip the variables x and y */
7980 SCIP_VAR* var;
7981 SCIP_RATIONAL* scalar;
7982
7983 /* switch the variables, such that varx is the aggregated variable */
7984 var = vary;
7985 vary = varx;
7986 varx = var;
7987 scalar = scalary;
7988 scalary = scalarx;
7989 scalarx = scalar;
7990 easyaggr = TRUE;
7991 SCIPrationalInvert(quotyx, quotyx);
7992 }
7993 else if( typex == SCIP_VARTYPE_CONTINUOUS )
7994 {
7995 /* the aggregation is still easy if both variables are continuous */
7996 assert(typey == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
7997 easyaggr = TRUE;
7998 }
7999 }
8000
8001 /* did we find an "easy" aggregation? */
8002 if( easyaggr )
8003 {
8004 SCIP_RATIONAL* constant;
8005
8006 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &constant) );
8007
8008 assert(typex >= typey);
8009
8010 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
8011 SCIPrationalNegate(quotyx, quotyx);
8012 SCIPrationalDiv(constant, rhs, scalarx);
8013
8014 if( REALABS(SCIPrationalGetReal(constant)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
8015 goto FREE;
8016
8017 /* check aggregation for integer feasibility */
8018 if( typex != SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS
8019 && SCIPrationalIsIntegral(quotyx) && !SCIPrationalIsIntegral(constant) )
8020 {
8021 *infeasible = TRUE;
8022 goto FREE;
8023 }
8024
8025 /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
8026 * since then we would loose the corresponding divisibility property
8027 */
8029
8030 /* aggregate the variable */
8031 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
8032 branchcand, eventqueue, eventfilter, vary, quotyx, constant, infeasible, aggregated) );
8033 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
8034FREE:
8035 SCIPrationalFreeBuffer(set->buffer, &constant);
8036 }
8037 else if( (typex == SCIP_VARTYPE_INTEGER || typex == SCIP_DEPRECATED_VARTYPE_IMPLINT)
8038 && (typey == SCIP_VARTYPE_INTEGER || typey == SCIP_DEPRECATED_VARTYPE_IMPLINT) )
8039 {
8040 /* the variables are both integral: we have to try to find an integer aggregation */
8041 SCIP_CALL( tryAggregateIntVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
8042 branchcand, eventqueue, eventfilter, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
8043 }
8044
8045 SCIPrationalFreeBuffer(set->buffer, &quotyx);
8046 SCIPrationalFreeBuffer(set->buffer, &quotxy);
8047
8048 return SCIP_OKAY;
8049}
8050
8051/** converts variable into multi-aggregated variable */
8053 SCIP_VAR* var, /**< problem variable */
8054 BMS_BLKMEM* blkmem, /**< block memory */
8055 SCIP_SET* set, /**< global SCIP settings */
8056 SCIP_STAT* stat, /**< problem statistics */
8057 SCIP_PROB* transprob, /**< tranformed problem data */
8058 SCIP_PROB* origprob, /**< original problem data */
8059 SCIP_PRIMAL* primal, /**< primal data */
8060 SCIP_TREE* tree, /**< branch and bound tree */
8061 SCIP_REOPT* reopt, /**< reoptimization data structure */
8062 SCIP_LP* lp, /**< current LP data */
8063 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8064 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8065 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8066 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
8067 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8068 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8069 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8070 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8071 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8072 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8073 )
8074{
8075 SCIP_VAR** tmpvars;
8076 SCIP_Real* tmpscalars;
8077 SCIP_Real obj;
8078 SCIP_Real branchfactor;
8079 int branchpriority;
8080 SCIP_BRANCHDIR branchdirection;
8081 int nlocksdown[NLOCKTYPES];
8082 int nlocksup[NLOCKTYPES];
8083 int v;
8084 SCIP_Real tmpconstant;
8085 SCIP_Real tmpscalar;
8086 int ntmpvars;
8087 int tmpvarssize;
8088 int tmprequiredsize;
8089 int i;
8090
8091 assert(var != NULL);
8092 assert(var->scip == set->scip);
8093 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
8094 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
8095 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
8096 assert(naggvars == 0 || aggvars != NULL);
8097 assert(naggvars == 0 || scalars != NULL);
8098 assert(infeasible != NULL);
8099 assert(aggregated != NULL);
8100
8101 SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
8102
8103 *infeasible = FALSE;
8104 *aggregated = FALSE;
8105
8106 switch( SCIPvarGetStatus(var) )
8107 {
8109 if( var->data.original.transvar == NULL )
8110 {
8111 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
8112 return SCIP_INVALIDDATA;
8113 }
8114 SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
8115 reopt, lp, cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8116 break;
8117
8119 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
8120
8121 /* check if we would create a self-reference */
8122 ntmpvars = naggvars;
8123 tmpvarssize = naggvars;
8124 tmpconstant = constant;
8125 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
8126 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
8127
8128 /* get all active variables for multi-aggregation */
8129 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) );
8130 if( tmprequiredsize > tmpvarssize )
8131 {
8132 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
8133 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
8134 tmpvarssize = tmprequiredsize;
8135 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) );
8136 assert( tmprequiredsize <= tmpvarssize );
8137 }
8138
8139 tmpscalar = 0.0;
8140
8141 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
8142 * possible multi-aggregated variable
8143 */
8144 for( v = ntmpvars - 1; v >= 0; --v )
8145 {
8146 assert(tmpvars[v] != NULL);
8148
8149 if( tmpvars[v]->index == var->index )
8150 {
8151 tmpscalar += tmpscalars[v];
8152 tmpvars[v] = tmpvars[ntmpvars - 1];
8153 tmpscalars[v] = tmpscalars[ntmpvars - 1];
8154 --ntmpvars;
8155 }
8156 }
8157
8158 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
8159 if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
8160 {
8161 if( ntmpvars == 0 )
8162 {
8163 if( SCIPsetIsFeasZero(set, tmpconstant) ) /* x = x */
8164 {
8165 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
8166 goto TERMINATE;
8167 }
8168 else /* 0 = c and c != 0 */
8169 {
8170 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
8171 *infeasible = TRUE;
8172 goto TERMINATE;
8173 }
8174 }
8175 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
8176 {
8177 assert(tmpscalars[0] != 0.0);
8178 assert(tmpvars[0] != NULL);
8179
8180 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
8181 SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
8182 branchcand, eventqueue, eventfilter, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
8183 goto TERMINATE;
8184 }
8185 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 */
8186 {
8187 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8188 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
8189 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
8190
8191 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
8192 cliquetable, branchcand, eventqueue, eventfilter, tmpvars[0], tmpvars[1], tmpscalars[0],
8193 tmpscalars[1], -tmpconstant, infeasible, aggregated) );
8194
8195 goto TERMINATE;
8196 }
8197 else
8198 /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
8199 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
8200 */
8201 goto TERMINATE;
8202 }
8203 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
8204 else if( tmpscalar != 0.0 ) /*lint !e777*/
8205 {
8206 tmpscalar = 1 - tmpscalar;
8207 tmpconstant /= tmpscalar;
8208 for( v = 0; v < ntmpvars; ++v )
8209 tmpscalars[v] /= tmpscalar;
8210 }
8211
8212 /* check, if we are in one of the simple cases */
8213 if( ntmpvars == 0 )
8214 {
8215 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
8216 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
8217 eventqueue, eventfilter, cliquetable, tmpconstant, infeasible, aggregated) );
8218 goto TERMINATE;
8219 }
8220
8221 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
8222 if( ntmpvars == 1 )
8223 {
8224 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
8225 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
8226
8227 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
8228 cliquetable, branchcand, eventqueue, eventfilter, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
8229 infeasible, aggregated) );
8230
8231 goto TERMINATE;
8232 }
8233
8234 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
8235 * empty hole list; this should be changed in the future */
8237 goto TERMINATE;
8238
8239 /* if the variable is not allowed to be multi-aggregated */
8241 {
8242 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
8243 goto TERMINATE;
8244 }
8245
8246 /* terminate if scalars may lead to numerical trouble */
8247 for( v = 0; v < ntmpvars; ++v )
8248 if( !SCIPvarIsAggrCoefAcceptable(set, var, tmpscalars[v]) )
8249 goto TERMINATE;
8250
8251 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
8252 * variable bound variable of another variable), we have to remove it from the other variables implications or
8253 * variable bounds
8254 */
8255 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
8256 assert(var->vlbs == NULL);
8257 assert(var->vubs == NULL);
8258 assert(var->implics == NULL);
8259
8260 /* set the aggregated variable's objective value to 0.0 */
8261 obj = var->obj;
8262 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
8263
8264 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
8265 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
8266 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
8267 * objective of this variable is set to zero
8268 */
8270
8271 /* unlock all rounding locks */
8272 for( i = 0; i < NLOCKTYPES; i++ )
8273 {
8274 nlocksdown[i] = var->nlocksdown[i];
8275 nlocksup[i] = var->nlocksup[i];
8276
8277 var->nlocksdown[i] = 0;
8278 var->nlocksup[i] = 0;
8279 }
8280
8281 /* update aggregation bounds */
8282 for( v = 0; v < ntmpvars; ++v )
8283 varUpdateMinMaxAggrCoef(tmpvars[v], var, tmpscalars[v]);
8284
8285 /* convert variable into multi-aggregated variable */
8286 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8287 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
8288 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
8289 var->data.multaggr.constant = tmpconstant;
8290 var->data.multaggr.nvars = ntmpvars;
8291 var->data.multaggr.varssize = ntmpvars;
8292
8293 /* mark variable to be non-deletable */
8295
8296 /* relock the variable, thus increasing the locks of the aggregation variables */
8297 for( i = 0; i < NLOCKTYPES; i++ )
8298 {
8299 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
8300 }
8301
8302 /* update flags and branching factors and priorities of aggregation variables;
8303 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
8304 */
8305 branchfactor = var->branchfactor;
8306 branchpriority = var->branchpriority;
8307 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
8308
8309 for( v = 0; v < ntmpvars; ++v )
8310 {
8311 assert(tmpvars[v] != NULL);
8312 tmpvars[v]->removable &= var->removable;
8313 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
8314 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
8315
8316 /* mark variable to be non-deletable */
8317 SCIPvarMarkNotDeletable(tmpvars[v]);
8318 }
8319 for( v = 0; v < ntmpvars; ++v )
8320 {
8321 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
8322 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
8323 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
8324 {
8325 if( tmpscalars[v] >= 0.0 )
8326 {
8327 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
8328 }
8329 else
8330 {
8331 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
8332 }
8333 }
8334 }
8335 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
8336 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8337
8338 if( var->probindex != -1 )
8339 {
8340 /* inform problem about the variable's status change */
8341 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
8342 }
8343
8344 /* issue VARFIXED event */
8345 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
8346
8347 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
8348 * variables and the problem's objective offset
8349 */
8350 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
8351
8352 *aggregated = TRUE;
8353
8354 TERMINATE:
8355 BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
8356 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
8357
8358 break;
8359
8361 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
8362 return SCIP_INVALIDDATA;
8363
8365 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
8366 return SCIP_INVALIDDATA;
8367
8369 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
8370 return SCIP_INVALIDDATA;
8371
8373 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
8374 return SCIP_INVALIDDATA;
8375
8377 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
8378 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
8379 */
8380 assert(SCIPsetIsZero(set, var->obj));
8381 assert(var->negatedvar != NULL);
8383 assert(var->negatedvar->negatedvar == var);
8384
8385 /* switch the signs of the aggregation scalars */
8386 for( v = 0; v < naggvars; ++v )
8387 scalars[v] *= -1.0;
8388
8389 /* perform the multi aggregation on the negation variable */
8390 SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
8391 cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars,
8392 var->data.negate.constant - constant, infeasible, aggregated) );
8393
8394 /* switch the signs of the aggregation scalars again, to reset them to their original values */
8395 for( v = 0; v < naggvars; ++v )
8396 scalars[v] *= -1.0;
8397 break;
8398
8399 default:
8400 SCIPerrorMessage("unknown variable status\n");
8401 return SCIP_INVALIDDATA;
8402 }
8403
8404 /* check multi-aggregation on debugging solution */
8405 if( *infeasible || *aggregated )
8406 SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
8407
8408 return SCIP_OKAY;
8409}
8410
8411/** converts variable into multi-aggregated variable */
8413 SCIP_VAR* var, /**< problem variable */
8414 BMS_BLKMEM* blkmem, /**< block memory */
8415 SCIP_SET* set, /**< global SCIP settings */
8416 SCIP_STAT* stat, /**< problem statistics */
8417 SCIP_PROB* transprob, /**< tranformed problem data */
8418 SCIP_PROB* origprob, /**< original problem data */
8419 SCIP_PRIMAL* primal, /**< primal data */
8420 SCIP_TREE* tree, /**< branch and bound tree */
8421 SCIP_REOPT* reopt, /**< reoptimization data structure */
8422 SCIP_LPEXACT* lpexact, /**< current LP data */
8423 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8424 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8425 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8426 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
8427 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8428 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8429 SCIP_RATIONAL** scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8430 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8431 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8432 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8433 )
8434{
8435 SCIP_VAR** tmpvars;
8436 SCIP_RATIONAL** tmpscalars;
8438 SCIP_RATIONAL* tmpconstant;
8439 SCIP_RATIONAL* tmpscalar;
8440 SCIP_RATIONAL* tmpval;
8441 SCIP_Real branchfactor;
8442 int branchpriority;
8443 SCIP_BRANCHDIR branchdirection;
8444 int nlocksdown[NLOCKTYPES];
8445 int nlocksup[NLOCKTYPES];
8446 int v;
8447 int ntmpvars;
8448 int tmpvarssize;
8449 int tmprequiredsize;
8450 int i;
8451
8452 assert(var != NULL);
8453 assert(var->scip == set->scip);
8454 assert(set->exact_enable);
8455 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb)); /*lint !e777*/
8456 assert(SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub)); /*lint !e777*/
8457 assert(naggvars == 0 || aggvars != NULL);
8458 assert(naggvars == 0 || scalars != NULL);
8459 assert(infeasible != NULL);
8460 assert(aggregated != NULL);
8461
8462 SCIPrationalDebugMessage("trying exact multi-aggregating variable <%s> == ...%d vars... %+q\n", var->name, naggvars, constant);
8463
8464 *infeasible = FALSE;
8465 *aggregated = FALSE;
8466
8467 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpconstant) );
8468 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpscalar) );
8470 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
8471
8472 switch( SCIPvarGetStatusExact(var) )
8473 {
8475 if( var->data.original.transvar == NULL )
8476 {
8477 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
8478 return SCIP_INVALIDDATA;
8479 }
8480 SCIP_CALL( SCIPvarMultiaggregateExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
8481 reopt, lpexact, cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8482 break;
8483
8485 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
8486
8487 /* check if we would create a self-reference */
8488 ntmpvars = naggvars;
8489 tmpvarssize = naggvars;
8490 SCIPrationalSetRational(tmpconstant, constant);
8491 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
8492 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &tmpscalars, scalars, ntmpvars) );
8493
8494 /* get all active variables for multi-aggregation */
8495 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, tmpconstant, &tmprequiredsize, FALSE) );
8496 if( tmprequiredsize > tmpvarssize )
8497 {
8498 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
8499 SCIP_CALL( SCIPrationalReallocBlockArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
8500 tmpvarssize = tmprequiredsize;
8501 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, tmpconstant, &tmprequiredsize, FALSE) );
8502 assert( tmprequiredsize <= tmpvarssize );
8503 }
8504
8505 SCIPrationalSetReal(tmpscalar, 0.0);
8506
8507 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
8508 * possible multi-aggregated variable
8509 */
8510 for( v = ntmpvars - 1; v >= 0; --v )
8511 {
8512 assert(tmpvars[v] != NULL);
8514
8515 if( tmpvars[v]->index == var->index )
8516 {
8517 SCIPrationalAdd(tmpscalar, tmpscalar, tmpscalars[v]);
8518 tmpvars[v] = tmpvars[ntmpvars - 1];
8519 SCIPrationalSetRational(tmpscalars[v], tmpscalars[ntmpvars - 1]);
8520 --ntmpvars;
8521 }
8522 }
8523
8524 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
8525 if( SCIPrationalIsEQReal(tmpscalar, 1.0) )
8526 {
8527 if( ntmpvars == 0 )
8528 {
8529 if( SCIPrationalIsZero(tmpconstant) ) /* x = x */
8530 {
8531 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
8532 goto TERMINATE;
8533 }
8534 else /* 0 = c and c != 0 */
8535 {
8536 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
8537 *infeasible = TRUE;
8538 goto TERMINATE;
8539 }
8540 }
8541 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
8542 {
8543 assert(!SCIPrationalIsZero(tmpscalars[0]));
8544 assert(tmpvars[0] != NULL);
8545
8546 SCIPrationalDiv(tmpval, constant, tmpscalars[0]);
8547 SCIPrationalNegate(tmpval, tmpval);
8548
8549 SCIPrationalDebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %q.\n", SCIPvarGetName(tmpvars[0]), tmpval);
8550 SCIP_CALL( SCIPvarFixExact(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8551 branchcand, eventqueue, eventfilter, cliquetable, tmpval, infeasible, aggregated) );
8552 goto TERMINATE;
8553 }
8554 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 */
8555 {
8556 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8557
8558 SCIPrationalNegate(tmpconstant, tmpconstant);
8559 SCIPrationalDebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %q and %q and constant %q.\n",
8560 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], tmpconstant);
8561
8562 SCIP_CALL( SCIPvarTryAggregateVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8563 cliquetable, branchcand, eventqueue, eventfilter, tmpvars[0], tmpvars[1], tmpscalars[0],
8564 tmpscalars[1], tmpconstant, infeasible, aggregated) );
8565
8566 goto TERMINATE;
8567 }
8568 else
8569 /** @todo: it is possible to multi-aggregate another variable, does it make sense?,
8570 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
8571 */
8572 goto TERMINATE;
8573 }
8574 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
8575 else if( !SCIPrationalIsZero(tmpscalar) )
8576 {
8577 SCIPrationalDiffReal(tmpscalar, tmpscalar, 1.0);
8578 SCIPrationalNegate(tmpscalar, tmpscalar);
8579 SCIPrationalDiv(tmpconstant, tmpconstant, tmpscalar);
8580 for( v = ntmpvars - 1; v >= 0; --v )
8581 SCIPrationalDiv(tmpscalars[v], tmpscalars[v], tmpscalar);
8582 }
8583
8584 /* check, if we are in one of the simple cases */
8585 if( ntmpvars == 0 )
8586 {
8587 SCIPrationalDebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %q.\n", SCIPvarGetName(var), tmpconstant);
8588 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp, branchcand,
8589 eventqueue, eventfilter, cliquetable, tmpconstant, infeasible, aggregated) );
8590 goto TERMINATE;
8591 }
8592
8593 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
8594 if( ntmpvars == 1 )
8595 {
8596 SCIPrationalNegate(tmpscalars[0], tmpscalars[0]);
8597 SCIPrationalSetReal(tmpval, 1.0);
8598 SCIPrationalDebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %f and %q and constant %q.\n",
8599 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, tmpscalars[0], tmpconstant);
8600
8601 SCIP_CALL( SCIPvarTryAggregateVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8602 cliquetable, branchcand, eventqueue, eventfilter, var, tmpvars[0], tmpval, tmpscalars[0], tmpconstant,
8603 infeasible, aggregated) );
8604
8605 goto TERMINATE;
8606 }
8607
8608 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
8609 * empty hole list; this should be changed in the future */
8611 goto TERMINATE;
8612
8613 /* if the variable is not allowed to be multi-aggregated */
8615 {
8616 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
8617 goto TERMINATE;
8618 }
8619
8620 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
8621 * variable bound variable of another variable), we have to remove it from the other variables implications or
8622 * variable bounds
8623 */
8624 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
8625 assert(var->vlbs == NULL);
8626 assert(var->vubs == NULL);
8627 assert(var->implics == NULL);
8628 assert(var->cliquelist == NULL);
8629
8630 /* set the aggregated variable's objective value to 0.0 */
8631 SCIPrationalSetRational(obj, var->exactdata->obj);
8632 SCIPrationalSetReal(tmpval, 0.0);
8633 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lpexact, eventqueue, tmpval) );
8634
8635 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
8636 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
8637 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
8638 * objective of this variable is set to zero
8639 */
8640 SCIPlpDecNLoosevars(lpexact->fplp);
8641 SCIPlpExactDecNLoosevars(lpexact);
8642
8643 /* unlock all rounding locks */
8644 for( i = 0; i < NLOCKTYPES; i++ )
8645 {
8646 nlocksdown[i] = var->nlocksdown[i];
8647 nlocksup[i] = var->nlocksup[i];
8648
8649 var->nlocksdown[i] = 0;
8650 var->nlocksup[i] = 0;
8651 }
8652
8653 /* convert variable into multi-aggregated variable */
8654 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8655 var->exactdata->varstatusexact = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8656 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
8657 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &(var->exactdata->multaggr.scalars), tmpscalars, ntmpvars) );
8658 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &var->data.multaggr.scalars, ntmpvars) );
8659 for( i = 0; i < ntmpvars; ++i )
8660 var->data.multaggr.scalars[i] = SCIPrationalGetReal(tmpscalars[i]);
8661 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &(var->exactdata->multaggr.constant), tmpconstant) );
8662 var->data.multaggr.constant = SCIPrationalGetReal(tmpconstant);
8663 var->data.multaggr.nvars = ntmpvars;
8664 var->data.multaggr.varssize = ntmpvars;
8665
8666 /* mark variable to be non-deletable */
8668
8669 /* relock the variable, thus increasing the locks of the aggregation variables */
8670 for( i = 0; i < NLOCKTYPES; i++ )
8671 {
8672 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
8673 }
8674
8675 /* update flags and branching factors and priorities of aggregation variables;
8676 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
8677 */
8678 branchfactor = var->branchfactor;
8679 branchpriority = var->branchpriority;
8680 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
8681
8682 for( v = 0; v < ntmpvars; ++v )
8683 {
8684 assert(tmpvars[v] != NULL);
8685 tmpvars[v]->removable &= var->removable;
8686 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
8687 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
8688
8689 /* mark variable to be non-deletable */
8690 SCIPvarMarkNotDeletable(tmpvars[v]);
8691 }
8692 for( v = 0; v < ntmpvars; ++v )
8693 {
8694 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
8695 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
8696 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
8697 {
8698 if( !SCIPrationalIsNegative(tmpscalars[v]) )
8699 {
8700 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
8701 }
8702 else
8703 {
8704 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
8705 }
8706 }
8707 }
8708 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
8709 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8710
8711 if( var->probindex != -1 )
8712 {
8713 /* inform problem about the variable's status change */
8714 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
8715 }
8716
8717 /* issue VARFIXED event */
8718 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
8719
8720 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
8721 * variables and the problem's objective offset
8722 */
8723 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp, eventqueue, eventfilter, obj) );
8724
8725 *aggregated = TRUE;
8726
8727 TERMINATE:
8728 SCIPrationalFreeBlockArray(blkmem, &tmpscalars, tmpvarssize);
8729 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
8730 break;
8731
8733 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
8734 return SCIP_INVALIDDATA;
8735
8737 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
8738 return SCIP_INVALIDDATA;
8739
8741 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
8742 return SCIP_INVALIDDATA;
8743
8745 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
8746 return SCIP_INVALIDDATA;
8747
8749 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
8750 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
8751 */
8752 assert(SCIPrationalIsZero(var->exactdata->obj));
8753 assert(var->negatedvar != NULL);
8755 assert(var->negatedvar->negatedvar == var);
8756
8757 /* switch the signs of the aggregation scalars */
8758 for( v = 0; v < naggvars; ++v )
8760
8761 SCIPrationalDiffReal(tmpval, constant, var->data.negate.constant);
8762 SCIPrationalNegate(tmpval, tmpval);
8763 /* perform the multi aggregation on the negation variable */
8764 SCIP_CALL( SCIPvarMultiaggregateExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact,
8765 cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars,
8766 tmpval, infeasible, aggregated) );
8767
8768 /* switch the signs of the aggregation scalars again, to reset them to their original values */
8769 for( v = 0; v < naggvars; ++v )
8771
8772 break;
8773
8774 default:
8775 SCIPerrorMessage("unknown variable status\n");
8776 return SCIP_INVALIDDATA;
8777 }
8778
8779 SCIPrationalFreeBuffer(set->buffer, &tmpval);
8780 SCIPrationalFreeBuffer(set->buffer, &obj);
8781 SCIPrationalFreeBuffer(set->buffer, &tmpscalar);
8782 SCIPrationalFreeBuffer(set->buffer, &tmpconstant);
8783
8784 return SCIP_OKAY;
8785}
8786
8787/** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
8788 * or for original variables the same variable is returned
8789 */
8790static
8792 SCIP_VAR* var /**< problem variable */
8793 )
8794{
8795 SCIP_VAR* retvar;
8796
8797 assert(var != NULL);
8798
8799 retvar = var;
8800
8801 SCIPdebugMessage("get active variable of <%s>\n", var->name);
8802
8803 while( TRUE ) /*lint !e716 */
8804 {
8805 assert(retvar != NULL);
8806
8807 switch( SCIPvarGetStatus(retvar) )
8808 {
8813 return retvar;
8814
8816 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
8817 if ( retvar->data.multaggr.nvars == 1 )
8818 retvar = retvar->data.multaggr.vars[0];
8819 else
8820 return retvar;
8821 break;
8822
8824 retvar = retvar->data.aggregate.var;
8825 break;
8826
8828 retvar = retvar->negatedvar;
8829 break;
8830
8831 default:
8832 SCIPerrorMessage("unknown variable status\n");
8833 SCIPABORT();
8834 return NULL; /*lint !e527*/
8835 }
8836 }
8837}
8838
8839/** returns whether variable is not allowed to be aggregated */
8841 SCIP_VAR* var /**< problem variable */
8842 )
8843{
8844 SCIP_VAR* retvar;
8845
8846 assert(var != NULL);
8847
8848 retvar = varGetActiveVar(var);
8849 assert(retvar != NULL);
8850
8851 switch( SCIPvarGetStatus(retvar) )
8852 {
8857 return retvar->donotaggr;
8858
8860 return FALSE;
8861
8864 default:
8865 /* aggregated and negated variables should be resolved by varGetActiveVar() */
8866 SCIPerrorMessage("wrong variable status\n");
8867 SCIPABORT();
8868 return FALSE; /*lint !e527 */
8869 }
8870}
8871
8872/** returns whether variable is not allowed to be multi-aggregated */
8874 SCIP_VAR* var /**< problem variable */
8875 )
8876{
8877 SCIP_VAR* retvar;
8878
8879 assert(var != NULL);
8880
8881 retvar = varGetActiveVar(var);
8882 assert(retvar != NULL);
8883
8884 switch( SCIPvarGetStatus(retvar) )
8885 {
8890 return retvar->donotmultaggr;
8891
8893 return FALSE;
8894
8897 default:
8898 /* aggregated and negated variables should be resolved by varGetActiveVar() */
8899 SCIPerrorMessage("wrong variable status\n");
8900 SCIPABORT();
8901 return FALSE; /*lint !e527 */
8902 }
8903}
8904
8905/** checks whether a loose variable can be used in a new aggregation with given coefficient */
8907 SCIP_SET* set, /**< global SCIP settings */
8908 SCIP_VAR* var, /**< problem variable */
8909 SCIP_Real scalar /**< aggregation scalar */
8910 )
8911{
8912 assert(set != NULL);
8913 assert(var != NULL);
8914 assert(scalar != 0.0); /*lint !e777*/
8918
8920 return FALSE;
8921
8922 if( SCIPsetIsSumZero(set, 1.0 / (SCIPvarGetMaxAggrCoef(var) * scalar)) )
8923 return FALSE;
8924
8925 return TRUE;
8926}
8927
8928/** adds correct bound-data to negated variable */
8929static
8931 SCIP_VAR* negvar, /**< the negated variable */
8932 SCIP_VAR* origvar, /**< the original variable */
8933 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
8934 )
8935{
8936 SCIP_Real constant;
8937
8938 if( origvar->exactdata == NULL )
8939 return SCIP_OKAY;
8940
8941 assert(negvar != NULL);
8942 assert(origvar != NULL);
8943 assert(origvar->exactdata != NULL);
8944 assert(negvar->exactdata == NULL);
8945
8946 constant = negvar->data.negate.constant;
8947
8948 SCIP_CALL( SCIPvarCopyExactData(blkmem, negvar, origvar, FALSE) );
8949
8950 SCIPrationalDiffReal(negvar->exactdata->glbdom.ub, origvar->exactdata->glbdom.lb, constant);
8952
8953 SCIPrationalDiffReal(negvar->exactdata->glbdom.lb, origvar->exactdata->glbdom.ub, constant);
8955
8956 SCIPrationalDiffReal(negvar->exactdata->locdom.ub, origvar->exactdata->locdom.lb, constant);
8958
8959 SCIPrationalDiffReal(negvar->exactdata->locdom.lb, origvar->exactdata->locdom.ub, constant);
8961
8963
8968
8969 return SCIP_OKAY;
8970}
8971
8972/** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
8973 * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
8974 * negated variable is created
8975 */
8977 SCIP_VAR* var, /**< problem variable to negate */
8978 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
8979 SCIP_SET* set, /**< global SCIP settings */
8980 SCIP_STAT* stat, /**< problem statistics */
8981 SCIP_VAR** negvar /**< pointer to store the negated variable */
8982 )
8983{
8984 assert(var != NULL);
8985 assert(var->scip == set->scip);
8986 assert(negvar != NULL);
8987
8988 /* check, if we already created the negated variable */
8989 if( var->negatedvar == NULL )
8990 {
8991 char negvarname[SCIP_MAXSTRLEN];
8992
8994
8995 SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
8996
8997 /* negation is only possible for bounded variables */
8998 if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
8999 {
9000 SCIPerrorMessage("cannot negate unbounded variable\n");
9001 return SCIP_INVALIDDATA;
9002 }
9003
9004 (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
9005
9006 /* create negated variable */
9007 SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
9008 SCIPvarGetType(var), SCIPvarGetImplType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
9009 (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
9010 if( SCIPvarIsBinary(var) )
9011 (*negvar)->data.negate.constant = 1.0;
9012 else
9013 (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
9014
9015 /* create event filter for transformed variable */
9017 {
9018 SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
9019 }
9020
9021 /* set the bounds corresponding to the negation variable */
9022 (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
9023 (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
9024 (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
9025 (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
9026
9027 SCIP_CALL( varNegateExactData(*negvar, var, blkmem) );
9028 /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
9029
9030 /* link the variables together */
9031 var->negatedvar = *negvar;
9032 (*negvar)->negatedvar = var;
9033
9034 /* mark both variables to be non-deletable */
9036 SCIPvarMarkNotDeletable(*negvar);
9037
9038 /* copy the branch factor and priority, and use the negative preferred branching direction */
9039 (*negvar)->branchfactor = var->branchfactor;
9040 (*negvar)->branchpriority = var->branchpriority;
9041 (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
9042
9043 /* copy donot(mult)aggr status */
9044 (*negvar)->donotaggr = var->donotaggr;
9045 (*negvar)->donotmultaggr = var->donotmultaggr;
9046
9047 /* copy lazy bounds (they have to be flipped) */
9048 (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
9049 (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
9050
9051 /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
9052 SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
9053 assert((*negvar)->nuses == 1);
9054 }
9055 assert(var->negatedvar != NULL);
9056
9057 /* return the negated variable */
9058 *negvar = var->negatedvar;
9059
9060 /* exactly one variable of the negation pair has to be marked as negated variable */
9062
9063 return SCIP_OKAY;
9064}
9065
9066/** informs variable that its position in problem's vars array changed */
9067static
9069 SCIP_VAR* var, /**< problem variable */
9070 int probindex /**< new problem index of variable (-1 for removal) */
9071 )
9072{
9073 assert(var != NULL);
9074
9075 var->probindex = probindex;
9077 {
9078 assert(var->data.col != NULL);
9079 var->data.col->var_probindex = probindex;
9080 }
9081}
9082
9083/** informs variable that its position in problem's vars array changed */
9085 SCIP_VAR* var, /**< problem variable */
9086 int probindex /**< new problem index of variable */
9087 )
9088{
9089 assert(var != NULL);
9090 assert(probindex >= 0);
9091
9092 varSetProbindex(var, probindex);
9093}
9094
9095/** gives the variable a new name
9096 *
9097 * @note the old pointer is overwritten, which might result in a memory leakage
9098 */
9100 SCIP_VAR* var, /**< problem variable */
9101 const char* name /**< new name of variable */
9102 )
9103{
9104 assert(var != NULL);
9105 assert(name != NULL);
9106
9107 var->name = (char*)name;
9108}
9109
9110/** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
9111 * implication graph;
9112 * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
9113 * variable bounds and implication data structures of the variable are freed. Since in the final removal
9114 * of all variables from the transformed problem, this deletes the implication graph completely and is faster
9115 * than removing the variables one by one, each time updating all lists of the other variables.
9116 * If 'keepimplics' is TRUE, the implications, variable bounds and cliques are kept. This should be used when the
9117 * variable type is upgraded, i.e. when it gains (implied) integrality, so that existing implications are not lost.
9118 */
9120 SCIP_VAR* var, /**< problem variable */
9121 BMS_BLKMEM* blkmem, /**< block memory buffer */
9122 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9123 SCIP_SET* set, /**< global SCIP settings */
9124 SCIP_Bool final, /**< is this the final removal of all problem variables? */
9125 SCIP_Bool keepimplics /**< should the implications be kept? */
9126 )
9127{
9129 assert(var->scip == set->scip);
9130
9131 /* if the variable is active in the transformed problem, remove it from the implication graph */
9134 {
9135 if( final )
9136 {
9137 /* just destroy the data structures */
9138 SCIPvboundsFree(&var->vlbs, blkmem);
9139 SCIPvboundsFree(&var->vubs, blkmem);
9140 SCIPimplicsFree(&var->implics, blkmem);
9141 }
9142 else if( !keepimplics )
9143 {
9144 /* unlink the variable from all other variables' lists and free the data structures */
9145 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
9146 }
9147 }
9148
9149 /* mark the variable to be no longer a member of the problem */
9150 varSetProbindex(var, -1);
9151
9152 return SCIP_OKAY;
9153}
9154
9155/** marks the variable to be deleted from the problem */
9157 SCIP_VAR* var /**< problem variable */
9158 )
9159{
9160 assert(var != NULL);
9161 assert(var->probindex != -1);
9162
9163 var->deleted = TRUE;
9164}
9165
9166/** marks the variable to not to be aggregated */
9168 SCIP_VAR* var /**< problem variable */
9169 )
9170{
9171 SCIP_VAR* retvar;
9172
9173 assert(var != NULL);
9174
9175 retvar = varGetActiveVar(var);
9176 assert(retvar != NULL);
9177
9178 switch( SCIPvarGetStatus(retvar) )
9179 {
9184 retvar->donotaggr = TRUE;
9185 break;
9186
9188 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
9189 return SCIP_INVALIDDATA;
9190
9193 default:
9194 /* aggregated and negated variables should be resolved by varGetActiveVar() */
9195 SCIPerrorMessage("wrong variable status\n");
9196 return SCIP_INVALIDDATA;
9197 }
9198
9199 return SCIP_OKAY;
9200}
9201
9202/** marks the variable to not to be multi-aggregated */
9204 SCIP_VAR* var /**< problem variable */
9205 )
9206{
9207 SCIP_VAR* retvar;
9208
9209 assert(var != NULL);
9210
9211 retvar = varGetActiveVar(var);
9212 assert(retvar != NULL);
9213
9214 switch( SCIPvarGetStatus(retvar) )
9215 {
9220 retvar->donotmultaggr = TRUE;
9221 break;
9222
9224 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
9225 return SCIP_INVALIDDATA;
9226
9229 default:
9230 /* aggregated and negated variables should be resolved by varGetActiveVar() */
9231 SCIPerrorMessage("wrong variable status\n");
9232 return SCIP_INVALIDDATA;
9233 }
9234
9235 return SCIP_OKAY;
9236}
9237
9238/** changes type of variable; cannot be called, if var belongs to a problem */
9240 SCIP_VAR* var, /**< variable to change */
9241 BMS_BLKMEM* blkmem, /**< block memory */
9242 SCIP_SET* set, /**< global SCIP settings */
9243 SCIP_PRIMAL* primal, /**< primal data */
9244 SCIP_LP* lp, /**< current LP data */
9245 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9246 SCIP_VARTYPE vartype /**< new type of variable */
9247 )
9248{
9249 SCIP_EVENT* event;
9250 SCIP_VARTYPE oldtype;
9251
9252 assert(var != NULL);
9253
9254 SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
9255
9256 if( var->probindex >= 0 )
9257 {
9258 SCIPerrorMessage("cannot change type of variable already in the problem\n");
9259 return SCIP_INVALIDDATA;
9260 }
9261
9262 if( vartype == SCIP_DEPRECATED_VARTYPE_IMPLINT )
9263 {
9265 {
9266 SCIP_CALL( SCIPvarChgImplType(var, blkmem, set, primal, lp, eventqueue, SCIP_IMPLINTTYPE_WEAK) );
9267 }
9268 return SCIP_OKAY;
9269 }
9270
9271 oldtype = (SCIP_VARTYPE)var->vartype;
9272 var->vartype = vartype; /*lint !e641*/
9273
9275 {
9276 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
9277 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9278 }
9279
9280 if( var->negatedvar != NULL )
9281 {
9282 assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
9283 || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
9284
9285 var->negatedvar->vartype = vartype; /*lint !e641*/
9286
9288 {
9289 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
9290 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9291 }
9292 }
9293
9294 return SCIP_OKAY;
9295}
9296
9297/** changes implied integral type of variable; cannot be called, if var belongs to a problem */
9299 SCIP_VAR* var, /**< variable to change */
9300 BMS_BLKMEM* blkmem, /**< block memory */
9301 SCIP_SET* set, /**< global SCIP settings */
9302 SCIP_PRIMAL* primal, /**< primal data */
9303 SCIP_LP* lp, /**< current LP data */
9304 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9305 SCIP_IMPLINTTYPE impltype /**< new implied integral type of variable */
9306 )
9307{
9308 SCIP_EVENT* event;
9309 SCIP_IMPLINTTYPE oldtype;
9310
9311 assert(var != NULL);
9312
9313 SCIPdebugMessage("change implied integral type of <%s> from %d to %d\n", var->name, SCIPvarGetImplType(var), impltype);
9314
9315 if( var->probindex >= 0 )
9316 {
9317 SCIPerrorMessage("cannot change type of variable already in the problem\n");
9318 return SCIP_INVALIDDATA;
9319 }
9320
9321 oldtype = (SCIP_IMPLINTTYPE) var->varimpltype;
9322 var->varimpltype = impltype; /*lint !e641*/
9323
9325 {
9326 SCIP_CALL( SCIPeventCreateImplTypeChanged(&event, blkmem, var, oldtype, impltype) );
9327 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9328 }
9329
9330 if( var->negatedvar != NULL )
9331 {
9332 var->negatedvar->varimpltype = impltype; /*lint !e641*/
9333
9335 {
9336 SCIP_CALL( SCIPeventCreateImplTypeChanged(&event, blkmem, var->negatedvar, oldtype, impltype) );
9337 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9338 }
9339 }
9340
9341 return SCIP_OKAY;
9342}
9343
9344/** appends OBJCHANGED event to the event queue */
9345static
9347 SCIP_VAR* var, /**< problem variable to change */
9348 BMS_BLKMEM* blkmem, /**< block memory */
9349 SCIP_SET* set, /**< global SCIP settings */
9350 SCIP_PRIMAL* primal, /**< primal data */
9351 SCIP_LP* lp, /**< current LP data */
9352 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9353 SCIP_Real oldobj, /**< old objective value for variable */
9354 SCIP_Real newobj /**< new objective value for variable */
9355 )
9356{
9357 SCIP_EVENT* event;
9358
9359 assert(var != NULL);
9360 assert(var->scip == set->scip);
9361 assert(var->eventfilter != NULL);
9364
9365 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
9366 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
9367 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
9368 * that make comparison with values close to epsilon inaccurate.
9369 */
9372 (set->exact_enable && oldobj != newobj)); /*lint !e777*/
9373
9374 SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
9375 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9376
9377 return SCIP_OKAY;
9378}
9379
9380/** appends OBJCHANGED event to the event queue */
9381static
9383 SCIP_VAR* var, /**< problem variable to change */
9384 BMS_BLKMEM* blkmem, /**< block memory */
9385 SCIP_SET* set, /**< global SCIP settings */
9386 SCIP_PRIMAL* primal, /**< primal data */
9387 SCIP_LP* lp, /**< current LP data */
9388 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9389 SCIP_RATIONAL* oldobj, /**< old objective value for variable */
9390 SCIP_RATIONAL* newobj /**< new objective value for variable */
9391 )
9392{
9393 SCIP_EVENT* event;
9394
9395 assert(var != NULL);
9396 assert(var->scip == set->scip);
9397 assert(var->eventfilter != NULL);
9400
9401 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
9402 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
9403 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
9404 * that make comparison with values close to epsilon inaccurate.
9405 */
9407
9409 SCIP_CALL( SCIPeventAddExactObjChg(event, blkmem, oldobj, newobj) );
9410 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9411
9412 return SCIP_OKAY;
9413}
9414
9415/** changes objective value of variable */
9417 SCIP_VAR* var, /**< variable to change */
9418 BMS_BLKMEM* blkmem, /**< block memory */
9419 SCIP_SET* set, /**< global SCIP settings */
9420 SCIP_PROB* prob, /**< problem data */
9421 SCIP_PRIMAL* primal, /**< primal data */
9422 SCIP_LP* lp, /**< current LP data */
9423 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9424 SCIP_Real newobj /**< new objective value for variable */
9425 )
9426{
9428
9429 assert(var != NULL);
9430 assert(set != NULL);
9431 assert(var->scip == set->scip);
9432
9433 SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
9434
9435 if( !SCIPsetIsEQ(set, var->obj, newobj) )
9436 {
9437 switch( SCIPvarGetStatus(var) )
9438 {
9440 if( var->data.original.transvar != NULL )
9441 {
9443
9444 SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
9445 (SCIP_Real) prob->objsense * newobj/prob->objscale) );
9446 }
9447 else
9448 assert(set->stage == SCIP_STAGE_PROBLEM);
9449
9450 var->obj = newobj;
9451 var->unchangedobj = newobj;
9452
9453 break;
9454
9457 oldobj = var->obj;
9458 var->obj = newobj;
9459
9460 /* update unchanged objective value of variable */
9461 if( !lp->divingobjchg )
9462 var->unchangedobj = newobj;
9463
9464 /* update the number of variables with non-zero objective coefficient;
9465 * we only want to do the update, if the variable is added to the problem;
9466 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9467 */
9468 if( SCIPvarIsActive(var) )
9469 SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
9470
9471 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
9472 break;
9473
9478 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
9479 return SCIP_INVALIDDATA;
9480
9481 default:
9482 SCIPerrorMessage("unknown variable status\n");
9483 return SCIP_INVALIDDATA;
9484 }
9485 }
9486
9487 return SCIP_OKAY;
9488}
9489
9490/** changes rational objective value of variable */
9492 SCIP_VAR* var, /**< variable to change */
9493 BMS_BLKMEM* blkmem, /**< block memory */
9494 SCIP_SET* set, /**< global SCIP settings */
9495 SCIP_PROB* prob, /**< problem data */
9496 SCIP_PRIMAL* primal, /**< primal data */
9497 SCIP_LPEXACT* lp, /**< current LP data */
9498 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9499 SCIP_RATIONAL* newobj /**< new objective value for variable */
9500 )
9501{
9502 SCIP_Real newobjreal;
9504 SCIP_RATIONAL* tmp;
9505
9506 assert(var != NULL);
9507 assert(set != NULL);
9508
9509 if( !set->exact_enable )
9510 return SCIP_OKAY;
9511
9512 assert(var->exactdata != NULL);
9513 assert(var->scip == set->scip);
9514
9515 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
9517 newobjreal = SCIPrationalGetReal(newobj);
9518
9519 SCIPrationalDebugMessage("changing exact objective value of <%s> from %q to %q\n", var->name, var->exactdata->obj, newobj);
9520
9521 if( !SCIPrationalIsEQ(var->exactdata->obj, newobj) )
9522 {
9523 switch( SCIPvarGetStatusExact(var) )
9524 {
9526 if( var->data.original.transvar != NULL )
9527 {
9529
9531
9532 SCIP_CALL( SCIPvarChgObjExact(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue, tmp) );
9533 }
9534 else
9535 assert(set->stage == SCIP_STAGE_PROBLEM);
9536
9537 SCIPrationalSetRational(var->exactdata->obj, newobj);
9538 SCIPintervalSetRational(&(var->exactdata->objinterval), newobj);
9539 var->obj = newobjreal;
9540 var->unchangedobj = newobjreal;
9541 break;
9542
9545 SCIPrationalSetRational(oldobj, var->exactdata->obj);
9546 SCIPrationalSetRational(var->exactdata->obj, newobj);
9547 SCIPintervalSetRational(&(var->exactdata->objinterval), newobj);
9548 var->obj = newobjreal;
9549
9550 /* update unchanged objective value of variable */
9551 if( !lp->fplp->divingobjchg )
9552 var->unchangedobj = newobjreal;
9553
9554 /* update the number of variables with non-zero objective coefficient;
9555 * we only want to do the update, if the variable is added to the problem;
9556 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9557 */
9558 if( SCIPvarIsActive(var) )
9560
9561 SCIP_CALL( varEventObjChangedExact(var, blkmem, set, primal, lp->fplp, eventqueue, oldobj, var->exactdata->obj) );
9562
9563 break;
9564
9569 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
9570 return SCIP_INVALIDDATA;
9571
9572 default:
9573 SCIPerrorMessage("unknown variable status\n");
9574 return SCIP_INVALIDDATA;
9575 }
9576 }
9577
9579 SCIPrationalFreeBuffer(set->buffer, &tmp);
9580
9581 return SCIP_OKAY;
9582}
9583
9584/** adds value to objective value of variable */
9586 SCIP_VAR* var, /**< variable to change */
9587 BMS_BLKMEM* blkmem, /**< block memory */
9588 SCIP_SET* set, /**< global SCIP settings */
9589 SCIP_STAT* stat, /**< problem statistics */
9590 SCIP_PROB* transprob, /**< transformed problem data */
9591 SCIP_PROB* origprob, /**< original problem data */
9592 SCIP_PRIMAL* primal, /**< primal data */
9593 SCIP_TREE* tree, /**< branch and bound tree */
9594 SCIP_REOPT* reopt, /**< reoptimization data structure */
9595 SCIP_LP* lp, /**< current LP data */
9596 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9597 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9598 SCIP_Real addobj /**< additional objective value for variable */
9599 )
9600{
9601 assert(var != NULL);
9602 assert(set != NULL);
9603 assert(var->scip == set->scip);
9605
9606 SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
9607
9608 if( !SCIPsetIsZero(set, addobj) )
9609 {
9611 int i;
9612
9613 switch( SCIPvarGetStatus(var) )
9614 {
9616 if( var->data.original.transvar != NULL )
9617 {
9618 SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
9619 reopt, lp, eventqueue, eventfilter, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
9620 }
9621 else
9622 assert(set->stage == SCIP_STAGE_PROBLEM);
9623
9624 var->obj += addobj;
9625 var->unchangedobj += addobj;
9626 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
9627
9628 break;
9629
9632 oldobj = var->obj;
9633 var->obj += addobj;
9634
9635 /* update unchanged objective value of variable */
9636 if( !lp->divingobjchg )
9637 {
9638 var->unchangedobj += addobj;
9639 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
9640 }
9641
9642 /* update the number of variables with non-zero objective coefficient;
9643 * we only want to do the update, if the variable is added to the problem;
9644 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9645 */
9646 if( SCIPvarIsActive(var) )
9647 SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
9648
9649 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
9650 break;
9651
9653 assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
9654 SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
9655 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9656 break;
9657
9659 assert(!var->donotaggr);
9660 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
9661 SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
9662 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9663 SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
9664 lp, eventqueue, eventfilter, var->data.aggregate.scalar * addobj) );
9665 break;
9666
9668 assert(!var->donotmultaggr);
9669 /* 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 */
9670 SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
9671 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9672 for( i = 0; i < var->data.multaggr.nvars; ++i )
9673 {
9674 SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
9675 reopt, lp, eventqueue, eventfilter, var->data.multaggr.scalars[i] * addobj) );
9676 }
9677 break;
9678
9680 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
9681 assert(var->negatedvar != NULL);
9683 assert(var->negatedvar->negatedvar == var);
9684 SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
9685 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9686 SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
9687 eventqueue, eventfilter, -addobj) );
9688 break;
9689
9690 default:
9691 SCIPerrorMessage("unknown variable status\n");
9692 return SCIP_INVALIDDATA;
9693 }
9694 }
9695
9696 return SCIP_OKAY;
9697}
9698
9699/** adds exact value to objective value of variable */
9701 SCIP_VAR* var, /**< variable to change */
9702 BMS_BLKMEM* blkmem, /**< block memory */
9703 SCIP_SET* set, /**< global SCIP settings */
9704 SCIP_STAT* stat, /**< problem statistics */
9705 SCIP_PROB* transprob, /**< transformed problem data */
9706 SCIP_PROB* origprob, /**< original problem data */
9707 SCIP_PRIMAL* primal, /**< primal data */
9708 SCIP_TREE* tree, /**< branch and bound tree */
9709 SCIP_REOPT* reopt, /**< reoptimization data structure */
9710 SCIP_LP* lp, /**< current LP data */
9711 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9712 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9713 SCIP_RATIONAL* addobj /**< additional objective value for variable */
9714 )
9715{
9716 SCIP_RATIONAL* tmpobj;
9718 SCIP_RATIONAL* multaggrobj;
9719 SCIP_Real oldobjreal;
9720
9721 assert(var != NULL);
9722 assert(set != NULL);
9723 assert(var->scip == set->scip);
9725
9726 SCIPrationalDebugMessage("adding %q to objective value %q of <%s>\n", addobj, var->exactdata->obj, var->name);
9727
9729 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpobj) );
9730
9731 if( !SCIPrationalIsZero(addobj) )
9732 {
9733 int i;
9734
9735 switch( SCIPvarGetStatusExact(var) )
9736 {
9738 if( var->data.original.transvar != NULL )
9739 {
9740 SCIPrationalMultReal(tmpobj, addobj, (SCIP_Real)transprob->objsense/transprob->objscale);
9741 SCIP_CALL( SCIPvarAddObjExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
9742 reopt, lp, eventqueue, eventfilter, tmpobj) );
9743 }
9744 else
9745 assert(set->stage == SCIP_STAGE_PROBLEM);
9746
9747 SCIPrationalAdd(var->exactdata->obj, var->exactdata->obj, addobj);
9748 SCIPintervalSetRational(&(var->exactdata->objinterval), var->exactdata->obj);
9749 var->obj = SCIPrationalGetReal(var->exactdata->obj);
9750 var->unchangedobj = var->obj;
9751
9752 break;
9753
9756 SCIPrationalSetRational(oldobj, var->exactdata->obj);
9757 oldobjreal = var->obj;
9758 SCIPrationalAdd(var->exactdata->obj, var->exactdata->obj, addobj);
9759 SCIPintervalSetRational(&(var->exactdata->objinterval), var->exactdata->obj);
9760 var->obj = SCIPrationalGetReal(var->exactdata->obj);
9761
9762 /* update unchanged objective value of variable */
9763 if( !lp->divingobjchg )
9764 {
9765 var->unchangedobj = var->obj;
9766 }
9767
9768 /* update the number of variables with non-zero objective coefficient;
9769 * we only want to do the update, if the variable is added to the problem;
9770 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9771 */
9772 if( SCIPvarIsActive(var) )
9773 SCIPprobUpdateNObjVars(transprob, set, oldobjreal, var->obj);
9774
9775 SCIP_CALL( varEventObjChangedExact(var, blkmem, set, primal, lp, eventqueue, oldobj, var->exactdata->obj) );
9776 break;
9777
9779 assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
9780 SCIPrationalMult(tmpobj, var->exactdata->locdom.lb, addobj);
9781 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9782 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9783 break;
9784
9786 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
9787 SCIPrationalMult(tmpobj, var->exactdata->aggregate.constant, addobj);
9788 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9789 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9790
9791 SCIPrationalMult(tmpobj, var->exactdata->aggregate.scalar, addobj);
9792
9793 SCIP_CALL( SCIPvarAddObjExact(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
9794 lp, eventqueue, eventfilter, tmpobj) );
9795 break;
9796
9798 assert(!var->donotmultaggr);
9799 /* 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 */
9800 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multaggrobj) );
9801
9802 SCIPrationalMult(tmpobj, var->exactdata->multaggr.constant, addobj);
9803 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9804 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9805
9806 for( i = 0; i < var->data.multaggr.nvars; ++i )
9807 {
9808 SCIPrationalMult(multaggrobj, addobj, var->exactdata->multaggr.scalars[i]);
9809 SCIP_CALL( SCIPvarAddObjExact(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
9810 reopt, lp, eventqueue, eventfilter, multaggrobj) );
9811 }
9812 SCIPrationalFreeBuffer(set->buffer, &multaggrobj);
9813 break;
9814
9816 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
9817 assert(var->negatedvar != NULL);
9819 assert(var->negatedvar->negatedvar == var);
9820
9821 SCIPrationalMultReal(tmpobj, addobj, var->data.negate.constant);
9822 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9823 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9824
9825 SCIPrationalNegate(tmpobj, addobj);
9826 SCIP_CALL( SCIPvarAddObjExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
9827 eventqueue, eventfilter, tmpobj) );
9828 break;
9829
9830 default:
9831 SCIPerrorMessage("unknown variable status\n");
9832 return SCIP_INVALIDDATA;
9833 }
9834 }
9835
9836 SCIPrationalFreeBuffer(set->buffer, &tmpobj);
9838
9839 return SCIP_OKAY;
9840}
9841
9842/** changes objective value of variable in current dive */
9844 SCIP_VAR* var, /**< problem variable to change */
9845 SCIP_SET* set, /**< global SCIP settings */
9846 SCIP_LP* lp, /**< current LP data */
9847 SCIP_Real newobj /**< new objective value for variable */
9848 )
9849{
9850 assert(var != NULL);
9851 assert(set != NULL);
9852 assert(var->scip == set->scip);
9853 assert(lp != NULL);
9854
9855 SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
9856
9857 if( SCIPsetIsZero(set, newobj) )
9858 newobj = 0.0;
9859
9860 /* change objective value of attached variables */
9861 switch( SCIPvarGetStatus(var) )
9862 {
9864 assert(var->data.original.transvar != NULL);
9865 SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
9866 break;
9867
9869 assert(var->data.col != NULL);
9870 SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
9871 break;
9872
9875 /* nothing to do here: only the constant shift in objective function would change */
9876 break;
9877
9878 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9879 assert(var->data.aggregate.var != NULL);
9880 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
9881 SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
9882 /* the constant can be ignored, because it would only affect the objective shift */
9883 break;
9884
9886 SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
9887 return SCIP_INVALIDDATA;
9888
9889 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9890 assert(var->negatedvar != NULL);
9892 assert(var->negatedvar->negatedvar == var);
9893 SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
9894 /* the offset can be ignored, because it would only affect the objective shift */
9895 break;
9896
9897 default:
9898 SCIPerrorMessage("unknown variable status\n");
9899 return SCIP_INVALIDDATA;
9900 }
9901
9902 return SCIP_OKAY;
9903}
9904
9905/** adjust lower bound to integral value, if variable is integral */
9907 SCIP_VAR* var, /**< problem variable */
9908 SCIP_SET* set, /**< global SCIP settings */
9909 SCIP_Real* lb /**< pointer to lower bound to adjust */
9910 )
9911{
9912 assert(var != NULL);
9913 assert(set != NULL);
9914 assert(var->scip == set->scip);
9915 assert(lb != NULL);
9916
9917 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
9918
9919 *lb = adjustedLb(set, SCIPvarIsIntegral(var), *lb);
9920}
9921
9922/** adjust lower bound to integral value, if variable is integral */
9924 SCIP_VAR* var, /**< problem variable */
9925 SCIP_SET* set, /**< global SCIP settings */
9926 SCIP_RATIONAL* lb /**< pointer to lower bound to adjust */
9927 )
9928{
9929 assert(var != NULL);
9930 assert(set != NULL);
9931 assert(var->scip == set->scip);
9932 assert(lb != NULL);
9933
9934 SCIPrationalDebugMessage("adjust lower bound %q of <%s>\n", lb, var->name);
9935
9937}
9938
9939/** adjust lower bound to integral value, if variable is integral */
9941 SCIP_VAR* var, /**< problem variable */
9942 SCIP_SET* set, /**< global SCIP settings */
9943 SCIP_Real* lb /**< pointer to lower bound to adjust */
9944 )
9945{
9946 assert(var != NULL);
9947 assert(set != NULL);
9948 assert(var->scip == set->scip);
9949 assert(lb != NULL);
9950
9951 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
9952
9954}
9955
9956/** adjust upper bound to integral value, if variable is integral */
9958 SCIP_VAR* var, /**< problem variable */
9959 SCIP_SET* set, /**< global SCIP settings */
9960 SCIP_Real* ub /**< pointer to upper bound to adjust */
9961 )
9962{
9963 assert(var != NULL);
9964 assert(set != NULL);
9965 assert(var->scip == set->scip);
9966 assert(ub != NULL);
9967
9968 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
9969
9970 *ub = adjustedUb(set, SCIPvarIsIntegral(var), *ub);
9971}
9972
9973/** adjust lower bound to integral value, if variable is integral */
9975 SCIP_VAR* var, /**< problem variable */
9976 SCIP_SET* set, /**< global SCIP settings */
9977 SCIP_RATIONAL* ub /**< pointer to lower bound to adjust */
9978 )
9979{
9980 assert(var != NULL);
9981 assert(set != NULL);
9982 assert(var->scip == set->scip);
9983 assert(ub != NULL);
9984
9985 SCIPrationalDebugMessage("adjust upper bound %q of <%s>\n", ub, var->name);
9986
9988}
9989
9990/** adjust lower bound to integral value, if variable is integral */
9992 SCIP_VAR* var, /**< problem variable */
9993 SCIP_SET* set, /**< global SCIP settings */
9994 SCIP_Real* ub /**< pointer to lower bound to adjust */
9995 )
9996{
9997 assert(var != NULL);
9998 assert(set != NULL);
9999 assert(var->scip == set->scip);
10000 assert(ub != NULL);
10001
10002 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
10003
10005}
10006
10007/** adjust lower or upper bound to integral value, if variable is integral */
10009 SCIP_VAR* var, /**< problem variable */
10010 SCIP_SET* set, /**< global SCIP settings */
10011 SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
10012 SCIP_Real* bd /**< pointer to bound to adjust */
10013 )
10014{
10015 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
10016
10017 if( boundtype == SCIP_BOUNDTYPE_LOWER )
10018 SCIPvarAdjustLb(var, set, bd);
10019 else
10020 SCIPvarAdjustUb(var, set, bd);
10021}
10022
10023/** changes lower bound of original variable in original problem */
10025 SCIP_VAR* var, /**< problem variable to change */
10026 SCIP_SET* set, /**< global SCIP settings */
10027 SCIP_Real newbound /**< new bound for variable */
10028 )
10029{
10030 int i;
10031
10032 assert(var != NULL);
10035 assert(set != NULL);
10036 assert(var->scip == set->scip);
10037 assert(set->stage == SCIP_STAGE_PROBLEM);
10038
10039 /* check that the bound is feasible */
10041 /* adjust bound to integral value if variable is of integral type */
10042 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
10043
10044 if( SCIPsetIsZero(set, newbound) )
10045 newbound = 0.0;
10046
10047 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10049 {
10050 SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
10051 var->name, var->data.original.origdom.lb, newbound);
10052
10053 if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
10054 return SCIP_OKAY;
10055
10056 /* change the bound */
10057 var->data.original.origdom.lb = newbound;
10058 }
10060 {
10061 assert( var->negatedvar != NULL );
10062 SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
10063 }
10064
10065 /* process parent variables */
10066 for( i = 0; i < var->nparentvars; ++i )
10067 {
10068 SCIP_VAR* parentvar;
10069
10070 parentvar = var->parentvars[i];
10071 assert(parentvar != NULL);
10073 assert(parentvar->negatedvar == var);
10074 assert(var->negatedvar == parentvar);
10075
10076 SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
10077 }
10078
10079 return SCIP_OKAY;
10080}
10081
10082/** changes exact lower bound of original variable in original problem */
10084 SCIP_VAR* var, /**< problem variable to change */
10085 SCIP_SET* set, /**< global SCIP settings */
10086 SCIP_RATIONAL* newbound /**< new bound for variable */
10087 )
10088{
10089 SCIP_RATIONAL* tmpval;
10090 int i;
10091
10092 assert(var != NULL);
10095 assert(set != NULL);
10096 assert(var->scip == set->scip);
10097 assert(set->stage == SCIP_STAGE_PROBLEM);
10098
10099 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
10100 SCIPrationalSetRational(tmpval, newbound);
10101
10102 /* check that the bound is feasible */
10104
10105 /* adjust bound to integral value if variable is of integral type */
10107
10108 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10110 {
10111 SCIPrationalDebugMessage("changing original lower bound of <%s> from %q to %q\n",
10112 var->name, var->exactdata->origdom.lb, newbound);
10113
10114 if( SCIPrationalIsEQ(var->exactdata->origdom.lb, newbound) )
10115 {
10116 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10117 return SCIP_OKAY;
10118 }
10119
10120 /* change the bound */
10121 SCIPrationalSetRational(var->exactdata->origdom.lb, newbound);
10122 var->data.original.origdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
10123 }
10125 {
10126 assert( var->negatedvar != NULL );
10127
10128 SCIPrationalSetReal(tmpval, var->data.negate.constant);
10129 SCIPrationalDiff(tmpval, tmpval, newbound);
10130
10131 SCIP_CALL( SCIPvarChgUbOriginalExact(var->negatedvar, set, tmpval) );
10132 }
10133
10134 /* process parent variables */
10135 for( i = 0; i < var->nparentvars; ++i )
10136 {
10137 SCIP_VAR* parentvar;
10138
10139 parentvar = var->parentvars[i];
10140 assert(parentvar != NULL);
10142 assert(parentvar->negatedvar == var);
10143 assert(var->negatedvar == parentvar);
10144
10145 SCIPrationalSetReal(tmpval, parentvar->data.negate.constant);
10146 SCIPrationalDiff(tmpval, tmpval, newbound);
10147
10148 SCIP_CALL( SCIPvarChgUbOriginalExact(parentvar, set, tmpval) );
10149 }
10150
10151 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10152
10153 return SCIP_OKAY;
10154}
10155
10156/** changes upper bound of original variable in original problem */
10158 SCIP_VAR* var, /**< problem variable to change */
10159 SCIP_SET* set, /**< global SCIP settings */
10160 SCIP_Real newbound /**< new bound for variable */
10161 )
10162{
10163 int i;
10164
10165 assert(var != NULL);
10168 assert(set != NULL);
10169 assert(var->scip == set->scip);
10170 assert(set->stage == SCIP_STAGE_PROBLEM);
10171
10172 /* check that the bound is feasible */
10174 /* adjust bound to integral value if variable is of integral type */
10175 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
10176
10177 if( SCIPsetIsZero(set, newbound) )
10178 newbound = 0.0;
10179
10180 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10182 {
10183 SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
10184 var->name, var->data.original.origdom.ub, newbound);
10185
10186 if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
10187 return SCIP_OKAY;
10188
10189 /* change the bound */
10190 var->data.original.origdom.ub = newbound;
10191 }
10193 {
10194 assert( var->negatedvar != NULL );
10195 SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
10196 }
10197
10198 /* process parent variables */
10199 for( i = 0; i < var->nparentvars; ++i )
10200 {
10201 SCIP_VAR* parentvar;
10202
10203 parentvar = var->parentvars[i];
10204 assert(parentvar != NULL);
10206 assert(parentvar->negatedvar == var);
10207 assert(var->negatedvar == parentvar);
10208
10209 SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
10210 }
10211
10212 return SCIP_OKAY;
10213}
10214
10215/** changes exact upper bound of original variable in original problem */
10217 SCIP_VAR* var, /**< problem variable to change */
10218 SCIP_SET* set, /**< global SCIP settings */
10219 SCIP_RATIONAL* newbound /**< new bound for variable */
10220 )
10221{
10222 SCIP_RATIONAL* tmpval;
10223 int i;
10224
10225 assert(var != NULL);
10228 assert(set != NULL);
10229 assert(var->scip == set->scip);
10230 assert(set->stage == SCIP_STAGE_PROBLEM);
10231
10232 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
10233
10234 /* check that the bound is feasible */
10236
10237 /* adjust bound to integral value if variable is of integral type */
10239
10240 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10242 {
10243 SCIPrationalDebugMessage("changing original upper bound of <%s> from %q to %q\n",
10244 var->name, var->exactdata->origdom.ub, newbound);
10245
10246 if( SCIPrationalIsEQ(var->exactdata->origdom.ub, newbound) )
10247 {
10248 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10249 return SCIP_OKAY;
10250 }
10251
10252 /* change the bound */
10253 SCIPrationalSetRational(var->exactdata->origdom.ub, newbound);
10254 var->data.original.origdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
10255 }
10257 {
10258 assert( var->negatedvar != NULL );
10259
10260 SCIPrationalSetReal(tmpval, var->data.negate.constant);
10261 SCIPrationalDiff(tmpval, tmpval, newbound);
10262
10263 SCIP_CALL( SCIPvarChgLbOriginalExact(var->negatedvar, set, tmpval) );
10264 }
10265
10266 /* process parent variables */
10267 for( i = 0; i < var->nparentvars; ++i )
10268 {
10269 SCIP_VAR* parentvar;
10270
10271 parentvar = var->parentvars[i];
10272 assert(parentvar != NULL);
10274 assert(parentvar->negatedvar == var);
10275 assert(var->negatedvar == parentvar);
10276
10277 SCIPrationalSetReal(tmpval, parentvar->data.negate.constant);
10278 SCIPrationalDiff(tmpval, tmpval, newbound);
10279
10280 SCIP_CALL( SCIPvarChgLbOriginalExact(parentvar, set, tmpval) );
10281 }
10282
10283 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10284
10285 return SCIP_OKAY;
10286}
10287
10288/** appends GLBCHANGED event to the event queue */
10289static
10291 SCIP_VAR* var, /**< problem variable to change */
10292 BMS_BLKMEM* blkmem, /**< block memory */
10293 SCIP_SET* set, /**< global SCIP settings */
10294 SCIP_LP* lp, /**< current LP data */
10295 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10296 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10297 SCIP_Real oldbound, /**< old lower bound for variable */
10298 SCIP_Real newbound /**< new lower bound for variable */
10299 )
10300{
10301 assert(var != NULL);
10302 assert(var->eventfilter != NULL);
10304 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
10305 assert(set != NULL);
10306 assert(var->scip == set->scip);
10307
10308 /* check, if the variable is being tracked for bound changes
10309 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10310 */
10311 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
10314 {
10315 SCIP_EVENT* event;
10316
10317 SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
10318
10319 SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
10320 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10321 }
10322
10323 return SCIP_OKAY;
10324}
10325
10326/** appends GLBCHANGED event to the event queue */
10327static
10329 SCIP_VAR* var, /**< problem variable to change */
10330 BMS_BLKMEM* blkmem, /**< block memory */
10331 SCIP_SET* set, /**< global SCIP settings */
10332 SCIP_LP* lp, /**< current LP data */
10333 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10334 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10335 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
10336 SCIP_RATIONAL* newbound /**< new lower bound for variable */
10337 )
10338{
10339 assert(var != NULL);
10340 assert(var->eventfilter != NULL);
10342 assert(!SCIPrationalIsEQ(oldbound, newbound));
10343 assert(set != NULL);
10344 assert(var->scip == set->scip);
10345
10346 /* check, if the variable is being tracked for bound changes
10347 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10348 */
10349 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
10352 {
10353 SCIP_EVENT* event;
10354
10355 SCIPrationalDebugMessage("issue exact GLBCHANGED event for variable <%s>: %q -> %q\n", var->name, oldbound, newbound);
10356
10359 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
10360 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10361 }
10362
10363 return SCIP_OKAY;
10364}
10365
10366/** appends GUBCHANGED event to the event queue */
10367static
10369 SCIP_VAR* var, /**< problem variable to change */
10370 BMS_BLKMEM* blkmem, /**< block memory */
10371 SCIP_SET* set, /**< global SCIP settings */
10372 SCIP_LP* lp, /**< current LP data */
10373 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10374 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10375 SCIP_Real oldbound, /**< old lower bound for variable */
10376 SCIP_Real newbound /**< new lower bound for variable */
10377 )
10378{
10379 assert(var != NULL);
10380 assert(var->eventfilter != NULL);
10382 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
10383 assert(set != NULL);
10384 assert(var->scip == set->scip);
10385
10386 /* check, if the variable is being tracked for bound changes
10387 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10388 */
10389 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
10392 {
10393 SCIP_EVENT* event;
10394
10395 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
10396
10397 SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
10398 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10399 }
10400
10401 return SCIP_OKAY;
10402}
10403
10404/** appends exact GUBCHANGED event to the event queue */
10405static
10407 SCIP_VAR* var, /**< problem variable to change */
10408 BMS_BLKMEM* blkmem, /**< block memory */
10409 SCIP_SET* set, /**< global SCIP settings */
10410 SCIP_LP* lp, /**< current LP data */
10411 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10412 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10413 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
10414 SCIP_RATIONAL* newbound /**< new lower bound for variable */
10415 )
10416{
10417 assert(var != NULL);
10418 assert(var->eventfilter != NULL);
10420 assert(!SCIPrationalIsEQ(oldbound, newbound));
10421 assert(set != NULL);
10422 assert(var->scip == set->scip);
10423
10424 /* check, if the variable is being tracked for bound changes
10425 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10426 */
10427 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
10430 {
10431 SCIP_EVENT* event;
10432
10433 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, SCIPrationalGetReal(oldbound), SCIPrationalGetReal(newbound));
10434
10437 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
10438 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10439 }
10440
10441 return SCIP_OKAY;
10442}
10443
10444/** appends GHOLEADDED event to the event queue */
10445static
10447 SCIP_VAR* var, /**< problem variable to change */
10448 BMS_BLKMEM* blkmem, /**< block memory */
10449 SCIP_SET* set, /**< global SCIP settings */
10450 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10451 SCIP_Real left, /**< left bound of open interval in new hole */
10452 SCIP_Real right /**< right bound of open interval in new hole */
10453 )
10454{
10455 assert(var != NULL);
10456 assert(var->eventfilter != NULL);
10458 assert(set != NULL);
10459 assert(var->scip == set->scip);
10460 assert(SCIPsetIsLT(set, left, right));
10461
10462 /* check, if the variable is being tracked for bound changes */
10463 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
10464 {
10465 SCIP_EVENT* event;
10466
10467 SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
10468
10469 SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
10470 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
10471 }
10472
10473 return SCIP_OKAY;
10474}
10475
10476/** increases root bound change statistics after a global bound change */
10477static
10479 SCIP_VAR* var, /**< problem variable to change */
10480 SCIP_SET* set, /**< global SCIP settings */
10481 SCIP_STAT* stat /**< problem statistics */
10482 )
10483{
10484 assert(var != NULL);
10485 assert(set != NULL);
10486 assert(var->scip == set->scip);
10487 assert(stat != NULL);
10488
10490 {
10491 stat->nrootboundchgs++;
10492 stat->nrootboundchgsrun++;
10494 {
10495 stat->nrootintfixings++;
10496 stat->nrootintfixingsrun++;
10497 }
10498 }
10499}
10500
10501/* forward declaration, because both methods call each other recursively */
10502
10503/* performs the current change in upper bound, changes all parents accordingly */
10504static
10506 SCIP_VAR* var, /**< problem variable to change */
10507 BMS_BLKMEM* blkmem, /**< block memory */
10508 SCIP_SET* set, /**< global SCIP settings */
10509 SCIP_STAT* stat, /**< problem statistics */
10510 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10511 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10512 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10513 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10514 SCIP_Real newbound /**< new bound for variable */
10515 );
10516
10517/** performs the current change in lower bound, changes all parents accordingly */
10518static
10520 SCIP_VAR* var, /**< problem variable to change */
10521 BMS_BLKMEM* blkmem, /**< block memory */
10522 SCIP_SET* set, /**< global SCIP settings */
10523 SCIP_STAT* stat, /**< problem statistics */
10524 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10525 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10526 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10527 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10528 SCIP_Real newbound /**< new bound for variable */
10529 )
10530{
10531 SCIP_VAR* parentvar;
10532 SCIP_Real oldbound;
10533 int i;
10534
10535 assert(var != NULL);
10536 /* local domains can violate global bounds but not more than feasibility epsilon */
10537 assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
10538 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
10539 assert(blkmem != NULL);
10540 assert(set != NULL);
10541 assert(var->scip == set->scip);
10542 assert(stat != NULL);
10543
10544 /* adjust bound to integral value if variable is of integral type */
10545 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
10546
10547 /* check that the bound is feasible */
10548 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
10549 {
10550 /* due to numerics we only want to be feasible in feasibility tolerance */
10551 assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
10552 newbound = var->glbdom.ub;
10553 }
10555
10556 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
10557
10558 SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
10559
10560 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
10561 return SCIP_OKAY;
10562
10563 /* check bound on debugging solution */
10564 SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
10565
10566 /* change the bound */
10567 oldbound = var->glbdom.lb;
10568 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
10569 var->glbdom.lb = newbound;
10570 if( set->exact_enable && SCIPrationalIsLTReal(SCIPvarGetLbGlobalExact(var), newbound) )
10571 SCIPrationalSetReal(var->exactdata->glbdom.lb, newbound);
10572 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
10573 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
10574
10576 {
10577 /* merges overlapping holes into single holes, moves bounds respectively */
10578 domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
10579 }
10580
10581 /* update the root bound changes counters */
10582 varIncRootboundchgs(var, set, stat);
10583
10584 /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
10585 * redundant bound changes to be branching decisions
10586 */
10587 for( i = 0; i < var->nlbchginfos; ++i )
10588 {
10589 assert(var->lbchginfos[i].var == var);
10590
10591 if( var->lbchginfos[i].oldbound < var->glbdom.lb )
10592 {
10593 SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
10594 SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
10595 var->lbchginfos[i].oldbound = var->glbdom.lb;
10596 if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
10597 {
10598 /* this bound change is redundant due to the new global bound */
10599 var->lbchginfos[i].newbound = var->glbdom.lb;
10600 var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
10601 var->lbchginfos[i].redundant = TRUE;
10602 }
10603 else
10604 break; /* from now on, the remaining local bound changes are not redundant */
10605 }
10606 else
10607 break; /* from now on, the remaining local bound changes are not redundant */
10608 }
10609
10610 /* remove redundant implications and variable bounds */
10612 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
10613 {
10614 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
10615 }
10616
10617 /* issue bound change event */
10618 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10619 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
10620 {
10621 SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
10622 }
10623
10624 /* process parent variables */
10625 for( i = 0; i < var->nparentvars; ++i )
10626 {
10627 parentvar = var->parentvars[i];
10628 assert(parentvar != NULL);
10629
10630 switch( SCIPvarGetStatus(parentvar) )
10631 {
10633 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
10634 break;
10635
10640 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10641 return SCIP_INVALIDDATA;
10642
10643 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10644 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
10645 {
10646 SCIP_Real parentnewbound;
10647 SCIP_Real scalar;
10648 SCIP_Real constant;
10649
10650 assert(parentvar->data.aggregate.var == var);
10651
10652 scalar = parentvar->data.aggregate.scalar;
10653 constant = parentvar->data.aggregate.constant;
10654
10655 if( scalar > 0.0 )
10656 {
10657 /* a > 0 -> change lower bound of y */
10658 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
10659 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * scalar + constant)
10660 || (SCIPsetIsZero(set, parentvar->glbdom.lb / scalar) && SCIPsetIsZero(set, oldbound)));
10661
10662 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10663 parentnewbound = scalar * newbound + constant;
10664 else
10665 parentnewbound = newbound;
10666 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10667 }
10668 else
10669 {
10670 /* a < 0 -> change upper bound of y */
10672 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
10673 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * scalar + constant)
10674 || (SCIPsetIsZero(set, parentvar->glbdom.ub / scalar) && SCIPsetIsZero(set, oldbound)));
10675
10676 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10677 parentnewbound = scalar * newbound + constant;
10678 else
10679 parentnewbound = -newbound;
10680 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10681 }
10682 break;
10683 }
10684
10685 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
10686 assert(parentvar->negatedvar != NULL);
10688 assert(parentvar->negatedvar->negatedvar == parentvar);
10689 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
10690 parentvar->data.negate.constant - newbound) );
10691 break;
10692
10693 default:
10694 SCIPerrorMessage("unknown variable status\n");
10695 return SCIP_INVALIDDATA;
10696 }
10697 }
10698
10699 return SCIP_OKAY;
10700}
10701
10702/** performs the current change in upper bound, changes all parents accordingly */
10703static
10705 SCIP_VAR* var, /**< problem variable to change */
10706 BMS_BLKMEM* blkmem, /**< block memory */
10707 SCIP_SET* set, /**< global SCIP settings */
10708 SCIP_STAT* stat, /**< problem statistics */
10709 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10710 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10711 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10712 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10713 SCIP_Real newbound /**< new bound for variable */
10714 )
10715{
10716 SCIP_VAR* parentvar;
10717 SCIP_Real oldbound;
10718 int i;
10719
10720 assert(var != NULL);
10721 /* local domains can violate global bounds but not more than feasibility epsilon */
10722 assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
10723 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
10724 assert(blkmem != NULL);
10725 assert(set != NULL);
10726 assert(var->scip == set->scip);
10727 assert(stat != NULL);
10728
10729 /* adjust bound to integral value if variable is of integral type */
10730 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
10731
10732 /* check that the bound is feasible */
10733 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
10734 {
10735 /* due to numerics we only want to be feasible in feasibility tolerance */
10736 assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
10737 newbound = var->glbdom.lb;
10738 }
10740
10741 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
10742
10743 SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
10744
10745 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
10746 return SCIP_OKAY;
10747
10748 /* check bound on debugging solution */
10749 SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
10750
10751 /* change the bound */
10752 oldbound = var->glbdom.ub;
10753 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
10754 var->glbdom.ub = newbound;
10755 if( set->exact_enable && SCIPrationalIsGTReal(SCIPvarGetUbGlobalExact(var), newbound) )
10756 SCIPrationalSetReal(var->exactdata->glbdom.ub, newbound);
10757
10758 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
10759 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
10760
10762 {
10763 /* merges overlapping holes into single holes, moves bounds respectively */
10764 domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
10765 }
10766
10767 /* update the root bound changes counters */
10768 varIncRootboundchgs(var, set, stat);
10769
10770 /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
10771 * redundant bound changes to be branching decisions
10772 */
10773 for( i = 0; i < var->nubchginfos; ++i )
10774 {
10775 assert(var->ubchginfos[i].var == var);
10776 if( var->ubchginfos[i].oldbound > var->glbdom.ub )
10777 {
10778 SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
10779 SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
10780 var->ubchginfos[i].oldbound = var->glbdom.ub;
10781 if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
10782 {
10783 /* this bound change is redundant due to the new global bound */
10784 var->ubchginfos[i].newbound = var->glbdom.ub;
10785 var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
10786 var->ubchginfos[i].redundant = TRUE;
10787 }
10788 else
10789 break; /* from now on, the remaining local bound changes are not redundant */
10790 }
10791 else
10792 break; /* from now on, the remaining local bound changes are not redundant */
10793 }
10794
10795 /* remove redundant implications and variable bounds */
10797 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
10798 {
10799 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
10800 }
10801
10802 /* issue bound change event */
10803 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10804 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
10805 {
10806 SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
10807 }
10808
10809 /* process parent variables */
10810 for( i = 0; i < var->nparentvars; ++i )
10811 {
10812 parentvar = var->parentvars[i];
10813 assert(parentvar != NULL);
10814
10815 switch( SCIPvarGetStatus(parentvar) )
10816 {
10818 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
10819 break;
10820
10825 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10826 return SCIP_INVALIDDATA;
10827
10828 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10829 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
10830 {
10831 SCIP_Real parentnewbound;
10832 SCIP_Real scalar;
10833 SCIP_Real constant;
10834
10835 assert(parentvar->data.aggregate.var == var);
10836
10837 scalar = parentvar->data.aggregate.scalar;
10838 constant = parentvar->data.aggregate.constant;
10839
10840 if( scalar > 0.0 )
10841 {
10842 /* a > 0 -> change upper bound of y */
10843 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
10844 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * scalar + constant));
10845 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10846 parentnewbound = scalar * newbound + constant;
10847 else
10848 parentnewbound = newbound;
10849 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10850 }
10851 else
10852 {
10853 /* a < 0 -> change lower bound of y */
10854 assert(SCIPsetIsNegative(set, scalar));
10855 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
10856 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * scalar + constant));
10857 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10858 parentnewbound = scalar * newbound + constant;
10859 else
10860 parentnewbound = -newbound;
10861 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10862 }
10863 break;
10864 }
10865
10866 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
10867 assert(parentvar->negatedvar != NULL);
10869 assert(parentvar->negatedvar->negatedvar == parentvar);
10870 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
10871 parentvar->data.negate.constant - newbound) );
10872 break;
10873
10874 default:
10875 SCIPerrorMessage("unknown variable status\n");
10876 return SCIP_INVALIDDATA;
10877 }
10878 }
10879
10880 return SCIP_OKAY;
10881}
10882
10883/* forward declaration, because both methods call each other recursively */
10884
10885/* performs the current change in upper bound, changes all parents accordingly */
10886static
10888 SCIP_VAR* var, /**< problem variable to change */
10889 BMS_BLKMEM* blkmem, /**< block memory */
10890 SCIP_SET* set, /**< global SCIP settings */
10891 SCIP_STAT* stat, /**< problem statistics */
10892 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
10893 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10894 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10895 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10896 SCIP_RATIONAL* newbound /**< new bound for variable */
10897 );
10898
10899/** performs the current change in lower bound, changes all parents accordingly */
10900static
10902 SCIP_VAR* var, /**< problem variable to change */
10903 BMS_BLKMEM* blkmem, /**< block memory */
10904 SCIP_SET* set, /**< global SCIP settings */
10905 SCIP_STAT* stat, /**< problem statistics */
10906 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
10907 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10908 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10909 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10910 SCIP_RATIONAL* newbound /**< new bound for variable */
10911 )
10912{
10913 SCIP_VAR* parentvar;
10914 SCIP_RATIONAL* oldbound;
10915 SCIP_RATIONAL* parentnewbound;
10916 int i;
10917
10918 assert(var != NULL);
10919 assert(SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
10920 assert(SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub));
10921 assert(blkmem != NULL);
10922 assert(set != NULL);
10923 assert(var->scip == set->scip);
10924 assert(stat != NULL);
10925
10926 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
10927
10928 /* adjust bound to integral value if variable is of integral type */
10930
10931 /* check that the bound is feasible */
10932 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub) )
10933 {
10934 /* due to numerics we only want to be feasible in feasibility tolerance */
10935 assert(SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
10936 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
10937 }
10939
10940 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPrationalIsEQReal(newbound, 0.0) || SCIPrationalIsEQReal(newbound, 1.0)); /*lint !e641*/
10941
10942 SCIPrationalDebugMessage("process changing exact global lower bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
10943
10944 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.lb) )
10945 {
10946 SCIPrationalFreeBuffer(set->buffer, &oldbound);
10947 return SCIP_OKAY;
10948 }
10949
10950 /* change the bound */
10951 SCIPrationalSetRational(oldbound, var->exactdata->glbdom.lb);
10952 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
10953 SCIPrationalSetRational(var->exactdata->glbdom.lb, newbound);
10954 var->glbdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
10955 assert( SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) );
10956 assert( SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub) );
10957
10958 /* update the root bound changes counters */
10959 varIncRootboundchgs(var, set, stat);
10960
10961 /* issue bound change event */
10962 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10963 if( var->eventfilter != NULL )
10964 {
10965 SCIP_CALL( varEventGlbChangedExact(var, blkmem, set, lpexact->fplp, branchcand, eventqueue, oldbound, newbound) );
10966 }
10967
10968 /* process parent variables */
10969 for( i = 0; i < var->nparentvars; ++i )
10970 {
10971 parentvar = var->parentvars[i];
10972 assert(parentvar != NULL);
10973
10974 switch( SCIPvarGetStatus(parentvar) )
10975 {
10977 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
10978 break;
10979
10984 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10985 return SCIP_INVALIDDATA;
10986
10987 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10988 assert(parentvar->data.aggregate.var == var);
10990 {
10991 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
10992 /* a > 0 -> change lower bound of y */
10993 if( !SCIPrationalIsAbsInfinity(newbound) )
10994 {
10995 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
10996 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
10997 }
10998 else
10999 SCIPrationalSetRational(parentnewbound, newbound);
11000 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11001 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11002 }
11003 else
11004 {
11005 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11006 /* a < 0 -> change upper bound of y */
11007 if( !SCIPrationalIsAbsInfinity(newbound) )
11008 {
11009 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11010 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11011 }
11012 else
11013 SCIPrationalNegate(parentnewbound, newbound);
11014 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11015 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11016 }
11017 break;
11018
11019 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11020 assert(parentvar->negatedvar != NULL);
11022 assert(parentvar->negatedvar->negatedvar == parentvar);
11023 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11024 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
11025 SCIPrationalNegate(parentnewbound, parentnewbound);
11026 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11027 parentnewbound) );
11028 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11029 break;
11030
11031 default:
11032 SCIPerrorMessage("unknown variable status\n");
11033 return SCIP_INVALIDDATA;
11034 }
11035 }
11036 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11037
11038 return SCIP_OKAY;
11039}
11040
11041/** performs the current change in exact upper bound, changes all parents accordingly */
11042static
11044 SCIP_VAR* var, /**< problem variable to change */
11045 BMS_BLKMEM* blkmem, /**< block memory */
11046 SCIP_SET* set, /**< global SCIP settings */
11047 SCIP_STAT* stat, /**< problem statistics */
11048 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11049 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11050 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11051 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11052 SCIP_RATIONAL* newbound /**< new bound for variable */
11053 )
11054{
11055 SCIP_VAR* parentvar;
11056 SCIP_RATIONAL* oldbound;
11057 SCIP_RATIONAL* parentnewbound;
11058 int i;
11059
11060 assert(var != NULL);
11061 assert(SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
11062 assert(SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub));
11063 assert(blkmem != NULL);
11064 assert(set != NULL);
11065 assert(var->scip == set->scip);
11066 assert(stat != NULL);
11067
11068 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
11069
11070 /* adjust bound to integral value if variable is of integral type */
11072
11073 /* check that the bound is feasible */
11074 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb) )
11075 {
11076 /* due to numerics we only want to be feasible in feasibility tolerance */
11077 assert(SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
11078 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
11079 }
11081
11082 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPrationalIsEQReal(newbound, 0.0) || SCIPrationalIsEQReal(newbound, 1.0)); /*lint !e641*/
11083
11084 SCIPrationalDebugMessage("process changing exact global upper bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
11085
11086 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.ub) )
11087 {
11088 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11089 return SCIP_OKAY;
11090 }
11091
11092 /* change the bound */
11093 SCIPrationalSetRational(oldbound, var->exactdata->glbdom.ub);
11094 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
11095 SCIPrationalSetRational(var->exactdata->glbdom.ub, newbound);
11096 var->glbdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
11097 assert( SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) );
11098 assert( SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub) );
11099
11100 /* update the root bound changes counters */
11101 varIncRootboundchgs(var, set, stat);
11102
11103 /* issue bound change event */
11104 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
11105 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
11106 {
11107 SCIP_CALL( varEventGubChangedExact(var, blkmem, set, lpexact->fplp, branchcand, eventqueue, oldbound, newbound) );
11108 }
11109
11110 /* process parent variables */
11111 for( i = 0; i < var->nparentvars; ++i )
11112 {
11113 parentvar = var->parentvars[i];
11114 assert(parentvar != NULL);
11115
11116 switch( SCIPvarGetStatus(parentvar) )
11117 {
11119 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11120 break;
11121
11126 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11127 return SCIP_INVALIDDATA;
11128
11129 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11130 assert(parentvar->data.aggregate.var == var);
11132 {
11133 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11134 /* a > 0 -> change lower bound of y */
11135 if( !SCIPrationalIsAbsInfinity(newbound) )
11136 {
11137 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11138 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11139 }
11140 else
11141 SCIPrationalSetRational(parentnewbound, newbound);
11142 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11143 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11144 }
11145 else
11146 {
11147 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11148 /* a < 0 -> change upper bound of y */
11149 if( !SCIPrationalIsAbsInfinity(newbound) )
11150 {
11151 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11152 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11153 }
11154 else
11155 SCIPrationalNegate(parentnewbound, newbound);
11156 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11157 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11158 }
11159 break;
11160
11161 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11162 assert(parentvar->negatedvar != NULL);
11164 assert(parentvar->negatedvar->negatedvar == parentvar);
11165 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11166 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
11167 SCIPrationalNegate(parentnewbound, parentnewbound);
11168 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11169 parentnewbound) );
11170 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11171 break;
11172
11173 default:
11174 SCIPerrorMessage("unknown variable status\n");
11175 return SCIP_INVALIDDATA;
11176 }
11177 }
11178 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11179
11180 return SCIP_OKAY;
11181}
11182
11183/** changes global lower bound of variable; if possible, adjusts bound to integral value;
11184 * updates local lower bound if the global bound is tighter
11185 */
11187 SCIP_VAR* var, /**< problem variable to change */
11188 BMS_BLKMEM* blkmem, /**< block memory */
11189 SCIP_SET* set, /**< global SCIP settings */
11190 SCIP_STAT* stat, /**< problem statistics */
11191 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11192 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11193 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11194 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11195 SCIP_Real newbound /**< new bound for variable */
11196 )
11197{
11198 assert(var != NULL);
11199 assert(blkmem != NULL);
11200 assert(set != NULL);
11201 assert(var->scip == set->scip);
11202
11203 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11204 * of the domain within feastol
11205 */
11206 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
11207
11208 /* adjust bound to integral value if variable is of integral type */
11209 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
11210
11211 /* check that the adjusted bound is feasible
11212 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11213 * here because we reset bounds to their original value!
11214 */
11215 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
11216
11218 {
11219 /* we do not want to exceed the upperbound, which could have happened due to numerics */
11220 newbound = MIN(newbound, var->glbdom.ub);
11221 }
11223
11224 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11225 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11226 */
11227 assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11228
11229 SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
11230
11231 if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
11232 return SCIP_OKAY;
11233
11234 /* change bounds of attached variables */
11235 switch( SCIPvarGetStatus(var) )
11236 {
11238 if( var->data.original.transvar != NULL )
11239 {
11240 SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
11241 cliquetable, newbound) );
11242 }
11243 else
11244 {
11245 assert(set->stage == SCIP_STAGE_PROBLEM);
11246 if( newbound > SCIPvarGetLbLocal(var) )
11247 {
11248 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11249 }
11250 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11251 }
11252 break;
11253
11256 if( newbound > SCIPvarGetLbLocal(var) )
11257 {
11258 /* ensure that the local bound change is not blocked */
11259 if( newbound > SCIPvarGetUbLocal(var) )
11260 {
11261 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11262 }
11263 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11264 }
11265 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11266 break;
11267
11269 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11270 return SCIP_INVALIDDATA;
11271
11272 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11273 {
11274 SCIP_VAR* aggrvar;
11275 SCIP_Real childnewbound;
11276 SCIP_Real scalar;
11277 SCIP_Real constant;
11278
11279 scalar = var->data.aggregate.scalar;
11280 constant = var->data.aggregate.constant;
11281 aggrvar = var->data.aggregate.var;
11282 assert(aggrvar != NULL);
11283
11284 if( scalar > 0.0 )
11285 {
11286 /* a > 0 -> change lower bound of y */
11287 assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -aggrvar->glbdom.lb))
11288 || SCIPsetIsFeasEQ(set, var->glbdom.lb, aggrvar->glbdom.lb * scalar + constant));
11289 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11290 childnewbound = (newbound - constant) / scalar;
11291 else
11292 childnewbound = newbound;
11293 SCIP_CALL( SCIPvarChgLbGlobal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11294 childnewbound) );
11295 }
11296 else
11297 {
11298 /* a < 0 -> change upper bound of y */
11299 assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
11300 || SCIPsetIsFeasEQ(set, var->glbdom.lb, aggrvar->glbdom.ub * scalar + constant));
11301 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11302 childnewbound = (newbound - constant) / scalar;
11303 else
11304 childnewbound = -newbound;
11305 SCIP_CALL( SCIPvarChgUbGlobal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11306 childnewbound) );
11307 }
11308 break;
11309 }
11310
11312 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11313 return SCIP_INVALIDDATA;
11314
11315 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11316 assert(var->negatedvar != NULL);
11318 assert(var->negatedvar->negatedvar == var);
11319 SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11320 var->data.negate.constant - newbound) );
11321 break;
11322
11323 default:
11324 SCIPerrorMessage("unknown variable status\n");
11325 return SCIP_INVALIDDATA;
11326 }
11327
11328 return SCIP_OKAY;
11329}
11330
11331/** changes global lower bound of variable; if possible, adjusts bound to integral value;
11332 * updates local lower bound if the global bound is tighter
11333 */
11335 SCIP_VAR* var, /**< problem variable to change */
11336 BMS_BLKMEM* blkmem, /**< block memory */
11337 SCIP_SET* set, /**< global SCIP settings */
11338 SCIP_STAT* stat, /**< problem statistics */
11339 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11340 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11341 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11342 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11343 SCIP_RATIONAL* newbound /**< new bound for variable */
11344 )
11345{
11346 SCIP_RATIONAL* childnewbound;
11347
11348 assert(var != NULL);
11349 assert(blkmem != NULL);
11350 assert(set != NULL);
11351 assert(var->scip == set->scip);
11352
11353 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11354 * of the domain within feastol
11355 */
11356 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub));
11357
11358 /* adjust bound to integral value if variable is of integral type */
11360
11361 /* check that the adjusted bound is feasible
11362 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11363 * here because we reset bounds to their original value!
11364 */
11365 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub));
11366
11368 {
11369 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11370 SCIPrationalMin(newbound, newbound, var->exactdata->glbdom.ub);
11371 }
11373
11374 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11375 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11376 */
11377 assert(lpexact == NULL || SCIPrationalIsLE(var->exactdata->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11378
11379 SCIPrationalDebugMessage("changing global lower bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
11380
11381 /* change bounds of attached variables */
11382 switch( SCIPvarGetStatus(var) )
11383 {
11385 if( var->data.original.transvar != NULL )
11386 {
11387 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11388 newbound) );
11389 }
11390 else
11391 {
11392 assert(set->stage == SCIP_STAGE_PROBLEM);
11394 {
11395 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11396 }
11397 SCIP_CALL( varProcessChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11398 }
11399 break;
11400
11404 {
11406 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11407 }
11408 SCIP_CALL( varProcessChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11409 break;
11410
11412 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11413 return SCIP_INVALIDDATA;
11414
11415 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11416 assert(var->data.aggregate.var != NULL);
11417 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
11418 {
11419 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11420
11421 /* a > 0 -> change lower bound of y */
11422 if( !SCIPrationalIsAbsInfinity(newbound) )
11423 {
11424 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11425 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11426 }
11427 else
11428 SCIPrationalSetRational(childnewbound, newbound);
11429
11430 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11431 childnewbound) );
11432
11433 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11434 }
11435 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
11436 {
11437 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11438
11439 /* a < 0 -> change upper bound of y */
11440 if( !SCIPrationalIsAbsInfinity(newbound) )
11441 {
11442 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11443 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11444 }
11445 else
11446 SCIPrationalSetRational(childnewbound, newbound);
11447
11448 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11449 childnewbound) );
11450
11451 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11452 }
11453 else
11454 {
11455 SCIPerrorMessage("scalar is zero in aggregation\n");
11456 return SCIP_INVALIDDATA;
11457 }
11458 break;
11459
11461 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11462 return SCIP_INVALIDDATA;
11463
11464 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11465 assert(var->negatedvar != NULL);
11467 assert(var->negatedvar->negatedvar == var);
11468
11469 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11470 SCIPrationalDiffReal(childnewbound, newbound, var->data.negate.constant);
11471 SCIPrationalNegate(childnewbound, childnewbound);
11472 SCIP_CALL( SCIPvarChgUbGlobalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11473 childnewbound) );
11474 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11475 break;
11476
11477 default:
11478 SCIPerrorMessage("unknown variable status\n");
11479 return SCIP_INVALIDDATA;
11480 }
11481
11482 return SCIP_OKAY;
11483}
11484
11485/** changes global upper bound of variable; if possible, adjusts bound to integral value;
11486 * updates local upper bound if the global bound is tighter
11487 */
11489 SCIP_VAR* var, /**< problem variable to change */
11490 BMS_BLKMEM* blkmem, /**< block memory */
11491 SCIP_SET* set, /**< global SCIP settings */
11492 SCIP_STAT* stat, /**< problem statistics */
11493 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11494 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11495 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11496 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11497 SCIP_Real newbound /**< new bound for variable */
11498 )
11499{
11500 assert(var != NULL);
11501 assert(blkmem != NULL);
11502 assert(set != NULL);
11503 assert(var->scip == set->scip);
11504
11505 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11506 * of the domain within feastol
11507 */
11508 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
11509
11510 /* adjust bound to integral value if variable is of integral type */
11511 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
11512
11513 /* check that the adjusted bound is feasible
11514 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11515 * here because we reset bounds to their original value!
11516 */
11517 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
11518
11520 {
11521 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11522 newbound = MAX(newbound, var->glbdom.lb);
11523 }
11525
11526 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11527 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11528 */
11529 assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11530
11531 SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
11532
11533 if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
11534 return SCIP_OKAY;
11535
11536 /* change bounds of attached variables */
11537 switch( SCIPvarGetStatus(var) )
11538 {
11540 if( var->data.original.transvar != NULL )
11541 {
11542 SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11543 newbound) );
11544 }
11545 else
11546 {
11547 assert(set->stage == SCIP_STAGE_PROBLEM);
11548 if( newbound < SCIPvarGetUbLocal(var) )
11549 {
11550 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11551 }
11552 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11553 }
11554 break;
11555
11558 if( newbound < SCIPvarGetUbLocal(var) )
11559 {
11560 /* ensure that the local bound change is not blocked */
11561 if( newbound < SCIPvarGetLbLocal(var) )
11562 {
11563 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11564 }
11565 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11566 }
11567 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11568 break;
11569
11571 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11572 return SCIP_INVALIDDATA;
11573
11574 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11575 {
11576 SCIP_VAR* aggrvar;
11577 SCIP_Real childnewbound;
11578 SCIP_Real scalar;
11579 SCIP_Real constant;
11580
11581 scalar = var->data.aggregate.scalar;
11582 constant = var->data.aggregate.constant;
11583 aggrvar = var->data.aggregate.var;
11584 assert(aggrvar != NULL);
11585
11586 if( scalar > 0.0 )
11587 {
11588 /* a > 0 -> change lower bound of y */
11589 assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, aggrvar->glbdom.ub))
11590 || SCIPsetIsFeasEQ(set, var->glbdom.ub, aggrvar->glbdom.ub * scalar + constant));
11591 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11592 childnewbound = (newbound - constant) / scalar;
11593 else
11594 childnewbound = newbound;
11595 SCIP_CALL( SCIPvarChgUbGlobal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11596 childnewbound) );
11597 }
11598 else
11599 {
11600 /* a < 0 -> change upper bound of y */
11601 assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -aggrvar->glbdom.lb))
11602 || SCIPsetIsFeasEQ(set, var->glbdom.ub, aggrvar->glbdom.lb * scalar + constant));
11603 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11604 childnewbound = (newbound - constant) / scalar;
11605 else
11606 childnewbound = -newbound;
11607 SCIP_CALL( SCIPvarChgLbGlobal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11608 childnewbound) );
11609 }
11610 break;
11611 }
11612
11614 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11615 return SCIP_INVALIDDATA;
11616
11617 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11618 assert(var->negatedvar != NULL);
11620 assert(var->negatedvar->negatedvar == var);
11621 SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11622 var->data.negate.constant - newbound) );
11623 break;
11624
11625 default:
11626 SCIPerrorMessage("unknown variable status\n");
11627 return SCIP_INVALIDDATA;
11628 }
11629
11630 return SCIP_OKAY;
11631}
11632
11633/** changes global upper bound of variable; if possible, adjusts bound to integral value;
11634 * updates local upper bound if the global bound is tighter
11635 */
11637 SCIP_VAR* var, /**< problem variable to change */
11638 BMS_BLKMEM* blkmem, /**< block memory */
11639 SCIP_SET* set, /**< global SCIP settings */
11640 SCIP_STAT* stat, /**< problem statistics */
11641 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11642 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11643 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11644 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11645 SCIP_RATIONAL* newbound /**< new bound for variable */
11646 )
11647{
11648 SCIP_RATIONAL* childnewbound;
11649
11650 assert(var != NULL);
11651 assert(blkmem != NULL);
11652 assert(set != NULL);
11653 assert(var->scip == set->scip);
11654
11655 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11656 * of the domain within feastol
11657 */
11658 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb));
11659
11660 /* adjust bound to integral value if variable is of integral type */
11662
11663 /* check that the adjusted bound is feasible
11664 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11665 * here because we reset bounds to their original value!
11666 */
11667 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb));
11668
11670 {
11671 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11672 SCIPrationalMax(newbound, newbound, var->exactdata->glbdom.lb);
11673 }
11675
11676 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11677 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11678 */
11679 assert(lpexact == NULL || SCIPrationalIsGE(var->exactdata->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11680
11681 SCIPrationalDebugMessage("changing global upper bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.ub, newbound);
11682
11683 /* change bounds of attached variables */
11684 switch( SCIPvarGetStatus(var) )
11685 {
11687 if( var->data.original.transvar != NULL )
11688 {
11689 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11690 newbound) );
11691 }
11692 else
11693 {
11694 assert(set->stage == SCIP_STAGE_PROBLEM);
11696 {
11697 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11698 }
11699
11700 SCIP_CALL( varProcessChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11701 }
11702 break;
11703
11707 {
11709 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11710 }
11711 SCIP_CALL( varProcessChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11712 break;
11713
11715 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11716 return SCIP_INVALIDDATA;
11717
11718 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11719 assert(var->data.aggregate.var != NULL);
11720 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
11721 {
11722 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11723
11724 /* a > 0 -> change lower bound of y */
11725 if( !SCIPrationalIsAbsInfinity(newbound) )
11726 {
11727 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11728 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11729 }
11730 else
11731 SCIPrationalSetRational(childnewbound, newbound);
11732
11733 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11734 childnewbound) );
11735
11736 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11737 }
11738 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
11739 {
11740 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11741
11742 /* a < 0 -> change upper bound of y */
11743 if( !SCIPrationalIsAbsInfinity(newbound) )
11744 {
11745 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11746 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11747 }
11748 else
11749 SCIPrationalSetRational(childnewbound, newbound);
11750
11751 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11752 childnewbound) );
11753
11754 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11755 }
11756 else
11757 {
11758 SCIPerrorMessage("scalar is zero in aggregation\n");
11759 return SCIP_INVALIDDATA;
11760 }
11761 break;
11762
11764 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11765 return SCIP_INVALIDDATA;
11766
11767 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11768 assert(var->negatedvar != NULL);
11770 assert(var->negatedvar->negatedvar == var);
11771
11772 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11773 SCIPrationalDiffReal(childnewbound, newbound, var->data.negate.constant);
11774 SCIPrationalNegate(childnewbound, childnewbound);
11775 SCIP_CALL( SCIPvarChgLbGlobalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11776 childnewbound) );
11777 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11778 break;
11779
11780 default:
11781 SCIPerrorMessage("unknown variable status\n");
11782 return SCIP_INVALIDDATA;
11783 }
11784
11785 return SCIP_OKAY;
11786}
11787
11788/** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
11790 SCIP_VAR* var, /**< problem variable */
11791 SCIP_SET* set, /**< global SCIP settings */
11792 SCIP_Real lazylb /**< the lazy lower bound to be set */
11793 )
11794{
11795 assert(var != NULL);
11796 assert(var->probindex != -1);
11797 assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
11798 assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
11799 assert(set != NULL);
11800 assert(var->scip == set->scip);
11801
11802 /* variable should not be in the LP */
11804 return SCIP_INVALIDCALL;
11805
11806 var->lazylb = lazylb;
11807
11808 return SCIP_OKAY;
11809}
11810
11811/** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
11813 SCIP_VAR* var, /**< problem variable */
11814 SCIP_SET* set, /**< global SCIP settings */
11815 SCIP_Real lazyub /**< the lazy upper bound to be set */
11816 )
11817{
11818 assert(var != NULL);
11819 assert(var->probindex != -1);
11820 assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
11821 assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
11822 assert(set != NULL);
11823 assert(var->scip == set->scip);
11824
11825 /* variable should not be in the LP */
11827 return SCIP_INVALIDCALL;
11828
11829 var->lazyub = lazyub;
11830
11831 return SCIP_OKAY;
11832}
11833
11834/** changes global bound of variable; if possible, adjusts bound to integral value;
11835 * updates local bound if the global bound is tighter
11836 */
11838 SCIP_VAR* var, /**< problem variable to change */
11839 BMS_BLKMEM* blkmem, /**< block memory */
11840 SCIP_SET* set, /**< global SCIP settings */
11841 SCIP_STAT* stat, /**< problem statistics */
11842 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11843 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11844 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11845 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11846 SCIP_Real newbound, /**< new bound for variable */
11847 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
11848 )
11849{
11850 /* apply bound change to the LP data */
11851 switch( boundtype )
11852 {
11854 return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
11856 return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
11857 default:
11858 SCIPerrorMessage("unknown bound type\n");
11859 return SCIP_INVALIDDATA;
11860 }
11861}
11862
11863/** changes exact global bound of variable; if possible, adjusts bound to integral value;
11864 * updates local bound if the global bound is tighter
11865 */
11867 SCIP_VAR* var, /**< problem variable to change */
11868 BMS_BLKMEM* blkmem, /**< block memory */
11869 SCIP_SET* set, /**< global SCIP settings */
11870 SCIP_STAT* stat, /**< problem statistics */
11871 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
11872 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11873 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11874 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11875 SCIP_RATIONAL* newbound, /**< new bound for variable */
11876 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
11877 )
11878{
11879 /* apply bound change to the LP data */
11880 switch( boundtype )
11881 {
11883 return SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound);
11885 return SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound);
11886 default:
11887 SCIPerrorMessage("unknown bound type\n");
11888 return SCIP_INVALIDDATA;
11889 }
11890}
11891
11892/** appends LBTIGHTENED or LBRELAXED event to the event queue */
11893static
11895 SCIP_VAR* var, /**< problem variable to change */
11896 BMS_BLKMEM* blkmem, /**< block memory */
11897 SCIP_SET* set, /**< global SCIP settings */
11898 SCIP_LP* lp, /**< current LP data */
11899 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11900 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11901 SCIP_Real oldbound, /**< old lower bound for variable */
11902 SCIP_Real newbound /**< new lower bound for variable */
11903 )
11904{
11905 assert(var != NULL);
11906 assert(var->eventfilter != NULL);
11908 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
11909 assert(set != NULL);
11910 assert(var->scip == set->scip);
11911
11912 /* check, if the variable is being tracked for bound changes
11913 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11914 */
11915 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
11918 {
11919 SCIP_EVENT* event;
11920
11921 SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
11922
11923 SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
11924 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
11925 }
11926
11927 return SCIP_OKAY;
11928}
11929
11930/** appends LBTIGHTENED or LBRELAXED event to the event queue */
11931static
11933 SCIP_VAR* var, /**< problem variable to change */
11934 BMS_BLKMEM* blkmem, /**< block memory */
11935 SCIP_SET* set, /**< global SCIP settings */
11936 SCIP_LPEXACT* lp, /**< current LP data */
11937 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11938 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11939 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
11940 SCIP_RATIONAL* newbound /**< new lower bound for variable */
11941 )
11942{
11943 assert(var != NULL);
11944 assert(var->eventfilter != NULL);
11946 assert(set != NULL);
11947 assert(var->scip == set->scip);
11948
11949 /* check, if the variable is being tracked for bound changes
11950 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11951 */
11952 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
11955 {
11956 SCIP_EVENT* event;
11957
11958 SCIPrationalDebugMessage("issue exact LBCHANGED event for variable <%s>: %q -> %q\n", var->name, oldbound, newbound);
11959
11962 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
11963 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp->fplp, branchcand, NULL, &event) );
11964 }
11965
11966 return SCIP_OKAY;
11967}
11968
11969/** appends UBTIGHTENED or UBRELAXED event to the event queue */
11970static
11972 SCIP_VAR* var, /**< problem variable to change */
11973 BMS_BLKMEM* blkmem, /**< block memory */
11974 SCIP_SET* set, /**< global SCIP settings */
11975 SCIP_LP* lp, /**< current LP data */
11976 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11977 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11978 SCIP_Real oldbound, /**< old upper bound for variable */
11979 SCIP_Real newbound /**< new upper bound for variable */
11980 )
11981{
11982 assert(var != NULL);
11983 assert(var->eventfilter != NULL);
11985 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
11986 assert(set != NULL);
11987 assert(var->scip == set->scip);
11988
11989 /* check, if the variable is being tracked for bound changes
11990 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11991 */
11992 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
11995 {
11996 SCIP_EVENT* event;
11997
11998 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
11999
12000 SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
12001 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
12002 }
12003
12004 return SCIP_OKAY;
12005}
12006
12007/** appends exact UBTIGHTENED or UBRELAXED event to the event queue */
12008static
12010 SCIP_VAR* var, /**< problem variable to change */
12011 BMS_BLKMEM* blkmem, /**< block memory */
12012 SCIP_SET* set, /**< global SCIP settings */
12013 SCIP_LPEXACT* lp, /**< current LP data */
12014 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
12015 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12016 SCIP_RATIONAL* oldbound, /**< old upper bound for variable */
12017 SCIP_RATIONAL* newbound /**< new upper bound for variable */
12018 )
12019{
12020 assert(var != NULL);
12021 assert(var->eventfilter != NULL);
12023 assert(set != NULL);
12024 assert(var->scip == set->scip);
12025
12026 /* check, if the variable is being tracked for bound changes
12027 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
12028 */
12029 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
12032 {
12033 SCIP_EVENT* event;
12034
12035 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, SCIPrationalGetReal(oldbound), SCIPrationalGetReal(newbound));
12036
12039 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
12040 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp->fplp, branchcand, NULL, &event) );
12041 }
12042
12043 return SCIP_OKAY;
12044}
12045
12046/* forward declaration, because both methods call each other recursively */
12047
12048/* performs the current change in upper bound, changes all parents accordingly */
12049static
12051 SCIP_VAR* var, /**< problem variable to change */
12052 BMS_BLKMEM* blkmem, /**< block memory */
12053 SCIP_SET* set, /**< global SCIP settings */
12054 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12055 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12056 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12057 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12058 SCIP_Real newbound /**< new bound for variable */
12059 );
12060
12061/** performs the current change in lower bound, changes all parents accordingly */
12062static
12064 SCIP_VAR* var, /**< problem variable to change */
12065 BMS_BLKMEM* blkmem, /**< block memory */
12066 SCIP_SET* set, /**< global SCIP settings */
12067 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12068 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12069 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12070 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12071 SCIP_Real newbound /**< new bound for variable */
12072 )
12073{
12074 SCIP_VAR* parentvar;
12075 SCIP_Real oldbound;
12076 int i;
12077
12078 assert(var != NULL);
12079 assert(set != NULL);
12080 assert(var->scip == set->scip);
12081 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
12082 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
12083 || (SCIPvarIsIntegral(var) && (SCIPsetIsIntegral(set, newbound)
12084 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
12085 || !SCIPvarIsIntegral(var));
12086
12087 /* check that the bound is feasible */
12088 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
12089 /* adjust bound to integral value if variable is of integral type */
12090 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
12091
12093 {
12094 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12095 newbound = MIN(newbound, var->locdom.ub);
12096
12097 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12098 newbound = MAX(newbound, var->glbdom.lb);
12099 }
12101
12102 SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
12103
12104 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
12105 newbound = var->glbdom.lb;
12106 else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
12107 return SCIP_OKAY;
12108
12109 /* change the bound */
12110 oldbound = var->locdom.lb;
12111 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
12112 var->locdom.lb = newbound;
12113 /* adjust the exact bound as well */
12114 if( set->exact_enable )
12115 {
12116 SCIPrationalSetReal(var->exactdata->locdom.lb, var->locdom.lb);
12117 SCIPrationalMax(var->exactdata->locdom.lb, var->exactdata->locdom.lb, var->exactdata->glbdom.lb);
12118 }
12119
12120 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12121 * once update the statistic
12122 */
12123 if( stat != NULL )
12124 SCIPstatIncrement(stat, set, domchgcount);
12125
12127 {
12128 /* merges overlapping holes into single holes, moves bounds respectively */
12129 domMerge(&var->locdom, blkmem, set, &newbound, NULL);
12130 }
12131
12134
12135 /* issue bound change event */
12136 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12137 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12138 {
12139 SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
12140 }
12141
12142 /* process parent variables */
12143 for( i = 0; i < var->nparentvars; ++i )
12144 {
12145 parentvar = var->parentvars[i];
12146 assert(parentvar != NULL);
12147
12148 switch( SCIPvarGetStatus(parentvar) )
12149 {
12151 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
12152 break;
12153
12158 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12159 return SCIP_INVALIDDATA;
12160
12161 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12162 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
12163 {
12164 SCIP_Real parentnewbound;
12165 SCIP_Real scalar;
12166 SCIP_Real constant;
12167
12168 assert(parentvar->data.aggregate.var == var);
12169
12170 scalar = parentvar->data.aggregate.scalar;
12171 constant = parentvar->data.aggregate.constant;
12172
12173 if (!set->exact_enable)
12174 {
12175 parentnewbound = scalar * newbound + constant;
12176 }
12177 else
12178 {
12179 SCIP_INTERVAL parentboundinterval;
12180 SCIPintervalSet(&parentboundinterval, newbound);
12181 SCIPintervalMulScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, scalar);
12182 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, constant);
12183 parentnewbound = scalar > 0.0 ? parentboundinterval.inf : parentboundinterval.sup;
12184 }
12185
12186 if( scalar > 0.0 )
12187 {
12188 /* a > 0 -> change lower bound of y */
12189 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
12190 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * scalar + constant)
12191 || (SCIPsetIsZero(set, parentvar->locdom.lb / scalar) && SCIPsetIsZero(set, oldbound)));
12192
12193 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12194 {
12195 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
12196 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
12197 * as a result, the parent's lower bound is set to it's upper bound, and not above
12198 */
12199 if( parentnewbound > parentvar->glbdom.ub )
12200 {
12201 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12202 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
12203 parentnewbound = parentvar->glbdom.ub;
12204 }
12205 }
12206 else
12207 parentnewbound = newbound;
12208 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12209 }
12210 else
12211 {
12212 /* a < 0 -> change upper bound of y */
12213 assert(SCIPsetIsNegative(set, scalar));
12214 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
12215 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * scalar + constant)
12216 || (SCIPsetIsZero(set, parentvar->locdom.ub / scalar) && SCIPsetIsZero(set, oldbound)));
12217
12218 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12219 {
12220 /* 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
12221 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
12222 * as a result, the parent's upper bound is set to it's lower bound, and not below
12223 */
12224 if( parentnewbound < parentvar->glbdom.lb )
12225 {
12226 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12227 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
12228 parentnewbound = parentvar->glbdom.lb;
12229 }
12230 }
12231 else
12232 parentnewbound = -newbound;
12233 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12234 }
12235 break;
12236 }
12237 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12238 assert(parentvar->negatedvar != NULL);
12240 assert(parentvar->negatedvar->negatedvar == parentvar);
12241 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
12242 parentvar->data.negate.constant - newbound) );
12243 break;
12244
12245 default:
12246 SCIPerrorMessage("unknown variable status\n");
12247 return SCIP_INVALIDDATA;
12248 }
12249 }
12250
12251 return SCIP_OKAY;
12252}
12253
12254/** performs the current change in upper bound, changes all parents accordingly */
12255static
12257 SCIP_VAR* var, /**< problem variable to change */
12258 BMS_BLKMEM* blkmem, /**< block memory */
12259 SCIP_SET* set, /**< global SCIP settings */
12260 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12261 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12262 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12263 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12264 SCIP_Real newbound /**< new bound for variable */
12265 )
12266{
12267 SCIP_VAR* parentvar;
12268 SCIP_Real oldbound;
12269 int i;
12270
12271 assert(var != NULL);
12272 assert(set != NULL);
12273 assert(var->scip == set->scip);
12274 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
12275 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
12276 || (SCIPvarIsIntegral(var) && (SCIPsetIsIntegral(set, newbound)
12277 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
12278 || !SCIPvarIsIntegral(var));
12279
12280 /* check that the bound is feasible */
12281 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
12282 /* adjust bound to integral value if variable is of integral type */
12283 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
12284
12286 {
12287 /* we do not want to undercut the lower bound, which could have happened due to numerics */
12288 newbound = MAX(newbound, var->locdom.lb);
12289
12290 /* we do not want to exceed the global upper bound, which could have happened due to numerics */
12291 newbound = MIN(newbound, var->glbdom.ub);
12292 }
12294
12295 SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
12296
12297 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
12298 newbound = var->glbdom.ub;
12299 else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
12300 return SCIP_OKAY;
12301
12302 /* change the bound */
12303 oldbound = var->locdom.ub;
12304 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
12305 var->locdom.ub = newbound;
12306 /* adjust the exact bound as well */
12307 if( set->exact_enable )
12308 {
12309 SCIPrationalSetReal(var->exactdata->locdom.ub, var->locdom.ub);
12310 SCIPrationalMin(var->exactdata->locdom.ub, var->exactdata->locdom.ub, var->exactdata->glbdom.ub);
12311 }
12312
12313 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12314 * once update the statistic
12315 */
12316 if( stat != NULL )
12317 SCIPstatIncrement(stat, set, domchgcount);
12318
12320 {
12321 /* merges overlapping holes into single holes, moves bounds respectively */
12322 domMerge(&var->locdom, blkmem, set, NULL, &newbound);
12323 }
12324
12327
12328 /* issue bound change event */
12329 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12330 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12331 {
12332 SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
12333 }
12334
12335 /* process parent variables */
12336 for( i = 0; i < var->nparentvars; ++i )
12337 {
12338 parentvar = var->parentvars[i];
12339 assert(parentvar != NULL);
12340
12341 switch( SCIPvarGetStatus(parentvar) )
12342 {
12344 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
12345 break;
12346
12351 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12352 return SCIP_INVALIDDATA;
12353
12354 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12355 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
12356 {
12357 SCIP_Real parentnewbound;
12358 SCIP_Real scalar;
12359 SCIP_Real constant;
12360
12361 assert(parentvar->data.aggregate.var == var);
12362
12363 scalar = parentvar->data.aggregate.scalar;
12364 constant = parentvar->data.aggregate.constant;
12365
12366 if( !set->exact_enable )
12367 {
12368 parentnewbound = scalar * newbound + constant;
12369 }
12370 else
12371 {
12372 SCIP_INTERVAL parentboundinterval;
12373 SCIPintervalSet(&parentboundinterval, newbound);
12374 SCIPintervalMulScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, scalar);
12375 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, constant);
12376 parentnewbound = scalar > 0.0 ? parentboundinterval.sup : parentboundinterval.inf;
12377 }
12378
12379 if( scalar > 0.0 )
12380 {
12381 /* a > 0 -> change upper bound of x */
12382 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
12383 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * scalar + constant));
12384 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12385 {
12386 /* 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
12387 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
12388 * as a result, the parent's upper bound is set to it's lower bound, and not below
12389 */
12390 if( parentnewbound < parentvar->glbdom.lb )
12391 {
12392 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12393 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
12394 parentnewbound = parentvar->glbdom.lb;
12395 }
12396 }
12397 else
12398 parentnewbound = newbound;
12399 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12400 }
12401 else
12402 {
12403 /* a < 0 -> change lower bound of x */
12404 assert(SCIPsetIsNegative(set, scalar));
12405 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
12406 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * scalar + constant));
12407 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12408 {
12409 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
12410 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
12411 * as a result, the parent's lower bound is set to it's upper bound, and not above
12412 */
12413 if( parentnewbound > parentvar->glbdom.ub )
12414 {
12415 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12416 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
12417 parentnewbound = parentvar->glbdom.ub;
12418 }
12419 }
12420 else
12421 parentnewbound = -newbound;
12422 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12423 }
12424 break;
12425 }
12426
12427 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12428 assert(parentvar->negatedvar != NULL);
12430 assert(parentvar->negatedvar->negatedvar == parentvar);
12431 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
12432 parentvar->data.negate.constant - newbound) );
12433 break;
12434
12435 default:
12436 SCIPerrorMessage("unknown variable status\n");
12437 return SCIP_INVALIDDATA;
12438 }
12439 }
12440
12441 return SCIP_OKAY;
12442}
12443
12444/* forward declaration, because both methods call each other recursively */
12445
12446/* performs the current change in upper bound, changes all parents accordingly */
12447static
12449 SCIP_VAR* var, /**< problem variable to change */
12450 BMS_BLKMEM* blkmem, /**< block memory */
12451 SCIP_SET* set, /**< global SCIP settings */
12452 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12453 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12454 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12455 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12456 SCIP_RATIONAL* newbound /**< new bound for variable */
12457 );
12458
12459/** performs the current change in lower bound, changes all parents accordingly */
12460static
12462 SCIP_VAR* var, /**< problem variable to change */
12463 BMS_BLKMEM* blkmem, /**< block memory */
12464 SCIP_SET* set, /**< global SCIP settings */
12465 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12466 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12467 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12468 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12469 SCIP_RATIONAL* newbound /**< new bound for variable */
12470 )
12471{
12472 SCIP_VAR* parentvar;
12473 SCIP_RATIONAL* oldbound;
12474 SCIP_RATIONAL* parentnewbound;
12475 int i;
12476
12477 assert(var != NULL);
12478 assert(set != NULL);
12479 assert(var->scip == set->scip);
12481 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12483 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12484 || !SCIPvarIsIntegral(var));
12485
12486 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
12487
12488 /* check that the bound is feasible */
12489 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
12490 /* adjust bound to integral value if variable is of integral type */
12492
12494 {
12495 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12496 SCIPrationalMin(newbound, newbound, var->exactdata->locdom.ub);
12497
12498 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12499 SCIPrationalMax(newbound, newbound, var->exactdata->glbdom.lb);
12500 }
12502
12503 SCIPrationalDebugMessage("process changing lower bound of <%s> from %q to %q\n", var->name, var->exactdata->locdom.lb, newbound);
12504
12505 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.lb) && !SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) ) /*lint !e777*/
12506 SCIPrationalSetRational(newbound, var->exactdata->glbdom.lb);
12507
12508 /* change the bound */
12509 SCIPrationalSetRational(oldbound, var->exactdata->locdom.lb);
12510 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->locdom.ub));
12511 SCIPrationalSetRational(var->exactdata->locdom.lb, newbound);
12512 var->locdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
12513
12514 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12515 * once update the statistic
12516 */
12517 if( stat != NULL )
12518 SCIPstatIncrement(stat, set, domchgcount);
12519
12520 /* issue bound change event */
12521 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12522 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12523 {
12524 SCIP_CALL( varEventLbChangedExact(var, blkmem, set, lpexact, branchcand, eventqueue, oldbound, newbound) );
12525 }
12526
12527 /* process parent variables */
12528 for( i = 0; i < var->nparentvars; ++i )
12529 {
12530 parentvar = var->parentvars[i];
12531 assert(parentvar != NULL);
12532
12533 switch( SCIPvarGetStatus(parentvar) )
12534 {
12536 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, newbound) );
12537 break;
12538
12543 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12544 return SCIP_INVALIDDATA;
12545
12546 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12547 assert(parentvar->data.aggregate.var == var);
12548 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12550 {
12551 /* a > 0 -> change lower bound of y */
12552 if( !SCIPrationalIsAbsInfinity(newbound) )
12553 {
12554 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12555 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12556 }
12557 else
12558 SCIPrationalSetRational(parentnewbound, newbound);
12559
12560 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12561 }
12562 else
12563 {
12564 /* a < 0 -> change upper bound of y */
12565 if( !SCIPrationalIsAbsInfinity(newbound) )
12566 {
12567 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12568 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12569 }
12570 else
12571 SCIPrationalNegate(parentnewbound, newbound);
12572
12573 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12574 }
12575 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12576 break;
12577
12578 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12579 assert(parentvar->negatedvar != NULL);
12581 assert(parentvar->negatedvar->negatedvar == parentvar);
12582 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12583 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
12584 SCIPrationalNegate(parentnewbound, parentnewbound);
12585 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue,
12586 parentnewbound) );
12587 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12588 break;
12589
12590 default:
12591 SCIPerrorMessage("unknown variable status\n");
12592 return SCIP_INVALIDDATA;
12593 }
12594 }
12595
12596 SCIPrationalFreeBuffer(set->buffer, &oldbound);
12597
12598 return SCIP_OKAY;
12599}
12600
12601/** performs the current change in upper bound, changes all parents accordingly */
12602static
12604 SCIP_VAR* var, /**< problem variable to change */
12605 BMS_BLKMEM* blkmem, /**< block memory */
12606 SCIP_SET* set, /**< global SCIP settings */
12607 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12608 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12609 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12610 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12611 SCIP_RATIONAL* newbound /**< new bound for variable */
12612 )
12613{
12614 SCIP_VAR* parentvar;
12615 SCIP_RATIONAL* oldbound;
12616 SCIP_RATIONAL* parentnewbound;
12617 int i;
12618
12619 assert(var != NULL);
12620 assert(set != NULL);
12621 assert(var->scip == set->scip);
12623 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12625 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12626 || !SCIPvarIsIntegral(var));
12627
12628 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
12629
12630 /* check that the bound is feasible */
12631 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
12632 /* adjust bound to integral value if variable is of integral type */
12634
12636 {
12637 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12638 SCIPrationalMax(newbound, newbound, var->exactdata->locdom.lb);
12639
12640 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12641 SCIPrationalMin(newbound, newbound, var->exactdata->glbdom.ub);
12642 }
12644
12645 SCIPrationalDebugMessage("process changing exact upper bound of <%s> from %q to %q\n", var->name, var->exactdata->locdom.ub, newbound);
12646
12647 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.ub) && !SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub) ) /*lint !e777*/
12648 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
12649
12650 /* change the bound */
12651 SCIPrationalSetRational(oldbound, var->exactdata->locdom.ub);
12652 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->locdom.lb));
12653 SCIPrationalSetRational(var->exactdata->locdom.ub, newbound);
12654 var->locdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
12655
12656 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12657 * once update the statistic
12658 */
12659 if( stat != NULL )
12660 SCIPstatIncrement(stat, set, domchgcount);
12661
12662 /* issue bound change event */
12663 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12664 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12665 {
12666 SCIP_CALL( varEventUbChangedExact(var, blkmem, set, lpexact, branchcand, eventqueue, oldbound, newbound) );
12667 }
12668
12669 /* process parent variables */
12670 for( i = 0; i < var->nparentvars; ++i )
12671 {
12672 parentvar = var->parentvars[i];
12673 assert(parentvar != NULL);
12674
12675 switch( SCIPvarGetStatus(parentvar) )
12676 {
12678 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, newbound) );
12679 break;
12680
12685 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12686 return SCIP_INVALIDDATA;
12687
12688 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12689 assert(parentvar->data.aggregate.var == var);
12690 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12692 {
12693 /* a > 0 -> change upper bound of y */
12694 if( !SCIPrationalIsAbsInfinity(newbound) )
12695 {
12696 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12697 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12698 }
12699 else
12700 SCIPrationalSetRational(parentnewbound, newbound);
12701
12702 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12703 }
12704 else
12705 {
12706 /* a < 0 -> change lower bound of y */
12707 if( !SCIPrationalIsAbsInfinity(newbound) )
12708 {
12709 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12710 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12711 }
12712 else
12713 SCIPrationalNegate(parentnewbound, newbound);
12714
12715 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12716 }
12717 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12718 break;
12719
12720 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12721 assert(parentvar->negatedvar != NULL);
12723 assert(parentvar->negatedvar->negatedvar == parentvar);
12724 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12725 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
12726 SCIPrationalNegate(parentnewbound, parentnewbound);
12727 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue,
12728 parentnewbound) );
12729 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12730 break;
12731
12732 default:
12733 SCIPerrorMessage("unknown variable status\n");
12734 return SCIP_INVALIDDATA;
12735 }
12736 }
12737
12738 SCIPrationalFreeBuffer(set->buffer, &oldbound);
12739
12740 return SCIP_OKAY;
12741}
12742
12743/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
12744 * information in variable
12745 */
12747 SCIP_VAR* var, /**< problem variable to change */
12748 BMS_BLKMEM* blkmem, /**< block memory */
12749 SCIP_SET* set, /**< global SCIP settings */
12750 SCIP_STAT* stat, /**< problem statistics */
12751 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12752 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12753 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12754 SCIP_Real newbound /**< new bound for variable */
12755 )
12756{
12757 assert(var != NULL);
12758 assert(blkmem != NULL);
12759 assert(set != NULL);
12760 assert(var->scip == set->scip);
12761
12762 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
12763 * of the domain within feastol
12764 */
12765 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
12766
12767 /* adjust bound to integral value if variable is of integral type */
12768 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
12769
12770 /* check that the adjusted bound is feasible */
12771 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
12772
12774 {
12775 /* we do not want to exceed the upperbound, which could have happened due to numerics */
12776 newbound = MIN(newbound, var->locdom.ub);
12777 }
12779
12780 SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
12781
12782 if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
12783 && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
12784 return SCIP_OKAY;
12785
12788
12789 /* change bounds of attached variables */
12790 switch( SCIPvarGetStatus(var) )
12791 {
12793 if( var->data.original.transvar != NULL )
12794 {
12795 SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
12796 newbound) );
12797 }
12798 else
12799 {
12800 assert(set->stage == SCIP_STAGE_PROBLEM);
12801 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
12802 }
12803 break;
12804
12807 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
12808 break;
12809
12811 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
12812 return SCIP_INVALIDDATA;
12813
12814 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12815 {
12816 SCIP_VAR* aggrvar;
12817 SCIP_Real childnewbound;
12818 SCIP_Real scalar;
12819 SCIP_Real constant;
12820
12821 scalar = var->data.aggregate.scalar;
12822 constant = var->data.aggregate.constant;
12823 aggrvar = var->data.aggregate.var;
12824 assert(aggrvar != NULL);
12825
12826 if( SCIPsetIsPositive(set, scalar) )
12827 {
12828 /* a > 0 -> change lower bound of y */
12829 assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -aggrvar->locdom.lb))
12830 || SCIPsetIsFeasEQ(set, var->locdom.lb, aggrvar->locdom.lb * scalar + constant));
12831 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12832 childnewbound = (newbound - constant) / scalar;
12833 else
12834 childnewbound = newbound;
12835 SCIP_CALL( SCIPvarChgLbLocal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue,
12836 childnewbound) );
12837 }
12838 else if( SCIPsetIsNegative(set, scalar) )
12839 {
12840 /* a < 0 -> change upper bound of y */
12841 assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, aggrvar->locdom.ub))
12842 || SCIPsetIsFeasEQ(set, var->locdom.lb, aggrvar->locdom.ub * scalar + constant));
12843 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12844 childnewbound = (newbound - constant) / scalar;
12845 else
12846 childnewbound = -newbound;
12847 SCIP_CALL( SCIPvarChgUbLocal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue,
12848 childnewbound) );
12849 }
12850 else
12851 {
12852 SCIPerrorMessage("scalar is zero in aggregation\n");
12853 return SCIP_INVALIDDATA;
12854 }
12855 break;
12856 }
12857
12859 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
12860 return SCIP_INVALIDDATA;
12861
12862 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12863 assert(var->negatedvar != NULL);
12865 assert(var->negatedvar->negatedvar == var);
12866 SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
12867 var->data.negate.constant - newbound) );
12868 break;
12869
12870 default:
12871 SCIPerrorMessage("unknown variable status\n");
12872 return SCIP_INVALIDDATA;
12873 }
12874
12875 return SCIP_OKAY;
12876}
12877
12878/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
12879 * information in variable
12880 */
12882 SCIP_VAR* var, /**< problem variable to change */
12883 BMS_BLKMEM* blkmem, /**< block memory */
12884 SCIP_SET* set, /**< global SCIP settings */
12885 SCIP_STAT* stat, /**< problem statistics */
12886 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12887 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12888 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12889 SCIP_RATIONAL* newbound /**< new bound for variable */
12890 )
12891{
12892 assert(var != NULL);
12893 assert(blkmem != NULL);
12894 assert(set != NULL);
12895 assert(var->scip == set->scip);
12896
12897 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
12898 * of the domain within feastol
12899 */
12900 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->locdom.ub));
12901
12902 /* adjust bound to integral value if variable is of integral type */
12904
12905 /* check that the adjusted bound is feasible */
12906 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->locdom.ub));
12907
12909 {
12910 /* we do not want to exceed the upperbound, which could have happened due to numerics */
12911 SCIPrationalMin(newbound, newbound, var->exactdata->locdom.ub);
12912 }
12914
12915 SCIPrationalDebugMessage("changing lower bound of <%s>[%q,%q] to %q\n", var->name, var->exactdata->locdom.lb, var->exactdata->locdom.ub, newbound);
12916
12919
12920 /* change bounds of attached variables */
12921 switch( SCIPvarGetStatusExact(var) )
12922 {
12924 if( var->data.original.transvar != NULL )
12925 {
12926 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
12927 newbound) );
12928 }
12929 else
12930 {
12931 assert(set->stage == SCIP_STAGE_PROBLEM);
12932 SCIP_CALL( varProcessChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
12933 }
12934 break;
12935
12938 SCIP_CALL( varProcessChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
12939 break;
12940
12942 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
12943 return SCIP_INVALIDDATA;
12944
12945 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12946 assert(var->data.aggregate.var != NULL);
12947 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
12948 {
12949 SCIP_RATIONAL* childnewbound;
12950
12951 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
12952
12953 /* a > 0 -> change lower bound of y */
12954 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
12955 {
12956 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
12957 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
12958 }
12959 else
12960 SCIPrationalSetRational(childnewbound, newbound);
12961
12962 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
12963 childnewbound) );
12964
12965 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
12966 }
12967 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
12968 {
12969 SCIP_RATIONAL* childnewbound;
12970
12971 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
12972
12973 /* a < 0 -> change upper bound of y */
12974 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
12975 {
12976 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
12977 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
12978 }
12979 else
12980 SCIPrationalNegate(childnewbound, newbound);
12981
12982 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
12983 childnewbound) );
12984
12985 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
12986 }
12987 else
12988 {
12989 SCIPerrorMessage("scalar is zero in aggregation\n");
12990 return SCIP_INVALIDDATA;
12991 }
12992 break;
12993
12995 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
12996 return SCIP_INVALIDDATA;
12997
12998 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12999 assert(var->negatedvar != NULL);
13001 assert(var->negatedvar->negatedvar == var);
13002 SCIPrationalDiffReal(newbound, newbound, var->data.negate.constant);
13003 SCIPrationalNegate(newbound, newbound);
13004 SCIP_CALL( SCIPvarChgUbLocalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
13005 newbound) );
13006 break;
13007
13008 default:
13009 SCIPerrorMessage("unknown variable status\n");
13010 return SCIP_INVALIDDATA;
13011 }
13012
13013 return SCIP_OKAY;
13014}
13015
13016/** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
13017 * information in variable
13018 */
13020 SCIP_VAR* var, /**< problem variable to change */
13021 BMS_BLKMEM* blkmem, /**< block memory */
13022 SCIP_SET* set, /**< global SCIP settings */
13023 SCIP_STAT* stat, /**< problem statistics */
13024 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
13025 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
13026 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
13027 SCIP_Real newbound /**< new bound for variable */
13028 )
13029{
13030 assert(var != NULL);
13031 assert(blkmem != NULL);
13032 assert(set != NULL);
13033 assert(var->scip == set->scip);
13034
13035 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
13036 * of the domain within feastol
13037 */
13038 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
13039
13040 /* adjust bound to integral value if variable is of integral type */
13041 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
13042
13043 /* check that the adjusted bound is feasible */
13044 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
13045
13047 {
13048 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
13049 newbound = MAX(newbound, var->locdom.lb);
13050 }
13052
13053 SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
13054
13055 if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
13056 && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
13057 return SCIP_OKAY;
13058
13061
13062 /* change bounds of attached variables */
13063 switch( SCIPvarGetStatus(var) )
13064 {
13066 if( var->data.original.transvar != NULL )
13067 {
13068 SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13069 }
13070 else
13071 {
13072 assert(set->stage == SCIP_STAGE_PROBLEM);
13073 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13074 }
13075 break;
13076
13079 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13080 break;
13081
13083 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13084 return SCIP_INVALIDDATA;
13085
13086 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13087 {
13088 SCIP_VAR* aggrvar;
13089 SCIP_Real childnewbound;
13090 SCIP_Real scalar;
13091 SCIP_Real constant;
13092
13093 scalar = var->data.aggregate.scalar;
13094 constant = var->data.aggregate.constant;
13095 aggrvar = var->data.aggregate.var;
13096 assert(aggrvar != NULL);
13097
13098 if( SCIPsetIsPositive(set, scalar) )
13099 {
13100 /* a > 0 -> change upper bound of y */
13101 assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, aggrvar->locdom.ub))
13102 || SCIPsetIsFeasEQ(set, var->locdom.ub, aggrvar->locdom.ub * scalar + constant));
13103 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13104 childnewbound = (newbound - constant) / scalar;
13105 else
13106 childnewbound = newbound;
13107 SCIP_CALL( SCIPvarChgUbLocal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue,
13108 childnewbound) );
13109 }
13110 else if( SCIPsetIsNegative(set, scalar) )
13111 {
13112 /* a < 0 -> change lower bound of y */
13113 assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -aggrvar->locdom.lb))
13114 || SCIPsetIsFeasEQ(set, var->locdom.ub, aggrvar->locdom.lb * scalar + constant));
13115 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13116 childnewbound = (newbound - constant) / scalar;
13117 else
13118 childnewbound = -newbound;
13119 SCIP_CALL( SCIPvarChgLbLocal(aggrvar, blkmem, set, stat, lp, branchcand, eventqueue,
13120 childnewbound) );
13121 }
13122 else
13123 {
13124 SCIPerrorMessage("scalar is zero in aggregation\n");
13125 return SCIP_INVALIDDATA;
13126 }
13127 break;
13128 }
13129
13131 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13132 return SCIP_INVALIDDATA;
13133
13134 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13135 assert(var->negatedvar != NULL);
13137 assert(var->negatedvar->negatedvar == var);
13138 SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
13139 var->data.negate.constant - newbound) );
13140 break;
13141
13142 default:
13143 SCIPerrorMessage("unknown variable status\n");
13144 return SCIP_INVALIDDATA;
13145 }
13146
13147 return SCIP_OKAY;
13148}
13149
13150/** changes current exact local upper bound of variable; if possible, adjusts bound to integral value; stores inference
13151 * information in variable
13152 */
13154 SCIP_VAR* var, /**< problem variable to change */
13155 BMS_BLKMEM* blkmem, /**< block memory */
13156 SCIP_SET* set, /**< global SCIP settings */
13157 SCIP_STAT* stat, /**< problem statistics */
13158 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
13159 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
13160 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
13161 SCIP_RATIONAL* newbound /**< new bound for variable */
13162 )
13163{
13164 assert(var != NULL);
13165 assert(blkmem != NULL);
13166 assert(set != NULL);
13167 assert(var->scip == set->scip);
13168
13169 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
13170 * of the domain within feastol
13171 */
13172 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->locdom.lb));
13173
13174 /* adjust bound to integral value if variable is of integral type */
13176
13177 /* check that the adjusted bound is feasible */
13178 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->locdom.lb));
13179
13181 {
13182 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
13183 SCIPrationalMax(newbound, newbound, var->exactdata->locdom.lb);
13184 }
13186
13187 SCIPrationalDebugMessage("changing upper bound of <%s>[%q,%q] to %q\n", var->name, var->exactdata->locdom.lb, var->exactdata->locdom.ub, newbound);
13188
13191
13192 /* change bounds of attached variables */
13193 switch( SCIPvarGetStatusExact(var) )
13194 {
13196 if( var->data.original.transvar != NULL )
13197 {
13198 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
13199 newbound) );
13200 }
13201 else
13202 {
13203 assert(set->stage == SCIP_STAGE_PROBLEM);
13204 SCIP_CALL( varProcessChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
13205 }
13206 break;
13207
13210 SCIP_CALL( varProcessChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
13211 break;
13212
13214 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13215 return SCIP_INVALIDDATA;
13216
13217 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13218 assert(var->data.aggregate.var != NULL);
13219 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
13220 {
13221 SCIP_RATIONAL* childnewbound;
13222
13223 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
13224
13225 /* a > 0 -> change upper bound of y */
13226 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
13227 {
13228 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
13229 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
13230 }
13231 else
13232 SCIPrationalSetRational(childnewbound, newbound);
13233 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
13234 childnewbound) );
13235
13236 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
13237 }
13238 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
13239 {
13240 SCIP_RATIONAL* childnewbound;
13241
13242 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
13243
13244 /* a < 0 -> change lower bound of y */
13245 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
13246 {
13247 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
13248 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
13249 }
13250 else
13251 SCIPrationalNegate(childnewbound, newbound);
13252
13253 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
13254 childnewbound) );
13255
13256 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
13257 }
13258 else
13259 {
13260 SCIPerrorMessage("scalar is zero in aggregation\n");
13261 return SCIP_INVALIDDATA;
13262 }
13263 break;
13264
13266 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13267 return SCIP_INVALIDDATA;
13268
13269 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13270 assert(var->negatedvar != NULL);
13272 assert(var->negatedvar->negatedvar == var);
13273 SCIPrationalDiffReal(newbound, newbound, var->data.negate.constant);
13274 SCIPrationalNegate(newbound, newbound);
13275 SCIP_CALL( SCIPvarChgLbLocalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
13276 newbound) );
13277 break;
13278
13279 default:
13280 SCIPerrorMessage("unknown variable status\n");
13281 return SCIP_INVALIDDATA;
13282 }
13283
13284 return SCIP_OKAY;
13285}
13286
13287/** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
13288 * information in variable
13289 */
13291 SCIP_VAR* var, /**< problem variable to change */
13292 BMS_BLKMEM* blkmem, /**< block memory */
13293 SCIP_SET* set, /**< global SCIP settings */
13294 SCIP_STAT* stat, /**< problem statistics */
13295 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
13296 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
13297 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
13298 SCIP_Real newbound, /**< new bound for variable */
13299 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13300 )
13301{
13302 /* apply bound change to the LP data */
13303 switch( boundtype )
13304 {
13306 return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
13308 return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
13309 default:
13310 SCIPerrorMessage("unknown bound type\n");
13311 return SCIP_INVALIDDATA;
13312 }
13313}
13314
13315/** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
13317 SCIP_VAR* var, /**< problem variable to change */
13318 SCIP_SET* set, /**< global SCIP settings */
13319 SCIP_LP* lp, /**< current LP data */
13320 SCIP_Real newbound /**< new bound for variable */
13321 )
13322{
13323 assert(var != NULL);
13324 assert(set != NULL);
13325 assert(var->scip == set->scip);
13326 assert(lp != NULL);
13327 assert(SCIPlpDiving(lp));
13328
13329 /* adjust bound for integral variables */
13330 SCIPvarAdjustLb(var, set, &newbound);
13331
13332 SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
13333
13334 /* change bounds of attached variables */
13335 switch( SCIPvarGetStatus(var) )
13336 {
13338 assert(var->data.original.transvar != NULL);
13339 SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
13340 break;
13341
13343 assert(var->data.col != NULL);
13344 SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
13345 break;
13346
13348 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13349 return SCIP_INVALIDDATA;
13350
13352 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13353 return SCIP_INVALIDDATA;
13354
13355 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13356 assert(var->data.aggregate.var != NULL);
13357 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13358 {
13359 SCIP_Real childnewbound;
13360
13361 /* a > 0 -> change lower bound of y */
13362 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13363 childnewbound = (newbound - var->data.aggregate.constant) / var->data.aggregate.scalar;
13364 else
13365 childnewbound = newbound;
13366 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
13367 }
13368 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13369 {
13370 SCIP_Real childnewbound;
13371
13372 /* a < 0 -> change upper bound of y */
13373 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13374 childnewbound = (newbound - var->data.aggregate.constant) / var->data.aggregate.scalar;
13375 else
13376 childnewbound = -newbound;
13377 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
13378 }
13379 else
13380 {
13381 SCIPerrorMessage("scalar is zero in aggregation\n");
13382 return SCIP_INVALIDDATA;
13383 }
13384 break;
13385
13387 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13388 return SCIP_INVALIDDATA;
13389
13390 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13391 assert(var->negatedvar != NULL);
13393 assert(var->negatedvar->negatedvar == var);
13394 SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
13395 break;
13396
13397 default:
13398 SCIPerrorMessage("unknown variable status\n");
13399 return SCIP_INVALIDDATA;
13400 }
13401
13402 return SCIP_OKAY;
13403}
13404
13405/** changes lower bound of variable in current exact dive */
13407 SCIP_VAR* var, /**< problem variable to change */
13408 SCIP_SET* set, /**< global SCIP settings */
13409 SCIP_LPEXACT* lpexact, /**< current exact LP data */
13410 SCIP_RATIONAL* newbound /**< new bound for variable */
13411 )
13412{
13413 assert(var != NULL);
13414 assert(set != NULL);
13415 assert(var->scip == set->scip);
13416 assert(lpexact != NULL);
13417 assert(SCIPlpExactDiving(lpexact));
13418
13419 SCIPrationalDebugMessage("changing lower bound of <%s> to %q in current exact dive\n", var->name, newbound);
13420
13421 /* change bounds of attached variables */
13422 switch( SCIPvarGetStatusExact(var) )
13423 {
13425 assert(var->data.original.transvar != NULL);
13426 SCIP_CALL( SCIPvarChgLbExactDive(var->data.original.transvar, set, lpexact, newbound) );
13427 break;
13428
13430 assert(var->data.col != NULL);
13431 SCIP_CALL( SCIPcolExactChgLb(var->exactdata->colexact, set, lpexact, newbound) );
13432 break;
13433
13435 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13436 return SCIP_INVALIDDATA;
13437
13439 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13440 return SCIP_INVALIDDATA;
13441
13442 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13443 SCIPerrorMessage("cannot change the bounds of an aggregated variable\n");
13444 return SCIP_INVALIDDATA;
13445
13447 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable\n");
13448 return SCIP_INVALIDDATA;
13449
13450 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13451 SCIPerrorMessage("cannot change the bounds of a negated variable\n");
13452 return SCIP_INVALIDDATA;
13453
13454 default:
13455 SCIPerrorMessage("unknown variable status\n");
13456 return SCIP_INVALIDDATA;
13457 }
13458
13459 return SCIP_OKAY;
13460}
13461
13462/** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
13464 SCIP_VAR* var, /**< problem variable to change */
13465 SCIP_SET* set, /**< global SCIP settings */
13466 SCIP_LP* lp, /**< current LP data */
13467 SCIP_Real newbound /**< new bound for variable */
13468 )
13469{
13470 assert(var != NULL);
13471 assert(set != NULL);
13472 assert(var->scip == set->scip);
13473 assert(lp != NULL);
13474 assert(SCIPlpDiving(lp));
13475
13476 /* adjust bound for integral variables */
13477 SCIPvarAdjustUb(var, set, &newbound);
13478
13479 SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
13480
13481 /* change bounds of attached variables */
13482 switch( SCIPvarGetStatus(var) )
13483 {
13485 assert(var->data.original.transvar != NULL);
13486 SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
13487 break;
13488
13490 assert(var->data.col != NULL);
13491 SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
13492 break;
13493
13495 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13496 return SCIP_INVALIDDATA;
13497
13499 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13500 return SCIP_INVALIDDATA;
13501
13502 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13503 assert(var->data.aggregate.var != NULL);
13504 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13505 {
13506 SCIP_Real childnewbound;
13507
13508 /* a > 0 -> change upper bound of y */
13509 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13510 childnewbound = (newbound - var->data.aggregate.constant) / var->data.aggregate.scalar;
13511 else
13512 childnewbound = newbound;
13513 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
13514 }
13515 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13516 {
13517 SCIP_Real childnewbound;
13518
13519 /* a < 0 -> change lower bound of y */
13520 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13521 childnewbound = (newbound - var->data.aggregate.constant) / var->data.aggregate.scalar;
13522 else
13523 childnewbound = -newbound;
13524 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
13525 }
13526 else
13527 {
13528 SCIPerrorMessage("scalar is zero in aggregation\n");
13529 return SCIP_INVALIDDATA;
13530 }
13531 break;
13532
13534 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13535 return SCIP_INVALIDDATA;
13536
13537 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13538 assert(var->negatedvar != NULL);
13540 assert(var->negatedvar->negatedvar == var);
13541 SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
13542 break;
13543
13544 default:
13545 SCIPerrorMessage("unknown variable status\n");
13546 return SCIP_INVALIDDATA;
13547 }
13548
13549 return SCIP_OKAY;
13550}
13551
13552/** changes upper bound of variable in current exact dive */
13554 SCIP_VAR* var, /**< problem variable to change */
13555 SCIP_SET* set, /**< global SCIP settings */
13556 SCIP_LPEXACT* lpexact, /**< current exact LP data */
13557 SCIP_RATIONAL* newbound /**< new bound for variable */
13558 )
13559{
13560 assert(var != NULL);
13561 assert(set != NULL);
13562 assert(var->scip == set->scip);
13563 assert(lpexact != NULL);
13564 assert(SCIPlpExactDiving(lpexact));
13565
13566 SCIPrationalDebugMessage("changing upper bound of <%s> to %d in current dive\n", var->name, newbound);
13567
13568 /* change bounds of attached variables */
13569 switch( SCIPvarGetStatusExact(var) )
13570 {
13572 assert(var->data.original.transvar != NULL);
13573 SCIP_CALL( SCIPvarChgUbExactDive(var->data.original.transvar, set, lpexact, newbound) );
13574 break;
13575
13577 assert(var->data.col != NULL);
13578 SCIP_CALL( SCIPcolExactChgUb(var->exactdata->colexact, set, lpexact, newbound) );
13579 break;
13580
13582 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13583 return SCIP_INVALIDDATA;
13584
13586 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13587 return SCIP_INVALIDDATA;
13588
13589 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13590 SCIPerrorMessage("cannot change the bounds of an aggregated variable\n");
13591 return SCIP_INVALIDDATA;
13592
13594 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13595 return SCIP_INVALIDDATA;
13596
13597 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13598 SCIPerrorMessage("cannot change the bounds of a negated variable\n");
13599 return SCIP_INVALIDDATA;
13600
13601 default:
13602 SCIPerrorMessage("unknown variable status\n");
13603 return SCIP_INVALIDDATA;
13604 }
13605
13606 return SCIP_OKAY;
13607}
13608
13609/** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
13610 * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
13611 * not updated if bounds of aggregation variables are changing
13612 *
13613 * calling this function for a non-multi-aggregated variable is not allowed
13614 */
13616 SCIP_VAR* var, /**< problem variable */
13617 SCIP_SET* set /**< global SCIP settings */
13618 )
13619{
13620 int i;
13621 SCIP_Real lb;
13622 SCIP_Real bnd;
13623 SCIP_VAR* aggrvar;
13624 SCIP_Bool posinf;
13625 SCIP_Bool neginf;
13626
13627 assert(var != NULL);
13628 assert(set != NULL);
13629 assert(var->scip == set->scip);
13631
13632 posinf = FALSE;
13633 neginf = FALSE;
13634 lb = var->data.multaggr.constant;
13635 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13636 {
13637 aggrvar = var->data.multaggr.vars[i];
13638 if( var->data.multaggr.scalars[i] > 0.0 )
13639 {
13641
13642 if( SCIPsetIsInfinity(set, bnd) )
13643 posinf = TRUE;
13644 else if( SCIPsetIsInfinity(set, -bnd) )
13645 neginf = TRUE;
13646 else
13647 lb += var->data.multaggr.scalars[i] * bnd;
13648 }
13649 else
13650 {
13652
13653 if( SCIPsetIsInfinity(set, -bnd) )
13654 posinf = TRUE;
13655 else if( SCIPsetIsInfinity(set, bnd) )
13656 neginf = TRUE;
13657 else
13658 lb += var->data.multaggr.scalars[i] * bnd;
13659 }
13660
13661 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13662 * variable
13663 */
13664 if( neginf )
13665 return SCIPvarGetLbLocal(var);
13666 }
13667
13668 /* if positive infinity flag was set to true return infinity */
13669 if( posinf )
13670 return SCIPsetInfinity(set);
13671
13672 return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
13673}
13674
13675/** for a multi-aggregated variable, gives the exact local lower bound computed by adding the local bounds from all
13676 * aggregation variables; this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
13677 * not updated if bounds of aggregation variables are changing
13678 *
13679 * calling this function for a non-multi-aggregated variable is not allowed
13680 */
13682 SCIP_VAR* var, /**< problem variable */
13683 SCIP_SET* set, /**< global SCIP settings */
13684 SCIP_RATIONAL* result /**< the resulting bound */
13685 )
13686{
13687 int i;
13688 SCIP_RATIONAL* lb;
13689 SCIP_RATIONAL* bnd;
13690 SCIP_VAR* aggrvar;
13691 SCIP_Bool posinf;
13692 SCIP_Bool neginf;
13693
13694 assert(var != NULL);
13695 assert(set != NULL);
13696 assert(var->scip == set->scip);
13698
13699 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lb) );
13700 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &bnd) );
13701
13702 posinf = FALSE;
13703 neginf = FALSE;
13704 SCIPrationalSetRational(lb, var->exactdata->multaggr.constant);
13705 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13706 {
13707 aggrvar = var->data.multaggr.vars[i];
13708 if( SCIPrationalIsPositive(var->exactdata->multaggr.scalars[i]) )
13709 {
13712 else
13714
13715 if( SCIPrationalIsInfinity(bnd) )
13716 posinf = TRUE;
13717 else if( SCIPrationalIsNegInfinity(bnd) )
13718 neginf = TRUE;
13719 else
13720 SCIPrationalAddProd(lb, var->exactdata->multaggr.scalars[i], bnd);
13721 }
13722 else
13723 {
13726 else
13728
13729 if( SCIPrationalIsNegInfinity(bnd) )
13730 posinf = TRUE;
13731 else if( SCIPrationalIsInfinity(bnd) )
13732 neginf = TRUE;
13733 else
13734 SCIPrationalAddProd(lb, var->exactdata->multaggr.scalars[i], bnd);
13735 }
13736
13737 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13738 * variable
13739 */
13740 if( neginf )
13741 {
13743 break;
13744 }
13745 }
13746
13747 /* if positive infinity flag was set to true return infinity */
13748 if( posinf && !neginf )
13750 else
13752
13753 SCIPrationalFreeBuffer(set->buffer, &bnd);
13754 SCIPrationalFreeBuffer(set->buffer, &lb);
13755
13756 return SCIP_OKAY;
13757}
13758
13759/** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
13760 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
13761 * not updated if bounds of aggregation variables are changing
13762 *
13763 * calling this function for a non-multi-aggregated variable is not allowed
13764 */
13766 SCIP_VAR* var, /**< problem variable */
13767 SCIP_SET* set /**< global SCIP settings */
13768 )
13769{
13770 int i;
13771 SCIP_Real ub;
13772 SCIP_Real bnd;
13773 SCIP_VAR* aggrvar;
13774 SCIP_Bool posinf;
13775 SCIP_Bool neginf;
13776
13777 assert(var != NULL);
13778 assert(set != NULL);
13779 assert(var->scip == set->scip);
13781
13782 posinf = FALSE;
13783 neginf = FALSE;
13784 ub = var->data.multaggr.constant;
13785 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13786 {
13787 aggrvar = var->data.multaggr.vars[i];
13788 if( var->data.multaggr.scalars[i] > 0.0 )
13789 {
13791
13792 if( SCIPsetIsInfinity(set, bnd) )
13793 posinf = TRUE;
13794 else if( SCIPsetIsInfinity(set, -bnd) )
13795 neginf = TRUE;
13796 else
13797 ub += var->data.multaggr.scalars[i] * bnd;
13798 }
13799 else
13800 {
13802
13803 if( SCIPsetIsInfinity(set, -bnd) )
13804 posinf = TRUE;
13805 else if( SCIPsetIsInfinity(set, bnd) )
13806 neginf = TRUE;
13807 else
13808 ub += var->data.multaggr.scalars[i] * bnd;
13809 }
13810
13811 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
13812 * variable
13813 */
13814 if( posinf )
13815 return SCIPvarGetUbLocal(var);
13816 }
13817
13818 /* if negative infinity flag was set to true return -infinity */
13819 if( neginf )
13820 return -SCIPsetInfinity(set);
13821
13822 return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
13823}
13824
13825/** for a multi-aggregated variable, gives the exact local upper bound computed by adding the local bounds from all aggregation variables
13826 * this upper bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is not updated if bounds of aggregation variables are changing
13827 * calling this function for a non-multi-aggregated variable is not allowed
13828 */
13830 SCIP_VAR* var, /**< problem variable */
13831 SCIP_SET* set, /**< global SCIP settings */
13832 SCIP_RATIONAL* result /**< the resulting bound */
13833 )
13834{
13835 int i;
13836 SCIP_RATIONAL* ub;
13837 SCIP_RATIONAL* bnd;
13838 SCIP_VAR* aggrvar;
13839 SCIP_Bool posinf;
13840 SCIP_Bool neginf;
13841
13842 assert(var != NULL);
13843 assert(set != NULL);
13844 assert(var->scip == set->scip);
13846
13847 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &ub) );
13848 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &bnd) );
13849
13850 posinf = FALSE;
13851 neginf = FALSE;
13852 SCIPrationalSetRational(ub, var->exactdata->multaggr.constant);
13853 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13854 {
13855 aggrvar = var->data.multaggr.vars[i];
13856 if( SCIPrationalIsPositive(var->exactdata->multaggr.scalars[i]) )
13857 {
13860 else
13862
13863 if( SCIPrationalIsInfinity(bnd) )
13864 posinf = TRUE;
13865 else if( SCIPrationalIsNegInfinity(bnd) )
13866 neginf = TRUE;
13867 else
13868 SCIPrationalAddProd(ub, var->exactdata->multaggr.scalars[i], bnd);
13869 }
13870 else
13871 {
13874 else
13876
13877 if( SCIPrationalIsNegInfinity(bnd) )
13878 posinf = TRUE;
13879 else if( SCIPrationalIsInfinity(bnd) )
13880 neginf = TRUE;
13881 else
13882 SCIPrationalAddProd(ub, var->exactdata->multaggr.scalars[i], bnd);
13883 }
13884
13885 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13886 * variable
13887 */
13888 if( posinf )
13889 {
13891 break;
13892 }
13893 }
13894
13895 /* if positive infinity flag was set to true return infinity */
13896 if( !posinf && neginf )
13898 else
13900
13901 SCIPrationalFreeBuffer(set->buffer, &bnd);
13902 SCIPrationalFreeBuffer(set->buffer, &ub);
13903
13904 return SCIP_OKAY;
13905}
13906
13907/** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
13908 * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
13909 * not updated if bounds of aggregation variables are changing
13910 *
13911 * calling this function for a non-multi-aggregated variable is not allowed
13912 */
13914 SCIP_VAR* var, /**< problem variable */
13915 SCIP_SET* set /**< global SCIP settings */
13916 )
13917{
13918 int i;
13919 SCIP_Real lb;
13920 SCIP_Real bnd;
13921 SCIP_VAR* aggrvar;
13922 SCIP_Bool posinf;
13923 SCIP_Bool neginf;
13924
13925 assert(var != NULL);
13926 assert(set != NULL);
13927 assert(var->scip == set->scip);
13929
13930 posinf = FALSE;
13931 neginf = FALSE;
13932 lb = var->data.multaggr.constant;
13933 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13934 {
13935 aggrvar = var->data.multaggr.vars[i];
13936 if( var->data.multaggr.scalars[i] > 0.0 )
13937 {
13939
13940 if( SCIPsetIsInfinity(set, bnd) )
13941 posinf = TRUE;
13942 else if( SCIPsetIsInfinity(set, -bnd) )
13943 neginf = TRUE;
13944 else
13945 lb += var->data.multaggr.scalars[i] * bnd;
13946 }
13947 else
13948 {
13950
13951 if( SCIPsetIsInfinity(set, -bnd) )
13952 posinf = TRUE;
13953 else if( SCIPsetIsInfinity(set, bnd) )
13954 neginf = TRUE;
13955 else
13956 lb += var->data.multaggr.scalars[i] * bnd;
13957 }
13958
13959 /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
13960 * variable
13961 */
13962 if( neginf )
13963 return SCIPvarGetLbGlobal(var);
13964 }
13965
13966 /* if positive infinity flag was set to true return infinity */
13967 if( posinf )
13968 return SCIPsetInfinity(set);
13969
13970 return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
13971}
13972
13973/** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
13974 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
13975 * not updated if bounds of aggregation variables are changing
13976 *
13977 * calling this function for a non-multi-aggregated variable is not allowed
13978 */
13980 SCIP_VAR* var, /**< problem variable */
13981 SCIP_SET* set /**< global SCIP settings */
13982 )
13983{
13984 int i;
13985 SCIP_Real ub;
13986 SCIP_Real bnd;
13987 SCIP_VAR* aggrvar;
13988 SCIP_Bool posinf;
13989 SCIP_Bool neginf;
13990
13991 assert(var != NULL);
13992 assert(set != NULL);
13993 assert(var->scip == set->scip);
13995
13996 posinf = FALSE;
13997 neginf = FALSE;
13998 ub = var->data.multaggr.constant;
13999 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
14000 {
14001 aggrvar = var->data.multaggr.vars[i];
14002 if( var->data.multaggr.scalars[i] > 0.0 )
14003 {
14005
14006 if( SCIPsetIsInfinity(set, bnd) )
14007 posinf = TRUE;
14008 else if( SCIPsetIsInfinity(set, -bnd) )
14009 neginf = TRUE;
14010 else
14011 ub += var->data.multaggr.scalars[i] * bnd;
14012 }
14013 else
14014 {
14016
14017 if( SCIPsetIsInfinity(set, -bnd) )
14018 posinf = TRUE;
14019 else if( SCIPsetIsInfinity(set, bnd) )
14020 neginf = TRUE;
14021 else
14022 ub += var->data.multaggr.scalars[i] * bnd;
14023 }
14024
14025 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
14026 * variable
14027 */
14028 if( posinf )
14029 return SCIPvarGetUbGlobal(var);
14030 }
14031
14032 /* if negative infinity flag was set to true return -infinity */
14033 if( neginf )
14034 return -SCIPsetInfinity(set);
14035
14036 return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
14037}
14038
14039/** adds a hole to the original domain of the variable */
14041 SCIP_VAR* var, /**< problem variable */
14042 BMS_BLKMEM* blkmem, /**< block memory */
14043 SCIP_SET* set, /**< global SCIP settings */
14044 SCIP_Real left, /**< left bound of open interval in new hole */
14045 SCIP_Real right /**< right bound of open interval in new hole */
14046 )
14047{
14048 SCIP_Bool added;
14049
14050 assert(var != NULL);
14054 assert(set != NULL);
14055 assert(var->scip == set->scip);
14056 assert(set->stage == SCIP_STAGE_PROBLEM);
14057
14058 SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
14059
14060 if( SCIPsetIsEQ(set, left, right) )
14061 return SCIP_OKAY;
14062
14063 /* the interval should not be empty */
14064 assert(SCIPsetIsLT(set, left, right));
14065
14066 /* the the interval bound should already be adjusted */
14069
14070 /* the the interval should lay between the lower and upper bound */
14073
14074 /* add domain hole */
14075 SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
14076
14077 /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
14078 if( added )
14079 {
14080 domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
14081 }
14082
14083 /**@todo add hole in parent and child variables (just like with bound changes);
14084 * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
14085 */
14086
14087 return SCIP_OKAY;
14088}
14089
14090/** performs the current add of domain, changes all parents accordingly */
14091static
14093 SCIP_VAR* var, /**< problem variable */
14094 BMS_BLKMEM* blkmem, /**< block memory */
14095 SCIP_SET* set, /**< global SCIP settings */
14096 SCIP_STAT* stat, /**< problem statistics */
14097 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14098 SCIP_Real left, /**< left bound of open interval in new hole */
14099 SCIP_Real right, /**< right bound of open interval in new hole */
14100 SCIP_Bool* added /**< pointer to store whether the hole was added */
14101 )
14102{
14103 SCIP_VAR* parentvar;
14104 SCIP_Real newlb;
14105 SCIP_Real newub;
14106 int i;
14107
14108 assert(var != NULL);
14109 assert(added != NULL);
14110 assert(blkmem != NULL);
14111
14112 /* the interval should not be empty */
14113 assert(SCIPsetIsLT(set, left, right));
14114
14115 /* the interval bound should already be adjusted */
14118
14119 /* the interval should lay between the lower and upper bound */
14122
14123 /* @todo add debugging mechanism for holes when using a debugging solution */
14124
14125 /* add hole to hole list */
14126 SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
14127
14128 /* check if the hole is redundant */
14129 if( !(*added) )
14130 return SCIP_OKAY;
14131
14132 /* current bounds */
14133 newlb = var->glbdom.lb;
14134 newub = var->glbdom.ub;
14135
14136 /* merge domain holes */
14137 domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
14138
14139 /* the bound should not be changed */
14140 assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
14141 assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
14142
14143 /* issue bound change event */
14144 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
14145 if( var->eventfilter != NULL )
14146 {
14147 SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
14148 }
14149
14150 /* process parent variables */
14151 for( i = 0; i < var->nparentvars; ++i )
14152 {
14153 SCIP_Real parentnewleft;
14154 SCIP_Real parentnewright;
14155 SCIP_Bool localadded;
14156
14157 parentvar = var->parentvars[i];
14158 assert(parentvar != NULL);
14159
14160 switch( SCIPvarGetStatus(parentvar) )
14161 {
14163 parentnewleft = left;
14164 parentnewright = right;
14165 break;
14166
14171 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
14172 return SCIP_INVALIDDATA;
14173
14174 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14175 assert(parentvar->data.aggregate.var == var);
14176
14177 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
14178 {
14179 /* a > 0 -> change upper bound of x */
14180 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14181 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14182 }
14183 else
14184 {
14185 /* a < 0 -> change lower bound of x */
14187
14188 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14189 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14190 }
14191 break;
14192
14193 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
14194 assert(parentvar->negatedvar != NULL);
14196 assert(parentvar->negatedvar->negatedvar == parentvar);
14197
14198 parentnewright = -left + parentvar->data.negate.constant;
14199 parentnewleft = -right + parentvar->data.negate.constant;
14200 break;
14201
14202 default:
14203 SCIPerrorMessage("unknown variable status\n");
14204 return SCIP_INVALIDDATA;
14205 }
14206
14207 SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
14208
14209 /* perform hole added for parent variable */
14210 assert(blkmem != NULL);
14211 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
14212 SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
14213 parentnewleft, parentnewright, &localadded) );
14214 assert(localadded);
14215 }
14216
14217 return SCIP_OKAY;
14218}
14219
14220/** adds a hole to the variable's global and local domain */
14222 SCIP_VAR* var, /**< problem variable */
14223 BMS_BLKMEM* blkmem, /**< block memory */
14224 SCIP_SET* set, /**< global SCIP settings */
14225 SCIP_STAT* stat, /**< problem statistics */
14226 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14227 SCIP_Real left, /**< left bound of open interval in new hole */
14228 SCIP_Real right, /**< right bound of open interval in new hole */
14229 SCIP_Bool* added /**< pointer to store whether the hole was added */
14230 )
14231{
14232 SCIP_Real childnewleft;
14233 SCIP_Real childnewright;
14234
14235 assert(var != NULL);
14237 assert(blkmem != NULL);
14238 assert(added != NULL);
14239
14240 SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
14241
14242 /* the interval should not be empty */
14243 assert(SCIPsetIsLT(set, left, right));
14244
14245 /* the the interval bound should already be adjusted */
14248
14249 /* the the interval should lay between the lower and upper bound */
14252
14253 /* change bounds of attached variables */
14254 switch( SCIPvarGetStatus(var) )
14255 {
14257 if( var->data.original.transvar != NULL )
14258 {
14259 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
14260 left, right, added) );
14261 }
14262 else
14263 {
14264 assert(set->stage == SCIP_STAGE_PROBLEM);
14265
14266 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
14267 if( *added )
14268 {
14269 SCIP_Bool localadded;
14270
14271 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
14272 }
14273 }
14274 break;
14275
14278 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
14279 if( *added )
14280 {
14281 SCIP_Bool localadded;
14282
14283 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
14284 }
14285 break;
14286
14288 SCIPerrorMessage("cannot add hole of a fixed variable\n");
14289 return SCIP_INVALIDDATA;
14290
14291 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14292 assert(var->data.aggregate.var != NULL);
14293
14294 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
14295 {
14296 /* a > 0 -> change lower bound of y */
14297 childnewleft = (left - var->data.aggregate.constant) / var->data.aggregate.scalar;
14298 childnewright = (right - var->data.aggregate.constant) / var->data.aggregate.scalar;
14299 }
14300 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
14301 {
14302 childnewright = (left - var->data.aggregate.constant) / var->data.aggregate.scalar;
14303 childnewleft = (right - var->data.aggregate.constant) / var->data.aggregate.scalar;
14304 }
14305 else
14306 {
14307 SCIPerrorMessage("scalar is zero in aggregation\n");
14308 return SCIP_INVALIDDATA;
14309 }
14310 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
14311 childnewleft, childnewright, added) );
14312 break;
14313
14315 SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
14316 return SCIP_INVALIDDATA;
14317
14318 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14319 assert(var->negatedvar != NULL);
14321 assert(var->negatedvar->negatedvar == var);
14322
14323 childnewright = -left + var->data.negate.constant;
14324 childnewleft = -right + var->data.negate.constant;
14325
14326 SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
14327 childnewleft, childnewright, added) );
14328 break;
14329
14330 default:
14331 SCIPerrorMessage("unknown variable status\n");
14332 return SCIP_INVALIDDATA;
14333 }
14334
14335 return SCIP_OKAY;
14336}
14337
14338/** performs the current add of domain, changes all parents accordingly */
14339static
14341 SCIP_VAR* var, /**< problem variable */
14342 BMS_BLKMEM* blkmem, /**< block memory */
14343 SCIP_SET* set, /**< global SCIP settings */
14344 SCIP_STAT* stat, /**< problem statistics */
14345 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14346 SCIP_Real left, /**< left bound of open interval in new hole */
14347 SCIP_Real right, /**< right bound of open interval in new hole */
14348 SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
14349 )
14350{
14351 SCIP_VAR* parentvar;
14352 SCIP_Real newlb;
14353 SCIP_Real newub;
14354 int i;
14355
14356 assert(var != NULL);
14357 assert(added != NULL);
14358 assert(blkmem != NULL);
14359
14360 /* the interval should not be empty */
14361 assert(SCIPsetIsLT(set, left, right));
14362
14363 /* the the interval bound should already be adjusted */
14366
14367 /* the the interval should lay between the lower and upper bound */
14370
14371 /* add hole to hole list */
14372 SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
14373
14374 /* check if the hole is redundant */
14375 if( !(*added) )
14376 return SCIP_OKAY;
14377
14378 /* current bounds */
14379 newlb = var->locdom.lb;
14380 newub = var->locdom.ub;
14381
14382 /* merge domain holes */
14383 domMerge(&var->locdom, blkmem, set, &newlb, &newub);
14384
14385 /* the bound should not be changed */
14386 assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
14387 assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
14388
14389#ifdef SCIP_DISABLED_CODE
14390 /* issue LHOLEADDED event */
14391 SCIP_EVENT event;
14392 assert(var->eventfilter != NULL);
14394 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, var->eventfilter) );
14395#endif
14396
14397 /* process parent variables */
14398 for( i = 0; i < var->nparentvars; ++i )
14399 {
14400 SCIP_Real parentnewleft;
14401 SCIP_Real parentnewright;
14402 SCIP_Bool localadded;
14403
14404 parentvar = var->parentvars[i];
14405 assert(parentvar != NULL);
14406
14407 switch( SCIPvarGetStatus(parentvar) )
14408 {
14410 parentnewleft = left;
14411 parentnewright = right;
14412 break;
14413
14418 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
14419 return SCIP_INVALIDDATA;
14420
14421 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14422 assert(parentvar->data.aggregate.var == var);
14423
14424 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
14425 {
14426 /* a > 0 -> change upper bound of x */
14427 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14428 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14429 }
14430 else
14431 {
14432 /* a < 0 -> change lower bound of x */
14434
14435 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14436 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14437 }
14438 break;
14439
14440 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
14441 assert(parentvar->negatedvar != NULL);
14443 assert(parentvar->negatedvar->negatedvar == parentvar);
14444
14445 parentnewright = -left + parentvar->data.negate.constant;
14446 parentnewleft = -right + parentvar->data.negate.constant;
14447 break;
14448
14449 default:
14450 SCIPerrorMessage("unknown variable status\n");
14451 return SCIP_INVALIDDATA;
14452 }
14453
14454 SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
14455
14456 /* perform hole added for parent variable */
14457 assert(blkmem != NULL);
14458 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
14459 SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
14460 parentnewleft, parentnewright, &localadded) );
14461 assert(localadded);
14462 }
14463
14464 return SCIP_OKAY;
14465}
14466
14467/** adds a hole to the variable's current local domain */
14469 SCIP_VAR* var, /**< problem variable */
14470 BMS_BLKMEM* blkmem, /**< block memory */
14471 SCIP_SET* set, /**< global SCIP settings */
14472 SCIP_STAT* stat, /**< problem statistics */
14473 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14474 SCIP_Real left, /**< left bound of open interval in new hole */
14475 SCIP_Real right, /**< right bound of open interval in new hole */
14476 SCIP_Bool* added /**< pointer to store whether the hole was added */
14477 )
14478{
14479 SCIP_Real childnewleft;
14480 SCIP_Real childnewright;
14481
14482 assert(var != NULL);
14483
14484 SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
14485
14486 assert(set != NULL);
14487 assert(var->scip == set->scip);
14489 assert(blkmem != NULL);
14490 assert(added != NULL);
14491
14492 /* the interval should not be empty */
14493 assert(SCIPsetIsLT(set, left, right));
14494
14495 /* the the interval bound should already be adjusted */
14498
14499 /* the the interval should lay between the lower and upper bound */
14502
14503 /* change bounds of attached variables */
14504 switch( SCIPvarGetStatus(var) )
14505 {
14507 if( var->data.original.transvar != NULL )
14508 {
14509 SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
14510 left, right, added) );
14511 }
14512 else
14513 {
14514 assert(set->stage == SCIP_STAGE_PROBLEM);
14515 SCIPstatIncrement(stat, set, domchgcount);
14516 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
14517 }
14518 break;
14519
14522 SCIPstatIncrement(stat, set, domchgcount);
14523 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
14524 break;
14525
14527 SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
14528 return SCIP_INVALIDDATA;
14529
14530 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14531 assert(var->data.aggregate.var != NULL);
14532
14533 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
14534 {
14535 /* a > 0 -> change lower bound of y */
14536 childnewleft = (left - var->data.aggregate.constant) / var->data.aggregate.scalar;
14537 childnewright = (right - var->data.aggregate.constant) / var->data.aggregate.scalar;
14538 }
14539 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
14540 {
14541 childnewright = (left - var->data.aggregate.constant) / var->data.aggregate.scalar;
14542 childnewleft = (right - var->data.aggregate.constant) / var->data.aggregate.scalar;
14543 }
14544 else
14545 {
14546 SCIPerrorMessage("scalar is zero in aggregation\n");
14547 return SCIP_INVALIDDATA;
14548 }
14549 SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
14550 childnewleft, childnewright, added) );
14551 break;
14552
14554 SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
14555 return SCIP_INVALIDDATA;
14556
14557 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14558 assert(var->negatedvar != NULL);
14560 assert(var->negatedvar->negatedvar == var);
14561
14562 childnewright = -left + var->data.negate.constant;
14563 childnewleft = -right + var->data.negate.constant;
14564
14565 SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
14566 break;
14567
14568 default:
14569 SCIPerrorMessage("unknown variable status\n");
14570 return SCIP_INVALIDDATA;
14571 }
14572
14573 return SCIP_OKAY;
14574}
14575
14576/** resets the global and local bounds of original variable to their original values */
14578 SCIP_VAR* var, /**< problem variable */
14579 BMS_BLKMEM* blkmem, /**< block memory */
14580 SCIP_SET* set, /**< global SCIP settings */
14581 SCIP_STAT* stat /**< problem statistics */
14582 )
14583{
14584 assert(var != NULL);
14585 assert(set != NULL);
14586 assert(var->scip == set->scip);
14588 /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
14589 * the transformed variable has been fixed */
14591
14592 /* copy the original bounds back to the global and local bounds */
14593 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
14594 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
14595 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
14596 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
14597
14598 if( var->exactdata != NULL )
14599 {
14600 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->exactdata->origdom.lb) );
14601 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->exactdata->origdom.ub) );
14602 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, NULL, NULL, NULL, var->exactdata->origdom.lb) );
14603 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, NULL, NULL, NULL, var->exactdata->origdom.ub) );
14604 }
14605
14606 /* free the global and local holelists and duplicate the original ones */
14607 /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
14608 holelistFree(&var->glbdom.holelist, blkmem);
14609 holelistFree(&var->locdom.holelist, blkmem);
14610 SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
14611 SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
14612
14613 return SCIP_OKAY;
14614}
14615
14616/** issues a IMPLADDED event on the given variable */
14617static
14619 SCIP_VAR* var, /**< problem variable to change */
14620 BMS_BLKMEM* blkmem, /**< block memory */
14621 SCIP_SET* set, /**< global SCIP settings */
14622 SCIP_EVENTQUEUE* eventqueue /**< event queue */
14623 )
14624{
14625 SCIP_EVENT* event;
14626
14627 assert(var != NULL);
14628
14629 /* issue IMPLADDED event on variable */
14630 SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
14631 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
14632
14633 return SCIP_OKAY;
14634}
14635
14636/** actually performs the addition of a variable bound to the variable's vbound arrays */
14637static
14639 SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
14640 BMS_BLKMEM* blkmem, /**< block memory */
14641 SCIP_SET* set, /**< global SCIP settings */
14642 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14643 SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
14644 SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
14645 SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
14646 SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
14647 )
14648{
14649 SCIP_Bool added;
14650
14651 /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
14652 * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
14653 * variable of the aggregated variable might be the same as the one its gets aggregated too.
14654 *
14655 * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
14656 * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
14657 * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
14658 * variable bound can be ignored.
14659 *
14660 * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
14661 * equivalence of the variables should be checked here.
14662 */
14663 if( var == vbvar )
14664 {
14665 /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
14666 * can be checked via the global bounds of the variable */
14667#ifndef NDEBUG
14668 SCIP_Real lb;
14669 SCIP_Real ub;
14670
14671 lb = SCIPvarGetLbGlobal(var);
14672 ub = SCIPvarGetUbGlobal(var);
14673
14674 if(vbtype == SCIP_BOUNDTYPE_LOWER)
14675 {
14676 if( vbcoef > 0.0 )
14677 {
14678 assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
14679 assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
14680 }
14681 else
14682 {
14683 assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
14684 assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
14685 }
14686 }
14687 else
14688 {
14689 assert(vbtype == SCIP_BOUNDTYPE_UPPER);
14690 if( vbcoef > 0.0 )
14691 {
14692 assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
14693 assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
14694 }
14695 else
14696 {
14697 assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
14698 assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
14699 }
14700 }
14701#endif
14702 SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
14703 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
14704
14705 return SCIP_OKAY;
14706 }
14707
14708 SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
14709 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
14710
14711 /* check variable bound on debugging solution */
14712 SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
14713
14714 /* perform the addition */
14715 if( vbtype == SCIP_BOUNDTYPE_LOWER )
14716 {
14717 SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
14718 }
14719 else
14720 {
14721 SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
14722 }
14723 var->closestvblpcount = -1;
14724
14725 if( added )
14726 {
14727 /* issue IMPLADDED event */
14728 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
14729 }
14730
14731 return SCIP_OKAY;
14732}
14733
14734/** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
14735static
14737 SCIP_SET* set, /**< global SCIP settings */
14738 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14739 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14740 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14741 SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
14742 SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
14743 )
14744{
14745 SCIP_Real impllb;
14746 SCIP_Real implub;
14747
14748 assert(redundant != NULL);
14749 assert(infeasible != NULL);
14750
14751 impllb = SCIPvarGetLbGlobal(implvar);
14752 implub = SCIPvarGetUbGlobal(implvar);
14753 if( impltype == SCIP_BOUNDTYPE_LOWER )
14754 {
14755 *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
14756 *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
14757 }
14758 else
14759 {
14760 *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
14761 *redundant = SCIPsetIsFeasGE(set, implbound, implub);
14762 }
14763}
14764
14765/** applies the given implication, if it is not redundant */
14766static
14768 BMS_BLKMEM* blkmem, /**< block memory */
14769 SCIP_SET* set, /**< global SCIP settings */
14770 SCIP_STAT* stat, /**< problem statistics */
14771 SCIP_PROB* transprob, /**< transformed problem */
14772 SCIP_PROB* origprob, /**< original problem */
14773 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
14774 SCIP_REOPT* reopt, /**< reoptimization data structure */
14775 SCIP_LP* lp, /**< current LP data */
14776 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
14777 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14778 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14779 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
14780 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14781 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14782 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14783 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
14784 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
14785 )
14786{
14787 SCIP_Real implub;
14788 SCIP_Real impllb;
14789
14790 assert(infeasible != NULL);
14791
14792 *infeasible = FALSE;
14793
14794 implub = SCIPvarGetUbGlobal(implvar);
14795 impllb = SCIPvarGetLbGlobal(implvar);
14796 if( impltype == SCIP_BOUNDTYPE_LOWER )
14797 {
14798 if( SCIPsetIsFeasGT(set, implbound, implub) )
14799 {
14800 /* the implication produces a conflict: the problem is infeasible */
14801 *infeasible = TRUE;
14802 }
14803 else if( SCIPsetIsFeasGT(set, implbound, impllb) )
14804 {
14805 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14806 * with the local bound, in this case we need to store the bound change as pending bound change
14807 */
14809 {
14810 assert(tree != NULL);
14811 assert(transprob != NULL);
14812 assert(SCIPprobIsTransformed(transprob));
14813
14814 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14815 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
14816 }
14817 else
14818 {
14819 SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
14820 }
14821
14822 if( nbdchgs != NULL )
14823 (*nbdchgs)++;
14824 }
14825 }
14826 else
14827 {
14828 if( SCIPsetIsFeasLT(set, implbound, impllb) )
14829 {
14830 /* the implication produces a conflict: the problem is infeasible */
14831 *infeasible = TRUE;
14832 }
14833 else if( SCIPsetIsFeasLT(set, implbound, implub) )
14834 {
14835 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14836 * with the local bound, in this case we need to store the bound change as pending bound change
14837 */
14839 {
14840 assert(tree != NULL);
14841 assert(transprob != NULL);
14842 assert(SCIPprobIsTransformed(transprob));
14843
14844 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14845 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
14846 }
14847 else
14848 {
14849 SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
14850 }
14851
14852 if( nbdchgs != NULL )
14853 (*nbdchgs)++;
14854 }
14855 }
14856
14857 return SCIP_OKAY;
14858}
14859
14860/** actually performs the addition of an implication to the variable's implication arrays,
14861 * and adds the corresponding implication or variable bound to the implied variable;
14862 * if the implication is conflicting, the variable is fixed to the opposite value;
14863 * if the variable is already fixed to the given value, the implication is performed immediately;
14864 * if the implication is redundant with respect to the variables' global bounds, it is ignored
14865 */
14866static
14868 SCIP_VAR* var, /**< problem variable */
14869 BMS_BLKMEM* blkmem, /**< block memory */
14870 SCIP_SET* set, /**< global SCIP settings */
14871 SCIP_STAT* stat, /**< problem statistics */
14872 SCIP_PROB* transprob, /**< transformed problem */
14873 SCIP_PROB* origprob, /**< original problem */
14874 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
14875 SCIP_REOPT* reopt, /**< reoptimization data structure */
14876 SCIP_LP* lp, /**< current LP data */
14877 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
14878 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
14879 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14880 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14881 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
14882 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14883 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14884 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14885 SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
14886 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
14887 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
14888 SCIP_Bool* added /**< pointer to store whether an implication was added */
14889 )
14890{
14891 SCIP_Bool redundant;
14892 SCIP_Bool conflict;
14893
14894 assert(var != NULL);
14899 assert(infeasible != NULL);
14900 assert(added != NULL);
14901
14902 /* check implication on debugging solution */
14903 SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
14904
14905 *infeasible = FALSE;
14906 *added = FALSE;
14907
14908 /* check, if the implication is redundant or infeasible */
14909 checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
14910 assert(!redundant || !conflict);
14911 if( redundant )
14912 return SCIP_OKAY;
14913
14914 if( var == implvar )
14915 {
14916 /* special cases appear were a bound to a variable implies itself to be outside the bounds:
14917 * x == varfixing => x < 0 or x > 1
14918 */
14919 if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
14920 conflict = TRUE;
14921 else
14922 {
14923 /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
14924 assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
14925 assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
14926 assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
14927 conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
14928 if( !conflict )
14929 return SCIP_OKAY;
14930 }
14931 }
14932
14933 /* check, if the variable is already fixed */
14934 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
14935 {
14936 /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
14937 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
14938 {
14939 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
14940 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
14941 }
14942 return SCIP_OKAY;
14943 }
14944
14945 assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
14946 || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
14947
14948 if( !conflict )
14949 {
14950 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
14951
14952 if( SCIPvarIsBinary(implvar) )
14953 {
14954 SCIP_VAR* vars[2];
14955 SCIP_Bool vals[2];
14956
14957 assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
14958 assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
14959
14960 vars[0] = var;
14961 vars[1] = implvar;
14962 vals[0] = varfixing;
14963 vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
14964
14965 /* add the clique to the clique table */
14966 SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
14967 eventqueue, eventfilter, vars, vals, 2, FALSE, &conflict, nbdchgs) );
14968
14969 if( !conflict )
14970 return SCIP_OKAY;
14971 }
14972 else
14973 {
14974 /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
14975 SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
14976 SCIPvarGetName(var), varfixing,
14977 SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
14978 SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
14979 isshortcut, &conflict, added) );
14980 }
14981 }
14982 assert(!conflict || !(*added));
14983
14984 /* on conflict, fix the variable to the opposite value */
14985 if( conflict )
14986 {
14987 SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
14988
14989 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14990 * with the local bound, in this case we need to store the bound change as pending bound change
14991 */
14993 {
14994 assert(tree != NULL);
14995 assert(transprob != NULL);
14996 assert(SCIPprobIsTransformed(transprob));
14997
14998 if( varfixing )
14999 {
15000 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15001 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
15002 }
15003 else
15004 {
15005 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15006 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
15007 }
15008 }
15009 else
15010 {
15011 if( varfixing )
15012 {
15013 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
15014 }
15015 else
15016 {
15017 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
15018 }
15019 }
15020 if( nbdchgs != NULL )
15021 (*nbdchgs)++;
15022
15023 return SCIP_OKAY;
15024 }
15025 else if( *added )
15026 {
15027 /* issue IMPLADDED event */
15028 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
15029 }
15030 else
15031 {
15032 /* the implication was redundant: the inverse is also redundant */
15033 return SCIP_OKAY;
15034 }
15035
15036 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
15037
15038 /* check, whether implied variable is binary */
15039 if( !SCIPvarIsBinary(implvar) )
15040 {
15041 SCIP_Real lb;
15042 SCIP_Real ub;
15043
15044 /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
15045 * x == 0 -> y <= b <-> y <= (ub - b)*x + b
15046 * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
15047 * x == 0 -> y >= b <-> y >= (lb - b)*x + b
15048 * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
15049 * for numerical reasons, ignore variable bounds with large absolute coefficient
15050 */
15051 lb = SCIPvarGetLbGlobal(implvar);
15052 ub = SCIPvarGetUbGlobal(implvar);
15053 if( impltype == SCIP_BOUNDTYPE_UPPER )
15054 {
15055 if( REALABS(implbound - ub) <= MAXABSVBCOEF )
15056 {
15057 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
15058 varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
15059 }
15060 }
15061 else
15062 {
15063 if( REALABS(implbound - lb) <= MAXABSVBCOEF )
15064 {
15065 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
15066 varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
15067 }
15068 }
15069 }
15070
15071 return SCIP_OKAY;
15072}
15073
15074/** adds transitive closure for binary implication x = a -> y = b */
15075static
15077 SCIP_VAR* var, /**< problem variable */
15078 BMS_BLKMEM* blkmem, /**< block memory */
15079 SCIP_SET* set, /**< global SCIP settings */
15080 SCIP_STAT* stat, /**< problem statistics */
15081 SCIP_PROB* transprob, /**< transformed problem */
15082 SCIP_PROB* origprob, /**< original problem */
15083 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15084 SCIP_REOPT* reopt, /**< reoptimization data structure */
15085 SCIP_LP* lp, /**< current LP data */
15086 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15087 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15088 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15089 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15090 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
15091 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
15092 SCIP_Bool implvarfixing, /**< fixing b in implication */
15093 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15094 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
15095 )
15096{
15097 SCIP_VAR** implvars;
15098 SCIP_BOUNDTYPE* impltypes;
15099 SCIP_Real* implbounds;
15100 int nimpls;
15101 int i;
15102
15103 *infeasible = FALSE;
15104
15105 /* binary variable: implications of implvar */
15106 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
15107 implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
15108 impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
15109 implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
15110
15111 /* if variable has too many implications, the implication graph may become too dense */
15112 i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
15113
15114 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15115 * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
15116 * array over which we currently iterate; the only thing that can happen, is that elements of the array are
15117 * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
15118 * only thing that can happen is that we add the same implication twice - this does no harm
15119 */
15120 while ( i >= 0 && !(*infeasible) )
15121 {
15122 SCIP_Bool added;
15123
15124 assert(implvars[i] != implvar);
15125
15126 /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
15127 * add implication x == varfixing -> z <= b / z >= b to the implications list of x
15128 */
15129 if( SCIPvarIsActive(implvars[i]) )
15130 {
15131 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
15132 eventqueue, eventfilter, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
15133 assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
15134 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
15135 i = MIN(i, nimpls); /* some elements from the array could have been removed */
15136 }
15137 --i;
15138 }
15139
15140 return SCIP_OKAY;
15141}
15142
15143/** adds given implication to the variable's implication list, and adds all implications directly implied by this
15144 * implication to the variable's implication list;
15145 * if the implication is conflicting, the variable is fixed to the opposite value;
15146 * if the variable is already fixed to the given value, the implication is performed immediately;
15147 * if the implication is redundant with respect to the variables' global bounds, it is ignored
15148 */
15149static
15151 SCIP_VAR* var, /**< problem variable */
15152 BMS_BLKMEM* blkmem, /**< block memory */
15153 SCIP_SET* set, /**< global SCIP settings */
15154 SCIP_STAT* stat, /**< problem statistics */
15155 SCIP_PROB* transprob, /**< transformed problem */
15156 SCIP_PROB* origprob, /**< original problem */
15157 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15158 SCIP_REOPT* reopt, /**< reoptimization data structure */
15159 SCIP_LP* lp, /**< current LP data */
15160 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15161 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15162 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15163 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15164 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
15165 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
15166 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
15167 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
15168 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15169 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15170 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
15171 )
15172{
15173 SCIP_Bool added;
15174
15175 assert(var != NULL);
15178 assert(implvar != NULL);
15180 assert(infeasible != NULL);
15181
15182 /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
15183 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
15184 eventqueue, eventfilter, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
15185
15186 if( *infeasible || var == implvar || !transitive || !added )
15187 return SCIP_OKAY;
15188
15189 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
15190
15191 /* add transitive closure */
15192 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(implvar) )
15193 {
15194 SCIP_Bool implvarfixing;
15195
15196 implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
15197
15198 /* binary variable: implications of implvar */
15199 SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15200 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
15201
15202 /* inverse implication */
15203 if( !(*infeasible) )
15204 {
15205 SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15206 cliquetable, branchcand, eventqueue, eventfilter, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
15207 }
15208 }
15209 else
15210 {
15211 /* non-binary variable: variable lower bounds of implvar */
15212 if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
15213 {
15214 SCIP_VAR** vlbvars;
15215 SCIP_Real* vlbcoefs;
15216 SCIP_Real* vlbconstants;
15217 int nvlbvars;
15218 int i;
15219
15220 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
15221 vlbvars = SCIPvboundsGetVars(implvar->vlbs);
15222 vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
15223 vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
15224
15225 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15226 * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
15227 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
15228 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
15229 * is that we add the same implication twice - this does no harm
15230 */
15231 i = nvlbvars-1;
15232 while ( i >= 0 && !(*infeasible) )
15233 {
15234 assert(vlbvars[i] != implvar);
15235 assert(!SCIPsetIsZero(set, vlbcoefs[i]));
15236
15237 /* we have x == varfixing -> y <= b and y >= c*z + d:
15238 * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
15239 * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
15240 *
15241 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
15242 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
15243 * aggregation variable (the one which will stay active);
15244 *
15245 * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
15246 * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
15247 * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
15248 * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
15249 * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
15250 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
15251 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
15252 * have to explicitly check that the active variable has not a variable status
15253 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
15254 */
15255 if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED
15256 && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
15257 {
15258 SCIP_Real vbimplbound;
15259
15260 vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
15261 if( vlbcoefs[i] >= 0.0 )
15262 {
15263 vbimplbound = adjustedUb(set, SCIPvarIsIntegral(vlbvars[i]), vbimplbound);
15264 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15265 branchcand, eventqueue, eventfilter, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
15266 infeasible, nbdchgs, &added) );
15267 }
15268 else
15269 {
15270 vbimplbound = adjustedLb(set, SCIPvarIsIntegral(vlbvars[i]), vbimplbound);
15271 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15272 branchcand, eventqueue, eventfilter, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
15273 infeasible, nbdchgs, &added) );
15274 }
15275 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
15276 i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
15277 }
15278 --i;
15279 }
15280 }
15281
15282 /* non-binary variable: variable upper bounds of implvar */
15283 if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
15284 {
15285 SCIP_VAR** vubvars;
15286 SCIP_Real* vubcoefs;
15287 SCIP_Real* vubconstants;
15288 int nvubvars;
15289 int i;
15290
15291 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
15292 vubvars = SCIPvboundsGetVars(implvar->vubs);
15293 vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
15294 vubconstants = SCIPvboundsGetConstants(implvar->vubs);
15295
15296 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15297 * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
15298 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
15299 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
15300 * is that we add the same implication twice - this does no harm
15301 */
15302 i = nvubvars-1;
15303 while ( i >= 0 && !(*infeasible) )
15304 {
15305 assert(vubvars[i] != implvar);
15306 assert(!SCIPsetIsZero(set, vubcoefs[i]));
15307
15308 /* we have x == varfixing -> y >= b and y <= c*z + d:
15309 * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
15310 * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
15311 *
15312 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
15313 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
15314 * aggregation variable (the one which will stay active);
15315 *
15316 * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
15317 * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
15318 * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
15319 * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
15320 * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
15321 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
15322 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
15323 * have to explicitly check that the active variable has not a variable status
15324 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
15325 */
15326 if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED
15327 && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
15328 {
15329 SCIP_Real vbimplbound;
15330
15331 vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
15332 if( vubcoefs[i] >= 0.0 )
15333 {
15334 vbimplbound = adjustedLb(set, SCIPvarIsIntegral(vubvars[i]), vbimplbound);
15335 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15336 branchcand, eventqueue, eventfilter, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
15337 infeasible, nbdchgs, &added) );
15338 }
15339 else
15340 {
15341 vbimplbound = adjustedUb(set, SCIPvarIsIntegral(vubvars[i]), vbimplbound);
15342 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15343 branchcand, eventqueue, eventfilter, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
15344 infeasible, nbdchgs, &added) );
15345 }
15346 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
15347 i = MIN(i, nvubvars); /* some elements from the array could have been removed */
15348 }
15349 --i;
15350 }
15351 }
15352 }
15353
15354 return SCIP_OKAY;
15355}
15356
15357/** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
15358 * if z is binary, the corresponding valid implication for z is also added;
15359 * improves the global bounds of the variable and the vlb variable if possible
15360 */
15362 SCIP_VAR* var, /**< problem variable */
15363 BMS_BLKMEM* blkmem, /**< block memory */
15364 SCIP_SET* set, /**< global SCIP settings */
15365 SCIP_STAT* stat, /**< problem statistics */
15366 SCIP_PROB* transprob, /**< transformed problem */
15367 SCIP_PROB* origprob, /**< original problem */
15368 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15369 SCIP_REOPT* reopt, /**< reoptimization data structure */
15370 SCIP_LP* lp, /**< current LP data */
15371 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15372 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15373 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15374 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15375 SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
15376 SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
15377 SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
15378 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15379 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15380 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
15381 )
15382{
15383 assert(var != NULL);
15384 assert(set != NULL);
15385 assert(var->scip == set->scip);
15386 assert(SCIPvarIsIntegral(vlbvar));
15387 assert(infeasible != NULL);
15388
15389 SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
15390
15391 *infeasible = FALSE;
15392 if( nbdchgs != NULL )
15393 *nbdchgs = 0;
15394
15395 switch( SCIPvarGetStatus(var) )
15396 {
15398 assert(var->data.original.transvar != NULL);
15399 SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15400 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
15401 break;
15402
15406 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15407 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
15408 SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n",
15409 SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
15410
15411 /* if the variables are the same, just update the corresponding bound */
15412 if( var == vlbvar )
15413 {
15414 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15415 if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
15416 {
15417 if( SCIPsetIsFeasPositive(set, vlbconstant) )
15418 *infeasible = TRUE;
15419 }
15420 else
15421 {
15424
15425 /* the variable bound constraint defines a new upper bound */
15426 if( SCIPsetIsGT(set, vlbcoef, 1.0) )
15427 {
15428 /* bound might be adjusted due to integrality condition */
15429 SCIP_Real newub = adjustedUb(set, SCIPvarIsIntegral(var), vlbconstant / (1.0 - vlbcoef));
15430
15431 /* check bounds for feasibility */
15432 if( SCIPsetIsFeasLT(set, newub, lb) )
15433 {
15434 *infeasible = TRUE;
15435 return SCIP_OKAY;
15436 }
15437
15438 /* improve global upper bound of variable */
15439 if( SCIPsetIsFeasLT(set, newub, ub) )
15440 {
15441 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15442 * with the local bound, in this case we need to store the bound change as pending bound change
15443 */
15445 {
15446 assert(tree != NULL);
15447 assert(transprob != NULL);
15448 assert(SCIPprobIsTransformed(transprob));
15449
15450 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15451 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15452 }
15453 else
15454 {
15455 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
15456 }
15457
15458 if( nbdchgs != NULL )
15459 (*nbdchgs)++;
15460 }
15461 }
15462 /* the variable bound constraint defines a new lower bound */
15463 else
15464 {
15465 assert(SCIPsetIsLT(set, vlbcoef, 1.0));
15466
15467 /* bound might be adjusted due to integrality condition */
15468 SCIP_Real newlb = adjustedLb(set, SCIPvarIsIntegral(var), vlbconstant / (1.0 - vlbcoef));
15469
15470 /* check bounds for feasibility */
15471 if( SCIPsetIsFeasGT(set, newlb, ub) )
15472 {
15473 *infeasible = TRUE;
15474 return SCIP_OKAY;
15475 }
15476
15477 /* improve global lower bound of variable */
15478 if( SCIPsetIsFeasGT(set, newlb, lb) )
15479 {
15480 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15481 * with the local bound, in this case we need to store the bound change as pending bound change
15482 */
15484 {
15485 assert(tree != NULL);
15486 assert(transprob != NULL);
15487 assert(SCIPprobIsTransformed(transprob));
15488
15489 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15490 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15491 }
15492 else
15493 {
15494 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
15495 }
15496
15497 if( nbdchgs != NULL )
15498 (*nbdchgs)++;
15499 }
15500 }
15501 }
15502 }
15503 /* if the vlb coefficient is zero, just update the lower bound of the variable */
15504 else if( SCIPsetIsZero(set, vlbcoef) )
15505 {
15506 /* bound might be adjusted due to integrality condition */
15507 vlbconstant = adjustedLb(set, SCIPvarIsIntegral(var), vlbconstant);
15508
15509 /* check bounds for feasibility */
15510 if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
15511 *infeasible = TRUE;
15512 /* improve global lower bound of variable */
15513 else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
15514 {
15515 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15516 * with the local bound, in this case we need to store the bound change as pending bound change
15517 */
15519 {
15520 assert(tree != NULL);
15521 assert(transprob != NULL);
15522 assert(SCIPprobIsTransformed(transprob));
15523
15524 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15525 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
15526 }
15527 else
15528 {
15529 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
15530 }
15531
15532 if( nbdchgs != NULL )
15533 (*nbdchgs)++;
15534 }
15535 }
15536 else if( SCIPvarIsActive(vlbvar) )
15537 {
15538 SCIP_Real xlb;
15539 SCIP_Real xub;
15540 SCIP_Real zlb;
15541 SCIP_Real zub;
15542 SCIP_Real minvlb;
15543 SCIP_Real maxvlb;
15544
15546 assert(vlbcoef != 0.0);
15547
15548 minvlb = -SCIPsetInfinity(set);
15549 maxvlb = SCIPsetInfinity(set);
15550
15551 xlb = SCIPvarGetLbGlobal(var);
15552 xub = SCIPvarGetUbGlobal(var);
15553 zlb = SCIPvarGetLbGlobal(vlbvar);
15554 zub = SCIPvarGetUbGlobal(vlbvar);
15555
15556 /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
15557 if( vlbcoef >= 0.0 )
15558 {
15559 if( !SCIPsetIsInfinity(set, xub) )
15560 {
15561 /* x >= b*z + d -> z <= (x-d)/b */
15562 SCIP_Real newzub = adjustedUb(set, SCIPvarIsIntegral(vlbvar), (xub - vlbconstant) / vlbcoef);
15563
15564 /* check bounds for feasibility */
15565 if( SCIPsetIsFeasLT(set, newzub, zlb) )
15566 {
15567 *infeasible = TRUE;
15568 return SCIP_OKAY;
15569 }
15570
15571 /* improve global upper bound of variable */
15572 if( SCIPsetIsFeasLT(set, newzub, zub) )
15573 {
15574 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15575 * with the local bound, in this case we need to store the bound change as pending bound change
15576 */
15578 {
15579 assert(tree != NULL);
15580 assert(transprob != NULL);
15581 assert(SCIPprobIsTransformed(transprob));
15582
15583 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15584 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15585 }
15586 else
15587 {
15588 SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
15589 }
15590 zub = newzub;
15591
15592 if( nbdchgs != NULL )
15593 (*nbdchgs)++;
15594 }
15595 maxvlb = vlbcoef * zub + vlbconstant;
15596 if( !SCIPsetIsInfinity(set, -zlb) )
15597 minvlb = vlbcoef * zlb + vlbconstant;
15598 }
15599 else
15600 {
15601 if( !SCIPsetIsInfinity(set, zub) )
15602 maxvlb = vlbcoef * zub + vlbconstant;
15603 if( !SCIPsetIsInfinity(set, -zlb) )
15604 minvlb = vlbcoef * zlb + vlbconstant;
15605 }
15606 }
15607 else
15608 {
15609 if( !SCIPsetIsInfinity(set, xub) )
15610 {
15611 /* x >= b*z + d -> z >= (x-d)/b */
15612 SCIP_Real newzlb = adjustedLb(set, SCIPvarIsIntegral(vlbvar), (xub - vlbconstant) / vlbcoef);
15613
15614 /* check bounds for feasibility */
15615 if( SCIPsetIsFeasGT(set, newzlb, zub) )
15616 {
15617 *infeasible = TRUE;
15618 return SCIP_OKAY;
15619 }
15620
15621 /* improve global lower bound of variable */
15622 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
15623 {
15624 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15625 * with the local bound, in this case we need to store the bound change as pending bound change
15626 */
15628 {
15629 assert(tree != NULL);
15630 assert(transprob != NULL);
15631 assert(SCIPprobIsTransformed(transprob));
15632
15633 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15634 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15635 }
15636 else
15637 {
15638 SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
15639 }
15640 zlb = newzlb;
15641
15642 if( nbdchgs != NULL )
15643 (*nbdchgs)++;
15644 }
15645 maxvlb = vlbcoef * zlb + vlbconstant;
15646 if( !SCIPsetIsInfinity(set, zub) )
15647 minvlb = vlbcoef * zub + vlbconstant;
15648 }
15649 else
15650 {
15651 if( !SCIPsetIsInfinity(set, -zlb) )
15652 maxvlb = vlbcoef * zlb + vlbconstant;
15653 if( !SCIPsetIsInfinity(set, zub) )
15654 minvlb = vlbcoef * zub + vlbconstant;
15655 }
15656 }
15657 if( maxvlb < minvlb )
15658 maxvlb = minvlb;
15659
15660 /* adjust bounds due to integrality of variable */
15661 minvlb = adjustedLb(set, SCIPvarIsIntegral(var), minvlb);
15662 maxvlb = adjustedLb(set, SCIPvarIsIntegral(var), maxvlb);
15663
15664 /* check bounds for feasibility */
15665 if( SCIPsetIsFeasGT(set, minvlb, xub) )
15666 {
15667 *infeasible = TRUE;
15668 return SCIP_OKAY;
15669 }
15670
15671 /* improve global lower bound of variable */
15672 if( SCIPsetIsFeasGT(set, minvlb, xlb) )
15673 {
15674 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15675 * with the local bound, in this case we need to store the bound change as pending bound change
15676 */
15678 {
15679 assert(tree != NULL);
15680 assert(transprob != NULL);
15681 assert(SCIPprobIsTransformed(transprob));
15682
15683 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15684 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15685 }
15686 else
15687 {
15688 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
15689 }
15690 xlb = minvlb;
15691
15692 if( nbdchgs != NULL )
15693 (*nbdchgs)++;
15694 }
15695 minvlb = xlb;
15696
15697 /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
15699 {
15700 /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
15701 * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
15702 */
15703
15704 assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
15705
15706 if( vlbcoef >= 0.0 )
15707 {
15708 vlbcoef = maxvlb - minvlb;
15709 vlbconstant = minvlb;
15710 }
15711 else
15712 {
15713 vlbcoef = minvlb - maxvlb;
15714 vlbconstant = maxvlb;
15715 }
15716 }
15717
15718 /* add variable bound to the variable bounds list */
15719 if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
15720 {
15722 assert(!SCIPsetIsZero(set, vlbcoef));
15723
15724 /* if one of the variables is binary, add the corresponding implication to the variable's implication
15725 * list, thereby also adding the variable bound (or implication) to the other variable
15726 */
15728 {
15729 /* add corresponding implication:
15730 * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
15731 * b < 0, x >= b*z + d <-> z == 0 -> x >= d
15732 */
15733 SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15734 cliquetable, branchcand, eventqueue, eventfilter, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
15735 infeasible, nbdchgs) );
15736 }
15738 {
15739 /* add corresponding implication:
15740 * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
15741 * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
15742 */
15743 SCIP_Real implbound;
15744 implbound = -vlbconstant/vlbcoef;
15745
15746 /* tighten the implication bound if the variable is integer */
15747 if( SCIPvarIsIntegral(vlbvar) )
15748 {
15749 if( vlbcoef >= 0 )
15750 implbound = SCIPsetFloor(set, implbound);
15751 else
15752 implbound = SCIPsetCeil(set, implbound);
15753 }
15754 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15755 cliquetable, branchcand, eventqueue, eventfilter, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
15756 implbound, transitive, infeasible, nbdchgs) );
15757 }
15758 else
15759 {
15760 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
15761 }
15762 }
15763 }
15764 break;
15765
15767 /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
15768 * y <= b/a * z + (d-c)/a, if a < 0
15769 */
15770
15771 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15772 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
15773
15774 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15775 assert(var->data.aggregate.var != NULL);
15776 if( var->data.aggregate.var == vlbvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vlbcoef) )
15777 {
15778 if( SCIPsetIsFeasLT(set, var->data.aggregate.constant, vlbconstant) )
15779 *infeasible = TRUE;
15780 }
15781 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
15782 {
15783 /* a > 0 -> add variable lower bound */
15784 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15785 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef / var->data.aggregate.scalar,
15786 (vlbconstant - var->data.aggregate.constant) / var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
15787 }
15788 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
15789 {
15790 /* a < 0 -> add variable upper bound */
15791 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15792 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef / var->data.aggregate.scalar,
15793 (vlbconstant - var->data.aggregate.constant) / var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
15794 }
15795 else
15796 {
15797 SCIPerrorMessage("scalar is zero in aggregation\n");
15798 return SCIP_INVALIDDATA;
15799 }
15800 break;
15801
15803 /* nothing to do here */
15804 break;
15805
15807 /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
15808 assert(var->negatedvar != NULL);
15810 assert(var->negatedvar->negatedvar == var);
15811 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15812 branchcand, eventqueue, eventfilter, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
15813 nbdchgs) );
15814 break;
15815
15816 default:
15817 SCIPerrorMessage("unknown variable status\n");
15818 return SCIP_INVALIDDATA;
15819 }
15820
15821 return SCIP_OKAY;
15822}
15823
15824/** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
15825 * if z is binary, the corresponding valid implication for z is also added;
15826 * updates the global bounds of the variable and the vub variable correspondingly
15827 */
15829 SCIP_VAR* var, /**< problem variable */
15830 BMS_BLKMEM* blkmem, /**< block memory */
15831 SCIP_SET* set, /**< global SCIP settings */
15832 SCIP_STAT* stat, /**< problem statistics */
15833 SCIP_PROB* transprob, /**< transformed problem */
15834 SCIP_PROB* origprob, /**< original problem */
15835 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15836 SCIP_REOPT* reopt, /**< reoptimization data structure */
15837 SCIP_LP* lp, /**< current LP data */
15838 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15839 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15840 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15841 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15842 SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
15843 SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
15844 SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
15845 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15846 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15847 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
15848 )
15849{
15850 assert(var != NULL);
15851 assert(set != NULL);
15852 assert(var->scip == set->scip);
15853 assert(SCIPvarIsIntegral(vubvar));
15854 assert(infeasible != NULL);
15855
15856 SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
15857
15858 *infeasible = FALSE;
15859 if( nbdchgs != NULL )
15860 *nbdchgs = 0;
15861
15862 switch( SCIPvarGetStatus(var) )
15863 {
15865 assert(var->data.original.transvar != NULL);
15866 SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15867 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
15868 break;
15869
15873 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15874 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
15875 SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
15876 SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
15877
15878 /* if the variables are the same, just update the corresponding bound */
15879 if( var == vubvar )
15880 {
15881 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15882 if( SCIPsetIsEQ(set, vubcoef, 1.0) )
15883 {
15884 if( SCIPsetIsFeasNegative(set, vubconstant) )
15885 *infeasible = TRUE;
15886 }
15887 else
15888 {
15891
15892 /* the variable bound constraint defines a new lower bound */
15893 if( SCIPsetIsGT(set, vubcoef, 1.0) )
15894 {
15895 /* bound might be adjusted due to integrality condition */
15896 SCIP_Real newlb = adjustedLb(set, SCIPvarIsIntegral(var), vubconstant / (1.0 - vubcoef));
15897
15898 /* check bounds for feasibility */
15899 if( SCIPsetIsFeasGT(set, newlb, ub) )
15900 {
15901 *infeasible = TRUE;
15902 return SCIP_OKAY;
15903 }
15904
15905 /* improve global lower bound of variable */
15906 if( SCIPsetIsFeasGT(set, newlb, lb) )
15907 {
15908 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15909 * with the local bound, in this case we need to store the bound change as pending bound change
15910 */
15912 {
15913 assert(tree != NULL);
15914 assert(transprob != NULL);
15915 assert(SCIPprobIsTransformed(transprob));
15916
15917 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15918 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15919 }
15920 else
15921 {
15922 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
15923 }
15924
15925 if( nbdchgs != NULL )
15926 (*nbdchgs)++;
15927 }
15928 }
15929 /* the variable bound constraint defines a new upper bound */
15930 else
15931 {
15932 assert(SCIPsetIsLT(set, vubcoef, 1.0));
15933
15934 /* bound might be adjusted due to integrality condition */
15935 SCIP_Real newub = adjustedUb(set, SCIPvarIsIntegral(var), vubconstant / (1.0 - vubcoef));
15936
15937 /* check bounds for feasibility */
15938 if( SCIPsetIsFeasLT(set, newub, lb) )
15939 {
15940 *infeasible = TRUE;
15941 return SCIP_OKAY;
15942 }
15943
15944 /* improve global upper bound of variable */
15945 if( SCIPsetIsFeasLT(set, newub, ub) )
15946 {
15947 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15948 * with the local bound, in this case we need to store the bound change as pending bound change
15949 */
15951 {
15952 assert(tree != NULL);
15953 assert(transprob != NULL);
15954 assert(SCIPprobIsTransformed(transprob));
15955
15956 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15957 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15958 }
15959 else
15960 {
15961 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
15962 }
15963
15964 if( nbdchgs != NULL )
15965 (*nbdchgs)++;
15966 }
15967 }
15968 }
15969 }
15970 /* if the vub coefficient is zero, just update the upper bound of the variable */
15971 else if( SCIPsetIsZero(set, vubcoef) )
15972 {
15973 /* bound might be adjusted due to integrality condition */
15974 vubconstant = adjustedUb(set, SCIPvarIsIntegral(var), vubconstant);
15975
15976 /* check bounds for feasibility */
15977 if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
15978 *infeasible = TRUE;
15979 /* improve global upper bound of variable */
15980 else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
15981 {
15982 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15983 * with the local bound, in this case we need to store the bound change as pending bound change
15984 */
15986 {
15987 assert(tree != NULL);
15988 assert(transprob != NULL);
15989 assert(SCIPprobIsTransformed(transprob));
15990
15991 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15992 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
15993 }
15994 else
15995 {
15996 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
15997 }
15998
15999 if( nbdchgs != NULL )
16000 (*nbdchgs)++;
16001 }
16002 }
16003 else if( SCIPvarIsActive(vubvar) )
16004 {
16005 SCIP_Real xlb;
16006 SCIP_Real xub;
16007 SCIP_Real zlb;
16008 SCIP_Real zub;
16009 SCIP_Real minvub;
16010 SCIP_Real maxvub;
16011
16013 assert(vubcoef != 0.0);
16014
16015 minvub = -SCIPsetInfinity(set);
16016 maxvub = SCIPsetInfinity(set);
16017
16018 xlb = SCIPvarGetLbGlobal(var);
16019 xub = SCIPvarGetUbGlobal(var);
16020 zlb = SCIPvarGetLbGlobal(vubvar);
16021 zub = SCIPvarGetUbGlobal(vubvar);
16022
16023 /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
16024 if( vubcoef >= 0.0 )
16025 {
16026 if( !SCIPsetIsInfinity(set, -xlb) )
16027 {
16028 /* x <= b*z + d -> z >= (x-d)/b */
16029 SCIP_Real newzlb = adjustedLb(set, SCIPvarIsIntegral(vubvar), (xlb - vubconstant) / vubcoef);
16030
16031 /* check bounds for feasibility */
16032 if( SCIPsetIsFeasGT(set, newzlb, zub) )
16033 {
16034 *infeasible = TRUE;
16035 return SCIP_OKAY;
16036 }
16037
16038 /* improve global lower bound of variable */
16039 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
16040 {
16041 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16042 * with the local bound, in this case we need to store the bound change as pending bound change
16043 */
16045 {
16046 assert(tree != NULL);
16047 assert(transprob != NULL);
16048 assert(SCIPprobIsTransformed(transprob));
16049
16050 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16051 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
16052 }
16053 else
16054 {
16055 SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
16056 }
16057 zlb = newzlb;
16058
16059 if( nbdchgs != NULL )
16060 (*nbdchgs)++;
16061 }
16062 minvub = vubcoef * zlb + vubconstant;
16063 if( !SCIPsetIsInfinity(set, zub) )
16064 maxvub = vubcoef * zub + vubconstant;
16065 }
16066 else
16067 {
16068 if( !SCIPsetIsInfinity(set, zub) )
16069 maxvub = vubcoef * zub + vubconstant;
16070 if( !SCIPsetIsInfinity(set, -zlb) )
16071 minvub = vubcoef * zlb + vubconstant;
16072 }
16073 }
16074 else
16075 {
16076 if( !SCIPsetIsInfinity(set, -xlb) )
16077 {
16078 /* x <= b*z + d -> z <= (x-d)/b */
16079 SCIP_Real newzub = adjustedUb(set, SCIPvarIsIntegral(vubvar), (xlb - vubconstant) / vubcoef);
16080
16081 /* check bounds for feasibility */
16082 if( SCIPsetIsFeasLT(set, newzub, zlb) )
16083 {
16084 *infeasible = TRUE;
16085 return SCIP_OKAY;
16086 }
16087
16088 /* improve global upper bound of variable */
16089 if( SCIPsetIsFeasLT(set, newzub, zub) )
16090 {
16091 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16092 * with the local bound, in this case we need to store the bound change as pending bound change
16093 */
16095 {
16096 assert(tree != NULL);
16097 assert(transprob != NULL);
16098 assert(SCIPprobIsTransformed(transprob));
16099
16100 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16101 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
16102 }
16103 else
16104 {
16105 SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
16106 }
16107 zub = newzub;
16108
16109 if( nbdchgs != NULL )
16110 (*nbdchgs)++;
16111 }
16112 minvub = vubcoef * zub + vubconstant;
16113 if( !SCIPsetIsInfinity(set, -zlb) )
16114 maxvub = vubcoef * zlb + vubconstant;
16115 }
16116 else
16117 {
16118 if( !SCIPsetIsInfinity(set, zub) )
16119 minvub = vubcoef * zub + vubconstant;
16120 if( !SCIPsetIsInfinity(set, -zlb) )
16121 maxvub = vubcoef * zlb + vubconstant;
16122 }
16123 }
16124 if( minvub > maxvub )
16125 minvub = maxvub;
16126
16127 /* adjust bounds due to integrality of vub variable */
16128 minvub = adjustedUb(set, SCIPvarIsIntegral(var), minvub);
16129 maxvub = adjustedUb(set, SCIPvarIsIntegral(var), maxvub);
16130
16131 /* check bounds for feasibility */
16132 if( SCIPsetIsFeasLT(set, maxvub, xlb) )
16133 {
16134 *infeasible = TRUE;
16135 return SCIP_OKAY;
16136 }
16137
16138 /* improve global upper bound of variable */
16139 if( SCIPsetIsFeasLT(set, maxvub, xub) )
16140 {
16141 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16142 * with the local bound, in this case we need to store the bound change as pending bound change
16143 */
16145 {
16146 assert(tree != NULL);
16147 assert(transprob != NULL);
16148 assert(SCIPprobIsTransformed(transprob));
16149
16150 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16151 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
16152 }
16153 else
16154 {
16155 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
16156 }
16157 xub = maxvub;
16158
16159 if( nbdchgs != NULL )
16160 (*nbdchgs)++;
16161 }
16162 maxvub = xub;
16163
16164 /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
16165 if( SCIPvarIsBinary(vubvar) )
16166 {
16167 /* b > 0: x <= (maxvub - minvub) * z + minvub
16168 * b < 0: x <= (minvub - maxvub) * z + maxvub
16169 */
16170
16171 assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
16172
16173 if( vubcoef >= 0.0 )
16174 {
16175 vubcoef = maxvub - minvub;
16176 vubconstant = minvub;
16177 }
16178 else
16179 {
16180 vubcoef = minvub - maxvub;
16181 vubconstant = maxvub;
16182 }
16183 }
16184
16185 /* add variable bound to the variable bounds list */
16186 if( SCIPsetIsFeasLT(set, minvub, xub) )
16187 {
16189 assert(!SCIPsetIsZero(set, vubcoef));
16190
16191 /* if one of the variables is binary, add the corresponding implication to the variable's implication
16192 * list, thereby also adding the variable bound (or implication) to the other variable
16193 */
16195 {
16196 /* add corresponding implication:
16197 * b > 0, x <= b*z + d <-> z == 0 -> x <= d
16198 * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
16199 */
16200 SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16201 cliquetable, branchcand, eventqueue, eventfilter, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
16202 infeasible, nbdchgs) );
16203 }
16205 {
16206 /* add corresponding implication:
16207 * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
16208 * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
16209 */
16210 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16211 cliquetable, branchcand, eventqueue, eventfilter, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
16212 (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
16213 }
16214 else
16215 {
16216 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
16217 }
16218 }
16219 }
16220 break;
16221
16223 /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
16224 * y >= b/a * z + (d-c)/a, if a < 0
16225 */
16226
16227 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
16228 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
16229
16230 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
16231 assert(var->data.aggregate.var != NULL);
16232 if( var->data.aggregate.var == vubvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vubcoef) )
16233 {
16234 if( SCIPsetIsFeasGT(set, var->data.aggregate.constant, vubconstant) )
16235 *infeasible = TRUE;
16236 }
16237 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
16238 {
16239 /* a > 0 -> add variable upper bound */
16240 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16241 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef / var->data.aggregate.scalar,
16242 (vubconstant - var->data.aggregate.constant) / var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
16243 }
16244 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
16245 {
16246 /* a < 0 -> add variable lower bound */
16247 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16248 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef / var->data.aggregate.scalar,
16249 (vubconstant - var->data.aggregate.constant) / var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
16250 }
16251 else
16252 {
16253 SCIPerrorMessage("scalar is zero in aggregation\n");
16254 return SCIP_INVALIDDATA;
16255 }
16256 break;
16257
16259 /* nothing to do here */
16260 break;
16261
16263 /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
16264 assert(var->negatedvar != NULL);
16266 assert(var->negatedvar->negatedvar == var);
16267 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16268 branchcand, eventqueue, eventfilter, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
16269 nbdchgs) );
16270 break;
16271
16272 default:
16273 SCIPerrorMessage("unknown variable status\n");
16274 return SCIP_INVALIDDATA;
16275 }
16276
16277 return SCIP_OKAY;
16278}
16279
16280/** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
16281 * also adds the corresponding implication or variable bound to the implied variable;
16282 * if the implication is conflicting, the variable is fixed to the opposite value;
16283 * if the variable is already fixed to the given value, the implication is performed immediately;
16284 * if the implication is redundant with respect to the variables' global bounds, it is ignored
16285 */
16287 SCIP_VAR* var, /**< problem variable */
16288 BMS_BLKMEM* blkmem, /**< block memory */
16289 SCIP_SET* set, /**< global SCIP settings */
16290 SCIP_STAT* stat, /**< problem statistics */
16291 SCIP_PROB* transprob, /**< transformed problem */
16292 SCIP_PROB* origprob, /**< original problem */
16293 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16294 SCIP_REOPT* reopt, /**< reoptimization data structure */
16295 SCIP_LP* lp, /**< current LP data */
16296 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16297 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16298 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16299 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16300 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
16301 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
16302 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
16303 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
16304 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
16305 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16306 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
16307 )
16308{
16309 assert(var != NULL);
16310 assert(set != NULL);
16311 assert(var->scip == set->scip);
16313 assert(infeasible != NULL);
16314
16315 *infeasible = FALSE;
16316 if( nbdchgs != NULL )
16317 *nbdchgs = 0;
16318
16319 switch( SCIPvarGetStatus(var) )
16320 {
16322 assert(var->data.original.transvar != NULL);
16323 SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16324 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible,
16325 nbdchgs) );
16326 break;
16327
16330 /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
16331 * the variable, the implication can be applied directly;
16332 * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
16333 */
16334 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
16335 {
16336 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
16337 {
16338 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
16339 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
16340 }
16341 }
16342 else
16343 {
16344 SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
16345 SCIPvarAdjustBd(implvar, set, impltype, &implbound);
16346 if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
16347 {
16348 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16349 branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
16350 }
16351 }
16352 break;
16353
16355 /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
16356 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
16357 {
16358 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
16359 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
16360 }
16361 break;
16362
16364 /* implication added for x == 1:
16365 * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16366 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16367 * implication added for x == 0:
16368 * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16369 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16370 *
16371 * use only binary variables z
16372 */
16373 assert(var->data.aggregate.var != NULL);
16374 if( SCIPvarIsBinary(var->data.aggregate.var) )
16375 {
16376 assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
16377 || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
16378
16379 if( var->data.aggregate.scalar > 0 )
16380 {
16381 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16382 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible,
16383 nbdchgs) );
16384 }
16385 else
16386 {
16387 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16388 cliquetable, branchcand, eventqueue, eventfilter, !varfixing, implvar, impltype, implbound, transitive, infeasible,
16389 nbdchgs) );
16390 }
16391 }
16392 break;
16393
16395 /* nothing to do here */
16396 break;
16397
16399 /* implication added for x == 1:
16400 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16401 * implication added for x == 0:
16402 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16403 */
16404 assert(var->negatedvar != NULL);
16406 assert(var->negatedvar->negatedvar == var);
16407 assert(SCIPvarIsBinary(var->negatedvar));
16408
16409 if( SCIPvarGetType(var->negatedvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(var->negatedvar) )
16410 {
16411 SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16412 cliquetable, branchcand, eventqueue, eventfilter, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
16413 }
16414 /* in case one both variables are not of binary type we have to add the implication as variable bounds */
16415 else
16416 {
16417 /* if the implied variable is of binary type exchange the variables */
16418 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
16419 {
16420 SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16421 branchcand, eventqueue, eventfilter, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
16422 varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
16423 infeasible, nbdchgs) );
16424 }
16425 else
16426 {
16427 /* both variables are not of binary type but are implicit binary; in that case we can only add this
16428 * implication as variable bounds
16429 */
16430
16431 /* add variable lower bound on the negation of var */
16432 if( varfixing )
16433 {
16434 /* (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
16435 * as variable lower bound
16436 */
16437 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16438 cliquetable, branchcand, eventqueue, eventfilter, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
16439 (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
16440 }
16441 else
16442 {
16443 /* (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
16444 * as variable upper bound
16445 */
16446 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16447 cliquetable, branchcand, eventqueue, eventfilter, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
16448 (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
16449 }
16450
16451 /* add variable bound on implvar */
16452 if( impltype == SCIP_BOUNDTYPE_UPPER )
16453 {
16454 /* (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
16455 * as variable upper bound
16456 */
16457 SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16458 branchcand, eventqueue, eventfilter, var->negatedvar, (varfixing) ? 1.0 : -1.0,
16459 (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
16460 }
16461 else
16462 {
16463 /* (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
16464 * as variable upper bound
16465 */
16466 SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16467 branchcand, eventqueue, eventfilter, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
16468 transitive, infeasible, nbdchgs) );
16469 }
16470 }
16471 }
16472 break;
16473
16474 default:
16475 SCIPerrorMessage("unknown variable status\n");
16476 return SCIP_INVALIDDATA;
16477 }
16478
16479 return SCIP_OKAY;
16480}
16481
16482/** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
16483 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
16484 * both variables must be active, variable x must be binary
16485 */
16487 SCIP_VAR* var, /**< problem variable x */
16488 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16489 SCIP_VAR* implvar, /**< variable y to search for */
16490 SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
16491 )
16492{
16493 assert(var != NULL);
16494 assert(implvar != NULL);
16496 assert(SCIPvarIsActive(implvar));
16498
16499 return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
16500}
16501
16502/** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
16503 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
16504 * both variables must be active binary variables
16505 */
16507 SCIP_VAR* var, /**< problem variable x */
16508 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16509 SCIP_VAR* implvar, /**< variable y to search for */
16510 SCIP_Bool implvarfixing /**< value of the implied variable to search for */
16511 )
16512{
16513 assert(SCIPvarIsBinary(implvar));
16514
16515 return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
16516}
16517
16518/** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
16519 * the values are set to SCIP_INVALID if there is no implied bound
16520 */
16522 SCIP_VAR* var, /**< problem variable x */
16523 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16524 SCIP_VAR* implvar, /**< variable y to search for */
16525 SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
16526 SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
16527 )
16528{
16529 int lowerpos;
16530 int upperpos;
16531 SCIP_Real* bounds;
16532
16533 assert(lb != NULL);
16534 assert(ub != NULL);
16535
16536 *lb = SCIP_INVALID;
16537 *ub = SCIP_INVALID;
16538
16539 if( var->implics == NULL )
16540 return;
16541
16542 SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
16543 bounds = SCIPvarGetImplBounds(var, varfixing);
16544
16545 if( bounds == NULL )
16546 return;
16547
16548 if( lowerpos >= 0 )
16549 *lb = bounds[lowerpos];
16550
16551 if( upperpos >= 0 )
16552 *ub = bounds[upperpos];
16553}
16554
16555
16556/** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
16558 SCIP_VAR* var, /**< problem variable */
16559 BMS_BLKMEM* blkmem, /**< block memory */
16560 SCIP_SET* set, /**< global SCIP settings */
16561 SCIP_STAT* stat, /**< problem statistics */
16562 SCIP_PROB* transprob, /**< transformed problem */
16563 SCIP_PROB* origprob, /**< original problem */
16564 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16565 SCIP_REOPT* reopt, /**< reoptimization data structure */
16566 SCIP_LP* lp, /**< current LP data */
16567 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16568 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16569 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16570 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16571 SCIP_Bool value, /**< value to fix variable to */
16572 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16573 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
16574 )
16575{
16576 assert(var != NULL);
16577 assert(set != NULL);
16578 assert(var->scip == set->scip);
16579 assert(infeasible != NULL);
16580
16581 *infeasible = FALSE;
16582
16583 if( value == FALSE )
16584 {
16585 if( var->glbdom.lb > 0.5 )
16586 *infeasible = TRUE;
16587 else if( var->glbdom.ub > 0.5 )
16588 {
16589 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16590 * with the local bound, in this case we need to store the bound change as pending bound change
16591 */
16593 {
16594 assert(tree != NULL);
16595 assert(transprob != NULL);
16596 assert(SCIPprobIsTransformed(transprob));
16597
16598 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16599 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
16600 }
16601 else
16602 {
16603 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
16604 }
16605
16606 if( nbdchgs != NULL )
16607 (*nbdchgs)++;
16608 }
16609 }
16610 else
16611 {
16612 if( var->glbdom.ub < 0.5 )
16613 *infeasible = TRUE;
16614 else if( var->glbdom.lb < 0.5 )
16615 {
16616 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16617 * with the local bound, in this case we need to store the bound change as pending bound change
16618 */
16620 {
16621 assert(tree != NULL);
16622 assert(transprob != NULL);
16623 assert(SCIPprobIsTransformed(transprob));
16624
16625 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16626 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
16627 }
16628 else
16629 {
16630 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
16631 }
16632
16633 if( nbdchgs != NULL )
16634 (*nbdchgs)++;
16635 }
16636 }
16637
16638 return SCIP_OKAY;
16639}
16640
16641/** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
16642 * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
16643 * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
16644 * the opposite of the value they take in the clique
16645 */
16647 SCIP_VAR* var, /**< problem variable */
16648 BMS_BLKMEM* blkmem, /**< block memory */
16649 SCIP_SET* set, /**< global SCIP settings */
16650 SCIP_STAT* stat, /**< problem statistics */
16651 SCIP_PROB* transprob, /**< transformed problem */
16652 SCIP_PROB* origprob, /**< original problem */
16653 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16654 SCIP_REOPT* reopt, /**< reoptimization data structure */
16655 SCIP_LP* lp, /**< current LP data */
16656 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16657 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16658 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16659 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16660 SCIP_Bool value, /**< value of the variable in the clique */
16661 SCIP_CLIQUE* clique, /**< clique the variable should be added to */
16662 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16663 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
16664 )
16665{
16666 assert(var != NULL);
16667 assert(set != NULL);
16668 assert(var->scip == set->scip);
16670 assert(infeasible != NULL);
16671
16672 *infeasible = FALSE;
16673
16674 /* get corresponding active problem variable */
16681
16682 /* only column and loose variables may be member of a clique */
16684 {
16685 SCIP_Bool doubleentry;
16686 SCIP_Bool oppositeentry;
16687
16688 /* add variable to clique */
16689 SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
16690
16691 /* add clique to variable's clique list */
16692 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
16693
16694 /* check consistency of cliquelist */
16695 SCIPcliquelistCheck(var->cliquelist, var);
16696
16697 /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
16698 if( doubleentry )
16699 {
16700 SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
16701 eventqueue, eventfilter, cliquetable, !value, infeasible, nbdchgs) );
16702 }
16703
16704 /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
16705 * to the opposite of the value they take in the clique
16706 */
16707 if( oppositeentry )
16708 {
16709 SCIP_VAR** vars;
16710 SCIP_Bool* values;
16711 int nvars;
16712 int i;
16713
16714 nvars = SCIPcliqueGetNVars(clique);
16715 vars = SCIPcliqueGetVars(clique);
16716 values = SCIPcliqueGetValues(clique);
16717 for( i = 0; i < nvars && !(*infeasible); ++i )
16718 {
16719 if( vars[i] == var )
16720 continue;
16721
16722 SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
16723 eventqueue, eventfilter, cliquetable, !values[i], infeasible, nbdchgs) );
16724 }
16725 }
16726 }
16727
16728 return SCIP_OKAY;
16729}
16730
16731/** adds a filled clique to the cliquelists of all corresponding variables */
16733 SCIP_VAR** vars, /**< problem variables */
16734 SCIP_Bool* values, /**< values of the variables in the clique */
16735 int nvars, /**< number of problem variables */
16736 BMS_BLKMEM* blkmem, /**< block memory */
16737 SCIP_SET* set, /**< global SCIP settings */
16738 SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
16739 )
16740{
16741 SCIP_VAR* var;
16742 int v;
16743
16744 assert(vars != NULL);
16745 assert(values != NULL);
16746 assert(nvars > 0);
16747 assert(set != NULL);
16748 assert(blkmem != NULL);
16749 assert(clique != NULL);
16750
16751 for( v = nvars - 1; v >= 0; --v )
16752 {
16753 var = vars[v];
16756
16757 /* add clique to variable's clique list */
16758 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
16759
16760 /* check consistency of cliquelist */
16761 SCIPcliquelistCheck(var->cliquelist, var);
16762 }
16763
16764 return SCIP_OKAY;
16765}
16766
16767/** adds a clique to the list of cliques of the given binary variable, but does not change the clique
16768 * itself
16769 */
16771 SCIP_VAR* var, /**< problem variable */
16772 BMS_BLKMEM* blkmem, /**< block memory */
16773 SCIP_SET* set, /**< global SCIP settings */
16774 SCIP_Bool value, /**< value of the variable in the clique */
16775 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
16776 )
16777{
16778 assert(var != NULL);
16781
16782 /* add clique to variable's clique list */
16783 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
16784
16785 return SCIP_OKAY;
16786}
16787
16788
16789/** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
16790 * itself
16791 */
16793 SCIP_VAR* var, /**< problem variable */
16794 BMS_BLKMEM* blkmem, /**< block memory */
16795 SCIP_Bool value, /**< value of the variable in the clique */
16796 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
16797 )
16798{
16799 assert(var != NULL);
16801
16802 /* delete clique from variable's clique list */
16803 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
16804
16805 return SCIP_OKAY;
16806}
16807
16808/** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
16810 SCIP_VAR* var, /**< problem variable */
16811 BMS_BLKMEM* blkmem, /**< block memory */
16812 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16813 SCIP_Bool value, /**< value of the variable in the clique */
16814 SCIP_CLIQUE* clique /**< clique the variable should be removed from */
16815 )
16816{
16817 assert(var != NULL);
16819
16820 /* get corresponding active problem variable */
16827
16828 /* only column and loose variables may be member of a clique */
16830 {
16831 /* delete clique from variable's clique list */
16832 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
16833
16834 /* delete variable from clique */
16835 SCIPcliqueDelVar(clique, cliquetable, var, value);
16836
16837 /* check consistency of cliquelist */
16838 SCIPcliquelistCheck(var->cliquelist, var);
16839 }
16840
16841 return SCIP_OKAY;
16842}
16843
16844/** returns whether there is a clique that contains both given variable/value pairs;
16845 * the variables must be active binary variables;
16846 * if regardimplics is FALSE, only the cliques in the clique table are looked at;
16847 * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
16848 *
16849 * @note a variable with it's negated variable are NOT! in a clique
16850 * @note a variable with itself are in a clique
16851 */
16853 SCIP_VAR* var1, /**< first variable */
16854 SCIP_Bool value1, /**< value of first variable */
16855 SCIP_VAR* var2, /**< second variable */
16856 SCIP_Bool value2, /**< value of second variable */
16857 SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
16858 )
16859{
16860 assert(var1 != NULL);
16861 assert(var2 != NULL);
16862 assert(SCIPvarIsActive(var1));
16863 assert(SCIPvarIsActive(var2));
16864 assert(SCIPvarIsBinary(var1));
16865 assert(SCIPvarIsBinary(var2));
16866
16867 return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
16868 || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
16869}
16870
16871/** actually changes the branch factor of the variable and of all parent variables */
16872static
16874 SCIP_VAR* var, /**< problem variable */
16875 SCIP_SET* set, /**< global SCIP settings */
16876 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
16877 )
16878{
16879 SCIP_VAR* parentvar;
16880 SCIP_Real eps;
16881 int i;
16882
16883 assert(var != NULL);
16884 assert(set != NULL);
16885 assert(var->scip == set->scip);
16886
16887 /* only use positive values */
16889 branchfactor = MAX(branchfactor, eps);
16890
16891 SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
16892
16893 if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
16894 return SCIP_OKAY;
16895
16896 /* change the branch factor */
16897 var->branchfactor = branchfactor;
16898
16899 /* process parent variables */
16900 for( i = 0; i < var->nparentvars; ++i )
16901 {
16902 parentvar = var->parentvars[i];
16903 assert(parentvar != NULL);
16904
16905 switch( SCIPvarGetStatus(parentvar) )
16906 {
16908 /* do not change priorities across the border between transformed and original problem */
16909 break;
16910
16915 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
16916 SCIPABORT();
16917 return SCIP_INVALIDDATA; /*lint !e527*/
16918
16921 SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
16922 break;
16923
16924 default:
16925 SCIPerrorMessage("unknown variable status\n");
16926 SCIPABORT();
16927 return SCIP_ERROR; /*lint !e527*/
16928 }
16929 }
16930
16931 return SCIP_OKAY;
16932}
16933
16934/** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
16935 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
16936 */
16938 SCIP_VAR* var, /**< problem variable */
16939 SCIP_SET* set, /**< global SCIP settings */
16940 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
16941 )
16942{
16943 int v;
16944
16945 assert(var != NULL);
16946 assert(set != NULL);
16947 assert(var->scip == set->scip);
16948 assert(branchfactor >= 0.0);
16949
16950 SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
16951
16952 if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
16953 return SCIP_OKAY;
16954
16955 /* change priorities of attached variables */
16956 switch( SCIPvarGetStatus(var) )
16957 {
16959 if( var->data.original.transvar != NULL )
16960 {
16961 SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
16962 }
16963 else
16964 {
16965 assert(set->stage == SCIP_STAGE_PROBLEM);
16966 var->branchfactor = branchfactor;
16967 }
16968 break;
16969
16973 SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
16974 break;
16975
16977 assert(!var->donotaggr);
16978 assert(var->data.aggregate.var != NULL);
16979 SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
16980 break;
16981
16983 assert(!var->donotmultaggr);
16984 for( v = 0; v < var->data.multaggr.nvars; ++v )
16985 {
16986 SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
16987 }
16988 break;
16989
16991 assert(var->negatedvar != NULL);
16993 assert(var->negatedvar->negatedvar == var);
16994 SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
16995 break;
16996
16997 default:
16998 SCIPerrorMessage("unknown variable status\n");
16999 SCIPABORT();
17000 return SCIP_ERROR; /*lint !e527*/
17001 }
17002
17003 return SCIP_OKAY;
17004}
17005
17006/** actually changes the branch priority of the variable and of all parent variables */
17007static
17009 SCIP_VAR* var, /**< problem variable */
17010 int branchpriority /**< branching priority of the variable */
17011 )
17012{
17013 SCIP_VAR* parentvar;
17014 int i;
17015
17016 assert(var != NULL);
17017
17018 SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
17019 var->name, var->branchpriority, branchpriority);
17020
17021 if( branchpriority == var->branchpriority )
17022 return SCIP_OKAY;
17023
17024 /* change the branch priority */
17025 var->branchpriority = branchpriority;
17026
17027 /* process parent variables */
17028 for( i = 0; i < var->nparentvars; ++i )
17029 {
17030 parentvar = var->parentvars[i];
17031 assert(parentvar != NULL);
17032
17033 switch( SCIPvarGetStatus(parentvar) )
17034 {
17036 /* do not change priorities across the border between transformed and original problem */
17037 break;
17038
17043 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
17044 SCIPABORT();
17045 return SCIP_INVALIDDATA; /*lint !e527*/
17046
17049 SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
17050 break;
17051
17052 default:
17053 SCIPerrorMessage("unknown variable status\n");
17054 return SCIP_ERROR;
17055 }
17056 }
17057
17058 return SCIP_OKAY;
17059}
17060
17061/** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
17062 * with lower priority in selection of branching variable
17063 */
17065 SCIP_VAR* var, /**< problem variable */
17066 int branchpriority /**< branching priority of the variable */
17067 )
17068{
17069 int v;
17070
17071 assert(var != NULL);
17072
17073 SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
17074
17075 if( var->branchpriority == branchpriority )
17076 return SCIP_OKAY;
17077
17078 /* change priorities of attached variables */
17079 switch( SCIPvarGetStatus(var) )
17080 {
17082 if( var->data.original.transvar != NULL )
17083 {
17084 SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
17085 }
17086 else
17087 var->branchpriority = branchpriority;
17088 break;
17089
17093 SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
17094 break;
17095
17097 assert(!var->donotaggr);
17098 assert(var->data.aggregate.var != NULL);
17099 SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
17100 break;
17101
17103 assert(!var->donotmultaggr);
17104 for( v = 0; v < var->data.multaggr.nvars; ++v )
17105 {
17106 SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
17107 }
17108 break;
17109
17111 assert(var->negatedvar != NULL);
17113 assert(var->negatedvar->negatedvar == var);
17114 SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
17115 break;
17116
17117 default:
17118 SCIPerrorMessage("unknown variable status\n");
17119 SCIPABORT();
17120 return SCIP_ERROR; /*lint !e527*/
17121 }
17122
17123 return SCIP_OKAY;
17124}
17125
17126/** actually changes the branch direction of the variable and of all parent variables */
17127static
17129 SCIP_VAR* var, /**< problem variable */
17130 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
17131 )
17132{
17133 SCIP_VAR* parentvar;
17134 int i;
17135
17136 assert(var != NULL);
17137
17138 SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
17139 var->name, var->branchdirection, branchdirection);
17140
17141 if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
17142 return SCIP_OKAY;
17143
17144 /* change the branch direction */
17145 var->branchdirection = branchdirection; /*lint !e641*/
17146
17147 /* process parent variables */
17148 for( i = 0; i < var->nparentvars; ++i )
17149 {
17150 parentvar = var->parentvars[i];
17151 assert(parentvar != NULL);
17152
17153 switch( SCIPvarGetStatus(parentvar) )
17154 {
17156 /* do not change directions across the border between transformed and original problem */
17157 break;
17158
17163 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
17164 SCIPABORT();
17165 return SCIP_INVALIDDATA; /*lint !e527*/
17166
17168 if( parentvar->data.aggregate.scalar > 0.0 )
17169 {
17170 SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
17171 }
17172 else
17173 {
17174 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
17175 }
17176 break;
17177
17179 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
17180 break;
17181
17182 default:
17183 SCIPerrorMessage("unknown variable status\n");
17184 SCIPABORT();
17185 return SCIP_ERROR; /*lint !e527*/
17186 }
17187 }
17188
17189 return SCIP_OKAY;
17190}
17191
17192/** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
17193 * with lower direction in selection of branching variable
17194 */
17196 SCIP_VAR* var, /**< problem variable */
17197 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
17198 )
17199{
17200 int v;
17201
17202 assert(var != NULL);
17203
17204 SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
17205
17206 if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
17207 return SCIP_OKAY;
17208
17209 /* change directions of attached variables */
17210 switch( SCIPvarGetStatus(var) )
17211 {
17213 if( var->data.original.transvar != NULL )
17214 {
17215 SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
17216 }
17217 else
17218 var->branchdirection = branchdirection; /*lint !e641*/
17219 break;
17220
17224 SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
17225 break;
17226
17228 assert(!var->donotaggr);
17229 assert(var->data.aggregate.var != NULL);
17230 if( var->data.aggregate.scalar > 0.0 )
17231 {
17232 SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
17233 }
17234 else
17235 {
17236 SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, SCIPbranchdirOpposite(branchdirection)) );
17237 }
17238 break;
17239
17241 assert(!var->donotmultaggr);
17242 for( v = 0; v < var->data.multaggr.nvars; ++v )
17243 {
17244 /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
17245 assert(var->data.multaggr.vars[v] != NULL);
17246 if( (SCIP_BRANCHDIR)var->data.multaggr.vars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
17247 {
17248 if( var->data.multaggr.scalars[v] > 0.0 )
17249 {
17250 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
17251 }
17252 else
17253 {
17254 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], SCIPbranchdirOpposite(branchdirection)) );
17255 }
17256 }
17257 }
17258 break;
17259
17261 assert(var->negatedvar != NULL);
17263 assert(var->negatedvar->negatedvar == var);
17264 SCIP_CALL( SCIPvarChgBranchDirection(var->negatedvar, SCIPbranchdirOpposite(branchdirection)) );
17265 break;
17266
17267 default:
17268 SCIPerrorMessage("unknown variable status\n");
17269 SCIPABORT();
17270 return SCIP_ERROR; /*lint !e527*/
17271 }
17272
17273 return SCIP_OKAY;
17274}
17275
17276/** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
17277 * is negated then the index of the corresponding active variable is taken, returns -1 if first is
17278 * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
17279 * are equal, which means both variables are equal
17280 */
17282 SCIP_VAR* var1, /**< first problem variable */
17283 SCIP_VAR* var2 /**< second problem variable */
17284 )
17285{
17286 assert(var1 != NULL);
17287 assert(var2 != NULL);
17290
17292 var1 = SCIPvarGetNegatedVar(var1);
17294 var2 = SCIPvarGetNegatedVar(var2);
17295
17296 assert(var1 != NULL);
17297 assert(var2 != NULL);
17298
17299 if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
17300 return -1;
17301 else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
17302 return +1;
17303
17304 assert(var1 == var2);
17305 return 0;
17306}
17307
17308/** comparison method for sorting active and negated variables by non-decreasing index, active and negated
17309 * variables are handled as the same variables
17310 */
17311SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
17312{
17313 return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
17314}
17315
17316/** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
17317 * variable index; returns 0 if both indices are equal, which means both variables are equal
17318 */
17320 SCIP_VAR* var1, /**< first problem variable */
17321 SCIP_VAR* var2 /**< second problem variable */
17322 )
17323{
17324 assert(var1 != NULL);
17325 assert(var2 != NULL);
17326
17327 if( var1->index < var2->index )
17328 return -1;
17329 else if( var1->index > var2->index )
17330 return +1;
17331 else
17332 {
17333 assert(var1 == var2);
17334 return 0;
17335 }
17336}
17337
17338/** comparison method for sorting variables by non-decreasing index */
17340{
17341 return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
17342}
17343
17344/** comparison method for sorting variables by non-decreasing objective coefficient */
17346{
17347 SCIP_Real obj1;
17348 SCIP_Real obj2;
17349
17350 obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
17351 obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
17352
17353 if( obj1 < obj2 )
17354 return -1;
17355 else if( obj1 > obj2 )
17356 return +1;
17357 else
17358 return 0;
17359}
17360
17361/** hash key retrieval function for variables */
17362SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
17363{ /*lint --e{715}*/
17364 return elem;
17365}
17366
17367/** returns TRUE iff the indices of both variables are equal */
17368SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
17369{ /*lint --e{715}*/
17370 if( key1 == key2 )
17371 return TRUE;
17372 return FALSE;
17373}
17374
17375/** returns the hash value of the key */
17376SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
17377{ /*lint --e{715}*/
17378 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
17379 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
17380}
17381
17382/** return for given variables all their active counterparts; all active variables will be pairwise different */
17384 SCIP_SET* set, /**< global SCIP settings */
17385 SCIP_VAR** vars, /**< variable array with given variables and as output all active
17386 * variables, if enough slots exist
17387 */
17388 int* nvars, /**< number of given variables, and as output number of active variables,
17389 * if enough slots exist
17390 */
17391 int varssize, /**< available slots in vars array */
17392 int* requiredsize /**< pointer to store the required array size for the active variables */
17393 )
17394{
17395 SCIP_VAR** activevars;
17396 int nactivevars;
17397 int activevarssize;
17398
17399 SCIP_VAR* var;
17400 int v;
17401
17402 SCIP_VAR** tmpvars;
17403 SCIP_VAR** multvars;
17404 int tmpvarssize;
17405 int ntmpvars;
17406 int noldtmpvars;
17407 int nmultvars;
17408
17409 assert(set != NULL);
17410 assert(nvars != NULL);
17411 assert(vars != NULL || *nvars == 0);
17412 assert(varssize >= *nvars);
17413 assert(requiredsize != NULL);
17414
17415 *requiredsize = 0;
17416
17417 if( *nvars == 0 )
17418 return SCIP_OKAY;
17419
17420 nactivevars = 0;
17421 activevarssize = *nvars;
17422 ntmpvars = *nvars;
17423 tmpvarssize = *nvars;
17424
17425 /* temporary memory */
17426 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
17427 /* coverity[copy_paste_error] */
17428 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
17429
17430 noldtmpvars = ntmpvars;
17431
17432 /* sort all variables to combine equal variables easily */
17433 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17434 for( v = ntmpvars - 1; v > 0; --v )
17435 {
17436 /* combine same variables */
17437 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
17438 {
17439 --ntmpvars;
17440 tmpvars[v] = tmpvars[ntmpvars];
17441 }
17442 }
17443 /* sort all variables again to combine equal variables later on */
17444 if( noldtmpvars > ntmpvars )
17445 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17446
17447 /* collect for each variable the representation in active variables */
17448 while( ntmpvars >= 1 )
17449 {
17450 --ntmpvars;
17451 var = tmpvars[ntmpvars];
17452 assert( var != NULL );
17453
17454 switch( SCIPvarGetStatus(var) )
17455 {
17457 if( var->data.original.transvar == NULL )
17458 {
17459 SCIPerrorMessage("original variable has no transformed variable attached\n");
17460 SCIPABORT();
17461 return SCIP_INVALIDDATA; /*lint !e527*/
17462 }
17463 tmpvars[ntmpvars] = var->data.original.transvar;
17464 ++ntmpvars;
17465 break;
17466
17468 tmpvars[ntmpvars] = var->data.aggregate.var;
17469 ++ntmpvars;
17470 break;
17471
17473 tmpvars[ntmpvars] = var->negatedvar;
17474 ++ntmpvars;
17475 break;
17476
17479 /* check for space in temporary memory */
17480 if( nactivevars >= activevarssize )
17481 {
17482 activevarssize *= 2;
17483 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
17484 assert(nactivevars < activevarssize);
17485 }
17486 activevars[nactivevars] = var;
17487 nactivevars++;
17488 break;
17489
17491 /* x = a_1*y_1 + ... + a_n*y_n + c */
17492 nmultvars = var->data.multaggr.nvars;
17493 multvars = var->data.multaggr.vars;
17494
17495 /* check for space in temporary memory */
17496 if( nmultvars + ntmpvars > tmpvarssize )
17497 {
17498 while( nmultvars + ntmpvars > tmpvarssize )
17499 tmpvarssize *= 2;
17500 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
17501 assert(nmultvars + ntmpvars <= tmpvarssize);
17502 }
17503
17504 /* copy all multi-aggregation variables into our working array */
17505 BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
17506
17507 /* get active, fixed or multi-aggregated corresponding variables for all new ones */
17508 SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
17509
17510 ntmpvars += nmultvars;
17511 noldtmpvars = ntmpvars;
17512
17513 /* sort all variables to combine equal variables easily */
17514 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17515 for( v = ntmpvars - 1; v > 0; --v )
17516 {
17517 /* combine same variables */
17518 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
17519 {
17520 --ntmpvars;
17521 tmpvars[v] = tmpvars[ntmpvars];
17522 }
17523 }
17524 /* sort all variables again to combine equal variables later on */
17525 if( noldtmpvars > ntmpvars )
17526 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17527
17528 break;
17529
17531 /* no need for memorizing fixed variables */
17532 break;
17533
17534 default:
17535 SCIPerrorMessage("unknown variable status\n");
17536 SCIPABORT();
17537 return SCIP_INVALIDDATA; /*lint !e527*/
17538 }
17539 }
17540
17541 /* sort variable array by variable index */
17542 SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
17543
17544 /* eliminate duplicates and count required size */
17545 v = nactivevars - 1;
17546 while( v > 0 )
17547 {
17548 /* combine both variable since they are the same */
17549 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
17550 {
17551 --nactivevars;
17552 activevars[v] = activevars[nactivevars];
17553 }
17554 --v;
17555 }
17556 *requiredsize = nactivevars;
17557
17558 if( varssize >= *requiredsize )
17559 {
17560 assert(vars != NULL);
17561
17562 *nvars = *requiredsize;
17563 BMScopyMemoryArray(vars, activevars, nactivevars);
17564 }
17565
17566 SCIPsetFreeBufferArray(set, &tmpvars);
17567 SCIPsetFreeBufferArray(set, &activevars);
17568
17569 return SCIP_OKAY;
17570}
17571
17572/** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
17573 * @note the content of the given array will/might change
17574 */
17576 SCIP_VAR** vars, /**< array of problem variables */
17577 int nvars /**< number of variables */
17578 )
17579{
17580 int v;
17581
17582 assert(vars != NULL || nvars == 0);
17583
17584 for( v = nvars - 1; v >= 0; --v )
17585 {
17586 assert(vars != NULL);
17587 assert(vars[v] != NULL);
17588
17589 vars[v] = SCIPvarGetProbvar(vars[v]);
17590 assert(vars[v] != NULL);
17591 }
17592}
17593
17594/** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
17596 SCIP_VAR* var /**< problem variable */
17597 )
17598{
17599 SCIP_VAR* retvar;
17600
17601 assert(var != NULL);
17602
17603 retvar = var;
17604
17605 SCIPdebugMessage("get problem variable of <%s>\n", var->name);
17606
17607 while( TRUE ) /*lint !e716 */
17608 {
17609 assert(retvar != NULL);
17610
17611 switch( SCIPvarGetStatus(retvar) )
17612 {
17614 if( retvar->data.original.transvar == NULL )
17615 {
17616 SCIPerrorMessage("original variable has no transformed variable attached\n");
17617 SCIPABORT();
17618 return NULL; /*lint !e527 */
17619 }
17620 retvar = retvar->data.original.transvar;
17621 break;
17622
17626 return retvar;
17627
17629 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17630 if ( retvar->data.multaggr.nvars == 1 )
17631 retvar = retvar->data.multaggr.vars[0];
17632 else
17633 return retvar;
17634 break;
17635
17637 retvar = retvar->data.aggregate.var;
17638 break;
17639
17641 retvar = retvar->negatedvar;
17642 break;
17643
17644 default:
17645 SCIPerrorMessage("unknown variable status\n");
17646 SCIPABORT();
17647 return NULL; /*lint !e527*/
17648 }
17649 }
17650}
17651
17652/** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
17653 * negation status of each variable
17654 */
17656 SCIP_VAR*** vars, /**< pointer to binary problem variables */
17657 SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
17658 int nvars /**< number of variables and values in vars and negated array */
17659 )
17660{
17661 SCIP_VAR** var;
17662 SCIP_Bool* negated;
17663 int v;
17664
17665 assert(vars != NULL);
17666 assert(*vars != NULL || nvars == 0);
17667 assert(negatedarr != NULL);
17668 assert(*negatedarr != NULL || nvars == 0);
17669
17670 for( v = nvars - 1; v >= 0; --v )
17671 {
17672 var = &((*vars)[v]);
17673 negated = &((*negatedarr)[v]);
17674
17675 /* get problem variable */
17677 }
17678
17679 return SCIP_OKAY;
17680}
17681
17682
17683/** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
17684 * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
17685 * FALSE is used)
17686 */
17688 SCIP_VAR** var, /**< pointer to binary problem variable */
17689 SCIP_Bool* negated /**< pointer to update the negation status */
17690 )
17691{
17693#ifndef NDEBUG
17694 SCIP_Real constant = 0.0;
17695 SCIP_Bool orignegated;
17696#endif
17697
17698 assert(var != NULL);
17699 assert(*var != NULL);
17700 assert(negated != NULL);
17702
17703#ifndef NDEBUG
17704 orignegated = *negated;
17705#endif
17706
17707 while( !active && *var != NULL )
17708 {
17709 switch( SCIPvarGetStatus(*var) )
17710 {
17712 if( (*var)->data.original.transvar == NULL )
17713 return SCIP_OKAY;
17714 *var = (*var)->data.original.transvar;
17715 break;
17716
17720 active = TRUE;
17721 break;
17722
17724 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17725 if ( (*var)->data.multaggr.nvars == 1 )
17726 {
17727 assert( (*var)->data.multaggr.vars != NULL );
17728 assert( (*var)->data.multaggr.scalars != NULL );
17729 assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
17730 assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
17731
17732 /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
17733 * another variable which needs to be fixed
17734 *
17735 * e.g. x = y - 1 => (x = 0 && y = 1)
17736 * e.g. x = y + 1 => (x = 1 && y = 0)
17737 *
17738 * is this special case we need to return the muti-aggregation
17739 */
17740 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)) )
17741 {
17742 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
17743 }
17744 else
17745 {
17746 /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
17747 * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
17748 * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
17749 * we will return the aggregated variable;
17750 */
17751 if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
17752 {
17753 active = TRUE;
17754 break;
17755 }
17756
17757 /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
17758 * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
17759 * so if this is the case, we will return the aggregated variable
17760 */
17761 assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
17762 || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
17763 || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
17764
17765 if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
17766 {
17767 active = TRUE;
17768 break;
17769 }
17770
17771 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
17772
17773 if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
17774 {
17775 /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
17776 * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
17777 * variable itself is multi-aggregated again?
17778 */
17779 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
17780 ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
17781 SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
17782 }
17783 else
17784 {
17785 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
17786#ifndef NDEBUG
17787 constant += (*negated) != orignegated ? -1.0 : 1.0;
17788#endif
17789
17790 *negated = !(*negated);
17791 }
17792 *var = (*var)->data.multaggr.vars[0];
17793 break;
17794 }
17795 }
17796 active = TRUE; /*lint !e838*/
17797 break;
17798
17799 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17800 assert((*var)->data.aggregate.var != NULL);
17801 assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
17802 assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
17803#ifndef NDEBUG
17804 constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
17805#endif
17806
17807 *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
17808 *var = (*var)->data.aggregate.var;
17809 break;
17810
17811 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17812 assert((*var)->negatedvar != NULL);
17813#ifndef NDEBUG
17814 constant += (*negated) != orignegated ? -1.0 : 1.0;
17815#endif
17816
17817 *negated = !(*negated);
17818 *var = (*var)->negatedvar;
17819 break;
17820
17821 default:
17822 SCIPerrorMessage("unknown variable status\n");
17823 return SCIP_INVALIDDATA;
17824 }
17825 }
17826 assert(active == (*var != NULL));
17827
17828 if( active )
17829 {
17831 assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
17832 assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
17833
17834 return SCIP_OKAY;
17835 }
17836 else
17837 {
17838 SCIPerrorMessage("active variable path leads to NULL pointer\n");
17839 return SCIP_INVALIDDATA;
17840 }
17841}
17842
17843/** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
17844 * values
17845 */
17847 SCIP_VAR** var, /**< pointer to problem variable */
17848 SCIP_Real* bound, /**< pointer to bound value to transform */
17849 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
17850 )
17851{
17852 assert(var != NULL);
17853 assert(*var != NULL);
17854 assert(bound != NULL);
17855 assert(boundtype != NULL);
17856
17857 SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
17858
17859 switch( SCIPvarGetStatus(*var) )
17860 {
17862 if( (*var)->data.original.transvar == NULL )
17863 {
17864 SCIPerrorMessage("original variable has no transformed variable attached\n");
17865 return SCIP_INVALIDDATA;
17866 }
17867 *var = (*var)->data.original.transvar;
17868 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17869 break;
17870
17874 break;
17875
17877 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17878 if ( (*var)->data.multaggr.nvars == 1 )
17879 {
17880 assert( (*var)->data.multaggr.vars != NULL );
17881 assert( (*var)->data.multaggr.scalars != NULL );
17882 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
17883
17884 (*bound) /= (*var)->data.multaggr.scalars[0];
17885 (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
17886 if ( (*var)->data.multaggr.scalars[0] < 0.0 )
17887 {
17888 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
17889 *boundtype = SCIP_BOUNDTYPE_UPPER;
17890 else
17891 *boundtype = SCIP_BOUNDTYPE_LOWER;
17892 }
17893 *var = (*var)->data.multaggr.vars[0];
17894 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17895 }
17896 break;
17897
17898 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
17899 assert((*var)->data.aggregate.var != NULL);
17900 assert((*var)->data.aggregate.scalar != 0.0);
17901
17902 (*bound) /= (*var)->data.aggregate.scalar;
17903 (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
17904 if( (*var)->data.aggregate.scalar < 0.0 )
17905 {
17906 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17907 *boundtype = SCIP_BOUNDTYPE_UPPER;
17908 else
17909 *boundtype = SCIP_BOUNDTYPE_LOWER;
17910 }
17911 *var = (*var)->data.aggregate.var;
17912 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17913 break;
17914
17915 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
17916 assert((*var)->negatedvar != NULL);
17917 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
17918 assert((*var)->negatedvar->negatedvar == *var);
17919 (*bound) = (*var)->data.negate.constant - *bound;
17920 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17921 *boundtype = SCIP_BOUNDTYPE_UPPER;
17922 else
17923 *boundtype = SCIP_BOUNDTYPE_LOWER;
17924 *var = (*var)->negatedvar;
17925 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17926 break;
17927
17928 default:
17929 SCIPerrorMessage("unknown variable status\n");
17930 return SCIP_INVALIDDATA;
17931 }
17932
17933 return SCIP_OKAY;
17934}
17935
17936/** transforms given variable, boundtype and exact bound to the corresponding active, fixed, or multi-aggregated variable
17937 * values
17938 */
17940 SCIP_VAR** var, /**< pointer to problem variable */
17941 SCIP_RATIONAL* bound, /**< pointer to bound value to transform */
17942 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
17943 )
17944{
17945 assert(var != NULL);
17946 assert(*var != NULL);
17947 assert(bound != NULL);
17948 assert(boundtype != NULL);
17949
17950 SCIPrationalDebugMessage("get probvar bound %q of type %d of variable <%s>\n", bound, *boundtype, (*var)->name);
17951
17952 switch( SCIPvarGetStatusExact(*var) )
17953 {
17955 if( (*var)->data.original.transvar == NULL )
17956 {
17957 SCIPerrorMessage("original variable has no transformed variable attached\n");
17958 return SCIP_INVALIDDATA;
17959 }
17960 *var = (*var)->data.original.transvar;
17962 break;
17963
17967 break;
17968
17970 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17971 if( (*var)->data.multaggr.nvars == 1 )
17972 {
17973 assert( (*var)->data.multaggr.vars != NULL );
17974 assert( (*var)->data.multaggr.scalars != NULL );
17975 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
17976
17977 SCIPrationalDiff(bound, bound, (*var)->exactdata->multaggr.constant);
17978 SCIPrationalDiv(bound, bound, (*var)->exactdata->multaggr.scalars[0]);
17979
17980 if( SCIPrationalIsNegative((*var)->exactdata->multaggr.scalars[0]) )
17981 {
17982 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
17983 *boundtype = SCIP_BOUNDTYPE_UPPER;
17984 else
17985 *boundtype = SCIP_BOUNDTYPE_LOWER;
17986 }
17987 *var = (*var)->data.multaggr.vars[0];
17989 }
17990 break;
17991
17992 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
17993 assert((*var)->data.aggregate.var != NULL);
17994 assert((*var)->data.aggregate.scalar != 0.0);
17995
17996 SCIPrationalDiff(bound, bound, (*var)->exactdata->aggregate.constant);
17997 SCIPrationalDiv(bound, bound, (*var)->exactdata->aggregate.scalar);
17998
17999 if( SCIPrationalIsNegative((*var)->exactdata->aggregate.scalar) )
18000 {
18001 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
18002 *boundtype = SCIP_BOUNDTYPE_UPPER;
18003 else
18004 *boundtype = SCIP_BOUNDTYPE_LOWER;
18005 }
18006 *var = (*var)->data.aggregate.var;
18008 break;
18009
18010 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18011 assert((*var)->negatedvar != NULL);
18012 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18013 assert((*var)->negatedvar->negatedvar == *var);
18014 SCIPrationalDiffReal(bound, bound, (*var)->data.negate.constant);
18016 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
18017 *boundtype = SCIP_BOUNDTYPE_UPPER;
18018 else
18019 *boundtype = SCIP_BOUNDTYPE_LOWER;
18020 *var = (*var)->negatedvar;
18022 break;
18023
18024 default:
18025 SCIPerrorMessage("unknown variable status\n");
18026 return SCIP_INVALIDDATA;
18027 }
18028
18029 return SCIP_OKAY;
18030}
18031
18032/** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
18033 * values
18034 */
18036 SCIP_VAR** var, /**< pointer to problem variable */
18037 SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
18038 SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
18039 )
18040{
18041 assert(var != NULL);
18042 assert(*var != NULL);
18043 assert(left != NULL);
18044 assert(right != NULL);
18045
18046 SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
18047
18048 switch( SCIPvarGetStatus(*var) )
18049 {
18051 if( (*var)->data.original.transvar == NULL )
18052 {
18053 SCIPerrorMessage("original variable has no transformed variable attached\n");
18054 return SCIP_INVALIDDATA;
18055 }
18056 *var = (*var)->data.original.transvar;
18057 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
18058 break;
18059
18064 break;
18065
18066 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
18067 assert((*var)->data.aggregate.var != NULL);
18068 assert((*var)->data.aggregate.scalar != 0.0);
18069
18070 /* scale back */
18071 (*left) /= (*var)->data.aggregate.scalar;
18072 (*right) /= (*var)->data.aggregate.scalar;
18073
18074 /* shift back */
18075 (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
18076 (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
18077
18078 *var = (*var)->data.aggregate.var;
18079
18080 /* check if the interval bounds have to swapped */
18081 if( (*var)->data.aggregate.scalar < 0.0 )
18082 {
18083 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
18084 }
18085 else
18086 {
18087 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
18088 }
18089 break;
18090
18091 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18092 assert((*var)->negatedvar != NULL);
18093 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18094 assert((*var)->negatedvar->negatedvar == *var);
18095
18096 /* shift and scale back */
18097 (*left) = (*var)->data.negate.constant - (*left);
18098 (*right) = (*var)->data.negate.constant - (*right);
18099
18100 *var = (*var)->negatedvar;
18101
18102 /* through the negated variable the left and right interval bound have to swapped */
18103 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
18104 break;
18105
18106 default:
18107 SCIPerrorMessage("unknown variable status\n");
18108 return SCIP_INVALIDDATA;
18109 }
18110
18111 return SCIP_OKAY;
18112}
18113
18114/** transforms given variable, scalar and constant to the corresponding active, fixed, or
18115 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
18116 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
18117 * with only one active variable (this can happen due to fixings after the multi-aggregation),
18118 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
18119 */
18121 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18122 SCIP_SET* set, /**< global SCIP settings */
18123 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
18124 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
18125 )
18126{
18127 assert(var != NULL);
18128 assert(scalar != NULL);
18129 assert(constant != NULL);
18130
18131 while( *var != NULL )
18132 {
18133 switch( SCIPvarGetStatus(*var) )
18134 {
18136 if( (*var)->data.original.transvar == NULL )
18137 {
18138 SCIPerrorMessage("original variable has no transformed variable attached\n");
18139 return SCIP_INVALIDDATA;
18140 }
18141 *var = (*var)->data.original.transvar;
18142 break;
18143
18146 return SCIP_OKAY;
18147
18148 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
18149 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18150 {
18151 if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
18152 {
18153 assert(*scalar != 0.0);
18154 if( (*scalar) * (*var)->glbdom.lb > 0.0 )
18155 (*constant) = SCIPsetInfinity(set);
18156 else
18157 (*constant) = -SCIPsetInfinity(set);
18158 }
18159 else
18160 (*constant) += *scalar * (*var)->glbdom.lb;
18161 }
18162#ifndef NDEBUG
18163 else
18164 {
18165 assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
18166 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
18167 assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
18168 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
18169 }
18170#endif
18171 *scalar = 0.0;
18172 return SCIP_OKAY;
18173
18175 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
18176 if ( (*var)->data.multaggr.nvars == 1 )
18177 {
18178 assert((*var)->data.multaggr.vars != NULL);
18179 assert((*var)->data.multaggr.scalars != NULL);
18180 assert((*var)->data.multaggr.vars[0] != NULL);
18181 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18182 {
18183 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
18184 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
18185 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
18186 */
18187 if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
18188 || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
18189 {
18190 if( (*scalar) * (*var)->data.multaggr.constant > 0 )
18191 {
18192 assert(!SCIPsetIsInfinity(set, -(*constant)));
18193 (*constant) = SCIPsetInfinity(set);
18194 }
18195 else
18196 {
18197 assert(!SCIPsetIsInfinity(set, *constant));
18198 (*constant) = -SCIPsetInfinity(set);
18199 }
18200 (*scalar) = 0.0;
18201 }
18202 else
18203 (*constant) += *scalar * (*var)->data.multaggr.constant;
18204 }
18205 (*scalar) *= (*var)->data.multaggr.scalars[0];
18206 *var = (*var)->data.multaggr.vars[0];
18207 break;
18208 }
18209 return SCIP_OKAY;
18210
18211 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18212 assert((*var)->data.aggregate.var != NULL);
18213 assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
18214 && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
18215 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18216 (*constant) += *scalar * (*var)->data.aggregate.constant;
18217 (*scalar) *= (*var)->data.aggregate.scalar;
18218 *var = (*var)->data.aggregate.var;
18219 break;
18220
18221 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18222 assert((*var)->negatedvar != NULL);
18223 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18224 assert((*var)->negatedvar->negatedvar == *var);
18225 assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
18226 && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
18227 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18228 (*constant) += *scalar * (*var)->data.negate.constant;
18229 (*scalar) *= -1.0;
18230 *var = (*var)->negatedvar;
18231 break;
18232
18233 default:
18234 SCIPerrorMessage("unknown variable status\n");
18235 SCIPABORT();
18236 return SCIP_INVALIDDATA; /*lint !e527*/
18237 }
18238 }
18239 *scalar = 0.0;
18240
18241 return SCIP_OKAY;
18242}
18243
18244/** transforms given variable, scalar and constant to the corresponding active, fixed, or
18245 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
18246 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
18247 * with only one active variable (this can happen due to fixings after the multi-aggregation),
18248 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
18249 */
18251 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18252 SCIP_RATIONAL* scalar, /**< pointer to scalar a in sum a*x + c */
18253 SCIP_RATIONAL* constant /**< pointer to constant c in sum a*x + c */
18254 )
18255{
18256 assert(var != NULL);
18257 assert(scalar != NULL);
18258 assert(constant != NULL);
18260
18261 while( *var != NULL )
18262 {
18263 switch( SCIPvarGetStatusExact(*var) )
18264 {
18266 if( (*var)->data.original.transvar == NULL )
18267 {
18268 SCIPerrorMessage("original variable has no transformed variable attached\n");
18269 return SCIP_INVALIDDATA;
18270 }
18271 *var = (*var)->data.original.transvar;
18272 break;
18273
18276 return SCIP_OKAY;
18277
18278 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
18279 if( !SCIPrationalIsInfinity(constant) && !SCIPrationalIsNegInfinity(constant) )
18280 {
18281 if( SCIPrationalIsInfinity((*var)->exactdata->glbdom.lb) || SCIPrationalIsNegInfinity(((*var)->exactdata->glbdom.lb)) )
18282 {
18283 assert(!SCIPrationalIsZero(scalar));
18284 if( SCIPrationalIsPositive(scalar) == SCIPrationalIsPositive((*var)->exactdata->glbdom.lb) )
18285 SCIPrationalSetInfinity(constant);
18286 else
18288 }
18289 else
18290 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->glbdom.lb);
18291 }
18292 SCIPrationalSetReal(scalar, 0.0);
18293 return SCIP_OKAY;
18294
18296 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
18297 if ( (*var)->data.multaggr.nvars == 1 )
18298 {
18299 assert((*var)->data.multaggr.vars != NULL);
18300 assert((*var)->data.multaggr.scalars != NULL);
18301 assert((*var)->data.multaggr.vars[0] != NULL);
18302 if( !SCIPrationalIsAbsInfinity(constant) )
18303 {
18304 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
18305 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
18306 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
18307 */
18308 if( SCIPrationalIsAbsInfinity((*var)->exactdata->multaggr.constant) )
18309 {
18310 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign((*var)->exactdata->multaggr.constant) && !SCIPrationalIsZero(scalar) )
18311 {
18313 SCIPrationalSetInfinity(constant);
18314 }
18315 else
18316 {
18317 assert(!SCIPrationalIsInfinity(constant));
18319 }
18320 SCIPrationalSetReal(scalar, 0.0);
18321 }
18322 else
18323 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->multaggr.constant);
18324 }
18325 SCIPrationalMult(scalar, scalar, (*var)->exactdata->multaggr.scalars[0]);
18326 *var = (*var)->data.multaggr.vars[0];
18327 break;
18328 }
18329 return SCIP_OKAY;
18330
18331 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18332 assert((*var)->data.aggregate.var != NULL);
18333 assert(!SCIPrationalIsAbsInfinity((*var)->exactdata->aggregate.constant));
18334 if( !SCIPrationalIsAbsInfinity(constant) )
18335 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->aggregate.constant);
18336 SCIPrationalMult(scalar, scalar, (*var)->exactdata->aggregate.scalar);
18337 *var = (*var)->data.aggregate.var;
18338 break;
18339 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18340 assert((*var)->negatedvar != NULL);
18341 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18342 assert((*var)->negatedvar->negatedvar == *var);
18343 if( !SCIPrationalIsInfinity(constant) && !SCIPrationalIsNegInfinity(constant) )
18344 SCIPrationalAddProdReal(constant, scalar, (*var)->data.negate.constant);
18345
18346 SCIPrationalNegate(scalar, scalar);
18347 *var = (*var)->negatedvar;
18348 break;
18349
18350 default:
18351 SCIPerrorMessage("unknown variable status\n");
18352 SCIPABORT();
18353 return SCIP_INVALIDDATA; /*lint !e527*/
18354 }
18355 }
18356 SCIPrationalSetReal(scalar, 0.0);
18357
18358 return SCIP_OKAY;
18359}
18360
18361
18362/** retransforms given variable, scalar and constant to the corresponding original variable, scalar
18363 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
18364 */
18366 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18367 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
18368 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
18369 )
18370{
18371 SCIP_VAR* parentvar;
18372
18373 assert(var != NULL);
18374 assert(*var != NULL);
18375 assert(scalar != NULL);
18376 assert(constant != NULL);
18377
18378 while( !SCIPvarIsOriginal(*var) )
18379 {
18380 /* if the variable has no parents, it was generated during solving and has no corresponding original var */
18381 if( (*var)->nparentvars == 0 )
18382 {
18383 /* negated variables do not need to have a parent variables, and negated variables can exist in original
18384 * space
18385 */
18387 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
18388 {
18389 *scalar *= -1.0;
18390 *constant -= (*var)->data.negate.constant * (*scalar);
18391 *var = (*var)->negatedvar;
18392
18393 continue;
18394 }
18395 else
18396 {
18397 *var = NULL;
18398
18399 return SCIP_OKAY;
18400 }
18401 }
18402
18403 /* follow the link to the first parent variable */
18404 parentvar = (*var)->parentvars[0];
18405 assert(parentvar != NULL);
18406
18407 switch( SCIPvarGetStatus(parentvar) )
18408 {
18410 break;
18411
18416 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
18417 return SCIP_INVALIDDATA;
18418
18419 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
18420 assert(parentvar->data.aggregate.var == *var);
18421 assert(parentvar->data.aggregate.scalar != 0.0);
18422 *scalar /= parentvar->data.aggregate.scalar;
18423 *constant -= parentvar->data.aggregate.constant * (*scalar);
18424 break;
18425
18426 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
18427 assert(parentvar->negatedvar != NULL);
18429 assert(parentvar->negatedvar->negatedvar == parentvar);
18430 *scalar *= -1.0;
18431 *constant -= parentvar->data.negate.constant * (*scalar);
18432 break;
18433
18434 default:
18435 SCIPerrorMessage("unknown variable status\n");
18436 return SCIP_INVALIDDATA;
18437 }
18438
18439 assert( parentvar != NULL );
18440 *var = parentvar;
18441 }
18442
18443 return SCIP_OKAY;
18444}
18445
18446/** retransforms given variable, scalar anqd constant to the corresponding original variable, scalar
18447 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
18448 */
18450 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18451 SCIP_RATIONAL* scalar, /**< pointer to scalar a in sum a*x + c */
18452 SCIP_RATIONAL* constant /**< pointer to constant c in sum a*x + c */
18453 )
18454{
18455 SCIP_VAR* parentvar;
18456
18457 assert(var != NULL);
18458 assert(*var != NULL);
18459 assert(scalar != NULL);
18460 assert(constant != NULL);
18461
18462 while( !SCIPvarIsOriginal(*var) )
18463 {
18464 /* if the variable has no parents, it was generated during solving and has no corresponding original var */
18465 if( (*var)->nparentvars == 0 )
18466 {
18467 /* negated variables do not need to have a parent variables, and negated variables can exist in original
18468 * space
18469 */
18471 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
18472 {
18473 SCIPrationalNegate(scalar, scalar);
18474 SCIPrationalDiffProdReal(constant, scalar, (*var)->data.negate.constant);
18475 *var = (*var)->negatedvar;
18476
18477 continue;
18478 }
18479 else
18480 {
18481 *var = NULL;
18482
18483 return SCIP_OKAY;
18484 }
18485 }
18486
18487 /* follow the link to the first parent variable */
18488 parentvar = (*var)->parentvars[0];
18489 assert(parentvar != NULL);
18490
18491 switch( SCIPvarGetStatusExact(parentvar) )
18492 {
18494 break;
18495
18500 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
18501 return SCIP_INVALIDDATA;
18502
18503 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
18504 assert(parentvar->data.aggregate.var == *var);
18505 assert(parentvar->data.aggregate.scalar != 0.0);
18506 SCIPrationalDiv(scalar, scalar, parentvar->exactdata->aggregate.scalar);
18507 SCIPrationalDiffProd(constant, scalar, parentvar->exactdata->aggregate.constant);
18508 break;
18509
18510 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
18511 assert(parentvar->negatedvar != NULL);
18513 assert(parentvar->negatedvar->negatedvar == parentvar);
18514 SCIPrationalNegate(scalar, scalar);
18515 SCIPrationalDiffProdReal(constant, scalar, parentvar->data.negate.constant);
18516 break;
18517
18518 default:
18519 SCIPerrorMessage("unknown variable status\n");
18520 return SCIP_INVALIDDATA;
18521 }
18522
18523 assert( parentvar != NULL );
18524 *var = parentvar;
18525 }
18526
18527 return SCIP_OKAY;
18528}
18529
18530
18531/** returns whether the given variable is the direct counterpart of an original problem variable */
18533 SCIP_VAR* var /**< problem variable */
18534 )
18535{
18536 SCIP_VAR* parentvar;
18537 assert(var != NULL);
18538
18539 if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
18540 return FALSE;
18541
18542 assert(var->parentvars != NULL);
18543 parentvar = var->parentvars[0];
18544 assert(parentvar != NULL);
18545
18546 /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
18547 while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
18548 parentvar = parentvar->parentvars[0];
18549 assert( parentvar != NULL );
18550
18551 return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
18552}
18553
18554/** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
18555 * the variable's own data due to diving, that operate only on the LP without updating the variables
18556 */
18558 SCIP_VAR* var /**< problem variable */
18559 )
18560{
18561 assert(var != NULL);
18562
18563 /* get bounds of attached variables */
18564 switch( SCIPvarGetStatus(var) )
18565 {
18567 assert(var->data.original.transvar != NULL);
18568 return SCIPvarGetObjLP(var->data.original.transvar);
18569
18571 assert(var->data.col != NULL);
18572 return SCIPcolGetObj(var->data.col);
18573
18576 return var->obj;
18577
18578 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18579 assert(var->data.aggregate.var != NULL);
18580 return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
18581
18583 SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
18584 SCIPABORT();
18585 return 0.0; /*lint !e527*/
18586
18587 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18588 assert(var->negatedvar != NULL);
18590 assert(var->negatedvar->negatedvar == var);
18591 return -SCIPvarGetObjLP(var->negatedvar);
18592
18593 default:
18594 SCIPerrorMessage("unknown variable status\n");
18595 SCIPABORT();
18596 return 0.0; /*lint !e527*/
18597 }
18598}
18599
18600/** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
18601 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
18602 */
18604 SCIP_VAR* var, /**< problem variable */
18605 SCIP_SET* set /**< global SCIP settings */
18606 )
18607{
18608 assert(var != NULL);
18609 assert(set != NULL);
18610 assert(var->scip == set->scip);
18611
18612 /* get bounds of attached variables */
18613 switch( SCIPvarGetStatus(var) )
18614 {
18616 assert(var->data.original.transvar != NULL);
18617 return SCIPvarGetLbLP(var->data.original.transvar, set);
18618
18620 assert(var->data.col != NULL);
18621 return SCIPcolGetLb(var->data.col);
18622
18625 return var->locdom.lb;
18626
18627 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18628 assert(var->data.aggregate.var != NULL);
18629 if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
18630 || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
18631 {
18632 return -SCIPsetInfinity(set);
18633 }
18634 else if( var->data.aggregate.scalar > 0.0 )
18635 {
18636 /* a > 0 -> get lower bound of y */
18637 return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18638 }
18639 else if( var->data.aggregate.scalar < 0.0 )
18640 {
18641 /* a < 0 -> get upper bound of y */
18642 return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18643 }
18644 else
18645 {
18646 SCIPerrorMessage("scalar is zero in aggregation\n");
18647 SCIPABORT();
18648 return SCIP_INVALID; /*lint !e527*/
18649 }
18650
18652 /**@todo get the sides of the corresponding linear constraint */
18653 SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
18654 SCIPABORT();
18655 return SCIP_INVALID; /*lint !e527*/
18656
18657 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18658 assert(var->negatedvar != NULL);
18660 assert(var->negatedvar->negatedvar == var);
18661 return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
18662
18663 default:
18664 SCIPerrorMessage("unknown variable status\n");
18665 SCIPABORT();
18666 return SCIP_INVALID; /*lint !e527*/
18667 }
18668}
18669
18670/** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
18671 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
18672 */
18674 SCIP_VAR* var, /**< problem variable */
18675 SCIP_SET* set /**< global SCIP settings */
18676 )
18677{
18678 assert(var != NULL);
18679 assert(set != NULL);
18680 assert(var->scip == set->scip);
18681
18682 /* get bounds of attached variables */
18683 switch( SCIPvarGetStatus(var) )
18684 {
18686 assert(var->data.original.transvar != NULL);
18687 return SCIPvarGetUbLP(var->data.original.transvar, set);
18688
18690 assert(var->data.col != NULL);
18691 return SCIPcolGetUb(var->data.col);
18692
18695 return var->locdom.ub;
18696
18697 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18698 assert(var->data.aggregate.var != NULL);
18699 if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
18700 || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
18701 {
18702 return SCIPsetInfinity(set);
18703 }
18704 if( var->data.aggregate.scalar > 0.0 )
18705 {
18706 /* a > 0 -> get upper bound of y */
18707 return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18708 }
18709 else if( var->data.aggregate.scalar < 0.0 )
18710 {
18711 /* a < 0 -> get lower bound of y */
18712 return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18713 }
18714 else
18715 {
18716 SCIPerrorMessage("scalar is zero in aggregation\n");
18717 SCIPABORT();
18718 return SCIP_INVALID; /*lint !e527*/
18719 }
18720
18722 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
18723 SCIPABORT();
18724 return SCIP_INVALID; /*lint !e527*/
18725
18726 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18727 assert(var->negatedvar != NULL);
18729 assert(var->negatedvar->negatedvar == var);
18730 return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
18731
18732 default:
18733 SCIPerrorMessage("unknown variable status\n");
18734 SCIPABORT();
18735 return SCIP_INVALID; /*lint !e527*/
18736 }
18737}
18738
18739/** gets primal LP solution value of variable */
18741 SCIP_VAR* var /**< problem variable */
18742 )
18743{
18744 assert(var != NULL);
18745
18746 switch( SCIPvarGetStatus(var) )
18747 {
18749 if( var->data.original.transvar == NULL )
18750 return SCIP_INVALID;
18751 return SCIPvarGetLPSol(var->data.original.transvar);
18752
18755
18757 assert(var->data.col != NULL);
18758 return SCIPcolGetPrimsol(var->data.col);
18759
18761 assert(var->locdom.lb == var->locdom.ub || (var->exactdata != NULL && SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub))); /*lint !e777*/
18762 return var->locdom.lb;
18763
18765 {
18766 SCIP_Real lpsolval;
18767
18768 assert(!var->donotaggr);
18769 assert(var->data.aggregate.var != NULL);
18770 lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
18771
18772 /* In the following test we use SCIP_DEFAULT_INFINITY, because we do not want to introduce a SCIP or SCIP_SET
18773 * pointer to this method, since it is (or is called by) a public interface method. Note that
18774 * this may yield inconsistent values if the parameter <numerics/infinity> is modified by the user.
18775 */
18776 if( lpsolval >= SCIP_DEFAULT_INFINITY )
18777 return (var->data.aggregate.scalar > 0) ? SCIP_DEFAULT_INFINITY : -SCIP_DEFAULT_INFINITY;
18778 else if( lpsolval <= -SCIP_DEFAULT_INFINITY )
18779 return (var->data.aggregate.scalar > 0) ? -SCIP_DEFAULT_INFINITY : SCIP_DEFAULT_INFINITY;
18780
18781 return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
18782 }
18784 {
18786 int i;
18787
18788 assert(!var->donotmultaggr);
18789 assert(var->data.multaggr.vars != NULL);
18790 assert(var->data.multaggr.scalars != NULL);
18791 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18792 * assert(var->data.multaggr.nvars >= 2);
18793 */
18794 primsol = var->data.multaggr.constant;
18795 for( i = 0; i < var->data.multaggr.nvars; ++i )
18796 primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
18797 return primsol;
18798 }
18799 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18800 assert(var->negatedvar != NULL);
18802 assert(var->negatedvar->negatedvar == var);
18803 return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
18804
18805 default:
18806 SCIPerrorMessage("unknown variable status\n");
18807 SCIPABORT();
18808 return SCIP_INVALID; /*lint !e527*/
18809 }
18810}
18811
18812/** gets exact primal LP solution value of variable or value of safe dual solution */
18814 SCIP_VAR* var, /**< problem variable */
18815 SCIP_RATIONAL* res /**< store the resulting value */
18816 )
18817{
18818 assert(var != NULL);
18819
18820 switch( SCIPvarGetStatusExact(var) )
18821 {
18823 if( var->data.original.transvar == NULL )
18825 SCIPvarGetLPSolExact(var->data.original.transvar, res);
18826 break;
18827
18830 break;
18831
18833 assert(var->data.col != NULL);
18834 SCIPrationalSetRational(res, SCIPcolExactGetPrimsol(var->exactdata->colexact));
18835 break;
18836
18838 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub)); /*lint !e777*/
18839 SCIPrationalSetRational(res, var->exactdata->locdom.lb);
18840 break;
18841
18843 assert(var->data.aggregate.var != NULL);
18844 SCIPvarGetLPSolExact(var->data.aggregate.var, res);
18845 SCIPrationalMult(res, res, var->exactdata->aggregate.scalar);
18846 SCIPrationalAdd(res, res, var->exactdata->aggregate.constant);
18847 break;
18848
18850 {
18851 SCIP_RATIONAL* tmp;
18852 int i;
18853
18854 assert(!var->donotmultaggr);
18855 assert(var->data.multaggr.vars != NULL);
18856 assert(var->data.multaggr.scalars != NULL);
18857
18858 (void) SCIPrationalCreate(&tmp);
18859 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18860 * assert(var->data.multaggr.nvars >= 2);
18861 */
18862 SCIPrationalSetRational(res, var->exactdata->multaggr.constant);
18863 for( i = 0; i < var->data.multaggr.nvars; ++i )
18864 {
18865 SCIPvarGetLPSolExact(var->data.multaggr.vars[i], tmp);
18866 SCIPrationalAddProd(res, var->exactdata->multaggr.scalars[i], tmp);
18867 }
18868 SCIPrationalFree(&tmp);
18869 break;
18870 }
18871
18872 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18873 assert(var->negatedvar != NULL);
18875 assert(var->negatedvar->negatedvar == var);
18876 SCIPvarGetLPSolExact(var->negatedvar, res);
18877 SCIPrationalDiffReal(res, res, var->data.negate.constant);
18878 SCIPrationalNegate(res, res);
18879 break;
18880
18881 default:
18882 SCIPerrorMessage("unknown variable status\n");
18883 SCIPABORT();
18884 }
18885}
18886
18887/** gets primal NLP solution value of variable */
18889 SCIP_VAR* var /**< problem variable */
18890 )
18891{
18892 SCIP_Real solval;
18893 int i;
18894
18895 assert(var != NULL);
18896
18897 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
18898 switch( SCIPvarGetStatus(var) )
18899 {
18901 return SCIPvarGetNLPSol(var->data.original.transvar);
18902
18905 return var->nlpsol;
18906
18908 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
18909 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
18910 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
18911 return SCIPvarGetLbGlobal(var);
18912
18913 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
18914 solval = SCIPvarGetNLPSol(var->data.aggregate.var);
18915 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
18916
18918 solval = var->data.multaggr.constant;
18919 for( i = 0; i < var->data.multaggr.nvars; ++i )
18920 solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
18921 return solval;
18922
18924 solval = SCIPvarGetNLPSol(var->negatedvar);
18925 return var->data.negate.constant - solval;
18926
18927 default:
18928 SCIPerrorMessage("unknown variable status\n");
18929 SCIPABORT();
18930 return SCIP_INVALID; /*lint !e527*/
18931 }
18932}
18933
18934/** gets pseudo solution value of variable at current node */
18935static
18937 SCIP_VAR* var /**< problem variable */
18938 )
18939{
18940 SCIP_Real pseudosol;
18941 int i;
18942
18943 assert(var != NULL);
18944
18945 switch( SCIPvarGetStatus(var) )
18946 {
18948 if( var->data.original.transvar == NULL )
18949 return SCIP_INVALID;
18950 return SCIPvarGetPseudoSol(var->data.original.transvar);
18951
18955
18957 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
18958 return var->locdom.lb;
18959
18961 {
18962 SCIP_Real pseudosolval;
18963 assert(!var->donotaggr);
18964 assert(var->data.aggregate.var != NULL);
18965 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
18966 * corresponding infinity value instead of performing an arithmetical transformation (compare method
18967 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
18968 * (or is called by) a public interface method; instead, we only assert that values are finite
18969 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
18970 * positives and negatives if the parameter <numerics/infinity> is modified by the user
18971 */
18972 pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
18973 assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
18974 assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
18975 return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
18976 }
18978 assert(!var->donotmultaggr);
18979 assert(var->data.multaggr.vars != NULL);
18980 assert(var->data.multaggr.scalars != NULL);
18981 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18982 * assert(var->data.multaggr.nvars >= 2);
18983 */
18984 pseudosol = var->data.multaggr.constant;
18985 for( i = 0; i < var->data.multaggr.nvars; ++i )
18986 pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
18987 return pseudosol;
18988
18989 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18990 assert(var->negatedvar != NULL);
18992 assert(var->negatedvar->negatedvar == var);
18993 return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
18994
18995 default:
18996 SCIPerrorMessage("unknown variable status\n");
18997 SCIPABORT();
18998 return SCIP_INVALID; /*lint !e527*/
18999 }
19000}
19001
19002/** gets exact pseudo solution value of variable at current node */
19003static
19005 SCIP_VAR* var /**< problem variable */
19006 )
19007{
19008 assert(var != NULL);
19009
19010 switch( SCIPvarGetStatusExact(var) )
19011 {
19013 if( var->data.original.transvar == NULL )
19014 return NULL;
19015 return SCIPvarGetPseudoSolExact(var->data.original.transvar);
19016
19020
19022 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19023 return var->exactdata->locdom.lb;
19024
19028 default:
19029 SCIPerrorMessage("unknown variable status\n");
19030 SCIPABORT();
19031 return NULL; /*lint !e527*/
19032 }
19033}
19034
19035/** gets current LP or pseudo solution value of variable */
19037 SCIP_VAR* var, /**< problem variable */
19038 SCIP_Bool getlpval /**< should the LP solution value be returned? */
19039 )
19040{
19041 if( getlpval )
19042 return SCIPvarGetLPSol(var);
19043 else
19044 return SCIPvarGetPseudoSol(var);
19045}
19046
19047/** gets current exact LP or pseudo solution value of variable */
19049 SCIP_VAR* var, /**< problem variable */
19050 SCIP_RATIONAL* res, /**< the resulting value */
19051 SCIP_Bool getlpval /**< should the LP solution value be returned? */
19052 )
19053{
19054 assert(var != NULL);
19055
19056 if( getlpval )
19058 else
19060}
19061
19062/** remembers the current solution as root solution in the problem variables */
19064 SCIP_VAR* var, /**< problem variable */
19065 SCIP_Bool roothaslp /**< is the root solution from LP? */
19066 )
19067{
19068 assert(var != NULL);
19069
19070 var->rootsol = SCIPvarGetSol(var, roothaslp);
19071}
19072
19073/** updates the current solution as best root solution of the given variable if it is better */
19075 SCIP_VAR* var, /**< problem variable */
19076 SCIP_SET* set, /**< global SCIP settings */
19077 SCIP_Real rootsol, /**< root solution value */
19078 SCIP_Real rootredcost, /**< root reduced cost */
19079 SCIP_Real rootlpobjval /**< objective value of the root LP */
19080 )
19081{
19082 assert(var != NULL);
19083 assert(set != NULL);
19084 assert(var->scip == set->scip);
19085
19086 /* if reduced cost are zero nothing to update */
19087 if( SCIPsetIsDualfeasZero(set, rootredcost) )
19088 return;
19089
19090 /* check if we have already a best combination stored */
19091 if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
19092 {
19093 SCIP_Real currcutoffbound;
19094 SCIP_Real cutoffbound;
19096
19097 /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
19098 * root reduced cost, and root LP objective value combination
19099 */
19100 if( var->bestrootredcost > 0.0 )
19102 else
19104
19105 currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
19106
19107 /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
19108 * cost, and root LP objective value combination
19109 */
19110 if( rootredcost > 0.0 )
19112 else
19114
19115 cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
19116
19117 /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
19118 if( cutoffbound > currcutoffbound )
19119 {
19120 SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
19121 SCIPvarGetName(var), currcutoffbound, cutoffbound);
19122
19123 var->bestrootsol = rootsol;
19124 var->bestrootredcost = rootredcost;
19125 var->bestrootlpobjval = rootlpobjval;
19126 }
19127 }
19128 else
19129 {
19130 SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
19131 SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
19132 SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
19133 SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
19134
19135 var->bestrootsol = rootsol;
19136 var->bestrootredcost = rootredcost;
19137 var->bestrootlpobjval = rootlpobjval;
19138 }
19139}
19140
19141/** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
19142 * completely solved, zero is returned
19143 */
19145 SCIP_VAR* var /**< problem variable */
19146 )
19147{
19149 int i;
19150
19151 assert(var != NULL);
19152
19153 switch( SCIPvarGetStatus(var) )
19154 {
19156 if( var->data.original.transvar == NULL )
19157 return 0.0;
19158 return SCIPvarGetRootSol(var->data.original.transvar);
19159
19162 return var->rootsol;
19163
19165 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19166 return var->locdom.lb;
19167
19169 assert(!var->donotaggr);
19170 assert(var->data.aggregate.var != NULL);
19171 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
19172 * corresponding infinity value instead of performing an arithmetical transformation (compare method
19173 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
19174 * (or is called by) a public interface method; instead, we only assert that values are finite
19175 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
19176 * positives and negatives if the parameter <numerics/infinity> is modified by the user
19177 */
19178 assert(SCIPvarGetRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
19179 assert(SCIPvarGetRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
19180 return var->data.aggregate.scalar * SCIPvarGetRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
19181
19183 assert(!var->donotmultaggr);
19184 assert(var->data.multaggr.vars != NULL);
19185 assert(var->data.multaggr.scalars != NULL);
19186 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19187 * assert(var->data.multaggr.nvars >= 2);
19188 */
19189 rootsol = var->data.multaggr.constant;
19190 for( i = 0; i < var->data.multaggr.nvars; ++i )
19191 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
19192 return rootsol;
19193
19194 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19195 assert(var->negatedvar != NULL);
19197 assert(var->negatedvar->negatedvar == var);
19198 return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
19199
19200 default:
19201 SCIPerrorMessage("unknown variable status\n");
19202 SCIPABORT();
19203 return SCIP_INVALID; /*lint !e527*/
19204 }
19205}
19206
19207/** returns for given variable the reduced cost */
19208static
19210 SCIP_VAR* var, /**< problem variable */
19211 SCIP_SET* set, /**< global SCIP settings */
19212 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
19213 SCIP_STAT* stat, /**< problem statistics */
19214 SCIP_LP* lp /**< current LP data */
19215 )
19216{
19218 {
19219 SCIP_COL* col;
19221 SCIP_BASESTAT basestat;
19222 SCIP_Bool lpissolbasic;
19223
19224 col = SCIPvarGetCol(var);
19225 assert(col != NULL);
19226
19227 basestat = SCIPcolGetBasisStatus(col);
19228 lpissolbasic = SCIPlpIsSolBasic(lp);
19230
19231 if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
19233 {
19234 SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
19235
19236 assert(set->exact_enable || (((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
19237 (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
19239 assert(set->exact_enable || (((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
19240 (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
19242
19243 if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
19244 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
19245 (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
19246 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
19247 return redcost;
19248 else
19249 return 0.0;
19250 }
19251
19252 return 0.0;
19253 }
19254
19255 return 0.0;
19256}
19257
19258#define MAX_CLIQUELENGTH 50
19259/** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
19260 * the binary variable is fixed to the given value
19261 */
19263 SCIP_VAR* var, /**< problem variable */
19264 SCIP_SET* set, /**< global SCIP settings */
19265 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
19266 SCIP_STAT* stat, /**< problem statistics */
19267 SCIP_PROB* prob, /**< transformed problem, or NULL */
19268 SCIP_LP* lp /**< current LP data */
19269 )
19270{
19271 SCIP_Real implredcost;
19272 int ncliques;
19273 int nvars;
19274
19277
19278 /* get reduced cost of given variable */
19279 implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
19280
19281#ifdef SCIP_MORE_DEBUG
19282 SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
19283#endif
19284
19285 /* the following algorithm is expensive */
19286 ncliques = SCIPvarGetNCliques(var, varfixing);
19287
19288 if( ncliques > 0 )
19289 {
19290 SCIP_CLIQUE** cliques;
19291 SCIP_CLIQUE* clique;
19292 SCIP_VAR** clqvars;
19293 SCIP_VAR** probvars;
19294 SCIP_VAR* clqvar;
19295 SCIP_Bool* clqvalues;
19296 int* entries;
19297 int* ids;
19298 SCIP_Real redcost;
19299 SCIP_Bool cleanedup;
19300 int nclqvars;
19301 int nentries;
19302 int nids;
19303 int id;
19304 int c;
19305 int v;
19306
19307 assert(prob != NULL);
19309
19310 nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
19311
19312 SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
19313 nids = 0;
19314 SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
19315
19316 cliques = SCIPvarGetCliques(var, varfixing);
19317 assert(cliques != NULL);
19318
19319 for( c = ncliques - 1; c >= 0; --c )
19320 {
19321 clique = cliques[c];
19322 assert(clique != NULL);
19323 nclqvars = SCIPcliqueGetNVars(clique);
19324 assert(nclqvars > 0);
19325
19326 if( nclqvars > MAX_CLIQUELENGTH )
19327 continue;
19328
19329 clqvars = SCIPcliqueGetVars(clique);
19330 clqvalues = SCIPcliqueGetValues(clique);
19331 assert(clqvars != NULL);
19332 assert(clqvalues != NULL);
19333
19334 cleanedup = SCIPcliqueIsCleanedUp(clique);
19335
19336 for( v = nclqvars - 1; v >= 0; --v )
19337 {
19338 clqvar = clqvars[v];
19339 assert(clqvar != NULL);
19340
19341 /* ignore binary variable which are fixed */
19342 if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
19343 (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
19344 {
19345 int probindex = SCIPvarGetProbindex(clqvar) + 1;
19346 assert(0 < probindex && probindex < nentries);
19347
19348#ifdef SCIP_DISABLED_CODE
19349 /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
19350 * can appear since there is no guarantee that all these infeasible bounds were found
19351 */
19352 assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
19353#endif
19354 if( entries[probindex] == 0 )
19355 {
19356 ids[nids] = probindex;
19357 ++nids;
19358
19359 /* mark variable as visited */
19360 entries[probindex] = (clqvalues[v] ? probindex : -probindex);
19361 }
19362 }
19363 }
19364 }
19365
19366 probvars = SCIPprobGetVars(prob);
19367 assert(probvars != NULL);
19368
19369 /* add all implied reduced cost */
19370 for( v = nids - 1; v >= 0; --v )
19371 {
19372 id = ids[v];
19373 assert(0 < id && id < nentries);
19374 assert(entries[id] != 0);
19375 assert(probvars[id - 1] != NULL);
19376 assert(SCIPvarIsActive(probvars[id - 1]));
19377 assert(SCIPvarIsBinary(probvars[id - 1]));
19378 assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
19379
19380 if( (entries[id] > 0) != varfixing )
19381 redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
19382 else
19383 redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
19384
19385 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
19386 implredcost += redcost;
19387
19388 /* reset entries clear buffer array */
19389 entries[id] = 0;
19390 }
19391
19394 }
19395
19396#ifdef SCIP_MORE_DEBUG
19397 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
19398 implredcost);
19399#endif
19400
19401 /* collect non-binary implication information */
19402 nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
19403
19404 if( nvars > 0 )
19405 {
19406 SCIP_VAR** vars;
19407 SCIP_VAR* implvar;
19408 SCIP_COL* col;
19409 SCIP_Real* bounds;
19410 SCIP_BOUNDTYPE* boundtypes;
19411 SCIP_Real redcost;
19412 SCIP_Real lb;
19413 SCIP_Real ub;
19414 SCIP_Bool lpissolbasic;
19415 int v;
19416
19417 vars = SCIPimplicsGetVars(var->implics, varfixing);
19418 boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
19419 bounds = SCIPimplicsGetBounds(var->implics, varfixing);
19420 lpissolbasic = SCIPlpIsSolBasic(lp);
19421
19422 for( v = nvars - 1; v >= 0; --v )
19423 {
19424 implvar = vars[v];
19425 assert(implvar != NULL);
19426
19427 lb = SCIPvarGetLbLocal(implvar);
19428 ub = SCIPvarGetUbLocal(implvar);
19429
19430 /* ignore binary variable which are fixed or not of column status */
19431 if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
19432 continue;
19433
19434 col = SCIPvarGetCol(implvar);
19435 assert(col != NULL);
19436 redcost = 0.0;
19437
19438 /* solved lp with basis information or not? */
19439 if( lpissolbasic )
19440 {
19441 SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
19442
19443 /* check if the implication is not not yet applied */
19444 if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
19445 {
19446 redcost = SCIPcolGetRedcost(col, stat, lp);
19448
19449 if( !varfixing )
19450 redcost *= (lb - bounds[v]);
19451 else
19452 redcost *= (bounds[v] - lb);
19453 }
19454 else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
19455 {
19456 redcost = SCIPcolGetRedcost(col, stat, lp);
19458
19459 if( varfixing )
19460 redcost *= (bounds[v] - ub);
19461 else
19462 redcost *= (ub - bounds[v]);
19463 }
19464 }
19465 else
19466 {
19468
19469 /* check if the implication is not not yet applied */
19470 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
19471 {
19472 redcost = SCIPcolGetRedcost(col, stat, lp);
19474
19475 if( varfixing )
19476 redcost *= (lb - bounds[v]);
19477 else
19478 redcost *= (bounds[v] - lb);
19479 }
19480 else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
19481 {
19482 redcost = SCIPcolGetRedcost(col, stat, lp);
19484
19485 if( varfixing )
19486 redcost *= (bounds[v] - ub);
19487 else
19488 redcost *= (ub - bounds[v]);
19489 }
19490 }
19491
19492 /* improve implied reduced cost */
19493 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
19494 implredcost += redcost;
19495 }
19496 }
19497
19498#ifdef SCIP_MORE_DEBUG
19499 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
19500 SCIPvarGetName(var), ncliques, nvars, implredcost);
19501#endif
19502
19503 return implredcost;
19504}
19505
19506/** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
19507 * the root relaxation is not yet completely solved, zero is returned
19508 */
19510 SCIP_VAR* var /**< problem variable */
19511 )
19512{
19514 int i;
19515
19516 assert(var != NULL);
19517
19518 switch( SCIPvarGetStatus(var) )
19519 {
19521 if( var->data.original.transvar == NULL )
19522 return 0.0;
19523 return SCIPvarGetBestRootSol(var->data.original.transvar);
19524
19527 return var->bestrootsol;
19528
19530 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19531 return var->locdom.lb;
19532
19534 assert(!var->donotaggr);
19535 assert(var->data.aggregate.var != NULL);
19536 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
19537 * corresponding infinity value instead of performing an arithmetical transformation (compare method
19538 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
19539 * (or is called by) a public interface method; instead, we only assert that values are finite
19540 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
19541 * positives and negatives if the parameter <numerics/infinity> is modified by the user
19542 */
19543 assert(SCIPvarGetBestRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
19544 assert(SCIPvarGetBestRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
19545 return var->data.aggregate.scalar * SCIPvarGetBestRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
19546
19548 assert(!var->donotmultaggr);
19549 assert(var->data.multaggr.vars != NULL);
19550 assert(var->data.multaggr.scalars != NULL);
19551 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19552 * assert(var->data.multaggr.nvars >= 2);
19553 */
19554 rootsol = var->data.multaggr.constant;
19555 for( i = 0; i < var->data.multaggr.nvars; ++i )
19556 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
19557 return rootsol;
19558
19559 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19560 assert(var->negatedvar != NULL);
19562 assert(var->negatedvar->negatedvar == var);
19563 return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
19564
19565 default:
19566 SCIPerrorMessage("unknown variable status\n");
19567 SCIPABORT();
19568 return 0.0; /*lint !e527*/
19569 }
19570}
19571
19572/** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
19573 * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
19574 * returned
19575 */
19577 SCIP_VAR* var /**< problem variable */
19578 )
19579{
19580 assert(var != NULL);
19581
19582 switch( SCIPvarGetStatus(var) )
19583 {
19585 if( var->data.original.transvar == NULL )
19586 return SCIP_INVALID;
19587 return SCIPvarGetBestRootRedcost(var->data.original.transvar);
19588
19591 return var->bestrootredcost;
19592
19597 return 0.0;
19598
19599 default:
19600 SCIPerrorMessage("unknown variable status\n");
19601 SCIPABORT();
19602 return 0.0; /*lint !e527*/
19603 }
19604}
19605
19606/** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
19607 * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
19608 * SCIP_INVALID is returned
19609 */
19611 SCIP_VAR* var /**< problem variable */
19612 )
19613{
19614 assert(var != NULL);
19615
19616 switch( SCIPvarGetStatus(var) )
19617 {
19619 if( var->data.original.transvar == NULL )
19620 return SCIP_INVALID;
19621 return SCIPvarGetBestRootLPObjval(var->data.original.transvar);
19622
19625 return var->bestrootlpobjval;
19626
19631 return SCIP_INVALID;
19632
19633 default:
19634 SCIPerrorMessage("unknown variable status\n");
19635 SCIPABORT();
19636 return SCIP_INVALID; /*lint !e527*/
19637 }
19638}
19639
19640/** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
19642 SCIP_VAR* var, /**< problem variable */
19643 SCIP_Real rootsol, /**< root solution value */
19644 SCIP_Real rootredcost, /**< root reduced cost */
19645 SCIP_Real rootlpobjval /**< objective value of the root LP */
19646 )
19647{
19648 assert(var != NULL);
19649
19650 var->bestrootsol = rootsol;
19651 var->bestrootredcost = rootredcost;
19652 var->bestrootlpobjval = rootlpobjval;
19653}
19654
19655/** stores the solution value as relaxation solution in the problem variable */
19657 SCIP_VAR* var, /**< problem variable */
19658 SCIP_SET* set, /**< global SCIP settings */
19659 SCIP_RELAXATION* relaxation, /**< global relaxation data */
19660 SCIP_Real solval, /**< solution value in the current relaxation solution */
19661 SCIP_Bool updateobj /**< should the objective value be updated? */
19662 )
19663{
19664 assert(var != NULL);
19665 assert(relaxation != NULL);
19666 assert(set != NULL);
19667 assert(var->scip == set->scip);
19668
19669 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
19670 switch( SCIPvarGetStatus(var) )
19671 {
19673 SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
19674 break;
19675
19678 if( updateobj )
19679 SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
19680 var->relaxsol = solval;
19681 break;
19682
19684 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
19685 {
19686 SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
19687 SCIPvarGetName(var), var->glbdom.lb, solval);
19688 return SCIP_INVALIDDATA;
19689 }
19690 break;
19691
19692 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19693 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
19694 SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
19695 (solval - var->data.aggregate.constant) / var->data.aggregate.scalar, updateobj) );
19696 break;
19698 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
19699 return SCIP_INVALIDDATA;
19700
19702 SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
19703 break;
19704
19705 default:
19706 SCIPerrorMessage("unknown variable status\n");
19707 return SCIP_INVALIDDATA;
19708 }
19709
19710 return SCIP_OKAY;
19711}
19712
19713/** returns the solution value of the problem variable in the relaxation solution
19714 *
19715 * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
19716 */
19718 SCIP_VAR* var, /**< problem variable */
19719 SCIP_SET* set /**< global SCIP settings */
19720 )
19721{
19722 SCIP_Real solvalsum;
19723 SCIP_Real solval;
19724 int i;
19725
19726 assert(var != NULL);
19727 assert(set != NULL);
19728 assert(var->scip == set->scip);
19729
19730 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
19731 switch( SCIPvarGetStatus(var) )
19732 {
19734 return SCIPvarGetRelaxSol(var->data.original.transvar, set);
19735
19738 return var->relaxsol;
19739
19741 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
19742 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
19743 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
19744 return SCIPvarGetLbGlobal(var);
19745
19746 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19747 solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
19748 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
19749 {
19750 if( var->data.aggregate.scalar * solval > 0.0 )
19751 return SCIPsetInfinity(set);
19752 if( var->data.aggregate.scalar * solval < 0.0 )
19753 return -SCIPsetInfinity(set);
19754 }
19755 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
19756
19758 solvalsum = var->data.multaggr.constant;
19759 for( i = 0; i < var->data.multaggr.nvars; ++i )
19760 {
19761 solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
19762 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
19763 {
19764 if( var->data.multaggr.scalars[i] * solval > 0.0 )
19765 return SCIPsetInfinity(set);
19766 if( var->data.multaggr.scalars[i] * solval < 0.0 )
19767 return -SCIPsetInfinity(set);
19768 }
19769 solvalsum += var->data.multaggr.scalars[i] * solval;
19770 }
19771 return solvalsum;
19772
19774 solval = SCIPvarGetRelaxSol(var->negatedvar, set);
19775 if( SCIPsetIsInfinity(set, solval) )
19776 return -SCIPsetInfinity(set);
19777 if( SCIPsetIsInfinity(set, -solval) )
19778 return SCIPsetInfinity(set);
19779 return var->data.negate.constant - solval;
19780
19781 default:
19782 SCIPerrorMessage("unknown variable status\n");
19783 SCIPABORT();
19784 return SCIP_INVALID; /*lint !e527*/
19785 }
19786}
19787
19788/** returns the solution value of the transformed problem variable in the relaxation solution */
19790 SCIP_VAR* var /**< problem variable */
19791 )
19792{
19793 assert(var != NULL);
19795
19796 return var->relaxsol;
19797}
19798
19799/** stores the solution value as NLP solution in the problem variable */
19801 SCIP_VAR* var, /**< problem variable */
19802 SCIP_SET* set, /**< global SCIP settings */
19803 SCIP_Real solval /**< solution value in the current NLP solution */
19804 )
19805{
19806 assert(var != NULL);
19807 assert(set != NULL);
19808 assert(var->scip == set->scip);
19809
19810 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
19811 switch( SCIPvarGetStatus(var) )
19812 {
19814 SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
19815 break;
19816
19819 var->nlpsol = solval;
19820 break;
19821
19823 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
19824 {
19825 SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
19826 SCIPvarGetName(var), var->glbdom.lb, solval);
19827 SCIPABORT();
19828 return SCIP_INVALIDCALL; /*lint !e527*/
19829 }
19830 break;
19831
19832 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19833 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
19834 SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant) / var->data.aggregate.scalar) );
19835 break;
19836
19838 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
19839 SCIPABORT();
19840 return SCIP_INVALIDCALL; /*lint !e527*/
19841
19843 SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
19844 break;
19845
19846 default:
19847 SCIPerrorMessage("unknown variable status\n");
19848 SCIPABORT();
19849 return SCIP_ERROR; /*lint !e527*/
19850 }
19851
19852 return SCIP_OKAY;
19853}
19854
19855/** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
19857 SCIP_VAR* var /**< problem variable */
19858 )
19859{
19860 SCIP_Real avgsol;
19861 int i;
19862
19863 assert(var != NULL);
19864
19865 switch( SCIPvarGetStatus(var) )
19866 {
19868 if( var->data.original.transvar == NULL )
19869 return 0.0;
19870 return SCIPvarGetAvgSol(var->data.original.transvar);
19871
19874 avgsol = var->primsolavg;
19875 avgsol = MAX(avgsol, var->glbdom.lb);
19876 avgsol = MIN(avgsol, var->glbdom.ub);
19877 return avgsol;
19878
19880 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19881 return var->locdom.lb;
19882
19884 assert(!var->donotaggr);
19885 assert(var->data.aggregate.var != NULL);
19886 return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
19887 + var->data.aggregate.constant;
19888
19890 assert(!var->donotmultaggr);
19891 assert(var->data.multaggr.vars != NULL);
19892 assert(var->data.multaggr.scalars != NULL);
19893 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19894 * assert(var->data.multaggr.nvars >= 2);
19895 */
19896 avgsol = var->data.multaggr.constant;
19897 for( i = 0; i < var->data.multaggr.nvars; ++i )
19898 avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
19899 return avgsol;
19900
19901 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19902 assert(var->negatedvar != NULL);
19904 assert(var->negatedvar->negatedvar == var);
19905 return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
19906
19907 default:
19908 SCIPerrorMessage("unknown variable status\n");
19909 SCIPABORT();
19910 return 0.0; /*lint !e527*/
19911 }
19912}
19913
19914/** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
19915 * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
19916 */
19918 SCIP_VAR* var, /**< active problem variable */
19919 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
19920 SCIP_SET* set, /**< global SCIP settings */
19921 SCIP_STAT* stat, /**< problem statistics */
19922 SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
19923 int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
19924 )
19925{
19926 int nvlbs;
19927
19928 assert(var != NULL);
19929 assert(stat != NULL);
19930 assert(set != NULL);
19931 assert(var->scip == set->scip);
19932 assert(closestvlb != NULL);
19933 assert(closestvlbidx != NULL);
19934
19935 *closestvlbidx = -1;
19936 *closestvlb = SCIP_REAL_MIN;
19937
19938 nvlbs = SCIPvarGetNVlbs(var);
19939 if( nvlbs > 0 )
19940 {
19941 SCIP_VAR** vlbvars;
19942 SCIP_Real* vlbcoefs;
19943 SCIP_Real* vlbconsts;
19944 int i;
19945
19946 vlbvars = SCIPvarGetVlbVars(var);
19947 vlbcoefs = SCIPvarGetVlbCoefs(var);
19948 vlbconsts = SCIPvarGetVlbConstants(var);
19949
19950 /* check for cached values */
19951 if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
19952 {
19953 i = var->closestvlbidx;
19954 assert(0 <= i && i < nvlbs);
19955 assert(SCIPvarIsActive(vlbvars[i]));
19956 *closestvlbidx = i;
19957 *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
19958 }
19959 else
19960 {
19961 /* search best VUB */
19962 for( i = 0; i < nvlbs; i++ )
19963 {
19964 if( SCIPvarIsActive(vlbvars[i]) )
19965 {
19966 SCIP_Real vlbsol;
19967
19968 vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
19969 if( vlbsol > *closestvlb )
19970 {
19971 *closestvlb = vlbsol;
19972 *closestvlbidx = i;
19973 }
19974 }
19975 }
19976
19977 if( sol == NULL )
19978 {
19979 /* update cached value */
19980 if( var->closestvblpcount != stat->lpcount )
19981 var->closestvubidx = -1;
19982 var->closestvlbidx = *closestvlbidx;
19983 var->closestvblpcount = stat->lpcount;
19984 }
19985 }
19986 }
19987}
19988
19989/** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
19990 * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
19991 */
19993 SCIP_VAR* var, /**< active problem variable */
19994 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
19995 SCIP_SET* set, /**< global SCIP settings */
19996 SCIP_STAT* stat, /**< problem statistics */
19997 SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
19998 int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
19999 )
20000{
20001 int nvubs;
20002
20003 assert(var != NULL);
20004 assert(set != NULL);
20005 assert(var->scip == set->scip);
20006 assert(closestvub != NULL);
20007 assert(closestvubidx != NULL);
20008
20009 *closestvubidx = -1;
20010 *closestvub = SCIP_REAL_MAX;
20011
20012 nvubs = SCIPvarGetNVubs(var);
20013 if( nvubs > 0 )
20014 {
20015 SCIP_VAR** vubvars;
20016 SCIP_Real* vubcoefs;
20017 SCIP_Real* vubconsts;
20018 int i;
20019
20020 vubvars = SCIPvarGetVubVars(var);
20021 vubcoefs = SCIPvarGetVubCoefs(var);
20022 vubconsts = SCIPvarGetVubConstants(var);
20023
20024 /* check for cached values */
20025 if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
20026 {
20027 i = var->closestvubidx;
20028 assert(0 <= i && i < nvubs);
20029 assert(SCIPvarIsActive(vubvars[i]));
20030 *closestvubidx = i;
20031 *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
20032 }
20033 else
20034 {
20035 /* search best VUB */
20036 for( i = 0; i < nvubs; i++ )
20037 {
20038 if( SCIPvarIsActive(vubvars[i]) )
20039 {
20040 SCIP_Real vubsol;
20041
20042 vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
20043 if( vubsol < *closestvub )
20044 {
20045 *closestvub = vubsol;
20046 *closestvubidx = i;
20047 }
20048 }
20049 }
20050
20051 if( sol == NULL )
20052 {
20053 /* update cached value */
20054 if( var->closestvblpcount != stat->lpcount )
20055 var->closestvlbidx = -1;
20056 var->closestvubidx = *closestvubidx;
20057 var->closestvblpcount = stat->lpcount;
20058 }
20059 }
20060 }
20061}
20062
20063/** resolves variable to columns and adds them with the coefficient to the row */
20065 SCIP_VAR* var, /**< problem variable */
20066 BMS_BLKMEM* blkmem, /**< block memory */
20067 SCIP_SET* set, /**< global SCIP settings */
20068 SCIP_STAT* stat, /**< problem statistics */
20069 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
20070 SCIP_PROB* prob, /**< problem data */
20071 SCIP_LP* lp, /**< current LP data */
20072 SCIP_ROW* row, /**< LP row */
20073 SCIP_Real val /**< value of coefficient */
20074 )
20075{
20076 int i;
20077
20078 assert(var != NULL);
20079 assert(set != NULL);
20080 assert(var->scip == set->scip);
20081 assert(row != NULL);
20083
20084 SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
20085
20086 if ( SCIPsetIsZero(set, val) )
20087 return SCIP_OKAY;
20088
20089 switch( SCIPvarGetStatus(var) )
20090 {
20092 if( var->data.original.transvar == NULL )
20093 {
20094 SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
20095 return SCIP_INVALIDDATA;
20096 }
20097 SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
20098 return SCIP_OKAY;
20099
20101 /* add globally fixed variables as constant */
20102 if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
20103 {
20104 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
20105 return SCIP_OKAY;
20106 }
20107 /* convert loose variable into column */
20108 SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
20110 /*lint -fallthrough*/
20111
20113 assert(var->data.col != NULL);
20114 assert(var->data.col->var == var);
20115 SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
20116 return SCIP_OKAY;
20117
20119 assert(var->glbdom.lb == var->glbdom.ub || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub))); /*lint !e777*/
20120 assert(var->locdom.lb == var->locdom.ub || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub))); /*lint !e777*/
20121 assert(var->locdom.lb == var->glbdom.lb || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb))); /*lint !e777*/
20122 assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
20123 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
20124 return SCIP_OKAY;
20125
20127 assert(!var->donotaggr);
20128 assert(var->data.aggregate.var != NULL);
20129 SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
20130 row, var->data.aggregate.scalar * val) );
20131 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
20132 return SCIP_OKAY;
20133
20135 assert(!var->donotmultaggr);
20136 assert(var->data.multaggr.vars != NULL);
20137 assert(var->data.multaggr.scalars != NULL);
20138 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
20139 * assert(var->data.multaggr.nvars >= 2);
20140 */
20141 for( i = 0; i < var->data.multaggr.nvars; ++i )
20142 {
20143 SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
20144 row, var->data.multaggr.scalars[i] * val) );
20145 }
20146 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
20147 return SCIP_OKAY;
20148
20149 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
20150 assert(var->negatedvar != NULL);
20152 assert(var->negatedvar->negatedvar == var);
20153 SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
20154 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
20155 return SCIP_OKAY;
20156
20157 default:
20158 SCIPerrorMessage("unknown variable status\n");
20159 return SCIP_INVALIDDATA;
20160 }
20161}
20162
20163/** resolves variable to exact columns and adds them with the coefficient to the exact Row */
20165 SCIP_VAR* var, /**< problem variable */
20166 BMS_BLKMEM* blkmem, /**< block memory */
20167 SCIP_SET* set, /**< global SCIP settings */
20168 SCIP_STAT* stat, /**< problem statistics */
20169 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
20170 SCIP_PROB* prob, /**< problem data */
20171 SCIP_LPEXACT* lpexact, /**< current LP data */
20172 SCIP_ROWEXACT* rowexact, /**< LP row */
20173 SCIP_RATIONAL* val /**< value of coefficient */
20174 )
20175{
20176 SCIP_RATIONAL* tmp;
20177 int i;
20178
20179 assert(var != NULL);
20180 assert(set != NULL);
20181 assert(var->scip == set->scip);
20182 assert(rowexact != NULL);
20184
20185 SCIPrationalDebugMessage("adding coefficient %q<%s> to exact row <%s>\n", val, var->name, rowexact->fprow->name);
20186
20187 if ( SCIPrationalIsZero(val) )
20188 return SCIP_OKAY;
20189
20190 switch( SCIPvarGetStatusExact(var) )
20191 {
20193 if( var->data.original.transvar == NULL )
20194 {
20195 SCIPerrorMessage("cannot add untransformed original variable <%s> to excact LP row <%s>\n", var->name, rowexact->fprow->name);
20196 return SCIP_INVALIDDATA;
20197 }
20198 SCIP_CALL( SCIPvarAddToRowExact(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lpexact, rowexact, val) );
20199 break;
20200
20202 /* add globally fixed variables as constant */
20203 if( SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub) )
20204 {
20205 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20206 SCIPrationalMult(tmp, val, var->exactdata->glbdom.lb);
20207 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20208 SCIPrationalFreeBuffer(set->buffer, &tmp);
20209 break;
20210 }
20211 /* convert loose variable into column */
20212 SCIP_CALL( SCIPvarColumnExact(var, blkmem, set, stat, lpexact) );
20214 /*lint -fallthrough*/
20215
20217 assert(var->data.col != NULL);
20218 assert(var->data.col->var == var);
20219 SCIP_CALL( SCIProwExactIncCoef(rowexact, blkmem, set, eventqueue, lpexact, var->exactdata->colexact, val) );
20220 break;
20221
20223 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub)); /*lint !e777*/
20224 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub)); /*lint !e777*/
20225 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->glbdom.lb)); /*lint !e777*/
20226 assert(!SCIPrationalIsAbsInfinity(var->exactdata->locdom.lb));
20227
20228 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20229
20230 SCIPrationalMult(tmp, val, var->exactdata->locdom.lb);
20231 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20232
20233 SCIPrationalFreeBuffer(set->buffer, &tmp);
20234
20235 break;
20236
20238 assert(var->data.aggregate.var != NULL);
20239
20240 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20241 SCIPrationalMult(tmp, var->exactdata->aggregate.scalar, val);
20242 SCIP_CALL( SCIPvarAddToRowExact(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lpexact,
20243 rowexact, tmp) );
20244 SCIPrationalMult(tmp, var->exactdata->aggregate.constant, val);
20245 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20246 SCIPrationalFreeBuffer(set->buffer, &tmp);
20247 return SCIP_OKAY;
20248
20250 assert(!var->donotmultaggr);
20251 assert(var->data.multaggr.vars != NULL);
20252 assert(var->data.multaggr.scalars != NULL);
20253
20254 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20255
20256 for( i = 0; i < var->data.multaggr.nvars; ++i )
20257 {
20258 SCIPrationalMult(tmp, var->exactdata->multaggr.scalars[i], val);
20259 SCIP_CALL( SCIPvarAddToRowExact(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lpexact,
20260 rowexact, tmp) );
20261 }
20262 SCIPrationalMult(tmp, var->exactdata->multaggr.constant, val);
20263 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20264
20265 SCIPrationalFreeBuffer(set->buffer, &tmp);
20266 return SCIP_OKAY;
20267
20268 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
20269 assert(var->negatedvar != NULL);
20271 assert(var->negatedvar->negatedvar == var);
20272
20273 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20274
20275 SCIPrationalNegate(tmp, val);
20276 SCIP_CALL( SCIPvarAddToRowExact(var->negatedvar, blkmem, set, stat, eventqueue, prob, lpexact, rowexact, tmp) );
20277
20278 SCIPrationalMultReal(tmp, val, var->data.negate.constant);
20279 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20280
20281 SCIPrationalFreeBuffer(set->buffer, &tmp);
20282
20283 break;
20284
20285 default:
20286 SCIPerrorMessage("unknown variable status\n");
20287 return SCIP_INVALIDDATA;
20288 }
20289
20290 return SCIP_OKAY;
20291}
20292
20293/* optionally, define this compiler flag to write complete variable histories to a file */
20294#ifdef SCIP_HISTORYTOFILE
20295SCIP_Longint counter = 0l;
20296const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
20297#include "scip/scip.h"
20298#endif
20299
20300/** updates the pseudo costs of the given variable and the global pseudo costs after a change of
20301 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the LP's objective value
20302 */
20304 SCIP_VAR* var, /**< problem variable */
20305 SCIP_SET* set, /**< global SCIP settings */
20306 SCIP_STAT* stat, /**< problem statistics */
20307 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
20308 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
20309 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
20310 )
20311{
20312 SCIP_Real oldrootpseudocosts;
20313 assert(var != NULL);
20314 assert(set != NULL);
20315 assert(var->scip == set->scip);
20316 assert(stat != NULL);
20317
20318 /* check if history statistics should be collected for a variable */
20319 if( !stat->collectvarhistory )
20320 return SCIP_OKAY;
20321
20322 switch( SCIPvarGetStatus(var) )
20323 {
20325 if( var->data.original.transvar == NULL )
20326 {
20327 SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
20328 return SCIP_INVALIDDATA;
20329 }
20330 SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
20331 return SCIP_OKAY;
20332
20335 /* store old pseudo-costs for root LP best-estimate update */
20336 oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
20337
20338 /* update history */
20339 SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
20340 SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
20341 SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
20342 SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
20343
20344 /* update root LP best-estimate */
20345 SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
20346
20347 /* append history to file */
20348#ifdef SCIP_HISTORYTOFILE
20349 {
20350 FILE* f;
20351 char filename[256];
20352 SCIP_NODE* currentnode;
20353 SCIP_NODE* parentnode;
20354 currentnode = SCIPgetFocusNode(set->scip);
20355 parentnode = SCIPnodeGetParent(currentnode);
20356
20357 sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
20358 f = fopen(filename, "a");
20359 if( NULL != f )
20360 {
20361 fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
20362 ++counter,
20364 SCIPnodeGetNumber(currentnode),
20365 parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
20367 SCIPgetDepth(set->scip),
20368 objdelta,
20369 solvaldelta);
20370 fclose(f);
20371 }
20372 }
20373#endif
20374 return SCIP_OKAY;
20375
20377 SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
20378 return SCIP_INVALIDDATA;
20379
20381 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
20382 SCIP_CALL( SCIPvarUpdatePseudocost(var->data.aggregate.var, set, stat,
20383 solvaldelta / var->data.aggregate.scalar, objdelta, weight) );
20384 return SCIP_OKAY;
20385
20387 SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
20388 return SCIP_INVALIDDATA;
20389
20391 SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
20392 return SCIP_OKAY;
20393
20394 default:
20395 SCIPerrorMessage("unknown variable status\n");
20396 return SCIP_INVALIDDATA;
20397 }
20398}
20399
20400/** updates the ancestral pseudo costs of the given variable and the global ancestral pseudo costs after a change of
20401 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the LP's objective value
20402 */
20404 SCIP_VAR* var, /**< problem variable */
20405 SCIP_SET* set, /**< global SCIP settings */
20406 SCIP_STAT* stat, /**< problem statistics */
20407 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
20408 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
20409 SCIP_Real weight /**< weight in (0,1] of this update in discounted pseudo cost sum */
20410 )
20411{
20412 assert(var != NULL);
20413 assert(set != NULL);
20414 assert(var->scip == set->scip);
20415 assert(stat != NULL);
20416
20417 /* check if history statistics should be collected for a variable */
20418 if( !stat->collectvarhistory )
20419 return SCIP_OKAY;
20420
20421 switch( SCIPvarGetStatus(var) )
20422 {
20424 if( var->data.original.transvar == NULL )
20425 {
20426 SCIPerrorMessage("cannot update ancestral pseudo costs of original untransformed variable\n");
20427 return SCIP_INVALIDDATA;
20428 }
20429 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
20430 return SCIP_OKAY;
20431
20434 /* update history */
20435 SCIPhistoryUpdateAncPseudocost(var->history, set, solvaldelta, objdelta, weight);
20436 SCIPhistoryUpdateAncPseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
20437 SCIPhistoryUpdateAncPseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
20438 SCIPhistoryUpdateAncPseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
20439 return SCIP_OKAY;
20440
20442 SCIPerrorMessage("cannot update ancestral pseudo cost values of a fixed variable\n");
20443 return SCIP_INVALIDDATA;
20444
20446 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
20447 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->data.aggregate.var, set, stat,
20448 solvaldelta / var->data.aggregate.scalar, objdelta, weight) );
20449 return SCIP_OKAY;
20450
20452 SCIPerrorMessage("cannot update ancestral pseudo cost values of a multi-aggregated variable\n");
20453 return SCIP_INVALIDDATA;
20454
20456 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
20457 return SCIP_OKAY;
20458
20459 default:
20460 SCIPerrorMessage("unknown variable status\n");
20461 return SCIP_INVALIDDATA;
20462 }
20463}
20464
20465/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
20467 SCIP_VAR* var, /**< problem variable */
20468 SCIP_STAT* stat, /**< problem statistics */
20469 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20470 )
20471{
20472 SCIP_BRANCHDIR dir;
20473
20474 assert(var != NULL);
20475 assert(stat != NULL);
20476
20477 switch( SCIPvarGetStatus(var) )
20478 {
20480 if( var->data.original.transvar == NULL )
20481 return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
20482 else
20483 return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
20484
20487 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20488
20489 return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
20490 ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
20491 : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
20492
20494 return 0.0;
20495
20497 return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20498
20500 return 0.0;
20501
20503 return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
20504
20505 default:
20506 SCIPerrorMessage("unknown variable status\n");
20507 SCIPABORT();
20508 return 0.0; /*lint !e527*/
20509 }
20510}
20511
20512/** gets the variable's ancestral pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
20514 SCIP_VAR* var, /**< problem variable */
20515 SCIP_STAT* stat, /**< problem statistics */
20516 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20517 )
20518{
20519 SCIP_BRANCHDIR dir;
20520
20521 assert(var != NULL);
20522 assert(stat != NULL);
20523
20524 switch( SCIPvarGetStatus(var) )
20525 {
20527 if( var->data.original.transvar == NULL )
20528 return SCIPhistoryGetAncPseudocost(stat->glbhistory, solvaldelta);
20529 else
20530 return SCIPvarGetAncPseudocost(var->data.original.transvar, stat, solvaldelta);
20531
20534 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20535
20536 return SCIPhistoryGetAncPseudocostCount(var->history, dir) > 0.0
20537 ? SCIPhistoryGetAncPseudocost(var->history, solvaldelta)
20538 : SCIPhistoryGetAncPseudocost(stat->glbhistory, solvaldelta);
20539
20541 return 0.0;
20542
20544 return SCIPvarGetAncPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20545
20547 return 0.0;
20548
20550 return SCIPvarGetAncPseudocost(var->negatedvar, stat, -solvaldelta);
20551
20552 default:
20553 SCIPerrorMessage("unknown variable status\n");
20554 SCIPABORT();
20555 return 0.0; /*lint !e527*/
20556 }
20557}
20558
20559/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
20560 * only using the pseudo cost information of the current run
20561 */
20563 SCIP_VAR* var, /**< problem variable */
20564 SCIP_STAT* stat, /**< problem statistics */
20565 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20566 )
20567{
20568 SCIP_BRANCHDIR dir;
20569
20570 assert(var != NULL);
20571 assert(stat != NULL);
20572
20573 switch( SCIPvarGetStatus(var) )
20574 {
20576 if( var->data.original.transvar == NULL )
20577 return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
20578 else
20579 return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
20580
20583 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20584
20585 return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
20586 ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
20587 : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
20588
20590 return 0.0;
20591
20593 return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20594
20596 return 0.0;
20597
20599 return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
20600
20601 default:
20602 SCIPerrorMessage("unknown variable status\n");
20603 SCIPABORT();
20604 return 0.0; /*lint !e527*/
20605 }
20606}
20607
20608/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
20610 SCIP_VAR* var, /**< problem variable */
20611 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20612 )
20613{
20614 assert(var != NULL);
20616
20617 switch( SCIPvarGetStatus(var) )
20618 {
20620 if( var->data.original.transvar == NULL )
20621 return 0.0;
20622 else
20623 return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
20624
20627 return SCIPhistoryGetPseudocostCount(var->history, dir);
20628
20630 return 0.0;
20631
20633 if( var->data.aggregate.scalar > 0.0 )
20634 return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
20635 else
20636 return SCIPvarGetPseudocostCount(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20637
20639 return 0.0;
20640
20642 return SCIPvarGetPseudocostCount(var->negatedvar, SCIPbranchdirOpposite(dir));
20643
20644 default:
20645 SCIPerrorMessage("unknown variable status\n");
20646 SCIPABORT();
20647 return 0.0; /*lint !e527*/
20648 }
20649}
20650
20651/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
20652 * only using the pseudo cost information of the current run
20653 */
20655 SCIP_VAR* var, /**< problem variable */
20656 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20657 )
20658{
20659 assert(var != NULL);
20661
20662 switch( SCIPvarGetStatus(var) )
20663 {
20665 if( var->data.original.transvar == NULL )
20666 return 0.0;
20667 else
20668 return SCIPvarGetPseudocostCountCurrentRun(var->data.original.transvar, dir);
20669
20672 return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
20673
20675 return 0.0;
20676
20678 if( var->data.aggregate.scalar > 0.0 )
20679 return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, dir);
20680 else
20681 return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20682
20684 return 0.0;
20685
20688
20689 default:
20690 SCIPerrorMessage("unknown variable status\n");
20691 SCIPABORT();
20692 return 0.0; /*lint !e527*/
20693 }
20694}
20695
20696/** gets the variable's (possible fractional) number of ancestor pseudo cost updates for the given direction,
20697 * only using the pseudo cost information of the current run
20698 */
20700 SCIP_VAR* var, /**< problem variable */
20701 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20702 )
20703{
20704 assert(var != NULL);
20706
20707 switch( SCIPvarGetStatus(var) )
20708 {
20710 if( var->data.original.transvar == NULL )
20711 return 0.0;
20712 else
20713 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.original.transvar, dir);
20714
20717 return SCIPhistoryGetAncPseudocostCount(var->historycrun, dir);
20718
20720 return 0.0;
20721
20723 if( var->data.aggregate.scalar > 0.0 )
20724 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.aggregate.var, dir);
20725 else
20726 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20727
20729 return 0.0;
20730
20733
20734 default:
20735 SCIPerrorMessage("unknown variable status\n");
20736 SCIPABORT();
20737 return 0.0; /*lint !e527*/
20738 }
20739}
20740
20741/** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
20743 SCIP_VAR* var, /**< problem variable */
20744 SCIP_STAT* stat, /**< problem statistics */
20745 SCIP_SET* set, /**< global SCIP settings */
20746 SCIP_Real solval /**< solution value, e.g., LP solution value */
20747 )
20748{
20749 SCIP_Real upscore;
20750 SCIP_Real downscore;
20751 SCIP_Real solvaldeltaup;
20752 SCIP_Real solvaldeltadown;
20753
20754 /* LP root estimate only works for variables with fractional LP root solution */
20755 if( SCIPsetIsFeasIntegral(set, solval) )
20756 return 0.0;
20757
20758 /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
20760 return 0.0;
20761
20762 /* compute delta's to ceil and floor of root LP solution value */
20763 solvaldeltaup = SCIPsetCeil(set, solval) - solval;
20764 solvaldeltadown = SCIPsetFloor(set, solval) - solval;
20765
20766 upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
20767 downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
20768
20769 return MIN(upscore, downscore);
20770}
20771
20772/** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
20774 SCIP_VAR* var, /**< problem variable */
20775 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
20776 SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
20777 )
20778{
20779 assert(var != NULL);
20781
20782 switch( SCIPvarGetStatus(var) )
20783 {
20785 if( var->data.original.transvar == NULL )
20786 return 0.0;
20787 else
20788 return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
20789
20792 if( onlycurrentrun )
20793 return SCIPhistoryGetPseudocostVariance(var->historycrun, dir);
20794 else
20795 return SCIPhistoryGetPseudocostVariance(var->history, dir);
20796
20798 return 0.0;
20799
20801 if( var->data.aggregate.scalar > 0.0 )
20802 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
20803 else
20804 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
20805
20807 return 0.0;
20808
20810 return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
20811
20812 default:
20813 SCIPerrorMessage("unknown variable status\n");
20814 SCIPABORT();
20815 return 0.0; /*lint !e527*/
20816 }
20817}
20818
20819/** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
20820 *
20821 * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
20822 * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
20823 * of 2 * clevel - 1.
20824 *
20825 * @return value of confidence bound for this variable
20826 */
20828 SCIP_VAR* var, /**< variable in question */
20829 SCIP_SET* set, /**< global SCIP settings */
20830 SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
20831 SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
20832 SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
20833 )
20834{
20835 SCIP_Real confidencebound;
20836
20837 confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
20838 if( SCIPsetIsFeasPositive(set, confidencebound) )
20839 {
20840 SCIP_Real count;
20841
20842 if( onlycurrentrun )
20844 else
20845 count = SCIPvarGetPseudocostCount(var, dir);
20846 /* assertion is valid because variance is positive */
20847 assert(count >= 1.9);
20848
20849 confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
20850 confidencebound = sqrt(confidencebound);
20851
20852 /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
20853 * the number of pseudo cost evaluations of this variable in the respective direction. */
20854 confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
20855 }
20856 else
20857 confidencebound = 0.0;
20858
20859 return confidencebound;
20860}
20861
20862/** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
20863 * Error is calculated at a specific confidence level
20864 */
20866 SCIP_VAR* var, /**< variable in question */
20867 SCIP_SET* set, /**< global SCIP settings */
20868 SCIP_STAT* stat, /**< problem statistics */
20869 SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
20870 SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
20871 )
20872{
20873 SCIP_Real downsize;
20874 SCIP_Real upsize;
20875 SCIP_Real size;
20876 SCIP_Real relerrorup;
20877 SCIP_Real relerrordown;
20878 SCIP_Real relerror;
20879
20880 /* check, if the pseudo cost score of the variable is reliable */
20883 size = MIN(downsize, upsize);
20884
20885 /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
20886 if( size <= 1.9 )
20887 return FALSE;
20888
20889 /* use the relative error between the current mean pseudo cost value of the candidate and its upper
20890 * confidence interval bound at confidence level of 95% for individual variable reliability.
20891 * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
20892 */
20893 if( downsize >= 1.9 )
20894 {
20895 SCIP_Real normval;
20896
20898 normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
20899 normval = MAX(1.0, normval);
20900
20901 relerrordown /= normval;
20902 }
20903 else
20904 relerrordown = 0.0;
20905
20906 if( upsize >= 1.9 )
20907 {
20908 SCIP_Real normval;
20909
20911 normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
20912 normval = MAX(1.0, normval);
20913 relerrorup /= normval;
20914 }
20915 else
20916 relerrorup = 0.0;
20917
20918 /* consider the relative error threshold violated, if it is violated in at least one branching direction */
20919 relerror = MAX(relerrorup, relerrordown);
20920
20921 return (relerror <= threshold);
20922}
20923
20924/** check if variable pseudo-costs have a significant difference in location. The significance depends on
20925 * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
20926 * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
20927 * unknown location means of the underlying pseudo-cost distributions of x and y.
20928 *
20929 * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
20930 * better than x (despite the current information), meaning that y can be expected to yield branching
20931 * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
20932 * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
20933 * than y.
20934 *
20935 * @note The order of x and y matters for the one-sided hypothesis
20936 *
20937 * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
20938 * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
20939 *
20940 * @return TRUE if the hypothesis can be safely rejected at the given confidence level
20941 */
20943 SCIP_SET* set, /**< global SCIP settings */
20944 SCIP_STAT* stat, /**< problem statistics */
20945 SCIP_VAR* varx, /**< variable x */
20946 SCIP_Real fracx, /**< the fractionality of variable x */
20947 SCIP_VAR* vary, /**< variable y */
20948 SCIP_Real fracy, /**< the fractionality of variable y */
20949 SCIP_BRANCHDIR dir, /**< branching direction */
20950 SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
20951 SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
20952 )
20953{
20954 SCIP_Real meanx;
20955 SCIP_Real meany;
20956 SCIP_Real variancex;
20957 SCIP_Real variancey;
20958 SCIP_Real countx;
20959 SCIP_Real county;
20960 SCIP_Real tresult;
20961 SCIP_Real realdirection;
20962
20963 if( varx == vary )
20964 return FALSE;
20965
20966 countx = SCIPvarGetPseudocostCount(varx, dir);
20967 county = SCIPvarGetPseudocostCount(vary, dir);
20968
20969 /* if not at least 2 measurements were taken, return FALSE */
20970 if( countx <= 1.9 || county <= 1.9 )
20971 return FALSE;
20972
20973 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
20974
20975 meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
20976 meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
20977
20978 variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
20979 variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
20980
20981 /* if there is no variance, the means are taken from a constant distribution */
20982 if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
20983 return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
20984
20985 tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
20986
20987 /* for the two-sided hypothesis, just take the absolute of t */
20988 if( !onesided )
20989 tresult = REALABS(tresult);
20990
20991 return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
20992}
20993
20994/** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
20995 * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
20996 * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
20997 * of at least \p threshold.
20998 *
20999 * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
21000 * the estimated probability to exceed \p threshold is less than 25 %.
21001 *
21002 * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
21003 * of confidence.
21004 *
21005 * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
21006 * at the given confidence level \p clevel.
21007 */
21009 SCIP_SET* set, /**< global SCIP settings */
21010 SCIP_STAT* stat, /**< problem statistics */
21011 SCIP_VAR* var, /**< variable x */
21012 SCIP_Real frac, /**< the fractionality of variable x */
21013 SCIP_Real threshold, /**< the threshold to test against */
21014 SCIP_BRANCHDIR dir, /**< branching direction */
21015 SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
21016 )
21017{
21018 SCIP_Real mean;
21019 SCIP_Real variance;
21020 SCIP_Real count;
21021 SCIP_Real realdirection;
21022 SCIP_Real probability;
21023 SCIP_Real problimit;
21024
21025 count = SCIPvarGetPseudocostCount(var, dir);
21026
21027 /* if not at least 2 measurements were taken, return FALSE */
21028 if( count <= 1.9 )
21029 return FALSE;
21030
21031 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
21032
21033 mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
21034 variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
21035
21036 /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
21037 if( SCIPsetIsFeasGE(set, mean, threshold) )
21038 return FALSE;
21039
21040 /* if there is no variance, the means are taken from a constant distribution */
21041 if( SCIPsetIsFeasEQ(set, variance, 0.0) )
21042 return SCIPsetIsFeasLT(set, mean, threshold);
21043
21044 /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
21045 probability = SCIPnormalCDF(mean, variance, threshold);
21046
21047 /* determine a probability limit corresponding to the given confidence level */
21048 switch( clevel )
21049 {
21051 problimit = 0.75;
21052 break;
21054 problimit = 0.875;
21055 break;
21057 problimit = 0.9;
21058 break;
21060 problimit = 0.95;
21061 break;
21063 problimit = 0.975;
21064 break;
21065 default:
21066 problimit = -1;
21067 SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
21068 SCIPABORT();
21069 break;
21070 }
21071
21072 return (probability >= problimit);
21073}
21074
21075/** find the corresponding history entry if already existing, otherwise create new entry */
21076static
21078 SCIP_VAR* var, /**< problem variable */
21079 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21080 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21081 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21082 SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
21083 )
21084{
21085 assert(var != NULL);
21086 assert(blkmem != NULL);
21087 assert(set != NULL);
21088 assert(history != NULL);
21089
21090 (*history) = NULL;
21091
21092 if( var->valuehistory == NULL )
21093 {
21094 SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
21095 }
21096
21097 SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
21098
21099 return SCIP_OKAY;
21100}
21101
21102/** check if value based history should be used */
21103static
21105 SCIP_VAR* var, /**< problem variable */
21106 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21107 SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21108 )
21109{
21110 /* check if the domain value is unknown (not specific) */
21111 if( value == SCIP_UNKNOWN ) /*lint !e777*/
21112 return FALSE;
21113
21114 assert(set != NULL);
21115
21116 /* check if value based history should be collected */
21117 if( !set->history_valuebased )
21118 return FALSE;
21119
21120 /* value based history is not collected for binary variable since the standard history already contains all information */
21122 return FALSE;
21123
21124 /* value based history is not collected for continuous variables */
21126 return FALSE;
21127
21128 return TRUE;
21129}
21130
21131/** increases VSIDS of the variable by the given weight */
21133 SCIP_VAR* var, /**< problem variable */
21134 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21135 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21136 SCIP_STAT* stat, /**< problem statistics */
21137 SCIP_BRANCHDIR dir, /**< branching direction */
21138 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21139 SCIP_Real weight /**< weight of this update in VSIDS */
21140 )
21141{
21142 assert(var != NULL);
21144
21145 /* check if history statistics should be collected for a variable */
21146 if( !stat->collectvarhistory )
21147 return SCIP_OKAY;
21148
21149 if( SCIPsetIsZero(set, weight) )
21150 return SCIP_OKAY;
21151
21152 switch( SCIPvarGetStatus(var) )
21153 {
21155 if( var->data.original.transvar == NULL )
21156 {
21157 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
21158 return SCIP_INVALIDDATA;
21159 }
21160 SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21161 return SCIP_OKAY;
21162
21165 {
21166 SCIPhistoryIncVSIDS(var->history, dir, weight);
21167 SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
21168
21169 if( useValuehistory(var, value, set) )
21170 {
21171 SCIP_HISTORY* history;
21172
21173 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21174 assert(history != NULL);
21175
21176 SCIPhistoryIncVSIDS(history, dir, weight);
21177 SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
21178 value, weight, SCIPhistoryGetVSIDS(history, dir));
21179 }
21180
21181 return SCIP_OKAY;
21182 }
21184 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
21185 return SCIP_INVALIDDATA;
21186
21188 value = (value - var->data.aggregate.constant) / var->data.aggregate.scalar;
21189
21190 if( var->data.aggregate.scalar > 0.0 )
21191 {
21192 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21193 }
21194 else
21195 {
21196 assert(var->data.aggregate.scalar < 0.0);
21197 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21198 }
21199 return SCIP_OKAY;
21200
21202 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
21203 return SCIP_INVALIDDATA;
21204
21206 value = 1.0 - value;
21207
21208 SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21209 return SCIP_OKAY;
21210
21211 default:
21212 SCIPerrorMessage("unknown variable status\n");
21213 return SCIP_INVALIDDATA;
21214 }
21215}
21216
21217/** scales the VSIDS of the variable by the given scalar */
21219 SCIP_VAR* var, /**< problem variable */
21220 SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
21221 )
21222{
21223 assert(var != NULL);
21224
21225 switch( SCIPvarGetStatus(var) )
21226 {
21228 if( var->data.original.transvar == NULL )
21229 {
21230 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
21231 return SCIP_INVALIDDATA;
21232 }
21233 SCIP_CALL( SCIPvarScaleVSIDS(var->data.original.transvar, scalar) );
21234 return SCIP_OKAY;
21235
21238 {
21239 SCIPhistoryScaleVSIDS(var->history, scalar);
21240 SCIPhistoryScaleVSIDS(var->historycrun, scalar);
21241 SCIPvaluehistoryScaleVSIDS(var->valuehistory, scalar);
21242
21243 return SCIP_OKAY;
21244 }
21246 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
21247 return SCIP_INVALIDDATA;
21248
21250 SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
21251 return SCIP_OKAY;
21252
21254 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
21255 return SCIP_INVALIDDATA;
21256
21258 SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
21259 return SCIP_OKAY;
21260
21261 default:
21262 SCIPerrorMessage("unknown variable status\n");
21263 return SCIP_INVALIDDATA;
21264 }
21265}
21266
21267/** increases the number of active conflicts by one and the overall length of the variable by the given length */
21269 SCIP_VAR* var, /**< problem variable */
21270 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21271 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21272 SCIP_STAT* stat, /**< problem statistics */
21273 SCIP_BRANCHDIR dir, /**< branching direction */
21274 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21275 SCIP_Real length /**< length of the conflict */
21276 )
21277{
21278 assert(var != NULL);
21280
21281 /* check if history statistics should be collected for a variable */
21282 if( !stat->collectvarhistory )
21283 return SCIP_OKAY;
21284
21285 switch( SCIPvarGetStatus(var) )
21286 {
21288 if( var->data.original.transvar == NULL )
21289 {
21290 SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
21291 return SCIP_INVALIDDATA;
21292 }
21293 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
21294 return SCIP_OKAY;
21295
21298 {
21299 SCIPhistoryIncNActiveConflicts(var->history, dir, length);
21300 SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
21301
21302 if( useValuehistory(var, value, set) )
21303 {
21304 SCIP_HISTORY* history;
21305
21306 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21307 assert(history != NULL);
21308
21309 SCIPhistoryIncNActiveConflicts(history, dir, length);
21310 }
21311
21312 return SCIP_OKAY;
21313 }
21315 SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
21316 return SCIP_INVALIDDATA;
21317
21319 value = (value - var->data.aggregate.constant) / var->data.aggregate.scalar;
21320
21321 if( var->data.aggregate.scalar > 0.0 )
21322 {
21323 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
21324 }
21325 else
21326 {
21327 assert(var->data.aggregate.scalar < 0.0);
21328 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
21329 }
21330 return SCIP_OKAY;
21331
21333 SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
21334 return SCIP_INVALIDDATA;
21335
21337 value = 1.0 - value;
21338
21339 SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
21340 return SCIP_OKAY;
21341
21342 default:
21343 SCIPerrorMessage("unknown variable status\n");
21344 return SCIP_INVALIDDATA;
21345 }
21346}
21347
21348/** gets the number of active conflicts containing this variable in given direction */
21350 SCIP_VAR* var, /**< problem variable */
21351 SCIP_STAT* stat, /**< problem statistics */
21352 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21353 )
21354{
21355 assert(var != NULL);
21356 assert(stat != NULL);
21358
21359 switch( SCIPvarGetStatus(var) )
21360 {
21362 if( var->data.original.transvar == NULL )
21363 return 0;
21364 else
21365 return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
21366
21369 return SCIPhistoryGetNActiveConflicts(var->history, dir);
21370
21372 return 0;
21373
21375 if( var->data.aggregate.scalar > 0.0 )
21376 return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
21377 else
21378 return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21379
21381 return 0;
21382
21384 return SCIPvarGetNActiveConflicts(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21385
21386 default:
21387 SCIPerrorMessage("unknown variable status\n");
21388 SCIPABORT();
21389 return 0; /*lint !e527*/
21390 }
21391}
21392
21393/** gets the number of active conflicts containing this variable in given direction
21394 * in the current run
21395 */
21397 SCIP_VAR* var, /**< problem variable */
21398 SCIP_STAT* stat, /**< problem statistics */
21399 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21400 )
21401{
21402 assert(var != NULL);
21403 assert(stat != NULL);
21405
21406 switch( SCIPvarGetStatus(var) )
21407 {
21409 if( var->data.original.transvar == NULL )
21410 return 0;
21411 else
21412 return SCIPvarGetNActiveConflictsCurrentRun(var->data.original.transvar, stat, dir);
21413
21416 return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
21417
21419 return 0;
21420
21422 if( var->data.aggregate.scalar > 0.0 )
21423 return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
21424 else
21425 return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21426
21428 return 0;
21429
21431 return SCIPvarGetNActiveConflictsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21432
21433 default:
21434 SCIPerrorMessage("unknown variable status\n");
21435 SCIPABORT();
21436 return 0; /*lint !e527*/
21437 }
21438}
21439
21440/** gets the average conflict length in given direction due to branching on the variable */
21442 SCIP_VAR* var, /**< problem variable */
21443 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21444 )
21445{
21446 assert(var != NULL);
21448
21449 switch( SCIPvarGetStatus(var) )
21450 {
21452 if( var->data.original.transvar == NULL )
21453 return 0.0;
21454 else
21455 return SCIPvarGetAvgConflictlength(var->data.original.transvar, dir);
21456
21459 return SCIPhistoryGetAvgConflictlength(var->history, dir);
21461 return 0.0;
21462
21464 if( var->data.aggregate.scalar > 0.0 )
21465 return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
21466 else
21467 return SCIPvarGetAvgConflictlength(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21468
21470 return 0.0;
21471
21473 return SCIPvarGetAvgConflictlength(var->negatedvar, SCIPbranchdirOpposite(dir));
21474
21475 default:
21476 SCIPerrorMessage("unknown variable status\n");
21477 SCIPABORT();
21478 return 0.0; /*lint !e527*/
21479 }
21480}
21481
21482/** gets the average conflict length in given direction due to branching on the variable
21483 * in the current run
21484 */
21486 SCIP_VAR* var, /**< problem variable */
21487 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21488 )
21489{
21490 assert(var != NULL);
21492
21493 switch( SCIPvarGetStatus(var) )
21494 {
21496 if( var->data.original.transvar == NULL )
21497 return 0.0;
21498 else
21499 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.original.transvar, dir);
21500
21503 return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
21504
21506 return 0.0;
21507
21509 if( var->data.aggregate.scalar > 0.0 )
21510 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, dir);
21511 else
21512 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21513
21515 return 0.0;
21516
21519
21520 default:
21521 SCIPerrorMessage("unknown variable status\n");
21522 SCIPABORT();
21523 return 0.0; /*lint !e527*/
21524 }
21525}
21526
21527/** increases the number of branchings counter of the variable */
21529 SCIP_VAR* var, /**< problem variable */
21530 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21531 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21532 SCIP_STAT* stat, /**< problem statistics */
21533 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21534 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21535 int depth /**< depth at which the bound change took place */
21536 )
21537{
21538 assert(var != NULL);
21539 assert(stat != NULL);
21541
21542 /* check if history statistics should be collected for a variable */
21543 if( !stat->collectvarhistory )
21544 return SCIP_OKAY;
21545
21546 switch( SCIPvarGetStatus(var) )
21547 {
21549 if( var->data.original.transvar == NULL )
21550 {
21551 SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
21552 return SCIP_INVALIDDATA;
21553 }
21554 SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
21555 return SCIP_OKAY;
21556
21559 {
21560 SCIPhistoryIncNBranchings(var->history, dir, depth);
21561 SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
21564
21565 if( useValuehistory(var, value, set) )
21566 {
21567 SCIP_HISTORY* history;
21568
21569 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21570 assert(history != NULL);
21571
21572 SCIPhistoryIncNBranchings(history, dir, depth);
21573 }
21574
21575 return SCIP_OKAY;
21576 }
21578 SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
21579 return SCIP_INVALIDDATA;
21580
21582 value = (value - var->data.aggregate.constant) / var->data.aggregate.scalar;
21583
21584 if( var->data.aggregate.scalar > 0.0 )
21585 {
21586 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
21587 }
21588 else
21589 {
21590 assert(var->data.aggregate.scalar < 0.0);
21591 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
21592 }
21593 return SCIP_OKAY;
21594
21596 SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
21597 return SCIP_INVALIDDATA;
21598
21600 value = 1.0 - value;
21601
21602 SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
21603 return SCIP_OKAY;
21604
21605 default:
21606 SCIPerrorMessage("unknown variable status\n");
21607 return SCIP_INVALIDDATA;
21608 }
21609}
21610
21611/** increases the inference sum of the variable by the given weight */
21613 SCIP_VAR* var, /**< problem variable */
21614 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21615 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21616 SCIP_STAT* stat, /**< problem statistics */
21617 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21618 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21619 SCIP_Real weight /**< weight of this update in inference score */
21620 )
21621{
21622 assert(var != NULL);
21623 assert(stat != NULL);
21625
21626 /* check if history statistics should be collected for a variable */
21627 if( !stat->collectvarhistory )
21628 return SCIP_OKAY;
21629
21630 switch( SCIPvarGetStatus(var) )
21631 {
21633 if( var->data.original.transvar == NULL )
21634 {
21635 SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
21636 return SCIP_INVALIDDATA;
21637 }
21638 SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21639 return SCIP_OKAY;
21640
21643 {
21644 SCIPhistoryIncInferenceSum(var->history, dir, weight);
21645 SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
21646 SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
21647 SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
21648
21649 if( useValuehistory(var, value, set) )
21650 {
21651 SCIP_HISTORY* history;
21652
21653 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21654 assert(history != NULL);
21655
21656 SCIPhistoryIncInferenceSum(history, dir, weight);
21657 }
21658
21659 return SCIP_OKAY;
21660 }
21662 SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
21663 return SCIP_INVALIDDATA;
21664
21666 value = (value - var->data.aggregate.constant) / var->data.aggregate.scalar;
21667
21668 if( var->data.aggregate.scalar > 0.0 )
21669 {
21670 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21671 }
21672 else
21673 {
21674 assert(var->data.aggregate.scalar < 0.0);
21675 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21676 }
21677 return SCIP_OKAY;
21678
21680 SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
21681 return SCIP_INVALIDDATA;
21682
21684 value = 1.0 - value;
21685
21686 SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21687 return SCIP_OKAY;
21688
21689 default:
21690 SCIPerrorMessage("unknown variable status\n");
21691 return SCIP_INVALIDDATA;
21692 }
21693}
21694
21695/** increases the cutoff sum of the variable by the given weight */
21697 SCIP_VAR* var, /**< problem variable */
21698 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21699 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21700 SCIP_STAT* stat, /**< problem statistics */
21701 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21702 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21703 SCIP_Real weight /**< weight of this update in cutoff score */
21704 )
21705{
21706 assert(var != NULL);
21707 assert(stat != NULL);
21709
21710 /* check if history statistics should be collected for a variable */
21711 if( !stat->collectvarhistory )
21712 return SCIP_OKAY;
21713
21714 switch( SCIPvarGetStatus(var) )
21715 {
21717 if( var->data.original.transvar == NULL )
21718 {
21719 SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
21720 return SCIP_INVALIDDATA;
21721 }
21722 SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21723 return SCIP_OKAY;
21724
21727 {
21728 SCIPhistoryIncCutoffSum(var->history, dir, weight);
21729 SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
21730 SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
21731 SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
21732
21733 if( useValuehistory(var, value, set) )
21734 {
21735 SCIP_HISTORY* history;
21736
21737 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21738 assert(history != NULL);
21739
21740 SCIPhistoryIncCutoffSum(history, dir, weight);
21741 }
21742
21743 return SCIP_OKAY;
21744 }
21746 SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
21747 return SCIP_INVALIDDATA;
21748
21750 value = (value - var->data.aggregate.constant) / var->data.aggregate.scalar;
21751
21752 if( var->data.aggregate.scalar > 0.0 )
21753 {
21754 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21755 }
21756 else
21757 {
21758 assert(var->data.aggregate.scalar < 0.0);
21759 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21760 }
21761 return SCIP_OKAY;
21762
21764 SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
21765 return SCIP_INVALIDDATA;
21766
21768 value = 1.0 - value;
21769
21770 SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21771 return SCIP_OKAY;
21772
21773 default:
21774 SCIPerrorMessage("unknown variable status\n");
21775 return SCIP_INVALIDDATA;
21776 }
21777}
21778
21779/** returns the number of times, a bound of the variable was changed in given direction due to branching */
21781 SCIP_VAR* var, /**< problem variable */
21782 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21783 )
21784{
21785 assert(var != NULL);
21787
21788 switch( SCIPvarGetStatus(var) )
21789 {
21791 if( var->data.original.transvar == NULL )
21792 return 0;
21793 else
21794 return SCIPvarGetNBranchings(var->data.original.transvar, dir);
21795
21798 return SCIPhistoryGetNBranchings(var->history, dir);
21799
21801 return 0;
21802
21804 if( var->data.aggregate.scalar > 0.0 )
21805 return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
21806 else
21807 return SCIPvarGetNBranchings(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21808
21810 return 0;
21811
21813 return SCIPvarGetNBranchings(var->negatedvar, SCIPbranchdirOpposite(dir));
21814
21815 default:
21816 SCIPerrorMessage("unknown variable status\n");
21817 SCIPABORT();
21818 return 0; /*lint !e527*/
21819 }
21820}
21821
21822/** returns the number of times, a bound of the variable was changed in given direction due to branching
21823 * in the current run
21824 */
21826 SCIP_VAR* var, /**< problem variable */
21827 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21828 )
21829{
21830 assert(var != NULL);
21832
21833 switch( SCIPvarGetStatus(var) )
21834 {
21836 if( var->data.original.transvar == NULL )
21837 return 0;
21838 else
21839 return SCIPvarGetNBranchingsCurrentRun(var->data.original.transvar, dir);
21840
21843 return SCIPhistoryGetNBranchings(var->historycrun, dir);
21844
21846 return 0;
21847
21849 if( var->data.aggregate.scalar > 0.0 )
21850 return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, dir);
21851 else
21852 return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21853
21855 return 0;
21856
21859
21860 default:
21861 SCIPerrorMessage("unknown variable status\n");
21862 SCIPABORT();
21863 return 0; /*lint !e527*/
21864 }
21865}
21866
21867/** returns the average depth of bound changes in given direction due to branching on the variable */
21869 SCIP_VAR* var, /**< problem variable */
21870 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21871 )
21872{
21873 assert(var != NULL);
21875
21876 switch( SCIPvarGetStatus(var) )
21877 {
21879 if( var->data.original.transvar == NULL )
21880 return 0.0;
21881 else
21882 return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
21883
21886 return SCIPhistoryGetAvgBranchdepth(var->history, dir);
21887
21889 return 0.0;
21890
21892 if( var->data.aggregate.scalar > 0.0 )
21893 return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
21894 else
21895 return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21896
21898 return 0.0;
21899
21901 return SCIPvarGetAvgBranchdepth(var->negatedvar, SCIPbranchdirOpposite(dir));
21902
21903 default:
21904 SCIPerrorMessage("unknown variable status\n");
21905 SCIPABORT();
21906 return 0.0; /*lint !e527*/
21907 }
21908}
21909
21910/** returns the average depth of bound changes in given direction due to branching on the variable
21911 * in the current run
21912 */
21914 SCIP_VAR* var, /**< problem variable */
21915 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21916 )
21917{
21918 assert(var != NULL);
21920
21921 switch( SCIPvarGetStatus(var) )
21922 {
21924 if( var->data.original.transvar == NULL )
21925 return 0.0;
21926 else
21927 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.original.transvar, dir);
21928
21931 return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
21932
21934 return 0.0;
21935
21937 if( var->data.aggregate.scalar > 0.0 )
21938 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var, dir);
21939 else
21940 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var,
21942
21944 return 0.0;
21945
21947 return SCIPvarGetAvgBranchdepthCurrentRun(var->negatedvar,
21949
21950 default:
21951 SCIPerrorMessage("unknown variable status\n");
21952 SCIPABORT();
21953 return 0.0; /*lint !e527*/
21954 }
21955}
21956
21957/** returns the variable's VSIDS score */
21959 SCIP_VAR* var, /**< problem variable */
21960 SCIP_STAT* stat, /**< problem statistics */
21961 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21962 )
21963{
21964 assert(var != NULL);
21965 assert(stat != NULL);
21967
21969 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
21970
21971 switch( SCIPvarGetStatus(var) )
21972 {
21974 if( var->data.original.transvar == NULL )
21975 return 0.0;
21976 else
21977 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
21978
21981 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
21982 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
21983
21985 return 0.0;
21986
21988 if( var->data.aggregate.scalar > 0.0 )
21989 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
21990 else
21991 /* coverity[overrun-local] */
21992 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21993
21995 return 0.0;
21996
21998 /* coverity[overrun-local] */
21999 return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22000
22001 default:
22002 SCIPerrorMessage("unknown variable status\n");
22003 SCIPABORT();
22004 return 0.0; /*lint !e527*/
22005 }
22006}
22007
22008/** returns the variable's VSIDS score only using conflicts of the current run */
22010 SCIP_VAR* var, /**< problem variable */
22011 SCIP_STAT* stat, /**< problem statistics */
22012 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22013 )
22014{
22015 assert(var != NULL);
22016 assert(stat != NULL);
22018
22020 {
22021 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
22022 return SCIP_INVALID;
22023 }
22024
22025 switch( SCIPvarGetStatus(var) )
22026 {
22028 if( var->data.original.transvar == NULL )
22029 return 0.0;
22030 else
22031 return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
22032
22035 return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
22036
22038 return 0.0;
22039
22041 if( var->data.aggregate.scalar > 0.0 )
22042 return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
22043 else
22044 return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22045
22047 return 0.0;
22048
22050 return SCIPvarGetVSIDSCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22051
22052 default:
22053 SCIPerrorMessage("unknown variable status\n");
22054 SCIPABORT();
22055 return 0.0; /*lint !e527*/
22056 }
22057}
22058
22059/** returns the number of inferences branching on this variable in given direction triggered */
22061 SCIP_VAR* var, /**< problem variable */
22062 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22063 )
22064{
22065 assert(var != NULL);
22067
22068 switch( SCIPvarGetStatus(var) )
22069 {
22071 if( var->data.original.transvar == NULL )
22072 return 0.0;
22073 else
22074 return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
22075
22078 return SCIPhistoryGetInferenceSum(var->history, dir);
22079
22081 return 0.0;
22082
22084 if( var->data.aggregate.scalar > 0.0 )
22085 return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
22086 else
22087 return SCIPvarGetInferenceSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22088
22090 return 0.0;
22091
22093 return SCIPvarGetInferenceSum(var->negatedvar, SCIPbranchdirOpposite(dir));
22094
22095 default:
22096 SCIPerrorMessage("unknown variable status\n");
22097 SCIPABORT();
22098 return 0.0; /*lint !e527*/
22099 }
22100}
22101
22102/** returns the number of inferences branching on this variable in given direction triggered
22103 * in the current run
22104 */
22106 SCIP_VAR* var, /**< problem variable */
22107 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22108 )
22109{
22110 assert(var != NULL);
22112
22113 switch( SCIPvarGetStatus(var) )
22114 {
22116 if( var->data.original.transvar == NULL )
22117 return 0.0;
22118 else
22119 return SCIPvarGetInferenceSumCurrentRun(var->data.original.transvar, dir);
22120
22123 return SCIPhistoryGetInferenceSum(var->historycrun, dir);
22124
22126 return 0.0;
22127
22129 if( var->data.aggregate.scalar > 0.0 )
22130 return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, dir);
22131 else
22132 return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22133
22135 return 0.0;
22136
22139
22140 default:
22141 SCIPerrorMessage("unknown variable status\n");
22142 SCIPABORT();
22143 return 0.0; /*lint !e527*/
22144 }
22145}
22146
22147/** returns the average number of inferences found after branching on the variable in given direction */
22149 SCIP_VAR* var, /**< problem variable */
22150 SCIP_STAT* stat, /**< problem statistics */
22151 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22152 )
22153{
22154 assert(var != NULL);
22155 assert(stat != NULL);
22157
22158 switch( SCIPvarGetStatus(var) )
22159 {
22161 if( var->data.original.transvar == NULL )
22162 return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
22163 else
22164 return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
22165
22168 if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
22169 return SCIPhistoryGetAvgInferences(var->history, dir);
22170 else
22171 {
22172 int nimpls;
22173 int ncliques;
22174
22176 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
22177 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
22178 }
22179
22181 return 0.0;
22182
22184 if( var->data.aggregate.scalar > 0.0 )
22185 return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
22186 else
22187 return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22188
22190 return 0.0;
22191
22193 return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22194
22195 default:
22196 SCIPerrorMessage("unknown variable status\n");
22197 SCIPABORT();
22198 return 0.0; /*lint !e527*/
22199 }
22200}
22201
22202/** returns the average number of inferences found after branching on the variable in given direction
22203 * in the current run
22204 */
22206 SCIP_VAR* var, /**< problem variable */
22207 SCIP_STAT* stat, /**< problem statistics */
22208 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22209 )
22210{
22211 assert(var != NULL);
22212 assert(stat != NULL);
22214
22215 switch( SCIPvarGetStatus(var) )
22216 {
22218 if( var->data.original.transvar == NULL )
22220 else
22221 return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
22222
22225 if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
22226 return SCIPhistoryGetAvgInferences(var->historycrun, dir);
22227 else
22228 {
22229 int nimpls;
22230 int ncliques;
22231
22233 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
22234 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
22235 }
22236
22238 return 0.0;
22239
22241 if( var->data.aggregate.scalar > 0.0 )
22242 return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
22243 else
22244 return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22245
22247 return 0.0;
22248
22250 return SCIPvarGetAvgInferencesCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22251
22252 default:
22253 SCIPerrorMessage("unknown variable status\n");
22254 SCIPABORT();
22255 return 0.0; /*lint !e527*/
22256 }
22257}
22258
22259/** returns the number of cutoffs branching on this variable in given direction produced */
22261 SCIP_VAR* var, /**< problem variable */
22262 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22263 )
22264{
22265 assert(var != NULL);
22267
22268 switch( SCIPvarGetStatus(var) )
22269 {
22271 if( var->data.original.transvar == NULL )
22272 return 0;
22273 else
22274 return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
22275
22278 return SCIPhistoryGetCutoffSum(var->history, dir);
22279
22281 return 0;
22282
22284 if( var->data.aggregate.scalar > 0.0 )
22285 return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
22286 else
22287 return SCIPvarGetCutoffSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22288
22290 return 0;
22291
22293 return SCIPvarGetCutoffSum(var->negatedvar, SCIPbranchdirOpposite(dir));
22294
22295 default:
22296 SCIPerrorMessage("unknown variable status\n");
22297 SCIPABORT();
22298 return 0; /*lint !e527*/
22299 }
22300}
22301
22302/** returns the number of cutoffs branching on this variable in given direction produced in the current run */
22304 SCIP_VAR* var, /**< problem variable */
22305 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22306 )
22307{
22308 assert(var != NULL);
22310
22311 switch( SCIPvarGetStatus(var) )
22312 {
22314 if( var->data.original.transvar == NULL )
22315 return 0;
22316 else
22317 return SCIPvarGetCutoffSumCurrentRun(var->data.original.transvar, dir);
22318
22321 return SCIPhistoryGetCutoffSum(var->historycrun, dir);
22322
22324 return 0;
22325
22327 if( var->data.aggregate.scalar > 0.0 )
22328 return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
22329 else
22330 return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22331
22333 return 0;
22334
22337
22338 default:
22339 SCIPerrorMessage("unknown variable status\n");
22340 SCIPABORT();
22341 return 0; /*lint !e527*/
22342 }
22343}
22344
22345/** returns the average number of cutoffs found after branching on the variable in given direction */
22347 SCIP_VAR* var, /**< problem variable */
22348 SCIP_STAT* stat, /**< problem statistics */
22349 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22350 )
22351{
22352 assert(var != NULL);
22353 assert(stat != NULL);
22355
22356 switch( SCIPvarGetStatus(var) )
22357 {
22359 if( var->data.original.transvar == NULL )
22360 return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
22361 else
22362 return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
22363
22366 return SCIPhistoryGetNBranchings(var->history, dir) > 0
22367 ? SCIPhistoryGetAvgCutoffs(var->history, dir)
22369
22371 return 0.0;
22372
22374 if( var->data.aggregate.scalar > 0.0 )
22375 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
22376 else
22377 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22378
22380 return 0.0;
22381
22383 return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22384
22385 default:
22386 SCIPerrorMessage("unknown variable status\n");
22387 SCIPABORT();
22388 return 0.0; /*lint !e527*/
22389 }
22390}
22391
22392/** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
22394 SCIP_VAR* var, /**< problem variable */
22395 SCIP_STAT* stat, /**< problem statistics */
22396 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22397 )
22398{
22399 assert(var != NULL);
22400 assert(stat != NULL);
22402
22403 switch( SCIPvarGetStatus(var) )
22404 {
22406 if( var->data.original.transvar == NULL )
22407 return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
22408 else
22409 return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
22410
22413 return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
22414 ? SCIPhistoryGetAvgCutoffs(var->historycrun, dir)
22416
22418 return 0.0;
22419
22421 if( var->data.aggregate.scalar > 0.0 )
22422 return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
22423 else
22424 return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22425
22427 return 0.0;
22428
22430 return SCIPvarGetAvgCutoffsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22431
22432 default:
22433 SCIPerrorMessage("unknown variable status\n");
22434 SCIPABORT();
22435 return 0.0; /*lint !e527*/
22436 }
22437}
22438
22439/** returns the variable's average GMI efficacy score value generated from simplex tableau rows of this variable */
22441 SCIP_VAR* var, /**< problem variable */
22442 SCIP_STAT* stat /**< problem statistics */
22443 )
22444{
22445 assert(var != NULL);
22446 assert(stat != NULL);
22447
22448 switch( SCIPvarGetStatus(var) )
22449 {
22451 if( var->data.original.transvar == NULL )
22452 return 0.0;
22453 else
22454 return SCIPvarGetAvgGMIScore(var->data.original.transvar, stat);
22455
22458 return SCIPhistoryGetAvgGMIeff(var->history);
22459
22461 return 0.0;
22462
22464 return SCIPvarGetAvgGMIScore(var->data.aggregate.var, stat);
22465
22467 return 0.0;
22468
22470 return SCIPvarGetAvgGMIScore(var->negatedvar, stat);
22471
22472 default:
22473 SCIPerrorMessage("unknown variable status\n");
22474 SCIPABORT();
22475 return 0.0; /*lint !e527*/
22476 }
22477}
22478
22479/** increase the variable's GMI efficacy scores generated from simplex tableau rows of this variable */
22481 SCIP_VAR* var, /**< problem variable */
22482 SCIP_STAT* stat, /**< problem statistics */
22483 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
22484 )
22485{
22486 assert(var != NULL);
22487 assert(stat != NULL);
22488 assert(gmieff >= 0);
22489
22490 switch( SCIPvarGetStatus(var) )
22491 {
22493 if( var->data.original.transvar != NULL )
22494 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.original.transvar, stat, gmieff) );
22495 return SCIP_OKAY;
22496
22499 SCIPhistoryIncGMIeffSum(var->history, gmieff);
22500 return SCIP_OKAY;
22501
22503 return SCIP_INVALIDDATA;
22504
22506 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.aggregate.var, stat, gmieff) );
22507 return SCIP_OKAY;
22508
22510 SCIP_CALL( SCIPvarIncGMIeffSum(var->negatedvar, stat, gmieff) );
22511 return SCIP_OKAY;
22512
22514 return SCIP_INVALIDDATA;
22515
22516 default:
22517 SCIPerrorMessage("unknown variable status\n");
22518 SCIPABORT();
22519 return SCIP_INVALIDDATA; /*lint !e527*/
22520 }
22521}
22522
22523/** returns the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
22525 SCIP_VAR* var, /**< problem variable */
22526 SCIP_STAT* stat /**< problem statistics */
22527 )
22528{
22529 assert(var != NULL);
22530 assert(stat != NULL);
22531
22532 switch( SCIPvarGetStatus(var) )
22533 {
22535 if( var->data.original.transvar != NULL )
22536 return SCIPvarGetLastGMIScore(var->data.original.transvar, stat);
22537 return 0.0;
22538
22541 return SCIPhistoryGetLastGMIeff(var->history);
22542
22544 return 0.0;
22545
22547 return SCIPvarGetLastGMIScore(var->data.aggregate.var, stat);
22548
22550 return 0.0;
22551
22553 return SCIPvarGetLastGMIScore(var->negatedvar, stat);
22554
22555 default:
22556 SCIPerrorMessage("unknown variable status\n");
22557 SCIPABORT();
22558 return 0.0; /*lint !e527*/
22559 }
22560}
22561
22562
22563/** sets the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
22565 SCIP_VAR* var, /**< problem variable */
22566 SCIP_STAT* stat, /**< problem statistics */
22567 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
22568 )
22569{
22570 assert(var != NULL);
22571 assert(stat != NULL);
22572 assert(gmieff >= 0);
22573
22574 switch( SCIPvarGetStatus(var) )
22575 {
22577 if( var->data.original.transvar != NULL )
22578 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.original.transvar, stat, gmieff) );
22579 return SCIP_OKAY;
22580
22583 SCIPhistorySetLastGMIeff(var->history, gmieff);
22584 return SCIP_OKAY;
22585
22587 return SCIP_INVALIDDATA;
22588
22590 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.aggregate.var, stat, gmieff) );
22591 return SCIP_OKAY;
22592
22594 SCIP_CALL( SCIPvarSetLastGMIScore(var->negatedvar, stat, gmieff) );
22595 return SCIP_OKAY;
22596
22598 return SCIP_INVALIDDATA;
22599
22600 default:
22601 SCIPerrorMessage("unknown variable status\n");
22602 SCIPABORT();
22603 return SCIP_INVALIDDATA; /*lint !e527*/
22604 }
22605}
22606
22607
22608
22609/*
22610 * information methods for bound changes
22611 */
22612
22613/** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
22615 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
22616 BMS_BLKMEM* blkmem, /**< block memory */
22617 SCIP_VAR* var, /**< active variable that changed the bounds */
22618 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
22619 SCIP_Real oldbound, /**< old value for bound */
22620 SCIP_Real newbound /**< new value for bound */
22621 )
22622{
22623 assert(bdchginfo != NULL);
22624
22625 SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
22626 (*bdchginfo)->oldbound = oldbound;
22627 (*bdchginfo)->newbound = newbound;
22628 (*bdchginfo)->var = var;
22629 (*bdchginfo)->inferencedata.var = var;
22630 (*bdchginfo)->inferencedata.reason.prop = NULL;
22631 (*bdchginfo)->inferencedata.info = 0;
22632 (*bdchginfo)->bdchgidx.depth = INT_MAX;
22633 (*bdchginfo)->bdchgidx.pos = -1;
22634 (*bdchginfo)->pos = 0;
22635 (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
22636 (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
22637 (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
22638 (*bdchginfo)->redundant = FALSE;
22639
22640 return SCIP_OKAY;
22641}
22642
22643/** frees a bound change information object */
22645 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
22646 BMS_BLKMEM* blkmem /**< block memory */
22647 )
22648{
22649 assert(bdchginfo != NULL);
22650
22651 BMSfreeBlockMemory(blkmem, bdchginfo);
22652}
22653
22654/** returns the bound change information for the last lower bound change on given active problem variable before or
22655 * after the bound change with the given index was applied;
22656 * returns NULL, if no change to the lower bound was applied up to this point of time
22657 */
22659 SCIP_VAR* var, /**< active problem variable */
22660 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22661 SCIP_Bool after /**< should the bound change with given index be included? */
22662 )
22663{
22664 int i;
22665
22666 assert(var != NULL);
22668
22669 /* search the correct bound change information for the given bound change index */
22670 if( after )
22671 {
22672 for( i = var->nlbchginfos-1; i >= 0; --i )
22673 {
22674 assert(var->lbchginfos[i].var == var);
22675 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22676 assert(var->lbchginfos[i].pos == i);
22677
22678 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22679 if( var->lbchginfos[i].redundant )
22680 return NULL;
22681 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
22682
22683 /* if we reached the bound change index, return the current bound change info */
22684 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
22685 return &var->lbchginfos[i];
22686 }
22687 }
22688 else
22689 {
22690 for( i = var->nlbchginfos-1; i >= 0; --i )
22691 {
22692 assert(var->lbchginfos[i].var == var);
22693 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22694 assert(var->lbchginfos[i].pos == i);
22695
22696 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22697 if( var->lbchginfos[i].redundant )
22698 return NULL;
22699 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
22700
22701 /* if we reached the bound change index, return the current bound change info */
22702 if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
22703 return &var->lbchginfos[i];
22704 }
22705 }
22706
22707 return NULL;
22708}
22709
22710/** returns the bound change information for the last upper bound change on given active problem variable before or
22711 * after the bound change with the given index was applied;
22712 * returns NULL, if no change to the upper bound was applied up to this point of time
22713 */
22715 SCIP_VAR* var, /**< active problem variable */
22716 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22717 SCIP_Bool after /**< should the bound change with given index be included? */
22718 )
22719{
22720 int i;
22721
22722 assert(var != NULL);
22724
22725 /* search the correct bound change information for the given bound change index */
22726 if( after )
22727 {
22728 for( i = var->nubchginfos-1; i >= 0; --i )
22729 {
22730 assert(var->ubchginfos[i].var == var);
22731 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22732 assert(var->ubchginfos[i].pos == i);
22733
22734 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22735 if( var->ubchginfos[i].redundant )
22736 return NULL;
22737 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
22738
22739 /* if we reached the bound change index, return the current bound change info */
22740 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
22741 return &var->ubchginfos[i];
22742 }
22743 }
22744 else
22745 {
22746 for( i = var->nubchginfos-1; i >= 0; --i )
22747 {
22748 assert(var->ubchginfos[i].var == var);
22749 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22750 assert(var->ubchginfos[i].pos == i);
22751
22752 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22753 if( var->ubchginfos[i].redundant )
22754 return NULL;
22755 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
22756
22757 /* if we reached the bound change index, return the current bound change info */
22758 if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
22759 return &var->ubchginfos[i];
22760 }
22761 }
22762
22763 return NULL;
22764}
22765
22766/** returns the bound change information for the last lower or upper bound change on given active problem variable
22767 * before or after the bound change with the given index was applied;
22768 * returns NULL, if no change to the lower/upper bound was applied up to this point of time
22769 */
22771 SCIP_VAR* var, /**< active problem variable */
22772 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
22773 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22774 SCIP_Bool after /**< should the bound change with given index be included? */
22775 )
22776{
22777 if( boundtype == SCIP_BOUNDTYPE_LOWER )
22778 return SCIPvarGetLbchgInfo(var, bdchgidx, after);
22779 else
22780 {
22781 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
22782 return SCIPvarGetUbchgInfo(var, bdchgidx, after);
22783 }
22784}
22785
22786/** bound change index representing the initial time before any bound changes took place */
22788
22789/** bound change index representing the presolving stage */
22791
22792/** returns the last bound change index, at which the bounds of the given variable were tightened */
22794 SCIP_VAR* var /**< problem variable */
22795 )
22796{
22797 SCIP_BDCHGIDX* lbchgidx;
22798 SCIP_BDCHGIDX* ubchgidx;
22799
22800 assert(var != NULL);
22801
22803
22804 /* check, if variable is original without transformed variable */
22805 if( var == NULL )
22806 return &initbdchgidx;
22807
22808 /* check, if variable was fixed in presolving */
22809 if( !SCIPvarIsActive(var) )
22810 return &presolvebdchgidx;
22811
22813
22814 /* get depths of last bound change information for the lower and upper bound */
22815 lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
22816 ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
22817 ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
22818 ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
22819
22820 if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
22821 return ubchgidx;
22822 else
22823 return lbchgidx;
22824}
22825
22826/** returns the last depth level, at which the bounds of the given variable were tightened;
22827 * returns -2, if the variable's bounds are still the global bounds
22828 * returns -1, if the variable was fixed in presolving
22829 */
22831 SCIP_VAR* var /**< problem variable */
22832 )
22833{
22834 SCIP_BDCHGIDX* bdchgidx;
22835
22836 bdchgidx = SCIPvarGetLastBdchgIndex(var);
22837 assert(bdchgidx != NULL);
22838
22839 return bdchgidx->depth;
22840}
22841
22842/** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
22843 * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
22844 */
22846 SCIP_VAR* var, /**< problem variable */
22847 SCIP_SET* set, /**< global SCIP settings */
22848 SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
22849 SCIP_Real bound /**< conflicting bound */
22850 )
22851{
22852 int i;
22853
22854 assert(var != NULL);
22855 assert(set != NULL);
22856 assert(var->scip == set->scip);
22857
22858 if( boundtype == SCIP_BOUNDTYPE_LOWER )
22859 {
22860 /* check if the bound is in conflict with the current local bounds */
22861 if( SCIPsetIsLE(set, bound, var->locdom.ub) )
22862 return -1;
22863
22864 /* check if the bound is in conflict with the global bound */
22865 if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
22866 return 0;
22867
22868 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
22869 assert(var->nubchginfos > 0);
22870 assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
22871
22872 /* search for the first conflicting bound change */
22873 for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
22874 {
22875 assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
22876 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22877 }
22878 assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
22879 assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
22880
22881 /* return the depth at which the first conflicting bound change took place */
22882 return var->ubchginfos[i].bdchgidx.depth;
22883 }
22884 else
22885 {
22886 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
22887
22888 /* check if the bound is in conflict with the current local bounds */
22889 if( SCIPsetIsGE(set, bound, var->locdom.lb) )
22890 return -1;
22891
22892 /* check if the bound is in conflict with the global bound */
22893 if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
22894 return 0;
22895
22896 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
22897 assert(var->nlbchginfos > 0);
22898 assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
22899
22900 /* search for the first conflicting bound change */
22901 for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
22902 {
22903 assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
22904 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22905 }
22906 assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
22907 assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
22908
22909 /* return the depth at which the first conflicting bound change took place */
22910 return var->lbchginfos[i].bdchgidx.depth;
22911 }
22912}
22913
22914/** returns whether the first binary variable was fixed earlier than the second one;
22915 * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
22916 * second one is not fixed
22917 */
22919 SCIP_VAR* var1, /**< first binary variable */
22920 SCIP_VAR* var2 /**< second binary variable */
22921 )
22922{
22923 SCIP_BDCHGIDX* bdchgidx1;
22924 SCIP_BDCHGIDX* bdchgidx2;
22925
22926 assert(var1 != NULL);
22927 assert(var2 != NULL);
22928 assert(SCIPvarIsBinary(var1));
22929 assert(SCIPvarIsBinary(var2));
22930
22931 var1 = SCIPvarGetProbvar(var1);
22932 var2 = SCIPvarGetProbvar(var2);
22933 assert(var1 != NULL);
22934 assert(var2 != NULL);
22935
22936 /* check, if variables are globally fixed */
22937 if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
22938 return FALSE;
22939 if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
22940 return TRUE;
22941
22944 assert(SCIPvarIsBinary(var1));
22945 assert(SCIPvarIsBinary(var2));
22946 assert(var1->nlbchginfos + var1->nubchginfos <= 1);
22947 assert(var2->nlbchginfos + var2->nubchginfos <= 1);
22948 assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
22949 assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
22950 assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
22951 assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
22952
22953 if( var1->nlbchginfos == 1 )
22954 bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
22955 else if( var1->nubchginfos == 1 )
22956 bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
22957 else
22958 bdchgidx1 = NULL;
22959
22960 if( var2->nlbchginfos == 1 )
22961 bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
22962 else if( var2->nubchginfos == 1 )
22963 bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
22964 else
22965 bdchgidx2 = NULL;
22966
22967 return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
22968}
22969
22970/** for a given array of variables, this function counts the numbers of variables for each variable and implied type combination */
22972 SCIP_VAR** vars, /**< array of variables to count the types for */
22973 int nvars, /**< number of variables in the array */
22974 int* nbinvars, /**< pointer to store number of binary variables or NULL if not needed */
22975 int* nintvars, /**< pointer to store number of integer variables or NULL if not needed */
22976 int* nbinimplvars, /**< pointer to store number of binary implied integral vars or NULL if not needed */
22977 int* nintimplvars, /**< pointer to store number of integer implied integral vars or NULL if not needed */
22978 int* ncontimplvars, /**< pointer to store number of continuous implied integral vars or NULL if not needed */
22979 int* ncontvars /**< pointer to store number of continuous variables or NULL if not needed */
22980 )
22981{
22982 int binvars = 0;
22983 int binimplvars = 0;
22984 int intvars = 0;
22985 int intimplvars = 0;
22986 int contvars = 0;
22987 int contimplvars = 0;
22988 int v;
22989
22990 assert(vars != NULL || nvars == 0);
22991
22992 for( v = 0; v < nvars; ++v )
22993 {
22995
22996 switch( SCIPvarGetType(vars[v]) )
22997 {
22999 if( implied )
23000 ++binimplvars;
23001 else
23002 ++binvars;
23003 break;
23005 if( implied )
23006 ++intimplvars;
23007 else
23008 ++intvars;
23009 break;
23011 if( implied )
23012 ++contimplvars;
23013 else
23014 ++contvars;
23015 break;
23016 default:
23017 SCIPerrorMessage("unknown variable type\n");
23018 SCIPABORT();
23019 } /*lint !e788*/
23020 }
23021
23022 if( nbinvars != NULL )
23023 *nbinvars = binvars;
23024 if( nintvars != NULL )
23025 *nintvars = intvars;
23026 if( nbinimplvars != NULL )
23027 *nbinimplvars = binimplvars;
23028 if( nintimplvars != NULL )
23029 *nintimplvars = intimplvars;
23030 if( ncontimplvars != NULL )
23031 *ncontimplvars = contimplvars;
23032 if( ncontvars != NULL )
23033 *ncontvars = contvars;
23034}
23035
23036/*
23037 * Hash functions
23038 */
23039
23040/** gets the key (i.e. the name) of the given variable */
23041SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
23042{ /*lint --e{715}*/
23043 SCIP_VAR* var = (SCIP_VAR*)elem;
23044
23045 assert(var != NULL);
23046 return var->name;
23047}
23048
23049
23050
23051
23052/*
23053 * simple functions implemented as defines
23054 */
23055
23056/* In debug mode, the following methods are implemented as function calls to ensure
23057 * type validity.
23058 * In optimized mode, the methods are implemented as defines to improve performance.
23059 * However, we want to have them in the library anyways, so we have to undef the defines.
23060 */
23061
23062#undef SCIPboundchgGetNewbound
23063#undef SCIPboundchgGetLPSolVal
23064#undef SCIPboundchgGetVar
23065#undef SCIPboundchgGetBoundchgtype
23066#undef SCIPboundchgGetBoundtype
23067#undef SCIPboundchgIsRedundant
23068#undef SCIPdomchgGetNBoundchgs
23069#undef SCIPdomchgGetBoundchg
23070#undef SCIPholelistGetLeft
23071#undef SCIPholelistGetRight
23072#undef SCIPholelistGetNext
23073#undef SCIPvarGetName
23074#undef SCIPvarGetNUses
23075#undef SCIPvarGetData
23076#undef SCIPvarSetData
23077#undef SCIPvarSetDelorigData
23078#undef SCIPvarSetTransData
23079#undef SCIPvarSetDeltransData
23080#undef SCIPvarGetStatus
23081#undef SCIPvarIsOriginal
23082#undef SCIPvarIsTransformed
23083#undef SCIPvarIsNegated
23084#undef SCIPvarGetType
23085#undef SCIPvarIsBinary
23086#undef SCIPvarIsIntegral
23087#undef SCIPvarIsImpliedIntegral
23088#undef SCIPvarIsNonimpliedIntegral
23089#undef SCIPvarIsInitial
23090#undef SCIPvarIsRemovable
23091#undef SCIPvarIsDeleted
23092#undef SCIPvarIsDeletable
23093#undef SCIPvarMarkDeletable
23094#undef SCIPvarMarkNotDeletable
23095#undef SCIPvarIsActive
23096#undef SCIPvarGetIndex
23097#undef SCIPvarGetProbindex
23098#undef SCIPvarGetTransVar
23099#undef SCIPvarGetCol
23100#undef SCIPvarIsInLP
23101#undef SCIPvarGetMinAggrCoef
23102#undef SCIPvarGetMaxAggrCoef
23103#undef SCIPvarGetAggrVar
23104#undef SCIPvarGetAggrScalar
23105#undef SCIPvarGetAggrConstant
23106#undef SCIPvarGetMultaggrNVars
23107#undef SCIPvarGetMultaggrVars
23108#undef SCIPvarGetMultaggrScalars
23109#undef SCIPvarGetMultaggrConstant
23110#undef SCIPvarGetNegatedVar
23111#undef SCIPvarGetNegationVar
23112#undef SCIPvarGetNegationConstant
23113#undef SCIPvarGetObj
23114#undef SCIPvarGetLbOriginal
23115#undef SCIPvarGetUbOriginal
23116#undef SCIPvarGetHolelistOriginal
23117#undef SCIPvarGetLbGlobal
23118#undef SCIPvarGetUbGlobal
23119#undef SCIPvarGetHolelistGlobal
23120#undef SCIPvarGetBestBoundGlobal
23121#undef SCIPvarGetWorstBoundGlobal
23122#undef SCIPvarGetLbLocal
23123#undef SCIPvarGetUbLocal
23124#undef SCIPvarGetHolelistLocal
23125#undef SCIPvarGetBestBoundLocal
23126#undef SCIPvarGetWorstBoundLocal
23127#undef SCIPvarGetBestBoundType
23128#undef SCIPvarGetWorstBoundType
23129#undef SCIPvarGetLbLazy
23130#undef SCIPvarGetUbLazy
23131#undef SCIPvarGetBranchFactor
23132#undef SCIPvarGetBranchPriority
23133#undef SCIPvarGetBranchDirection
23134#undef SCIPvarGetNVlbs
23135#undef SCIPvarGetVlbVars
23136#undef SCIPvarGetVlbCoefs
23137#undef SCIPvarGetVlbConstants
23138#undef SCIPvarGetNVubs
23139#undef SCIPvarGetVubVars
23140#undef SCIPvarGetVubCoefs
23141#undef SCIPvarGetVubConstants
23142#undef SCIPvarGetNImpls
23143#undef SCIPvarGetImplVars
23144#undef SCIPvarGetImplTypes
23145#undef SCIPvarGetImplBounds
23146#undef SCIPvarGetImplIds
23147#undef SCIPvarGetNCliques
23148#undef SCIPvarGetCliques
23149#undef SCIPvarGetLPSol
23150#undef SCIPvarGetNLPSol
23151#undef SCIPvarGetBdchgInfoLb
23152#undef SCIPvarGetNBdchgInfosLb
23153#undef SCIPvarGetBdchgInfoUb
23154#undef SCIPvarGetNBdchgInfosUb
23155#undef SCIPvarGetValuehistory
23156#undef SCIPvarGetPseudoSol
23157#undef SCIPvarCatchEvent
23158#undef SCIPvarDropEvent
23159#undef SCIPvarGetVSIDS
23160#undef SCIPvarGetCliqueComponentIdx
23161#undef SCIPvarIsRelaxationOnly
23162#undef SCIPvarMarkRelaxationOnly
23163#undef SCIPbdchgidxGetPos
23164#undef SCIPbdchgidxGetDepth
23165#undef SCIPbdchgidxIsEarlierNonNull
23166#undef SCIPbdchgidxIsEarlier
23167#undef SCIPbdchginfoGetOldbound
23168#undef SCIPbdchginfoGetNewbound
23169#undef SCIPbdchginfoGetVar
23170#undef SCIPbdchginfoGetChgtype
23171#undef SCIPbdchginfoGetBoundtype
23172#undef SCIPbdchginfoGetDepth
23173#undef SCIPbdchginfoGetPos
23174#undef SCIPbdchginfoGetIdx
23175#undef SCIPbdchginfoGetInferVar
23176#undef SCIPbdchginfoGetInferCons
23177#undef SCIPbdchginfoGetInferProp
23178#undef SCIPbdchginfoGetInferInfo
23179#undef SCIPbdchginfoGetInferBoundtype
23180#undef SCIPbdchginfoIsRedundant
23181#undef SCIPbdchginfoHasInferenceReason
23182#undef SCIPbdchginfoIsTighter
23183
23184
23185/** returns the new value of the bound in the bound change data */
23187 SCIP_BOUNDCHG* boundchg /**< bound change data */
23188 )
23189{
23190 assert(boundchg != NULL);
23191
23192 return boundchg->newbound;
23193}
23194
23195/** returns the lp solution value in the branching data of the bound change data */
23197 SCIP_BOUNDCHG* boundchg /**< bound change data */
23198 )
23199{
23200 assert(boundchg != NULL);
23201
23202 return boundchg->data.branchingdata.lpsolval;
23203}
23204
23205/** returns the variable of the bound change in the bound change data */
23207 SCIP_BOUNDCHG* boundchg /**< bound change data */
23208 )
23209{
23210 assert(boundchg != NULL);
23211
23212 return boundchg->var;
23213}
23214
23215/** returns the bound change type of the bound change in the bound change data */
23217 SCIP_BOUNDCHG* boundchg /**< bound change data */
23218 )
23219{
23220 assert(boundchg != NULL);
23221
23222 return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
23223}
23224
23225/** returns the bound type of the bound change in the bound change data */
23227 SCIP_BOUNDCHG* boundchg /**< bound change data */
23228 )
23229{
23230 assert(boundchg != NULL);
23231
23232 return (SCIP_BOUNDTYPE)(boundchg->boundtype);
23233}
23234
23235/** returns whether the bound change is redundant due to a more global bound that is at least as strong */
23237 SCIP_BOUNDCHG* boundchg /**< bound change data */
23238 )
23239{
23240 assert(boundchg != NULL);
23241
23242 return boundchg->redundant;
23243}
23244
23245/** returns the number of bound changes in the domain change data */
23247 SCIP_DOMCHG* domchg /**< domain change data */
23248 )
23249{
23250 return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
23251}
23252
23253/** returns a particular bound change in the domain change data */
23255 SCIP_DOMCHG* domchg, /**< domain change data */
23256 int pos /**< position of the bound change in the domain change data */
23257 )
23258{
23259 assert(domchg != NULL);
23260 assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
23261
23262 return &domchg->domchgbound.boundchgs[pos];
23263}
23264
23265/** returns left bound of open interval in hole */
23267 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23268 )
23269{
23270 assert(holelist != NULL);
23271
23272 return holelist->hole.left;
23273}
23274
23275/** returns right bound of open interval in hole */
23277 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23278 )
23279{
23280 assert(holelist != NULL);
23281
23282 return holelist->hole.right;
23283}
23284
23285/** returns next hole in list */
23287 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23288 )
23289{
23290 assert(holelist != NULL);
23291
23292 return holelist->next;
23293}
23294
23295/** returns the name of the variable
23296 *
23297 * @note to change the name of a variable, use SCIPchgVarName() from scip.h
23298 */
23299const char* SCIPvarGetName(
23300 SCIP_VAR* var /**< problem variable */
23301 )
23302{
23303 assert(var != NULL);
23304
23305 return var->name;
23306}
23307
23308/** gets number of times, the variable is currently captured */
23310 SCIP_VAR* var /**< problem variable */
23311 )
23312{
23313 assert(var != NULL);
23314
23315 return var->nuses;
23316}
23317
23318/** returns the user data of the variable */
23320 SCIP_VAR* var /**< problem variable */
23321 )
23322{
23323 assert(var != NULL);
23324
23325 return var->vardata;
23326}
23327
23328/** sets the user data for the variable */
23330 SCIP_VAR* var, /**< problem variable */
23331 SCIP_VARDATA* vardata /**< user variable data */
23332 )
23333{
23334 assert(var != NULL);
23335
23336 var->vardata = vardata;
23337}
23338
23339/** sets method to free user data for the original variable */
23341 SCIP_VAR* var, /**< problem variable */
23342 SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
23343 )
23344{
23345 assert(var != NULL);
23347
23348 var->vardelorig = vardelorig;
23349}
23350
23351/** sets method to transform user data of the variable */
23353 SCIP_VAR* var, /**< problem variable */
23354 SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
23355 )
23356{
23357 assert(var != NULL);
23359
23360 var->vartrans = vartrans;
23361}
23362
23363/** sets method to free transformed user data for the variable */
23365 SCIP_VAR* var, /**< problem variable */
23366 SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
23367 )
23368{
23369 assert(var != NULL);
23370
23371 var->vardeltrans = vardeltrans;
23372}
23373
23374/** sets method to copy this variable into sub-SCIPs */
23376 SCIP_VAR* var, /**< problem variable */
23377 SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
23378 )
23379{
23380 assert(var != NULL);
23381
23382 var->varcopy = varcopy;
23383}
23384
23385/** sets the initial flag of a variable; only possible for original or loose variables */
23387 SCIP_VAR* var, /**< problem variable */
23388 SCIP_Bool initial /**< initial flag */
23389 )
23390{
23391 assert(var != NULL);
23392
23394 return SCIP_INVALIDCALL;
23395
23396 var->initial = initial;
23397
23398 return SCIP_OKAY;
23399}
23400
23401/** sets the removable flag of a variable; only possible for original or loose variables */
23403 SCIP_VAR* var, /**< problem variable */
23404 SCIP_Bool removable /**< removable flag */
23405 )
23406{
23407 assert(var != NULL);
23408
23410 return SCIP_INVALIDCALL;
23411
23412 var->removable = removable;
23413
23414 return SCIP_OKAY;
23415}
23416
23417/** gets status of variable */
23419 SCIP_VAR* var /**< problem variable */
23420 )
23421{
23422 assert(var != NULL);
23423
23424 return (SCIP_VARSTATUS)(var->varstatus);
23425}
23426
23427/** returns the status of the exact variable data */
23429 SCIP_VAR* var /**< scip variable */
23430 )
23431{
23432 assert(var != NULL);
23433 assert(var->exactdata != NULL);
23434
23435 return var->exactdata->varstatusexact;
23436}
23437
23438/** returns whether the variable has exact variable data */
23440 SCIP_VAR* var /**< scip variable */
23441 )
23442{
23443 assert(var != NULL);
23444
23445 return (var->exactdata != NULL);
23446}
23447
23448/** returns whether the variable belongs to the original problem */
23450 SCIP_VAR* var /**< problem variable */
23451 )
23452{
23453 assert(var != NULL);
23455
23458 && SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL));
23459}
23460
23461/** returns whether the variable belongs to the transformed problem */
23463 SCIP_VAR* var /**< problem variable */
23464 )
23465{
23466 assert(var != NULL);
23468
23471 || SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_ORIGINAL));
23472}
23473
23474/** returns whether the variable was created by negation of a different variable */
23476 SCIP_VAR* var /**< problem variable */
23477 )
23478{
23479 assert(var != NULL);
23480
23482}
23483
23484/** gets type of variable */
23486 SCIP_VAR* var /**< problem variable */
23487 )
23488{
23489 assert(var != NULL);
23490
23491 return (SCIP_VARTYPE)(var->vartype);
23492}
23493
23494/** gets the implied integral type of the variable */
23496 SCIP_VAR* var /**< problem variable */
23497 )
23498{
23499 assert(var != NULL);
23500
23501 return (SCIP_IMPLINTTYPE)(var->varimpltype);
23502}
23503
23504/** returns TRUE if the variable is of binary type; this is the case if:
23505 * (1) variable type is binary
23506 * (2) variable type is integer or implicit integer and
23507 * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
23508 * (ii) the lazy upper bound or the global upper bound is less than or equal to one
23509 */
23511 SCIP_VAR* var /**< problem variable */
23512 )
23513{
23514 assert(var != NULL);
23515
23518 && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
23519}
23520
23521/** returns whether variable is of integral type (binary, integer, or implied integral of any type) */
23523 SCIP_VAR* var /**< problem variable */
23524 )
23525{
23527}
23528
23529/** returns whether variable is implied integral (weakly or strongly) */
23531 SCIP_VAR* var /**< problem variable */
23532 )
23533{
23535}
23536
23537/** returns TRUE if the variable is integral, but not implied integral. */
23539 SCIP_VAR* var /**< problem variable */
23540 )
23541{
23543}
23544
23545/** returns whether variable's column should be present in the initial root LP */
23547 SCIP_VAR* var /**< problem variable */
23548 )
23549{
23550 assert(var != NULL);
23551
23552 return var->initial;
23553}
23554
23555/** returns whether variable's column is removable from the LP (due to aging or cleanup) */
23557 SCIP_VAR* var /**< problem variable */
23558 )
23559{
23560 assert(var != NULL);
23561
23562 return var->removable;
23563}
23564
23565/** returns whether the variable was deleted from the problem */
23567 SCIP_VAR* var /**< problem variable */
23568 )
23569{
23570 assert(var != NULL);
23571
23572 return var->deleted;
23573}
23574
23575/** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
23576 * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
23577 */
23579 SCIP_VAR* var /**< problem variable */
23580 )
23581{
23582 assert(var != NULL);
23583 assert(var->probindex == -1);
23584
23585 var->deletable = TRUE;
23586}
23587
23588/** marks the variable to be not deletable from the problem */
23590 SCIP_VAR* var
23591 )
23592{
23593 assert(var != NULL);
23594
23595 var->deletable = FALSE;
23596}
23597
23598/** marks variable to be deleted from global structures (cliques etc.) when cleaning up
23599 *
23600 * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
23601 */
23603 SCIP_VAR* var /**< problem variable */
23604 )
23605{
23606 assert(var != NULL);
23607
23608 var->delglobalstructs = TRUE;
23609}
23610
23611/** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
23613 SCIP_VAR* var /**< problem variable */
23614 )
23615{
23616 assert(var != NULL);
23617
23618 return var->delglobalstructs;
23619}
23620
23621/** returns whether a variable has been introduced to define a relaxation
23622 *
23623 * These variables are only valid for the current SCIP solve round,
23624 * they are not contained in any (checked) constraints, but may be used
23625 * in cutting planes, for example.
23626 * Relaxation-only variables are not copied by SCIPcopyVars and cuts
23627 * that contain these variables are not added as linear constraints when
23628 * restarting or transferring information from a copied SCIP to a SCIP.
23629 * Also conflicts with relaxation-only variables are not generated at
23630 * the moment.
23631 */
23633 SCIP_VAR* var /**< problem variable */
23634 )
23635{
23636 assert(var != NULL);
23637
23638 return var->relaxationonly;
23639}
23640
23641/** marks that this variable has only been introduced to define a relaxation
23642 *
23643 * The variable must not have a coefficient in the objective and must be deletable.
23644 * If it is not marked deletable, it will be marked as deletable, which is only possible
23645 * before the variable is added to a problem.
23646 *
23647 * @see SCIPvarIsRelaxationOnly
23648 * @see SCIPvarMarkDeletable
23649 */
23651 SCIP_VAR* var /**< problem variable */
23652 )
23653{
23654 assert(var != NULL);
23655 assert(SCIPvarGetObj(var) == 0.0);
23656
23657 if( !SCIPvarIsDeletable(var) )
23659
23660 var->relaxationonly = TRUE;
23661}
23662
23663/** returns whether variable is allowed to be deleted completely from the problem */
23665 SCIP_VAR* var
23666 )
23667{
23668 assert(var != NULL);
23669
23670 return var->deletable;
23671}
23672
23673/** returns whether variable is an active (neither fixed nor aggregated) variable */
23675 SCIP_VAR* var /**< problem variable */
23676 )
23677{
23678 assert(var != NULL);
23679
23680 return (var->probindex >= 0);
23681}
23682
23683/** gets unique index of variable */
23685 SCIP_VAR* var /**< problem variable */
23686 )
23687{
23688 assert(var != NULL);
23689
23690 return var->index;
23691}
23692
23693/** gets position of variable in problem, or -1 if variable is not active */
23695 SCIP_VAR* var /**< problem variable */
23696 )
23697{
23698 assert(var != NULL);
23699
23700 return var->probindex;
23701}
23702
23703/** gets transformed variable of ORIGINAL variable */
23705 SCIP_VAR* var /**< problem variable */
23706 )
23707{
23708 assert(var != NULL);
23710
23711 return var->data.original.transvar;
23712}
23713
23714/** gets column of COLUMN variable */
23716 SCIP_VAR* var /**< problem variable */
23717 )
23718{
23719 assert(var != NULL);
23721
23722 return var->data.col;
23723}
23724
23725/** gets exact column of COLUMN variable */
23727 SCIP_VAR* var /**< problem variable */
23728 )
23729{
23730 assert(var != NULL);
23731 assert(var->exactdata != NULL);
23733
23734 return var->exactdata->colexact;
23735}
23736
23737/** returns whether the variable is a COLUMN variable that is member of the current LP */
23739 SCIP_VAR* var /**< problem variable */
23740 )
23741{
23742 assert(var != NULL);
23743
23744 return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
23745}
23746
23747/** gets minimal absolute coefficient of a loose variable in (multi)aggregations of other variables */
23749 SCIP_VAR* var /**< problem variable */
23750 )
23751{
23753
23754 return var->data.loose.minaggrcoef;
23755}
23756
23757/** gets lower bound on absolute coefficient of a loose variable in (multi)aggregations of other variables */
23759 SCIP_VAR* var /**< problem variable */
23760 )
23761{
23763
23764 return var->data.loose.maxaggrcoef;
23765}
23766
23767/** gets upper bound on absolute coefficient of a loose variable in (multi)aggregations of other variables */
23769 SCIP_VAR* var /**< problem variable */
23770 )
23771{
23772 assert(var != NULL);
23774 assert(!var->donotaggr);
23775
23776 return var->data.aggregate.var;
23777}
23778
23779/** gets aggregation scalar a of an aggregated variable x = a*y + c */
23781 SCIP_VAR* var /**< problem variable */
23782 )
23783{
23784 assert(var != NULL);
23786 assert(!var->donotaggr);
23787
23788 return var->data.aggregate.scalar;
23789}
23790
23791/** gets aggregation scalar a of an aggregated variable x = a*y + c */
23793 SCIP_VAR* var /**< problem variable */
23794 )
23795{
23796 assert(var != NULL);
23798
23799 return var->exactdata->aggregate.scalar;
23800}
23801
23802/** gets aggregation constant c of an aggregated variable x = a*y + c */
23804 SCIP_VAR* var /**< problem variable */
23805 )
23806{
23807 assert(var != NULL);
23809 assert(!var->donotaggr);
23810
23811 return var->data.aggregate.constant;
23812}
23813
23814/** gets aggregation constant c of an aggregated variable x = a*y + c */
23816 SCIP_VAR* var /**< problem variable */
23817 )
23818{
23819 assert(var != NULL);
23821
23822 return var->exactdata->aggregate.constant;
23823}
23824
23825/** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23827 SCIP_VAR* var /**< problem variable */
23828 )
23829{
23830 assert(var != NULL);
23832 assert(!var->donotmultaggr);
23833
23834 return var->data.multaggr.nvars;
23835}
23836
23837/** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23839 SCIP_VAR* var /**< problem variable */
23840 )
23841{
23842 assert(var != NULL);
23844 assert(!var->donotmultaggr);
23845
23846 return var->data.multaggr.vars;
23847}
23848
23849/** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23851 SCIP_VAR* var /**< problem variable */
23852 )
23853{
23854 assert(var != NULL);
23856 assert(!var->donotmultaggr);
23857
23858 return var->data.multaggr.scalars;
23859}
23860
23861/** gets vector of exact aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23863 SCIP_VAR* var /**< problem variable */
23864 )
23865{
23866 assert(var != NULL);
23868 assert(!var->donotmultaggr);
23869 assert(var->exactdata != NULL);
23870
23871 return var->exactdata->multaggr.scalars;
23872}
23873
23874/** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23876 SCIP_VAR* var /**< problem variable */
23877 )
23878{
23879 assert(var != NULL);
23881 assert(!var->donotmultaggr);
23882
23883 return var->data.multaggr.constant;
23884}
23885
23886/** gets exact aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23888 SCIP_VAR* var /**< problem variable */
23889 )
23890{
23891 assert(var != NULL);
23893 assert(!var->donotmultaggr);
23894 assert(var->exactdata != NULL);
23895
23896 return var->exactdata->multaggr.constant;
23897}
23898
23899/** gets the negation of the given variable; may return NULL, if no negation is existing yet */
23901 SCIP_VAR* var /**< negated problem variable */
23902 )
23903{
23904 assert(var != NULL);
23905
23906 return var->negatedvar;
23907}
23908
23909/** gets the negation variable x of a negated variable x' = offset - x */
23911 SCIP_VAR* var /**< negated problem variable */
23912 )
23913{
23914 assert(var != NULL);
23916
23917 return var->negatedvar;
23918}
23919
23920/** gets the negation offset of a negated variable x' = offset - x */
23922 SCIP_VAR* var /**< negated problem variable */
23923 )
23924{
23925 assert(var != NULL);
23927
23928 return var->data.negate.constant;
23929}
23930
23931/** gets objective function value of variable */
23933 SCIP_VAR* var /**< problem variable */
23934 )
23935{
23936 assert(var != NULL);
23937
23938 return var->obj;
23939}
23940
23941/** gets exact objective function value of variable */
23943 SCIP_VAR* var /**< problem variable */
23944 )
23945{
23946 assert(var != NULL);
23947 assert(var->exactdata != NULL);
23948
23949 return var->exactdata->obj;
23950}
23951
23952/** gets exact objective function value of variable */
23954 SCIP_VAR* var /**< problem variable */
23955 )
23956{
23957 assert(var != NULL);
23958 assert(var->exactdata != NULL);
23959
23960 return var->exactdata->objinterval;
23961}
23962
23963/** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
23965 SCIP_VAR* var /**< problem variable */
23966 )
23967{
23968 assert(var != NULL);
23969
23970 return var->unchangedobj;
23971}
23972
23973/** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
23974 * e.g. obj(x) = 1 this method returns for ~x the value -1
23975 */
23977 SCIP_VAR* var, /**< problem variable */
23978 SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
23979 )
23980{
23981 SCIP_VAR* probvar = var;
23982 SCIP_Real mult = 1.0;
23983
23984 assert(probvar != NULL);
23985 assert(aggrobj != NULL);
23986
23987 while( probvar != NULL )
23988 {
23989 switch( SCIPvarGetStatus(probvar) )
23990 {
23994 (*aggrobj) = mult * SCIPvarGetObj(probvar);
23995 return SCIP_OKAY;
23996
23998 assert(SCIPvarGetObj(probvar) == 0.0);
23999 (*aggrobj) = 0.0;
24000 return SCIP_OKAY;
24001
24003 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
24004 if ( probvar->data.multaggr.nvars == 1 )
24005 {
24006 assert( probvar->data.multaggr.vars != NULL );
24007 assert( probvar->data.multaggr.scalars != NULL );
24008 assert( probvar->data.multaggr.vars[0] != NULL );
24009 mult *= probvar->data.multaggr.scalars[0];
24010 probvar = probvar->data.multaggr.vars[0];
24011 break;
24012 }
24013 else
24014 {
24015 SCIP_Real tmpobj;
24016 int v;
24017
24018 (*aggrobj) = 0.0;
24019
24020 for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
24021 {
24022 SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
24023 (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
24024 }
24025 return SCIP_OKAY;
24026 }
24027
24028 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
24029 assert(probvar->data.aggregate.var != NULL);
24030 mult *= probvar->data.aggregate.scalar;
24031 probvar = probvar->data.aggregate.var;
24032 break;
24033
24034 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
24035 assert(probvar->negatedvar != NULL);
24037 assert(probvar->negatedvar->negatedvar == probvar);
24038 mult *= -1.0;
24039 probvar = probvar->negatedvar;
24040 break;
24041
24042 default:
24043 SCIPABORT();
24044 return SCIP_INVALIDDATA; /*lint !e527*/
24045 }
24046 }
24047
24048 return SCIP_INVALIDDATA;
24049}
24050
24051/** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
24053 SCIP_VAR* var /**< original problem variable */
24054 )
24055{
24056 assert(var != NULL);
24058
24060 return var->data.original.origdom.lb;
24061 else
24062 {
24064 assert(var->negatedvar != NULL);
24066
24067 return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
24068 }
24069}
24070
24071/** gets exact original lower bound of original problem variable (i.e. the bound set in problem creation) */
24073 SCIP_VAR* var /**< original problem variable */
24074 )
24075{
24076 assert(var != NULL);
24078 assert(var->exactdata != NULL);
24079
24081 return var->exactdata->origdom.lb;
24082 else
24083 {
24085 assert(var->negatedvar != NULL);
24087
24088 SCIPerrorMessage("negated var not implemented yet for rational data \n");
24089 SCIPABORT();
24090 return NULL;
24091 }
24092}
24093
24094/** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
24096 SCIP_VAR* var /**< original problem variable */
24097 )
24098{
24099 assert(var != NULL);
24101
24103 return var->data.original.origdom.ub;
24104 else
24105 {
24107 assert(var->negatedvar != NULL);
24109
24110 return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
24111 }
24112}
24113
24114/** gets exact original upper bound of original problem variable (i.e. the bound set in problem creation) */
24116 SCIP_VAR* var /**< original problem variable */
24117 )
24118{
24119 assert(var != NULL);
24121 assert(var->exactdata != NULL);
24122
24124 return var->exactdata->origdom.ub;
24125 else
24126 {
24128 assert(var->negatedvar != NULL);
24130
24131 SCIPerrorMessage("negated var not implemented yet for rational data \n");
24132 SCIPABORT();
24133 return NULL;
24134 }
24135}
24136
24137/** gets the original hole list of an original variable */
24139 SCIP_VAR* var /**< problem variable */
24140 )
24141{
24142 assert(var != NULL);
24144
24146 return var->data.original.origdom.holelist;
24147
24148 return NULL;
24149}
24150
24151/** gets global lower bound of variable */
24153 SCIP_VAR* var /**< problem variable */
24154 )
24155{
24156 assert(var != NULL);
24157
24158 return var->glbdom.lb;
24159}
24160
24161/** gets exact global lower bound of variable */
24163 SCIP_VAR* var /**< problem variable */
24164 )
24165{
24166 assert(var != NULL);
24167 assert(var->exactdata != NULL);
24168 assert(var->exactdata->glbdom.lb != NULL);
24169
24170 return var->exactdata->glbdom.lb;
24171}
24172
24173/** gets global upper bound of variable */
24175 SCIP_VAR* var /**< problem variable */
24176 )
24177{
24178 assert(var != NULL);
24179
24180 return var->glbdom.ub;
24181}
24182
24183/** gets exact global upper bound of variable */
24185 SCIP_VAR* var /**< problem variable */
24186 )
24187{
24188 assert(var != NULL);
24189 assert(var->exactdata != NULL);
24190 assert(var->exactdata->glbdom.ub != NULL);
24191
24192 return var->exactdata->glbdom.ub;
24193}
24194
24195/** gets the global hole list of an active variable */
24197 SCIP_VAR* var /**< problem variable */
24198 )
24199{
24200 assert(var != NULL);
24201
24202 return var->glbdom.holelist;
24203}
24204
24205/** gets best global bound of variable with respect to the objective function */
24207 SCIP_VAR* var /**< problem variable */
24208 )
24209{
24210 assert(var != NULL);
24211
24212 if( var->obj >= 0.0 )
24213 return var->glbdom.lb;
24214 else
24215 return var->glbdom.ub;
24216}
24217
24218/** gets best exact global bound of variable with respect to the objective function */
24220 SCIP_VAR* var /**< problem variable */
24221 )
24222{
24223 assert(var != NULL);
24224 assert(var->exactdata != NULL);
24225 assert(var->exactdata->glbdom.lb != NULL);
24226 assert(var->exactdata->glbdom.ub != NULL);
24227 assert(var->exactdata->obj != NULL);
24228
24229 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24230 return var->exactdata->glbdom.lb;
24231 else
24232 return var->exactdata->glbdom.ub;
24233}
24234
24235/** gets worst global bound of variable with respect to the objective function */
24237 SCIP_VAR* var /**< problem variable */
24238 )
24239{
24240 assert(var != NULL);
24241
24242 if( var->obj >= 0.0 )
24243 return var->glbdom.ub;
24244 else
24245 return var->glbdom.lb;
24246}
24247
24248/** gets worst exact global bound of variable with respect to the objective function */
24250 SCIP_VAR* var /**< problem variable */
24251 )
24252{
24253 assert(var != NULL);
24254 assert(var->exactdata != NULL);
24255 assert(var->exactdata->glbdom.lb != NULL);
24256 assert(var->exactdata->glbdom.ub != NULL);
24257 assert(var->exactdata->obj != NULL);
24258
24259 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24260 return var->exactdata->glbdom.ub;
24261 else
24262 return var->exactdata->glbdom.lb;
24263}
24264
24265/** gets current lower bound of variable */
24267 SCIP_VAR* var /**< problem variable */
24268 )
24269{
24270 assert(var != NULL);
24271
24272 return var->locdom.lb;
24273}
24274
24275/** gets current exact lower bound of variable */
24277 SCIP_VAR* var /**< problem variable */
24278 )
24279{
24280 assert(var != NULL);
24281 assert(var->exactdata != NULL);
24282 assert(var->exactdata->locdom.lb != NULL);
24283
24284 return var->exactdata->locdom.lb;
24285}
24286
24288 SCIP_VAR* var, /**< problem variable */
24289 SCIP_RATIONAL* output /**< output rational */
24290 )
24291{
24292 assert(var != NULL);
24293 assert(var->exactdata != NULL);
24294 assert(var->exactdata->locdom.lb != NULL);
24295 SCIPrationalSetFraction(output, (SCIP_Longint) (floor(var->locdom.lb)), 1LL);
24296 SCIPrationalMax(output, output, var->exactdata->locdom.lb);
24297}
24298
24299/** gets current upper bound of variable */
24301 SCIP_VAR* var /**< problem variable */
24302 )
24303{
24304 assert(var != NULL);
24305
24306 return var->locdom.ub;
24307}
24308
24309/** gets current exact upper bound of variable */
24311 SCIP_VAR* var /**< problem variable */
24312 )
24313{
24314 assert(var != NULL);
24315 assert(var->exactdata != NULL);
24316 assert(var->exactdata->locdom.ub != NULL);
24317
24318 return var->exactdata->locdom.ub;
24319}
24320
24322 SCIP_VAR* var, /**< problem variable */
24323 SCIP_RATIONAL* output /**< output rational */
24324 )
24325{
24326 assert(var != NULL);
24327 assert(var->exactdata != NULL);
24328 assert(var->exactdata->locdom.ub != NULL);
24329 SCIPrationalSetFraction(output, (SCIP_Longint) (ceil(var->locdom.ub)), 1LL);
24330 SCIPrationalMin(output, output, var->exactdata->locdom.ub);
24331}
24332
24333/** gets the current hole list of an active variable */
24335 SCIP_VAR* var /**< problem variable */
24336 )
24337{
24338 assert(var != NULL);
24339
24340 return var->locdom.holelist;
24341}
24342
24343/** gets best local bound of variable with respect to the objective function */
24345 SCIP_VAR* var /**< problem variable */
24346 )
24347{
24348 assert(var != NULL);
24349
24350 if( var->obj >= 0.0 )
24351 return var->locdom.lb;
24352 else
24353 return var->locdom.ub;
24354}
24355
24356/** gets best exact local bound of variable with respect to the objective function */
24358 SCIP_VAR* var /**< problem variable */
24359 )
24360{
24361 assert(var != NULL);
24362 assert(var->exactdata != NULL);
24363 assert(var->exactdata->locdom.lb != NULL);
24364 assert(var->exactdata->locdom.ub != NULL);
24365 assert(var->exactdata->obj != NULL);
24366
24367 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24368 return var->exactdata->locdom.lb;
24369 else
24370 return var->exactdata->locdom.ub;
24371}
24372
24373/** gets worst local bound of variable with respect to the objective function */
24375 SCIP_VAR* var /**< problem variable */
24376 )
24377{
24378 assert(var != NULL);
24379
24380 if( var->obj >= 0.0 )
24381 return var->locdom.ub;
24382 else
24383 return var->locdom.lb;
24384}
24385
24386/** gets worst exact local bound of variable with respect to the objective function */
24388 SCIP_VAR* var /**< problem variable */
24389 )
24390{
24391 assert(var != NULL);
24392 assert(var->exactdata != NULL);
24393 assert(var->exactdata->locdom.lb != NULL);
24394 assert(var->exactdata->locdom.ub != NULL);
24395 assert(var->exactdata->obj != NULL);
24396
24397 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24398 return var->exactdata->locdom.ub;
24399 else
24400 return var->exactdata->locdom.lb;
24401}
24402
24403/** gets type (lower or upper) of best bound of variable with respect to the objective function */
24405 SCIP_VAR* var /**< problem variable */
24406 )
24407{
24408 assert(var != NULL);
24409
24410 if( var->obj >= 0.0 )
24411 return SCIP_BOUNDTYPE_LOWER;
24412 else
24413 return SCIP_BOUNDTYPE_UPPER;
24414}
24415
24416/** gets type (lower or upper) of best bound of variable with respect to the objective function */
24418 SCIP_VAR* var /**< problem variable */
24419 )
24420{
24421 assert(var != NULL);
24422 assert(var->exactdata != NULL);
24423 assert(var->exactdata->obj != NULL);
24424
24425 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24426 return SCIP_BOUNDTYPE_LOWER;
24427 else
24428 return SCIP_BOUNDTYPE_UPPER;
24429}
24430
24431/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
24433 SCIP_VAR* var /**< problem variable */
24434 )
24435{
24436 assert(var != NULL);
24437
24438 if( var->obj >= 0.0 )
24439 return SCIP_BOUNDTYPE_UPPER;
24440 else
24441 return SCIP_BOUNDTYPE_LOWER;
24442}
24443
24444/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
24446 SCIP_VAR* var /**< problem variable */
24447 )
24448{
24449 assert(var != NULL);
24450 assert(var->exactdata != NULL);
24451 assert(var->exactdata->obj != NULL);
24452
24453 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24454 return SCIP_BOUNDTYPE_UPPER;
24455 else
24456 return SCIP_BOUNDTYPE_LOWER;
24457}
24458
24459/** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
24461 SCIP_VAR* var /**< problem variable */
24462 )
24463{
24464 assert(var != NULL);
24465
24466 return var->lazylb;
24467}
24468
24469/** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
24471 SCIP_VAR* var /**< problem variable */
24472 )
24473{
24474 assert(var != NULL);
24475
24476 return var->lazyub;
24477}
24478
24479/** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
24480 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
24481 */
24483 SCIP_VAR* var /**< problem variable */
24484 )
24485{
24486 assert(var != NULL);
24487
24488 return var->branchfactor;
24489}
24490
24491/** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
24492 * with lower priority
24493 */
24495 SCIP_VAR* var /**< problem variable */
24496 )
24497{
24498 assert(var != NULL);
24499
24500 return var->branchpriority;
24501}
24502
24503/** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
24505 SCIP_VAR* var /**< problem variable */
24506 )
24507{
24508 assert(var != NULL);
24509
24510 return (SCIP_BRANCHDIR)var->branchdirection;
24511}
24512
24513/** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
24515 SCIP_VAR* var /**< problem variable */
24516 )
24517{
24518 assert(var != NULL);
24519
24520 return SCIPvboundsGetNVbds(var->vlbs);
24521}
24522
24523/** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
24524 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
24525 */
24527 SCIP_VAR* var /**< problem variable */
24528 )
24529{
24530 assert(var != NULL);
24531
24532 return SCIPvboundsGetVars(var->vlbs);
24533}
24534
24535/** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
24537 SCIP_VAR* var /**< problem variable */
24538 )
24539{
24540 assert(var != NULL);
24541
24542 return SCIPvboundsGetCoefs(var->vlbs);
24543}
24544
24545/** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
24547 SCIP_VAR* var /**< problem variable */
24548 )
24549{
24550 assert(var != NULL);
24551
24552 return SCIPvboundsGetConstants(var->vlbs);
24553}
24554
24555/** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
24557 SCIP_VAR* var /**< problem variable */
24558 )
24559{
24560 assert(var != NULL);
24561
24562 return SCIPvboundsGetNVbds(var->vubs);
24563}
24564
24565/** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
24566 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
24567 */
24569 SCIP_VAR* var /**< problem variable */
24570 )
24571{
24572 assert(var != NULL);
24573
24574 return SCIPvboundsGetVars(var->vubs);
24575}
24576
24577/** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
24579 SCIP_VAR* var /**< problem variable */
24580 )
24581{
24582 assert(var != NULL);
24583
24584 return SCIPvboundsGetCoefs(var->vubs);
24585}
24586
24587/** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
24589 SCIP_VAR* var /**< problem variable */
24590 )
24591{
24592 assert(var != NULL);
24593
24594 return SCIPvboundsGetConstants(var->vubs);
24595}
24596
24597/** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
24598 * there are no implications for nonbinary variable x
24599 */
24601 SCIP_VAR* var, /**< active problem variable */
24602 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24603 )
24604{
24605 assert(var != NULL);
24607
24608 return SCIPimplicsGetNImpls(var->implics, varfixing);
24609}
24610
24611/** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
24612 * problem variable x, there are no implications for nonbinary variable x;
24613 * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
24614 * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
24615 * (see SCIPvarGetIndex())
24616 */
24618 SCIP_VAR* var, /**< active problem variable */
24619 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24620 )
24621{
24622 assert(var != NULL);
24624
24625 return SCIPimplicsGetVars(var->implics, varfixing);
24626}
24627
24628/** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
24629 * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
24630 * there are no implications for nonbinary variable x
24631 */
24633 SCIP_VAR* var, /**< active problem variable */
24634 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24635 )
24636{
24637 assert(var != NULL);
24639
24640 return SCIPimplicsGetTypes(var->implics, varfixing);
24641}
24642
24643/** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
24644 * variable x, there are no implications for nonbinary variable x
24645 */
24647 SCIP_VAR* var, /**< active problem variable */
24648 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24649 )
24650{
24651 assert(var != NULL);
24653
24654 return SCIPimplicsGetBounds(var->implics, varfixing);
24655}
24656
24657/** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
24658 * there are no implications for nonbinary variable x.
24659 * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
24660 * its id is negative, otherwise it is nonnegative.
24661 */
24663 SCIP_VAR* var, /**< active problem variable */
24664 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24665 )
24666{
24667 assert(var != NULL);
24669
24670 return SCIPimplicsGetIds(var->implics, varfixing);
24671}
24672
24673/** gets number of cliques, the active variable is contained in */
24675 SCIP_VAR* var, /**< active problem variable */
24676 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
24677 )
24678{
24679 assert(var != NULL);
24680
24681 return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
24682}
24683
24684/** gets array of cliques, the active variable is contained in */
24686 SCIP_VAR* var, /**< active problem variable */
24687 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
24688 )
24689{
24690 assert(var != NULL);
24691
24692 return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
24693}
24694
24695/** gets primal LP solution value of variable */
24697 SCIP_VAR* var /**< problem variable */
24698 )
24699{
24700 assert(var != NULL);
24701
24703 return SCIPcolGetPrimsol(var->data.col);
24704 else
24705 return SCIPvarGetLPSol_rec(var);
24706}
24707
24708/** gets exact primal LP solution value of variable */
24710 SCIP_VAR* var, /**< problem variable */
24711 SCIP_RATIONAL* res /**< resulting value */
24712 )
24713{
24714 assert(var != NULL);
24715
24717 SCIPrationalSetRational(res, SCIPcolExactGetPrimsol(var->exactdata->colexact));
24718 else
24720}
24721
24722/** gets primal NLP solution value of variable */
24724 SCIP_VAR* var /**< problem variable */
24725 )
24726{
24727 assert(var != NULL);
24728
24730 return var->nlpsol;
24731 else
24732 return SCIPvarGetNLPSol_rec(var);
24733}
24734
24735/** return lower bound change info at requested position */
24737 SCIP_VAR* var, /**< problem variable */
24738 int pos /**< requested position */
24739 )
24740{
24741 assert(pos >= 0);
24742 assert(pos < var->nlbchginfos);
24743
24744 return &var->lbchginfos[pos];
24745}
24746
24747/** gets the number of lower bound change info array */
24749 SCIP_VAR* var /**< problem variable */
24750 )
24751{
24752 return var->nlbchginfos;
24753}
24754
24755/** return upper bound change info at requested position */
24757 SCIP_VAR* var, /**< problem variable */
24758 int pos /**< requested position */
24759 )
24760{
24761 assert(pos >= 0);
24762 assert(pos < var->nubchginfos);
24763
24764 return &var->ubchginfos[pos];
24765}
24766
24767/** gets the number upper bound change info array */
24769 SCIP_VAR* var /**< problem variable */
24770 )
24771{
24772 assert(var != NULL);
24773
24774 return var->nubchginfos;
24775}
24776
24777/** returns the value based history for the variable */
24779 SCIP_VAR* var /**< problem variable */
24780 )
24781{
24782 assert(var != NULL);
24783
24784 return var->valuehistory;
24785}
24786
24787/** gets pseudo solution value of variable */
24789 SCIP_VAR* var /**< problem variable */
24790 )
24791{
24792 assert(var != NULL);
24793
24796 else
24798}
24799
24800/** gets exact pseudo solution value of variable */
24802 SCIP_VAR* var /**< problem variable */
24803 )
24804{
24805 assert(var != NULL);
24806
24809 else
24811}
24812
24813/** returns the variable's VSIDS score */
24815 SCIP_VAR* var, /**< problem variable */
24816 SCIP_STAT* stat, /**< problem statistics */
24817 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
24818 )
24819{
24820 assert(var != NULL);
24821
24823 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
24824 else
24825 return SCIPvarGetVSIDS_rec(var, stat, dir);
24826}
24827
24828/** includes event handler with given data in variable's event filter */
24830 SCIP_VAR* var, /**< problem variable */
24831 BMS_BLKMEM* blkmem, /**< block memory */
24832 SCIP_SET* set, /**< global SCIP settings */
24833 SCIP_EVENTTYPE eventtype, /**< event type to catch */
24834 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
24835 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
24836 int* filterpos /**< pointer to store position of event filter entry, or NULL */
24837 )
24838{
24839 assert(var != NULL);
24840 assert(set != NULL);
24841 assert(var->scip == set->scip);
24842 assert(var->eventfilter != NULL);
24843 assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
24844 assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
24846
24847 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
24848 eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
24849
24850 SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
24851
24852 return SCIP_OKAY;
24853}
24854
24855/** deletes event handler with given data from variable's event filter */
24857 SCIP_VAR* var, /**< problem variable */
24858 BMS_BLKMEM* blkmem, /**< block memory */
24859 SCIP_SET* set, /**< global SCIP settings */
24860 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
24861 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
24862 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
24863 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
24864 )
24865{
24866 assert(var != NULL);
24867 assert(set != NULL);
24868 assert(var->scip == set->scip);
24869 assert(var->eventfilter != NULL);
24871
24872 SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
24873 (void*)eventdata);
24874
24875 SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
24876
24877 return SCIP_OKAY;
24878}
24879
24880/** returns the position of the bound change index */
24882 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
24883 )
24884{
24885 assert(bdchgidx != NULL);
24886
24887 return bdchgidx->pos;
24888}
24889
24890/** returns the depth of the bound change index */
24892 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
24893 )
24894{
24895 assert(bdchgidx != NULL);
24896
24897 return bdchgidx->depth;
24898}
24899
24900/** returns whether first bound change index belongs to an earlier applied bound change than second one */
24902 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
24903 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
24904 )
24905{
24906 assert(bdchgidx1 != NULL);
24907 assert(bdchgidx1->depth >= -2);
24908 assert(bdchgidx1->pos >= 0);
24909 assert(bdchgidx2 != NULL);
24910 assert(bdchgidx2->depth >= -2);
24911 assert(bdchgidx2->pos >= 0);
24912
24913 return (bdchgidx1->depth < bdchgidx2->depth)
24914 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
24915}
24916
24917/** returns whether first bound change index belongs to an earlier applied bound change than second one;
24918 * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
24919 * last bound change was applied to the current node
24920 */
24922 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
24923 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
24924 )
24925{
24926 assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
24927 assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
24928 assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
24929 assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
24930
24931 if( bdchgidx1 == NULL )
24932 return FALSE;
24933 else if( bdchgidx2 == NULL )
24934 return TRUE;
24935 else
24936 return (bdchgidx1->depth < bdchgidx2->depth)
24937 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
24938}
24939
24940/** returns old bound that was overwritten for given bound change information */
24942 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24943 )
24944{
24945 assert(bdchginfo != NULL);
24946
24947 return bdchginfo->oldbound;
24948}
24949
24950/** returns new bound installed for given bound change information */
24952 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24953 )
24954{
24955 assert(bdchginfo != NULL);
24956
24957 return bdchginfo->newbound;
24958}
24959
24960/** returns variable that belongs to the given bound change information */
24962 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24963 )
24964{
24965 assert(bdchginfo != NULL);
24966
24967 return bdchginfo->var;
24968}
24969
24970/** returns whether the bound change information belongs to a branching decision or a deduction */
24972 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24973 )
24974{
24975 assert(bdchginfo != NULL);
24976
24977 return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
24978}
24979
24980/** returns whether the bound change information belongs to a lower or upper bound change */
24982 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24983 )
24984{
24985 assert(bdchginfo != NULL);
24986
24987 return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
24988}
24989
24990/** returns depth level of given bound change information */
24992 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24993 )
24994{
24995 assert(bdchginfo != NULL);
24996
24997 return bdchginfo->bdchgidx.depth;
24998}
24999
25000/** returns bound change position in its depth level of given bound change information */
25002 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25003 )
25004{
25005 assert(bdchginfo != NULL);
25006
25007 return bdchginfo->bdchgidx.pos;
25008}
25009
25010/** returns bound change index of given bound change information */
25012 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25013 )
25014{
25015 assert(bdchginfo != NULL);
25016
25017 return &bdchginfo->bdchgidx;
25018}
25019
25020/** returns inference variable of given bound change information */
25022 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25023 )
25024{
25025 assert(bdchginfo != NULL);
25028
25029 return bdchginfo->inferencedata.var;
25030}
25031
25032/** returns inference constraint of given bound change information */
25034 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25035 )
25036{
25037 assert(bdchginfo != NULL);
25039 assert(bdchginfo->inferencedata.reason.cons != NULL);
25040
25041 return bdchginfo->inferencedata.reason.cons;
25042}
25043
25044/** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
25046 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25047 )
25048{
25049 assert(bdchginfo != NULL);
25051
25052 return bdchginfo->inferencedata.reason.prop;
25053}
25054
25055/** returns inference user information of given bound change information */
25057 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25058 )
25059{
25060 assert(bdchginfo != NULL);
25063
25064 return bdchginfo->inferencedata.info;
25065}
25066
25067/** returns inference bound of inference variable of given bound change information */
25069 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25070 )
25071{
25072 assert(bdchginfo != NULL);
25075
25076 return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
25077}
25078
25079/** returns the relaxed bound change type */
25081 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
25082 )
25083{
25084 return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
25085}
25086
25087
25088/** returns whether the bound change information belongs to a redundant bound change */
25090 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25091 )
25092{
25093 assert(bdchginfo != NULL);
25094 assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
25095
25096 return bdchginfo->redundant;
25097}
25098
25099/** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
25101 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25102 )
25103{
25104 assert(bdchginfo != NULL);
25105
25108 && bdchginfo->inferencedata.reason.prop != NULL);
25109}
25110
25111/** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
25112 * has a tighter new bound as the second bound change
25113 */
25115 SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
25116 SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
25117 )
25118{
25119 assert(bdchginfo1 != NULL);
25120 assert(bdchginfo2 != NULL);
25121 assert(bdchginfo1->var == bdchginfo2->var);
25122 assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
25123
25124 return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
25125 ? bdchginfo1->newbound > bdchginfo2->newbound
25126 : bdchginfo1->newbound < bdchginfo2->newbound);
25127}
25128
25129/** returns position of variable in certificate */
25131 SCIP_VAR* var /**< variable to get index for */
25132 )
25133{
25134 assert(var != NULL);
25135 assert(var->exactdata != NULL);
25136
25137 return var->exactdata->certificateindex;
25138}
25139
25140/** sets index of variable in certificate */
25142 SCIP_VAR* var, /**< variable to set index for */
25143 int certidx /**< the index */
25144 )
25145{
25146 assert(var != NULL);
25147 assert(var->exactdata != NULL);
25148 assert(certidx >= 0);
25149
25150 var->exactdata->certificateindex = certidx;
25151}
25152
25153/** sets index of variable in certificate */
25155 SCIP_VAR* var, /**< variable to set index for */
25156 SCIP_Longint certidx /**< the index */
25157 )
25158{
25159 assert(var != NULL);
25160 assert(var->exactdata != NULL);
25161 assert(certidx >= 0);
25162
25163 var->exactdata->glbdom.ubcertificateidx = certidx;
25164 var->exactdata->locdom.ubcertificateidx = certidx;
25165}
25166
25167/** sets index of variable in certificate */
25169 SCIP_VAR* var, /**< variable to set index for */
25170 SCIP_Longint certidx /**< the index */
25171 )
25172{
25173 assert(var != NULL);
25174 assert(var->exactdata != NULL);
25175 assert(certidx >= 0);
25176
25177 var->exactdata->locdom.ubcertificateidx = certidx;
25178}
25179
25180/** sets index of variable in certificate */
25182 SCIP_VAR* var, /**< variable to set index for */
25183 SCIP_Longint certidx /**< the index */
25184 )
25185{
25186 assert(var != NULL);
25187 assert(var->exactdata != NULL);
25188 assert(certidx >= 0);
25189
25190 var->exactdata->locdom.lbcertificateidx = certidx;
25191}
25192
25193/** sets index of variable in certificate */
25195 SCIP_VAR* var, /**< variable to set index for */
25196 SCIP_Longint certidx /**< the index */
25197 )
25198{
25199 assert(var != NULL);
25200 assert(var->exactdata != NULL);
25201 assert(certidx >= 0);
25202
25203 var->exactdata->glbdom.lbcertificateidx = certidx;
25204 var->exactdata->locdom.lbcertificateidx = certidx;
25205}
25206
25207/** returns index of variable bound in vipr certificate */
25209 SCIP_VAR* var /**< variable to get index for */
25210 )
25211{
25212 assert(var->exactdata != NULL);
25213 assert(var->exactdata->locdom.lbcertificateidx >= 0);
25214 assert(var->exactdata->locdom.lbcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)));
25215
25216 return var->exactdata->locdom.lbcertificateidx;
25217}
25218
25219/** returns index of variable bound in vipr certificate */
25221 SCIP_VAR* var /**< variable to get index for */
25222 )
25223{
25224 assert(var->exactdata != NULL);
25225 assert(var->exactdata->locdom.ubcertificateidx >= 0);
25226 assert(var->exactdata->locdom.ubcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)));
25227
25228 return var->exactdata->locdom.ubcertificateidx;
25229}
25230
25231/** returns index of variable bound in vipr certificate */
25233 SCIP_VAR* var /**< variable to get index for */
25234 )
25235{
25236 assert(var->exactdata != NULL);
25237 assert(var->exactdata->glbdom.lbcertificateidx >= 0);
25238 assert(var->exactdata->glbdom.lbcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)));
25239
25240 return var->exactdata->glbdom.lbcertificateidx;
25241}
25242
25243/** returns index of variable bound in vipr certificate */
25245 SCIP_VAR* var /**< variable to get index for */
25246 )
25247{
25248 assert(var->exactdata != NULL);
25249 assert(var->exactdata->glbdom.ubcertificateidx >= 0);
25250 assert(var->exactdata->glbdom.ubcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)));
25251
25252 return var->exactdata->glbdom.ubcertificateidx;
25253}
static long bound
static GRAPHNODE ** active
SCIP_CERTIFICATE * SCIPgetCertificate(SCIP *scip)
SCIP_RETCODE SCIPcertificateSetLastBoundIndex(SCIP_CERTIFICATE *certificate, SCIP_Longint index)
SCIP_Longint SCIPcertificateGetLastBoundIndex(SCIP_CERTIFICATE *certificate)
SCIP_Bool SCIPcertificateIsEnabled(SCIP_CERTIFICATE *certificate)
SCIP_Longint SCIPcertificateGetCurrentIndex(SCIP_CERTIFICATE *certificate)
SCIP_Bool SCIPcertificateEnsureLastBoundInfoConsistent(SCIP_CERTIFICATE *certificate, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real newbound, SCIP_Bool needsglobal)
methods for certificate output
SCIP_VAR * a
SCIP_VAR ** b
void SCIPconsCapture(SCIP_CONS *cons)
Definition cons.c:6431
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition cons.c:6443
internal methods for constraints and constraint handlers
#define MAX_CLIQUELENGTH
#define MAXABSVBCOEF
#define MAXDNOM
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition debug.h:299
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition debug.h:306
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition debug.h:300
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition debug.h:305
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition debug.h:307
#define SCIP_DEFAULT_INFINITY
Definition def.h:172
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define EPSISINT(x, eps)
Definition def.h:204
#define SCIP_REAL_MAX
Definition def.h:167
#define SCIP_INVALID
Definition def.h:187
#define SCIP_INTERVAL_INFINITY
Definition def.h:189
#define SCIP_Bool
Definition def.h:100
#define EPSLE(x, y, eps)
Definition def.h:194
#define MIN(x, y)
Definition def.h:233
#define SCIP_ALLOC(x)
Definition def.h:375
#define SCIP_Real
Definition def.h:165
#define SCIP_UNKNOWN
Definition def.h:188
#define ABS(x)
Definition def.h:225
#define SQR(x)
Definition def.h:208
#define EPSEQ(x, y, eps)
Definition def.h:192
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL_ABORT(x)
Definition def.h:343
#define SCIPABORT()
Definition def.h:336
#define SCIP_REAL_MIN
Definition def.h:168
#define REALABS(x)
Definition def.h:191
#define EPSZ(x, eps)
Definition def.h:197
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:752
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:634
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:780
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:656
SCIP_RETCODE SCIPeventAddExactObjChg(SCIP_EVENT *event, BMS_BLKMEM *blkmem, SCIP_RATIONAL *oldobj, SCIP_RATIONAL *newobj)
Definition event.c:827
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition event.c:677
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition event.c:2561
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition event.c:2167
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition event.c:2933
SCIP_RETCODE SCIPeventAddExactBdChg(SCIP_EVENT *event, BMS_BLKMEM *blkmem, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition event.c:808
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition event.c:845
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition event.c:2300
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition event.c:2142
SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition event.c:1804
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:933
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition event.c:1204
SCIP_RETCODE SCIPeventCreateImplTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_IMPLINTTYPE oldtype, SCIP_IMPLINTTYPE newtype)
Definition event.c:975
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition event.c:2207
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:727
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:702
SCIP_RETCODE SCIPeventCreateTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_VARTYPE oldtype, SCIP_VARTYPE newtype)
Definition event.c:952
internal methods for managing events
const char * SCIPgetProbName(SCIP *scip)
Definition scip_prob.c:1242
int SCIPgetNTotalVars(SCIP *scip)
Definition scip_prob.c:3064
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3143
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9197
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9449
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition misc.c:9470
void SCIPswapInts(int *value1, int *value2)
Definition misc.c:10485
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_Bool SCIPshouldCertificateTrackBounds(SCIP *scip)
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition lp.c:17336
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition lp.c:17346
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition lp.c:17379
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition lp.c:17356
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition lp.c:17509
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition lp.c:17414
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
struct SCIP_Interval SCIP_INTERVAL
void SCIPintervalMulScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
void SCIPintervalAddScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
void SCIPintervalSetRational(SCIP_INTERVAL *resultant, SCIP_RATIONAL *value)
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition tree.c:8513
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition tree.c:8812
SCIP_Bool SCIPinProbing(SCIP *scip)
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition prop.c:951
SCIP_Bool SCIPrationalIsLTReal(SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_Bool SCIPrationalIsFpRepresentable(SCIP_RATIONAL *rational)
void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalRoundLong(SCIP_Longint *res, SCIP_RATIONAL *src, SCIP_ROUNDMODE_RAT roundmode)
SCIP_RETCODE SCIPrationalCreateBlock(BMS_BLKMEM *blkmem, SCIP_RATIONAL **rational)
Definition rational.cpp:109
SCIP_RETCODE SCIPrationalCreate(SCIP_RATIONAL **rational)
Definition rational.cpp:95
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
void SCIPrationalInvert(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:619
void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition rational.cpp:936
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsString(const char *desc)
Definition rational.cpp:653
void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
Definition rational.cpp:462
#define SCIPrationalDebugMessage
Definition rational.h:641
void SCIPrationalRoundInteger(SCIP_RATIONAL *res, SCIP_RATIONAL *src, SCIP_ROUNDMODE_RAT roundmode)
void SCIPrationalDiv(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsLT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition rational.cpp:604
SCIP_Bool SCIPrationalIsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
SCIP_RETCODE SCIPrationalCopyBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **result, SCIP_RATIONAL *src)
Definition rational.cpp:152
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition rational.cpp:474
SCIP_RETCODE SCIPrationalCopyBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***target, SCIP_RATIONAL **src, int len)
Definition rational.cpp:250
void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition rational.cpp:984
SCIP_RETCODE SCIPrationalCopyBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***result, SCIP_RATIONAL **src, int len)
Definition rational.cpp:268
SCIP_Bool SCIPrationalIsPositive(SCIP_RATIONAL *rational)
SCIP_Longint SCIPrationalDenominator(SCIP_RATIONAL *rational)
int SCIPrationalGetSign(const SCIP_RATIONAL *rational)
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition rational.cpp:124
void SCIPrationalAddProd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition rational.cpp:570
void SCIPrationalSetString(SCIP_RATIONAL *res, const char *desc)
Definition rational.cpp:717
SCIP_Bool SCIPrationalIsIntegral(SCIP_RATIONAL *rational)
void SCIPrationalMax(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_Bool SCIPrationalIsGE(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalCanonicalize(SCIP_RATIONAL *rational)
Definition rational.cpp:539
void SCIPrationalMessage(SCIP_MESSAGEHDLR *msg, FILE *file, SCIP_RATIONAL *rational)
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition rational.cpp:631
void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
Definition rational.cpp:583
void SCIPrationalNegate(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
void SCIPrationalDiffReal(SCIP_RATIONAL *res, SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
void SCIPrationalFreeBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***ratblockarray, int size)
Definition rational.cpp:502
SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
SCIP_Longint SCIPrationalNumerator(SCIP_RATIONAL *rational)
SCIP_Bool SCIPrationalIsEQReal(SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_RETCODE SCIPrationalCreateBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition rational.cpp:215
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
void SCIPrationalFree(SCIP_RATIONAL **rational)
Definition rational.cpp:451
void SCIPrationalDiffProdReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
SCIP_Bool SCIPrationalIsGTReal(SCIP_RATIONAL *rat, SCIP_Real real)
SCIP_RETCODE SCIPrationalReallocBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition rational.cpp:345
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalDiffProd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
SCIP_RETCODE SCIPrationalReallocBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition rational.cpp:315
void SCIPrationalMultReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
Definition rational.cpp:519
SCIP_Bool SCIPrationalIsLE(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
void SCIPrationalAddProdReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition scip_tree.c:72
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition var.c:23546
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition var.c:18740
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17281
SCIP_Longint SCIPvarGetUbCertificateIndexLocal(SCIP_VAR *var)
Definition var.c:25220
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18365
void SCIPvarSetLbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25194
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition var.c:24334
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition var.c:24514
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition var.c:17846
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:23566
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition var.c:23921
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:23715
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25089
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21913
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition var.c:4478
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition var.c:23875
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition var.c:24404
void SCIPvarSetTransData(SCIP_VAR *var,)
Definition var.c:23352
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition var.c:17575
SCIP_BOUNDTYPE SCIPvarGetWorstBoundTypeExact(SCIP_VAR *var)
Definition var.c:24445
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition var.c:19036
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23900
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition var.c:24536
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
SCIP_Longint SCIPvarGetUbCertificateIndexGlobal(SCIP_VAR *var)
Definition var.c:25244
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23226
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition var.c:23276
void SCIPvarSetDelorigData(SCIP_VAR *var,)
Definition var.c:23340
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21868
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition var.c:24206
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:24921
SCIP_RATIONAL * SCIPvarGetBestBoundGlobalExact(SCIP_VAR *var)
Definition var.c:24219
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:22918
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25011
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition var.c:23206
void SCIPvarSetCertificateIndex(SCIP_VAR *var, int certidx)
Definition var.c:25141
SCIP_RATIONAL * SCIPvarGetAggrScalarExact(SCIP_VAR *var)
Definition var.c:23792
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition var.c:16486
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition var.c:23254
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24600
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23216
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22060
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition var.c:23803
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition var.c:23976
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition var.c:4443
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition var.c:19509
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition var.c:23286
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:24052
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22658
SCIP_RATIONAL * SCIPvarGetAggrConstantExact(SCIP_VAR *var)
Definition var.c:23815
SCIP_RATIONAL * SCIPvarGetPseudoSolExact(SCIP_VAR *var)
Definition var.c:24801
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23462
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition var.c:23578
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition var.c:16521
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25045
int SCIPvarGetCertificateIndex(SCIP_VAR *var)
Definition var.c:25130
SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
Definition var.c:23538
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition var.c:23186
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition var.c:4467
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition var.c:23780
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17595
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition var.c:23650
SCIP_RETCODE SCIPvarGetOrigvarSumExact(SCIP_VAR **var, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant)
Definition var.c:18449
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_BOUNDTYPE SCIPvarGetBestBoundTypeExact(SCIP_VAR *var)
Definition var.c:24417
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition var.c:23386
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24617
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition var.c:19641
SCIP_VARSTATUS SCIPvarGetStatusExact(SCIP_VAR *var)
Definition var.c:23428
SCIP_RATIONAL * SCIPvarGetWorstBoundLocalExact(SCIP_VAR *var)
Definition var.c:24387
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24991
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25056
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
SCIP_INTERVAL SCIPvarGetObjInterval(SCIP_VAR *var)
Definition var.c:23953
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25033
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition var.c:18888
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition var.c:22793
SCIP_COLEXACT * SCIPvarGetColExact(SCIP_VAR *var)
Definition var.c:23726
void SCIPvarGetLPSolExact_rec(SCIP_VAR *var, SCIP_RATIONAL *res)
Definition var.c:18813
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25001
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition var.c:24374
int SCIPvarGetNUses(SCIP_VAR *var)
Definition var.c:23309
SCIP_RATIONAL * SCIPvarGetLbOriginalExact(SCIP_VAR *var)
Definition var.c:24072
SCIP_RATIONAL * SCIPvarGetUbOriginalExact(SCIP_VAR *var)
Definition var.c:24115
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition var.c:23246
SCIP_Longint SCIPvarGetLbCertificateIndexGlobal(SCIP_VAR *var)
Definition var.c:25232
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:23694
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Bool SCIPvarIsExact(SCIP_VAR *var)
Definition var.c:23439
SCIP_RETCODE SCIPvarGetProbvarBoundExact(SCIP_VAR **var, SCIP_RATIONAL *bound, SCIP_BOUNDTYPE *boundtype)
Definition var.c:17939
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition var.c:24095
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition var.c:24236
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24961
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition var.c:16506
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:23602
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition var.c:24546
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition var.c:19144
SCIP_RATIONAL * SCIPvarGetMultaggrConstantExact(SCIP_VAR *var)
Definition var.c:23887
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24662
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition var.c:24344
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition var.c:24556
SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
Definition var.c:24310
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition var.c:24482
void SCIPvarSetUbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25154
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition var.c:19856
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition var.c:23664
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24941
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition var.c:18532
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition var.c:24470
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition var.c:24788
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition var.c:24504
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25068
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition var.c:23329
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24646
void SCIPvarSetDeltransData(SCIP_VAR *var,)
Definition var.c:23364
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:24696
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22770
void SCIPvarGetSolExact(SCIP_VAR *var, SCIP_RATIONAL *res, SCIP_Bool getlpval)
Definition var.c:19048
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition var.c:23319
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:23838
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition var.c:25114
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23826
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition var.c:23402
SCIP_Longint SCIPvarGetLbCertificateIndexLocal(SCIP_VAR *var)
Definition var.c:25208
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition var.c:24138
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition var.c:23556
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24674
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24971
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25021
SCIP_RATIONAL * SCIPvarGetBestBoundLocalExact(SCIP_VAR *var)
Definition var.c:24357
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25100
SCIP_RATIONAL * SCIPvarGetLbGlobalExact(SCIP_VAR *var)
Definition var.c:24162
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition var.c:23236
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21780
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:23632
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:23910
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition var.c:18035
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition var.c:24526
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22714
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition var.c:23266
SCIP_RATIONAL ** SCIPvarGetMultaggrScalarsExact(SCIP_VAR *var)
Definition var.c:23862
SCIP_Real SCIPvarGetMaxAggrCoef(SCIP_VAR *var)
Definition var.c:23758
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition var.c:24494
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:23449
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24685
SCIP_Real SCIPvarGetMinAggrCoef(SCIP_VAR *var)
Definition var.c:23748
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition var.c:23589
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition var.c:19576
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition var.c:24736
SCIP_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
Definition var.c:24276
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition var.c:23495
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17319
void SCIPvarsCountTypes(SCIP_VAR **vars, int nvars, int *nbinvars, int *nintvars, int *nbinimplvars, int *nintimplvars, int *ncontimplvars, int *ncontvars)
Definition var.c:22971
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22303
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition var.c:19610
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition var.c:17687
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21825
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition var.c:24588
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition var.c:4456
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition var.c:23704
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition var.c:24723
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition var.c:24568
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition var.c:24768
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24981
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition var.c:24778
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition var.c:24432
void SCIPvarSetCopyData(SCIP_VAR *var,)
Definition var.c:23375
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22105
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition var.c:16852
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:24901
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition var.c:24578
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition var.c:24196
void SCIPvarGetLPSolExact(SCIP_VAR *var, SCIP_RATIONAL *res)
Definition var.c:24709
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24951
SCIP_RATIONAL * SCIPvarGetWorstBoundGlobalExact(SCIP_VAR *var)
Definition var.c:24249
SCIP_Real SCIPboundchgGetLPSolVal(SCIP_BOUNDCHG *boundchg)
Definition var.c:23196
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
SCIP_RATIONAL * SCIPvarGetObjExact(SCIP_VAR *var)
Definition var.c:23942
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition var.c:24756
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition var.c:24748
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24632
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition var.c:22830
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition var.c:17655
SCIP_RATIONAL * SCIPvarGetUbGlobalExact(SCIP_VAR *var)
Definition var.c:24184
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition var.c:23964
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:23850
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22260
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition var.c:24460
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition var.c:23738
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition var.c:23768
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition misc.c:200
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition misc.c:127
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition misc.c:110
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPsortPtrPtr(void **ptrarray1, void **ptrarray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition misc.c:10955
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition misc.c:10985
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:323
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition history.c:364
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:342
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition history.c:409
return SCIP_OKAY
int c
int depth
SCIP_Bool cutoff
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real primsol
SCIP_Real frac
SCIP_Real newobj
SCIP_Real oldobj
static SCIP_VAR ** vars
SCIP_Real * rootsol
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition history.c:78
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition history.c:532
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:793
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:693
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:767
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:706
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:819
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition history.c:51
SCIP_Real SCIPhistoryGetAncPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:599
void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition history.c:910
void SCIPhistoryUpdateAncPseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition history.c:255
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:735
SCIP_Real SCIPhistoryGetAncPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition history.c:546
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:806
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:584
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition history.c:560
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition history.c:677
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition history.c:652
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:751
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition history.c:719
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition history.c:191
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:664
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:832
SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
Definition history.c:900
SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
Definition history.c:877
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:780
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition history.c:66
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition history.c:117
void SCIPhistoryIncGMIeffSum(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition history.c:887
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition history.c:523
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:638
internal methods for branching and inference history
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3335
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition implics.c:1285
SCIP_RETCODE SCIPcliquetableAdd(SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition implics.c:2377
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition implics.c:1683
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition implics.c:73
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition implics.c:3310
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition implics.c:333
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition implics.c:3384
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3459
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition implics.c:1605
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3353
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition implics.c:3468
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition implics.c:3302
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition implics.c:3374
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition implics.c:3396
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition implics.c:288
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3365
SCIP_RETCODE SCIPimplicsAdd(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *conflict, SCIP_Bool *added)
Definition implics.c:633
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition implics.c:206
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition implics.c:1441
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3326
SCIP_RETCODE SCIPcliqueAddVar(SCIP_CLIQUE *clique, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Bool value, SCIP_Bool *doubleentry, SCIP_Bool *oppositeentry)
Definition implics.c:1151
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3344
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3450
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition implics.c:1527
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition implics.c:3430
void SCIPimplicsGetVarImplicPoss(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, int *lowerimplicpos, int *upperimplicpos)
Definition implics.c:916
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition implics.c:836
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition implics.c:3318
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition implics.c:3294
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition implics.c:933
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition implics.c:451
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition implics.c:1482
methods for implications, variable bounds, and cliques
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition lp.c:18241
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition lp.c:3997
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition lp.c:3572
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition lp.c:3952
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition lp.c:14686
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition lp.c:5856
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition lp.c:3893
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition lp.c:5744
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition lp.c:18251
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition lp.c:4147
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition lp.c:3473
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14665
static const SCIP_Real scalars[]
Definition lp.c:5959
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14541
internal methods for LP management
SCIP_RETCODE SCIPlpExactUpdateVarColumn(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_VAR *var)
Definition lpexact.c:6663
SCIP_RETCODE SCIProwExactIncCoef(SCIP_ROWEXACT *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LPEXACT *lpexact, SCIP_COLEXACT *col, SCIP_RATIONAL *incval)
Definition lpexact.c:5321
void SCIPlpExactDecNLoosevars(SCIP_LPEXACT *lpexact)
Definition lpexact.c:6770
SCIP_RATIONAL * SCIPcolExactGetPrimsol(SCIP_COLEXACT *col)
Definition lpexact.c:6039
SCIP_Bool SCIPlpExactDiving(SCIP_LPEXACT *lpexact)
Definition lpexact.c:8423
SCIP_RETCODE SCIPcolExactFree(SCIP_COLEXACT **col, BMS_BLKMEM *blkmem)
Definition lpexact.c:2754
SCIP_RETCODE SCIPcolExactChgUb(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newub)
Definition lpexact.c:3093
SCIP_RETCODE SCIProwExactAddConstant(SCIP_ROWEXACT *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *addval)
Definition lpexact.c:5416
SCIP_RETCODE SCIPcolExactCreate(SCIP_COLEXACT **col, SCIP_COL *fpcol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROWEXACT **rows, SCIP_RATIONAL **vals, SCIP_Bool removable)
Definition lpexact.c:2410
SCIP_RETCODE SCIPcolExactChgLb(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newlb)
Definition lpexact.c:3048
internal methods for exact LP management
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition memory.h:456
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition memory.h:462
#define BMSfreeBlockMemory(mem, ptr)
Definition memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition memory.h:451
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition memory.h:468
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition memory.h:469
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition memory.h:458
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition memory.h:453
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition message.c:618
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition message.c:427
real eps
SCIP_RETCODE SCIPprimalUpdateObjoffsetExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition primal.c:646
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition primal.c:590
internal methods for collecting primal CIP solutions and primal informations
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition prob.c:1871
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition prob.c:2901
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition prob.c:1409
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition prob.c:2856
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition prob.c:1666
SCIP_RETCODE SCIPprobAddVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *var)
Definition prob.c:1096
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition prob.c:2865
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition prob.c:2910
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition prob.c:2800
void SCIPprobAddObjoffsetExact(SCIP_PROB *prob, SCIP_RATIONAL *addval)
Definition prob.c:1682
internal methods for storing and manipulating the main problem
public methods for managing constraints
public methods for branching and inference history structure
public methods for implications, variable bounds, and cliques
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPdebugMessage
Definition pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for propagators
public methods for problem variables
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition relax.c:864
internal methods for relaxators
SCIP callable library.
public methods for certified solving
public methods for exact solving
public methods for global and local (sub)problems
public methods for the probing mode
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:7298
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:6722
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:7082
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6623
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:7142
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:7093
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition set.c:6428
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:6734
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:7023
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6999
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6951
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:6654
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6583
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:7130
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:7320
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition set.c:6408
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6543
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:7071
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition set.c:3203
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6975
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition set.c:6386
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6563
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition set.c:6521
SCIP_Bool SCIPsetIsSumZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6870
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:7309
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6603
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:6676
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6643
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:7047
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition set.c:6398
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition set.c:6746
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition set.c:6086
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:7104
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:6665
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition set.h:1782
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition set.h:1789
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition set.h:1775
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition set.h:1786
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition set.h:1777
#define SCIPsetDebugMsg
Definition set.h:1811
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition set.h:1779
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition sol.c:1912
internal methods for storing primal CIP solutions
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition stat.c:871
internal methods for problem statistics
#define SCIPstatIncrement(stat, set, field)
Definition stat.h:260
SCIP_RATIONAL * scalar
Definition struct_var.h:218
SCIP_RATIONAL * constant
Definition struct_var.h:219
SCIP_VAR * var
Definition struct_var.h:212
SCIP_Real scalar
Definition struct_var.h:210
SCIP_Real constant
Definition struct_var.h:211
SCIP_BDCHGIDX bdchgidx
Definition struct_var.h:127
SCIP_Real newbound
Definition struct_var.h:123
SCIP_INFERENCEDATA inferencedata
Definition struct_var.h:126
unsigned int boundchgtype
Definition struct_var.h:129
unsigned int boundtype
Definition struct_var.h:130
SCIP_VAR * var
Definition struct_var.h:125
unsigned int redundant
Definition struct_var.h:132
unsigned int inferboundtype
Definition struct_var.h:131
SCIP_Real oldbound
Definition struct_var.h:122
SCIP_RATIONAL * newboundexact
Definition struct_var.h:97
union SCIP_BoundChg::@126301315365336333353356203157377037022074222233 data
SCIP_Longint certificateindex
Definition struct_var.h:103
SCIP_Real newbound
Definition struct_var.h:96
unsigned int applied
Definition struct_var.h:108
unsigned int boundtype
Definition struct_var.h:106
SCIP_INFERENCEDATA inferencedata
Definition struct_var.h:101
unsigned int redundant
Definition struct_var.h:109
SCIP_VAR * var
Definition struct_var.h:104
SCIP_BRANCHINGDATA branchingdata
Definition struct_var.h:100
unsigned int inferboundtype
Definition struct_var.h:107
unsigned int boundchgtype
Definition struct_var.h:105
SCIP_HOLECHG * holechgs
Definition struct_var.h:149
SCIP_BOUNDCHG * boundchgs
Definition struct_var.h:140
unsigned int nboundchgs
Definition struct_var.h:138
SCIP_BOUNDCHG * boundchgs
Definition struct_var.h:158
SCIP_HOLECHG * holechgs
Definition struct_var.h:159
unsigned int nboundchgs
Definition struct_var.h:156
unsigned int domchgtype
Definition struct_var.h:157
SCIP_RATIONAL * ub
Definition struct_var.h:185
SCIP_RATIONAL * lb
Definition struct_var.h:184
SCIP_Real lb
Definition struct_var.h:176
SCIP_Real ub
Definition struct_var.h:177
SCIP_HOLELIST * holelist
Definition struct_var.h:178
SCIP_HOLELIST ** ptr
Definition struct_var.h:70
SCIP_HOLELIST * oldlist
Definition struct_var.h:72
SCIP_HOLELIST * newlist
Definition struct_var.h:71
SCIP_Real right
Definition struct_var.h:57
SCIP_Real left
Definition struct_var.h:56
SCIP_HOLELIST * next
Definition struct_var.h:64
SCIP_HOLE hole
Definition struct_var.h:63
SCIP_Real sup
SCIP_Real inf
SCIP_Real minaggrcoef
Definition struct_var.h:203
SCIP_Real maxaggrcoef
Definition struct_var.h:204
SCIP_LPEXACT * lpexact
Definition struct_lp.h:309
SCIP_Bool divingobjchg
Definition struct_lp.h:387
SCIP_RATIONAL ** scalars
Definition struct_var.h:236
SCIP_RATIONAL * constant
Definition struct_var.h:235
SCIP_VAR ** vars
Definition struct_var.h:227
SCIP_Real * scalars
Definition struct_var.h:226
SCIP_Real constant
Definition struct_var.h:242
SCIP_VAR * transvar
Definition struct_var.h:194
SCIP_OBJSENSE objsense
Definition struct_prob.h:92
SCIP_Real objscale
Definition struct_prob.h:51
SCIP_ROW * fprow
char * name
Definition struct_lp.h:229
SCIP_VAR * lastbranchvar
SCIP_Longint lpcount
SCIP_HISTORY * glbhistory
int nrootboundchgs
int nrootintfixingsrun
int nrootintfixings
SCIP_Real vsidsweight
SCIP_BRANCHDIR lastbranchdir
int nrootboundchgsrun
SCIP_Bool collectvarhistory
SCIP_HISTORY * glbhistorycrun
SCIP_Real lastbranchvalue
SCIP_INTERVAL objinterval
Definition struct_var.h:249
SCIP_DOMEXACT glbdom
Definition struct_var.h:251
SCIP_RATIONAL * obj
Definition struct_var.h:248
SCIP_DOMEXACT origdom
Definition struct_var.h:252
SCIP_COLEXACT * colexact
Definition struct_var.h:255
SCIP_MULTAGGREXACT multaggr
Definition struct_var.h:254
SCIP_VARSTATUS varstatusexact
Definition struct_var.h:256
SCIP_AGGREGATEEXACT aggregate
Definition struct_var.h:253
SCIP_DOMEXACT locdom
Definition struct_var.h:250
SCIP_Real lazylb
Definition struct_var.h:277
SCIP_VARDATA * vardata
Definition struct_var.h:296
int nubchginfos
Definition struct_var.h:325
SCIP_Real lazyub
Definition struct_var.h:278
SCIP_ORIGINAL original
Definition struct_var.h:283
SCIP_VBOUNDS * vlbs
Definition struct_var.h:299
SCIP_AGGREGATE aggregate
Definition struct_var.h:286
SCIP_IMPLICS * implics
Definition struct_var.h:301
SCIP_VAR ** parentvars
Definition struct_var.h:297
SCIP_BDCHGINFO * lbchginfos
Definition struct_var.h:304
SCIP_VAR * negatedvar
Definition struct_var.h:298
SCIP * scip
Definition struct_var.h:345
int nlocksdown[NLOCKTYPES]
Definition struct_var.h:319
SCIP_HISTORY * historycrun
Definition struct_var.h:307
unsigned int donotmultaggr
Definition struct_var.h:335
SCIP_DOM glbdom
Definition struct_var.h:279
SCIP_Real branchfactor
Definition struct_var.h:265
SCIP_Real conflictrelaxedub
Definition struct_var.h:276
SCIP_BDCHGINFO * ubchginfos
Definition struct_var.h:305
char * name
Definition struct_var.h:291
union SCIP_Var::@062351145146014100220174313010263165251013276204 data
SCIP_Real conflictrelaxedlb
Definition struct_var.h:275
SCIP_VARDATAEXACT * exactdata
Definition struct_var.h:290
unsigned int initial
Definition struct_var.h:330
SCIP_DOM locdom
Definition struct_var.h:280
unsigned int removable
Definition struct_var.h:331
SCIP_CLIQUELIST * cliquelist
Definition struct_var.h:302
SCIP_MULTAGGR multaggr
Definition struct_var.h:287
SCIP_Real obj
Definition struct_var.h:263
int nlocksup[NLOCKTYPES]
Definition struct_var.h:320
int nlbchginfos
Definition struct_var.h:323
unsigned int branchdirection
Definition struct_var.h:340
SCIP_HISTORY * history
Definition struct_var.h:306
SCIP_VBOUNDS * vubs
Definition struct_var.h:300
int nparentvars
Definition struct_var.h:317
unsigned int donotaggr
Definition struct_var.h:334
SCIP_LOOSE loose
Definition struct_var.h:284
SCIP_NEGATE negate
Definition struct_var.h:285
SCIP_Longint closestvblpcount
Definition struct_var.h:309
int branchpriority
Definition struct_var.h:321
datastructures for managing events
data structures for LP management
data structures for exact LP management
datastructures for storing and manipulating the main problem
SCIP main data structure.
datastructures for global SCIP settings
datastructures for problem statistics
datastructures for problem variables
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition tree.c:2539
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition tree.c:9559
internal methods for branch and bound tree
struct SCIP_BranchCand SCIP_BRANCHCAND
Definition type_branch.h:55
struct SCIP_Certificate SCIP_CERTIFICATE
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_EVENTTYPE_GHOLEADDED
Definition type_event.h:81
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#define SCIP_EVENTTYPE_GUBCHANGED
Definition type_event.h:76
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
struct SCIP_EventFilter SCIP_EVENTFILTER
Definition type_event.h:180
struct SCIP_EventQueue SCIP_EVENTQUEUE
Definition type_event.h:181
#define SCIP_EVENTTYPE_FORMAT
Definition type_event.h:157
#define SCIP_EVENTTYPE_GLBCHANGED
Definition type_event.h:75
#define SCIP_EVENTTYPE_VARCHANGED
Definition type_event.h:132
#define SCIP_EVENTTYPE_LBCHANGED
Definition type_event.h:123
#define SCIP_EVENTTYPE_UBCHANGED
Definition type_event.h:124
#define SCIP_EVENTTYPE_LHOLEADDED
Definition type_event.h:83
uint64_t SCIP_EVENTTYPE
Definition type_event.h:156
struct SCIP_Event SCIP_EVENT
Definition type_event.h:161
struct SCIP_History SCIP_HISTORY
@ SCIP_BRANCHDIR_DOWNWARDS
@ SCIP_BRANCHDIR_AUTO
@ SCIP_BRANCHDIR_UPWARDS
struct SCIP_ValueHistory SCIP_VALUEHISTORY
enum SCIP_BranchDir SCIP_BRANCHDIR
struct SCIP_Clique SCIP_CLIQUE
struct SCIP_CliqueTable SCIP_CLIQUETABLE
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_Lp SCIP_LP
Definition type_lp.h:111
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
struct SCIP_Col SCIP_COL
Definition type_lp.h:99
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:60
struct SCIP_LpExact SCIP_LPEXACT
struct SCIP_RowExact SCIP_ROWEXACT
struct SCIP_ColExact SCIP_COLEXACT
@ SCIP_BASESTAT_UPPER
Definition type_lpi.h:93
@ SCIP_BASESTAT_LOWER
Definition type_lpi.h:91
enum SCIP_BaseStat SCIP_BASESTAT
Definition type_lpi.h:96
struct SCIP_Messagehdlr SCIP_MESSAGEHDLR
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:189
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
@ SCIP_CONFIDENCELEVEL_MAX
Definition type_misc.h:51
@ SCIP_CONFIDENCELEVEL_MEDIUM
Definition type_misc.h:49
@ SCIP_CONFIDENCELEVEL_HIGH
Definition type_misc.h:50
@ SCIP_CONFIDENCELEVEL_MIN
Definition type_misc.h:47
@ SCIP_CONFIDENCELEVEL_LOW
Definition type_misc.h:48
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition type_misc.h:53
struct SCIP_Primal SCIP_PRIMAL
Definition type_primal.h:39
struct SCIP_Prob SCIP_PROB
Definition type_prob.h:52
enum SCIP_Objsense SCIP_OBJSENSE
Definition type_prob.h:50
struct SCIP_Prop SCIP_PROP
Definition type_prop.h:51
struct SCIP_Rational SCIP_RATIONAL
@ SCIP_R_ROUND_UPWARDS
@ SCIP_R_ROUND_DOWNWARDS
struct SCIP_Relaxation SCIP_RELAXATION
Definition type_relax.h:51
struct SCIP_Reopt SCIP_REOPT
Definition type_reopt.h:39
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_SUCCESS
Definition type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
@ SCIP_INVALIDRESULT
@ SCIP_READERROR
@ SCIP_INVALIDDATA
@ SCIP_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Set SCIP_SET
Definition type_set.h:71
@ SCIP_STAGE_PROBLEM
Definition type_set.h:45
@ SCIP_STAGE_PRESOLVING
Definition type_set.h:49
@ SCIP_STAGE_INITSOLVE
Definition type_set.h:52
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition type_set.h:51
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Stat SCIP_STAT
Definition type_stat.h:66
struct SCIP_Node SCIP_NODE
Definition type_tree.h:63
struct SCIP_Tree SCIP_TREE
Definition type_tree.h:65
struct SCIP_VarData SCIP_VARDATA
Definition type_var.h:167
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition type_var.h:135
struct SCIP_DomChgBoth SCIP_DOMCHGBOTH
Definition type_var.h:147
#define NLOCKTYPES
Definition type_var.h:138
enum SCIP_ImplintType SCIP_IMPLINTTYPE
Definition type_var.h:117
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90
@ SCIP_IMPLINTTYPE_STRONG
Definition type_var.h:106
@ SCIP_IMPLINTTYPE_WEAK
Definition type_var.h:91
#define SCIP_DECL_VARDELORIG(x)
Definition type_var.h:180
struct SCIP_HoleChg SCIP_HOLECHG
Definition type_var.h:155
union SCIP_DomChg SCIP_DOMCHG
Definition type_var.h:149
@ SCIP_DOMCHGTYPE_DYNAMIC
Definition type_var.h:122
@ SCIP_DOMCHGTYPE_BOUND
Definition type_var.h:124
@ SCIP_DOMCHGTYPE_BOTH
Definition type_var.h:123
struct SCIP_BoundChg SCIP_BOUNDCHG
Definition type_var.h:150
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
struct SCIP_DomChgDyn SCIP_DOMCHGDYN
Definition type_var.h:148
#define SCIP_DECL_VARTRANS(x)
Definition type_var.h:200
#define SCIP_DEPRECATED_VARTYPE_IMPLINT
Definition type_var.h:79
struct SCIP_DomChgBound SCIP_DOMCHGBOUND
Definition type_var.h:146
struct SCIP_Holelist SCIP_HOLELIST
Definition type_var.h:157
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_BOUNDCHGTYPE_PROPINFER
Definition type_var.h:133
@ SCIP_BOUNDCHGTYPE_BRANCHING
Definition type_var.h:131
@ SCIP_BOUNDCHGTYPE_CONSINFER
Definition type_var.h:132
@ SCIP_VARSTATUS_ORIGINAL
Definition type_var.h:51
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:53
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:55
@ SCIP_VARSTATUS_LOOSE
Definition type_var.h:52
struct SCIP_BdChgInfo SCIP_BDCHGINFO
Definition type_var.h:152
#define SCIP_DECL_VARCOPY(x)
Definition type_var.h:243
#define SCIP_DECL_VARDELTRANS(x)
Definition type_var.h:213
struct SCIP_Dom SCIP_DOM
Definition type_var.h:158
enum SCIP_LockType SCIP_LOCKTYPE
Definition type_var.h:144
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73
enum SCIP_Varstatus SCIP_VARSTATUS
Definition type_var.h:59
SCIP_DOMCHGBOUND domchgbound
Definition struct_var.h:168
SCIP_DOMCHGDYN domchgdyn
Definition struct_var.h:170
SCIP_DOMCHGBOTH domchgboth
Definition struct_var.h:169
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition var.c:18557
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20466
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition var.c:17383
SCIP_RETCODE SCIPvarMultiaggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:8052
SCIP_RETCODE SCIPvarTryAggregateVarsExact(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_RATIONAL *scalarx, SCIP_RATIONAL *scalary, SCIP_RATIONAL *rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7860
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_RATIONAL *lbexact, SCIP_RATIONAL *ubexact, SCIP_RATIONAL *objexact, SCIP_VARTYPE *vartype, SCIP_IMPLINTTYPE *impltype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_RATIONAL *lazylbexact, SCIP_RATIONAL *lazyubexact, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition var.c:2974
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:21528
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:10290
static SCIP_RETCODE varFreeExactData(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition var.c:3606
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:459
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_RATIONAL *newboundexact, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition var.c:1734
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition var.c:11789
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:1540
SCIP_RETCODE SCIPvarFixBinary(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:16557
static SCIP_RETCODE varEventGubChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:10406
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:12256
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20609
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:14577
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition var.c:22644
static SCIP_RETCODE domAddHole(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition var.c:230
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition var.c:4575
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:9416
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:17008
void SCIPvarGetUbLocalExactMinimal(SCIP_VAR *var, SCIP_RATIONAL *output)
Definition var.c:24321
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition var.c:20773
static SCIP_RETCODE boundchgApplyGlobal(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition var.c:1181
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:19262
static SCIP_RETCODE applyImplic(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:14767
SCIP_RETCODE SCIPvarSetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition var.c:22564
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, SCIP_RATIONAL *lbexact, SCIP_RATIONAL *ubexact, char **endptr)
Definition var.c:2928
void SCIPvarInitSolve(SCIP_VAR *var)
Definition var.c:3848
SCIP_RETCODE SCIPvarChgUbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:11636
SCIP_Real SCIPvarGetAncPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20699
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:21612
static SCIP_RETCODE varAddTransitiveBinaryClosureImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15076
SCIP_RETCODE SCIPvarChgLbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:11334
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:6170
SCIP_RETCODE SCIPvarChgBdGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound, SCIP_BOUNDTYPE boundtype)
Definition var.c:11866
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition var.c:3861
SCIP_RETCODE SCIPvarTryAggregateVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7684
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:21132
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:12063
static SCIP_RETCODE varAddLbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition var.c:485
SCIP_RETCODE SCIPvarChgUbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:13153
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:1640
static SCIP_RETCODE varProcessAddHoleLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition var.c:14340
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22346
SCIP_RETCODE SCIPboundchgApply(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, int pos, SCIP_Bool *cutoff)
Definition var.c:845
SCIP_RETCODE SCIPvarGetProbvarSumExact(SCIP_VAR **var, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant)
Definition var.c:18250
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1451
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition var.c:14736
SCIP_RETCODE SCIPvarGetMultaggrUbLocalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *result)
Definition var.c:13829
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition var.c:8791
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition var.c:20303
void SCIPvarSetLbCertificateIndexLocal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25181
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition var.c:4488
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:14040
static SCIP_RETCODE varProcessChgLbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:12461
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16770
int SCIPbdchgidxGetDepth(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:24891
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:9346
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3658
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:14221
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22205
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:14618
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3789
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition var.c:19992
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:21268
static SCIP_RETCODE varCreate(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata)
Definition var.c:2325
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final, SCIP_Bool keepimplics)
Definition var.c:9119
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:9906
static SCIP_RATIONAL * SCIPvarGetPseudoSolExact_rec(SCIP_VAR *var)
Definition var.c:19004
void SCIPvarAdjustLbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *lb)
Definition var.c:9923
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:24856
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:11186
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition var.c:19800
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:2753
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:20827
static SCIP_BDCHGIDX presolvebdchgidx
Definition var.c:22790
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:11894
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:20865
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, SCIP_RATIONAL *valueexact)
Definition var.c:2874
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:10024
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:20064
static SCIP_RETCODE varAddTransitiveImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15150
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18603
static SCIP_RETCODE tryAggregateIntVarsExact(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_RATIONAL *scalarx, SCIP_RATIONAL *scalary, SCIP_RATIONAL *rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7417
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition var.c:10008
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:11971
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition var.c:9843
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1348
SCIP_RETCODE SCIPvarColumnExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lp)
Definition var.c:4640
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition var.c:19789
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition var.c:3955
SCIP_Real SCIPvarGetAvgGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition var.c:22440
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:24814
SCIP_RETCODE SCIPvarAddObjExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_RATIONAL *addobj)
Definition var.c:9700
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition var.c:4719
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:21696
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13615
static SCIP_RETCODE varNegateExactData(SCIP_VAR *negvar, SCIP_VAR *origvar, BMS_BLKMEM *blkmem)
Definition var.c:8930
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:20942
void SCIPvarCapture(SCIP_VAR *var)
Definition var.c:3764
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:10368
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:17195
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20562
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition var.c:1839
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition var.c:19063
void SCIPvarGetLbLocalExactMaximal(SCIP_VAR *var, SCIP_RATIONAL *output)
Definition var.c:24287
static void adjustedLbExact(SCIP_SET *set, SCIP_Bool isintegral, SCIP_RATIONAL *lb)
Definition var.c:1921
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:1567
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:433
static SCIP_RETCODE varProcessChgLbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:10901
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition var.c:8840
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:9239
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:5983
void SCIPvarAdjustUbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *ub)
Definition var.c:9974
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21349
SCIP_RETCODE SCIPvarChgLbExactDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newbound)
Definition var.c:13406
SCIP_RETCODE SCIPvarCreateOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition var.c:2487
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition var.c:19074
static SCIP_Real adjustedLbExactFloat(SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1908
SCIP_RETCODE SCIPvarFixExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:4981
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21958
SCIP_RETCODE SCIPvarChgImplType(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_IMPLINTTYPE impltype)
Definition var.c:9298
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:13290
static SCIP_RETCODE boundchgApplyExact(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, int pos, SCIP_Bool *cutoff)
Definition var.c:635
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition var.c:21218
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition var.c:21077
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21441
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1888
static SCIP_RETCODE varProcessChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition var.c:10704
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20654
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:11488
SCIP_RETCODE SCIPvarMultiaggregateExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LPEXACT *lpexact, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int naggvars, SCIP_VAR **aggvars, SCIP_RATIONAL **scalars, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:8412
static void overwriteMultAggrWithExactData(SCIP_SET *set, SCIP_VAR *var)
Definition var.c:1986
SCIP_RETCODE SCIPvarChgUbOriginalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *newbound)
Definition var.c:10216
static SCIP_RETCODE varProcessChgUbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:11043
static SCIP_RETCODE varUpdateAggregationBoundsExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:6362
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:6595
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:3481
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_Bool isintegral, SCIP_Real ub)
Definition var.c:1937
SCIP_RETCODE SCIPvarCreateTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition var.c:2531
SCIP_RETCODE SCIPvarParseTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition var.c:3359
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18673
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:4606
SCIP_Real SCIPvarGetAncPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20513
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:10157
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:13463
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition var.c:274
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22148
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Real addobj)
Definition var.c:9585
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition var.c:22845
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:4181
static void adjustedUbExact(SCIP_SET *set, SCIP_Bool isintegral, SCIP_RATIONAL *ub)
Definition var.c:1970
SCIP_RETCODE SCIPvarChgUbExactDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newbound)
Definition var.c:13553
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13979
static SCIP_RETCODE varEventLbChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LPEXACT *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:11932
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition var.c:19917
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition var.c:11812
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:14638
static SCIP_RETCODE tryAggregateIntVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7179
SCIP_RETCODE SCIPvarChgLbOriginalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *newbound)
Definition var.c:10083
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:21008
SCIP_RETCODE SCIPdomchgApplyGlobal(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition var.c:1675
SCIP_RETCODE SCIPboundchgUndo(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:1059
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition var.c:9156
#define MAXIMPLSCLOSURE
Definition var.c:83
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition var.c:2294
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition var.c:6112
SCIP_RETCODE SCIPvarAddVlb(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15361
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:10446
static void varUpdateMinMaxAggrCoef(SCIP_VAR *var, SCIP_VAR *aggvar, SCIP_Real aggscalar)
Definition var.c:6143
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition var.c:3921
void SCIPdomchgAddCurrentCertificateIndex(SCIP_DOMCHG *domchg, SCIP_CERTIFICATE *certificate)
Definition var.c:1714
static SCIP_RETCODE varAddUbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition var.c:560
SCIP_RETCODE SCIPvarUpdateAncPseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition var.c:20403
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:24829
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:14468
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:23612
SCIP_RETCODE SCIPdomchgApply(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, SCIP_Bool *cutoff)
Definition var.c:1591
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16809
static SCIP_RETCODE varEventObjChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldobj, SCIP_RATIONAL *newobj)
Definition var.c:9382
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:19717
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16792
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:24881
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:11837
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition var.c:21104
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition var.c:16732
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition var.c:9167
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:16873
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:12746
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:4674
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3533
static SCIP_BDCHGIDX initbdchgidx
Definition var.c:22787
SCIP_RETCODE SCIPvarAddClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:16646
static SCIP_RETCODE varProcessChgUbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:12603
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:17064
SCIP_RETCODE SCIPvarChgLbLocalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newbound)
Definition var.c:12881
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1327
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition var.c:9203
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:158
static SCIP_Real adjustedUbExactFloat(SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1957
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LOCKTYPE locktype, int addnlocksdown, int addnlocksup)
Definition var.c:4202
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition var.c:8976
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13765
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition var.c:22614
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition var.c:20742
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18120
SCIP_Bool SCIPvarIsAggrCoefAcceptable(SCIP_SET *set, SCIP_VAR *var, SCIP_Real scalar)
Definition var.c:8906
SCIP_RETCODE SCIPvarAddExactData(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, SCIP_RATIONAL *obj)
Definition var.c:2578
SCIP_RETCODE SCIPvarIncGMIeffSum(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition var.c:22480
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition var.c:182
static SCIP_RETCODE varProcessChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition var.c:10519
SCIP_Real SCIPvarGetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition var.c:22524
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:9957
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25080
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition var.c:19209
SCIP_RETCODE SCIPvarGetActiveRepresentatives(SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition var.c:5174
static SCIP_RETCODE varAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *infeasible, int *nbdchgs, SCIP_Bool *added)
Definition var.c:14867
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:13316
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:4814
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition var.c:18936
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21485
SCIP_RETCODE SCIPvarCopyExactData(BMS_BLKMEM *blkmem, SCIP_VAR *targetvar, SCIP_VAR *sourcevar, SCIP_Bool negateobj)
Definition var.c:2687
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:13019
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1399
SCIP_RETCODE SCIPvarParseOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition var.c:3236
SCIP_RETCODE SCIPvarAddVub(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15828
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22009
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:10478
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition var.c:9099
SCIP_RETCODE SCIPvarAggregateExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *aggvar, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:6905
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition var.c:208
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition var.c:3830
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition var.c:6128
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:14092
void SCIPvarSetUbCertificateIndexLocal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25168
void SCIPvarAdjustUbExactFloat(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:9991
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:9084
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition var.c:3505
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13913
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition var.c:19656
void SCIPvarAdjustLbExactFloat(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:9940
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:16937
static SCIP_RETCODE boundchgReleaseData(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1290
static SCIP_RETCODE varEventUbChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LPEXACT *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:12009
SCIP_RETCODE SCIPvarAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:16286
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21396
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition var.c:1258
SCIP_RETCODE SCIPvarChgObjExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LPEXACT *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *newobj)
Definition var.c:9491
static SCIP_RETCODE varEventGlbChangedExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition var.c:10328
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:17128
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22393
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition var.c:8873
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition var.c:2006
SCIP_RETCODE SCIPvarGetMultaggrLbLocalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *result)
Definition var.c:13681
static void printBoundsExact(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, const char *name)
Definition var.c:3891
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:9068
SCIP_RETCODE SCIPvarGetActiveRepresentativesExact(SCIP_SET *set, SCIP_VAR **vars, SCIP_RATIONAL **scalars, int *nvars, int varssize, SCIP_RATIONAL *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition var.c:5505
SCIP_RETCODE SCIPvarAddToRowExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LPEXACT *lpexact, SCIP_ROWEXACT *rowexact, SCIP_RATIONAL *val)
Definition var.c:20164
internal methods for problem variables