SCIP Doxygen Documentation
Loading...
Searching...
No Matches
var.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file var.c
26 * @ingroup OTHER_CFILES
27 * @brief methods for problem variables
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Gerald Gamrath
31 * @author Stefan Heinz
32 * @author Marc Pfetsch
33 * @author Michael Winkler
34 * @author Kati Wolter
35 * @author Stefan Vigerske
36 *
37 * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
38 * corresponding linear constraint if it exists. This seems to require some work, since the linear
39 * constraint has to be stored. Moreover, it has even to be created in case the original constraint
40 * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
41 * changed. This has to be done with care in order to not loose the performance gains of
42 * multi-aggregation.
43 */
44
45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46#include "scip/cons.h"
47#include "scip/certificate.h"
48#include "scip/event.h"
49#include "scip/history.h"
50#include "scip/implics.h"
51#include "scip/lp.h"
52#include "scip/lpexact.h"
53#include "scip/primal.h"
54#include "scip/prob.h"
55#include "scip/pub_cons.h"
56#include "scip/pub_history.h"
57#include "scip/pub_implics.h"
58#include "scip/pub_lp.h"
59#include "scip/pub_message.h"
60#include "scip/pub_misc.h"
61#include "scip/pub_misc_sort.h"
62#include "scip/pub_prop.h"
63#include "scip/pub_var.h"
64#include "scip/relax.h"
66#include "scip/scip_exact.h"
67#include "scip/scip_prob.h"
68#include "scip/scip_probing.h"
69#include "scip/set.h"
70#include "scip/sol.h"
71#include "scip/stat.h"
72#include "scip/struct_event.h"
73#include "scip/struct_lp.h"
74#include "scip/struct_lpexact.h"
75#include "scip/struct_prob.h"
76#include "scip/struct_set.h"
77#include "scip/struct_stat.h"
78#include "scip/struct_var.h"
79#include "scip/tree.h"
80#include "scip/var.h"
81#include <string.h>
82
83#define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
84 * in implication graph */
85#define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
86
87
88/*
89 * Debugging variable release and capture
90 *
91 * Define DEBUGUSES_VARNAME to the name of the variable for which to print
92 * a backtrace when it is captured and released.
93 * Optionally define DEBUGUSES_PROBNAME to the name of a SCIP problem to consider.
94 * Have DEBUGUSES_NOADDR2LINE defined if you do not have addr2line installed on your system.
95 */
96/* #define DEBUGUSES_VARNAME "t_t_b7" */
97/* #define DEBUGUSES_PROBNAME "t_st_e35_rens" */
98/* #define DEBUGUSES_NOADDR2LINE */
99
100#ifdef DEBUGUSES_VARNAME
101#include <execinfo.h>
102#include <stdio.h>
103#include <stdlib.h>
104#include "scip/struct_scip.h"
105
106/** obtains a backtrace and prints it to stdout. */
107static
108void print_backtrace(void)
109{
110 void* array[10];
111 char** strings;
112 int size;
113 int i;
114
115 size = backtrace(array, 10);
116 strings = backtrace_symbols(array, size);
117 if( strings == NULL )
118 return;
119
120 /* skip first entry, which is the print_backtrace function */
121 for( i = 1; i < size; ++i )
122 {
123 /* if string is something like
124 * /path/to/scip/bin/../lib/shared/libscip-7.0.1.3.linux.x86_64.gnu.dbg.so(+0x2675dd3)
125 * (that is, no function name because it is a inlined function), then call
126 * addr2line -e <libname> <addr> to get func and code line
127 * dladdr() may be an alternative
128 */
129 char* openpar;
130 char* closepar = NULL;
131#ifndef DEBUGUSES_NOADDR2LINE
132 openpar = strchr(strings[i], '(');
133 if( openpar != NULL && openpar[1] == '+' )
134 closepar = strchr(openpar+2, ')');
135#endif
136 if( closepar != NULL )
137 {
138 char cmd[SCIP_MAXSTRLEN];
139 (void) SCIPsnprintf(cmd, SCIP_MAXSTRLEN, "addr2line -f -p -e \"%.*s\" %.*s", openpar - strings[i], strings[i], closepar-openpar-1, openpar+1);
140 printf(" ");
141 fflush(stdout);
142 system(cmd);
143 }
144 else
145 printf(" %s\n", strings[i]);
146 }
147
148 free(strings);
149}
150#endif
151
152/*
153 * hole, holelist, and domain methods
154 */
155
156/** creates a new holelist element */
157static
159 SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
160 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
161 SCIP_SET* set, /**< global SCIP settings */
162 SCIP_Real left, /**< left bound of open interval in new hole */
163 SCIP_Real right /**< right bound of open interval in new hole */
164 )
165{
166 assert(holelist != NULL);
167 assert(blkmem != NULL);
168 assert(SCIPsetIsLT(set, left, right));
169
170 SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
171
172 SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
173 (*holelist)->hole.left = left;
174 (*holelist)->hole.right = right;
175 (*holelist)->next = NULL;
176
177 return SCIP_OKAY;
178}
179
180/** frees all elements in the holelist */
181static
183 SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
184 BMS_BLKMEM* blkmem /**< block memory for target holelist */
185 )
186{
187 assert(holelist != NULL);
188 assert(blkmem != NULL);
189
190 while( *holelist != NULL )
191 {
192 SCIP_HOLELIST* next;
193
194 SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
195 (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
196
197 next = (*holelist)->next;
198 BMSfreeBlockMemory(blkmem, holelist);
199 assert(*holelist == NULL);
200
201 *holelist = next;
202 }
203 assert(*holelist == NULL);
204}
205
206/** duplicates a list of holes */
207static
209 SCIP_HOLELIST** target, /**< pointer to target holelist */
210 BMS_BLKMEM* blkmem, /**< block memory for target holelist */
211 SCIP_SET* set, /**< global SCIP settings */
212 SCIP_HOLELIST* source /**< holelist to duplicate */
213 )
214{
215 assert(target != NULL);
216
217 while( source != NULL )
218 {
219 assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
220 SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
221 source = source->next;
222 target = &(*target)->next;
223 }
224
225 return SCIP_OKAY;
226}
227
228/** adds a hole to the domain */
229static
231 SCIP_DOM* dom, /**< domain to add hole to */
232 BMS_BLKMEM* blkmem, /**< block memory */
233 SCIP_SET* set, /**< global SCIP settings */
234 SCIP_Real left, /**< left bound of open interval in new hole */
235 SCIP_Real right, /**< right bound of open interval in new hole */
236 SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
237 )
238{
239 SCIP_HOLELIST** insertpos;
240 SCIP_HOLELIST* next;
241
242 assert(dom != NULL);
243 assert(added != NULL);
244
245 /* search for the position of the new hole */
246 insertpos = &dom->holelist;
247 while( *insertpos != NULL && (*insertpos)->hole.left < left )
248 insertpos = &(*insertpos)->next;
249
250 /* check if new hole already exists in the hole list or is a sub hole of an existing one */
251 if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
252 {
253 SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
254 left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
255 *added = FALSE;
256 return SCIP_OKAY;
257 }
258
259 /* add hole */
260 *added = TRUE;
261
262 next = *insertpos;
263 SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
264 (*insertpos)->next = next;
265
266 return SCIP_OKAY;
267}
268
269/** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
270/**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
271 * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
272 * merge */
273static
275 SCIP_DOM* dom, /**< domain to merge */
276 BMS_BLKMEM* blkmem, /**< block memory */
277 SCIP_SET* set, /**< global SCIP settings */
278 SCIP_Real* newlb, /**< pointer to store new lower bound */
279 SCIP_Real* newub /**< pointer to store new upper bound */
280 )
281{
282 SCIP_HOLELIST** holelistptr;
283 SCIP_HOLELIST** lastnextptr;
284 SCIP_Real* lastrightptr;
285
286 assert(dom != NULL);
287 assert(SCIPsetIsLE(set, dom->lb, dom->ub));
288
289#ifndef NDEBUG
290 {
291 /* check if the holelist is sorted w.r.t. to the left interval bounds */
292 SCIP_Real lastleft;
293
294 holelistptr = &dom->holelist;
295
296 lastleft = -SCIPsetInfinity(set);
297
298 while( *holelistptr != NULL )
299 {
300 if( (*holelistptr)->next != NULL )
301 {
302 assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
303 lastleft = (*holelistptr)->hole.left;
304 }
305
306 holelistptr = &(*holelistptr)->next;
307 }
308 }
309#endif
310
311 SCIPsetDebugMsg(set, "merge hole list\n");
312
313 holelistptr = &dom->holelist;
314 lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
315 lastnextptr = holelistptr;
316
317 while( *holelistptr != NULL )
318 {
319 SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
320
321 /* check that the hole is not empty */
322 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
323
324 if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
325 {
326 /* the remaining holes start behind the upper bound: remove them */
327 SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
328 holelistFree(holelistptr, blkmem);
329 assert(*holelistptr == NULL);
330
331 /* unlink this hole from the previous hole */
332 *lastnextptr = NULL;
333 }
334 else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
335 {
336 /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
337 SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
338
339 assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
340
341 /* adjust upper bound */
342 dom->ub = (*holelistptr)->hole.left;
343
344 if(newub != NULL )
345 *newub = (*holelistptr)->hole.left;
346
347 /* remove remaining hole list */
348 holelistFree(holelistptr, blkmem);
349 assert(*holelistptr == NULL);
350
351 /* unlink this hole from the previous hole */
352 *lastnextptr = NULL;
353 }
354 else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
355 {
356 /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
357 * the last hole, delete this hole */
358 SCIP_HOLELIST* nextholelist;
359
360 if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
361 {
362 /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
363 * the lower bound */
364 SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
365 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
366
367 /* adjust lower bound */
368 dom->lb = *lastrightptr;
369
370 if(newlb != NULL )
371 *newlb = *lastrightptr;
372 }
373 else
374 {
375 SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
376 *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
377 *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
378 }
379 nextholelist = (*holelistptr)->next;
380 (*holelistptr)->next = NULL;
381 holelistFree(holelistptr, blkmem);
382
383 /* connect the linked list after removing the hole */
384 *lastnextptr = nextholelist;
385
386 /* get next hole */
387 *holelistptr = nextholelist;
388 }
389 else
390 {
391 /* the holes do not overlap: update lastholelist and lastrightptr */
392 lastrightptr = &(*holelistptr)->hole.right;
393 lastnextptr = &(*holelistptr)->next;
394
395 /* get next hole */
396 holelistptr = &(*holelistptr)->next;
397 }
398 }
399
400#ifndef NDEBUG
401 {
402 /* check that holes are merged */
403 SCIP_Real lastright;
404
405 lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
406 holelistptr = &dom->holelist;
407
408 while( *holelistptr != NULL )
409 {
410 /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
411 assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
412
413 /* check the hole property (check that the hole is not empty) */
414 assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
415 lastright = (*holelistptr)->hole.right;
416
417 /* get next hole */
418 holelistptr = &(*holelistptr)->next;
419 }
420
421 /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
422 assert( SCIPsetIsLE(set, lastright, dom->ub) );
423 }
424#endif
425}
426
427/*
428 * domain change methods
429 */
430
431/** ensures, that bound change info array for lower bound changes can store at least num entries */
432static
434 SCIP_VAR* var, /**< problem variable */
435 BMS_BLKMEM* blkmem, /**< block memory */
436 SCIP_SET* set, /**< global SCIP settings */
437 int num /**< minimum number of entries to store */
438 )
439{
440 assert(var != NULL);
441 assert(var->nlbchginfos <= var->lbchginfossize);
443
444 if( num > var->lbchginfossize )
445 {
446 int newsize;
447
448 newsize = SCIPsetCalcMemGrowSize(set, num);
449 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
450 var->lbchginfossize = newsize;
451 }
452 assert(num <= var->lbchginfossize);
453
454 return SCIP_OKAY;
455}
456
457/** ensures, that bound change info array for upper bound changes can store at least num entries */
458static
460 SCIP_VAR* var, /**< problem variable */
461 BMS_BLKMEM* blkmem, /**< block memory */
462 SCIP_SET* set, /**< global SCIP settings */
463 int num /**< minimum number of entries to store */
464 )
465{
466 assert(var != NULL);
467 assert(var->nubchginfos <= var->ubchginfossize);
469
470 if( num > var->ubchginfossize )
471 {
472 int newsize;
473
474 newsize = SCIPsetCalcMemGrowSize(set, num);
475 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
476 var->ubchginfossize = newsize;
477 }
478 assert(num <= var->ubchginfossize);
479
480 return SCIP_OKAY;
481}
482
483/** adds domain change info to the variable's lower bound change info array */
484static
486 SCIP_VAR* var, /**< problem variable */
487 BMS_BLKMEM* blkmem, /**< block memory */
488 SCIP_SET* set, /**< global SCIP settings */
489 SCIP_Real oldbound, /**< old value for bound */
490 SCIP_Real newbound, /**< new value for bound */
491 int depth, /**< depth in the tree, where the bound change takes place */
492 int pos, /**< position of the bound change in its bound change array */
493 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
494 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
495 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
496 int inferinfo, /**< user information for inference to help resolving the conflict */
497 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
498 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
499 )
500{
501 assert(var != NULL);
502 assert(SCIPsetIsLT(set, oldbound, newbound));
505 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
506 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
507 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
508 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
509 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
510
511 SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
512 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
513 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
514 oldbound, newbound);
515
516 SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
517 var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
518 var->lbchginfos[var->nlbchginfos].newbound = newbound;
519 var->lbchginfos[var->nlbchginfos].var = var;
520 var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
521 var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
522 var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
523 var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
524 var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
525 var->lbchginfos[var->nlbchginfos].redundant = FALSE;
526 var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
527 var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
528 var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
529
530 /**@note The "pos" data member of the bound change info has a size of 27 bits */
531 assert(var->nlbchginfos < 1 << 27);
532
533 switch( boundchgtype )
534 {
536 break;
538 assert(infercons != NULL);
539 var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
540 break;
542 var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
543 break;
544 default:
545 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
546 return SCIP_INVALIDDATA;
547 }
548
549 var->nlbchginfos++;
550
551 assert(var->nlbchginfos < 2
552 || SCIPbdchgidxIsEarlier(&var->lbchginfos[var->nlbchginfos-2].bdchgidx,
553 &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
554
555 return SCIP_OKAY;
556}
557
558/** adds domain change info to the variable's upper bound change info array */
559static
561 SCIP_VAR* var, /**< problem variable */
562 BMS_BLKMEM* blkmem, /**< block memory */
563 SCIP_SET* set, /**< global SCIP settings */
564 SCIP_Real oldbound, /**< old value for bound */
565 SCIP_Real newbound, /**< new value for bound */
566 int depth, /**< depth in the tree, where the bound change takes place */
567 int pos, /**< position of the bound change in its bound change array */
568 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
569 SCIP_CONS* infercons, /**< constraint that inferred this bound change, or NULL */
570 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
571 int inferinfo, /**< user information for inference to help resolving the conflict */
572 SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
573 SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or inferred bound change */
574 )
575{
576 assert(var != NULL);
577 assert(SCIPsetIsGT(set, oldbound, newbound));
580 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
581 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
582 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
583 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
584 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
585
586 SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
587 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
588 infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
589 oldbound, newbound);
590
591 SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
592 var->ubchginfos[var->nubchginfos].oldbound = oldbound;
593 var->ubchginfos[var->nubchginfos].newbound = newbound;
594 var->ubchginfos[var->nubchginfos].var = var;
595 var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
596 var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
597 var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
598 var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
599 var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
600 var->ubchginfos[var->nubchginfos].redundant = FALSE;
601 var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
602 var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
603 var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
604
605 /**@note The "pos" data member of the bound change info has a size of 27 bits */
606 assert(var->nubchginfos < 1 << 27);
607
608 switch( boundchgtype )
609 {
611 break;
613 assert(infercons != NULL);
614 var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
615 break;
617 var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
618 break;
619 default:
620 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
621 return SCIP_INVALIDDATA;
622 }
623
624 var->nubchginfos++;
625
626 assert(var->nubchginfos < 2
627 || SCIPbdchgidxIsEarlier(&var->ubchginfos[var->nubchginfos-2].bdchgidx,
628 &var->ubchginfos[var->nubchginfos-1].bdchgidx));
629
630 return SCIP_OKAY;
631}
632
633/** applies single bound change */
634static
636 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
637 BMS_BLKMEM* blkmem, /**< block memory */
638 SCIP_SET* set, /**< global SCIP settings */
639 SCIP_STAT* stat, /**< problem statistics */
640 SCIP_LP* lp, /**< current LP data */
641 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
642 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
643 int depth, /**< depth in the tree, where the bound change takes place */
644 int pos, /**< position of the bound change in its bound change array */
645 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
646 )
647{
648 SCIP_VAR* var;
649
650 assert(boundchg != NULL);
651 assert(stat != NULL);
652 assert(depth > 0);
653 assert(pos >= 0);
654 assert(cutoff != NULL);
655 assert(boundchg->newboundexact != NULL);
656
657 *cutoff = FALSE;
658
659 /* ignore redundant bound changes */
660 if( boundchg->redundant )
661 return SCIP_OKAY;
662
663 var = boundchg->var;
664 assert(var != NULL);
667
668 /* apply bound change */
669 switch( boundchg->boundtype )
670 {
672 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
674 {
676 {
677 /* add the bound change info to the variable's bound change info array */
678 switch( boundchg->boundchgtype )
679 {
681 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
682 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
683 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
685 stat->lastbranchvar = var;
687 stat->lastbranchvalue = boundchg->newbound;
688 break;
689
691 assert(boundchg->data.inferencedata.reason.cons != NULL);
692 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
693 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
694 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
695 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
696 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
697 boundchg->data.inferencedata.info,
699 break;
700
702 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
703 boundchg->data.inferencedata.reason.prop != NULL
704 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
705 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
706 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
707 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
708 boundchg->data.inferencedata.info,
710 break;
711
712 default:
713 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
714 return SCIP_INVALIDDATA;
715 }
717 {
718 assert( var->exactdata->locdom.lbcertificateidx != -1 || SCIPsetIsInfinity(set, -var->locdom.lb) );
719 var->lbchginfos[var->nlbchginfos - 1].oldcertificateindex = var->exactdata->locdom.lbcertificateidx;
721 }
722 /* change local bound of variable */
723 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, boundchg->newboundexact) );
724 }
725 else
726 {
727 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
728 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
729 *cutoff = TRUE;
730 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
731 }
732 }
733 else
734 {
735 /* mark bound change to be inactive */
736 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
737 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
738 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
739 boundchg->redundant = TRUE;
740 }
741 break;
742
744 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
746 {
748 {
749 /* add the bound change info to the variable's bound change info array */
750 switch( boundchg->boundchgtype )
751 {
753 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
754 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
755 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
757 stat->lastbranchvar = var;
759 stat->lastbranchvalue = boundchg->newbound;
760 break;
761
763 assert(boundchg->data.inferencedata.reason.cons != NULL);
764 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
765 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
766 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
767 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
768 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
769 boundchg->data.inferencedata.info,
771 break;
772
774 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
775 boundchg->data.inferencedata.reason.prop != NULL
776 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
777 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
778 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
779 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
780 boundchg->data.inferencedata.info,
782 break;
783
784 default:
785 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
786 return SCIP_INVALIDDATA;
787 }
788
790 {
791 assert( var->exactdata->locdom.ubcertificateidx != -1 || SCIPsetIsInfinity(set, var->locdom.ub) );
792 var->ubchginfos[var->nubchginfos - 1].oldcertificateindex = var->exactdata->locdom.ubcertificateidx;
794 }
795 /* change local bound of variable */
796 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, boundchg->newboundexact) );
797 }
798 else
799 {
800 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
801 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
802 *cutoff = TRUE;
803 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
804 }
805 }
806 else
807 {
808 /* mark bound change to be inactive */
809 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
810 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
811 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
812 boundchg->redundant = TRUE;
813 }
814 break;
815
816 default:
817 SCIPerrorMessage("unknown bound type\n");
818 return SCIP_INVALIDDATA;
819 }
820
821 /* update the branching and inference history */
822 if( !boundchg->applied && !boundchg->redundant )
823 {
824 assert(var == boundchg->var);
825
827 {
828 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
831 }
832 else if( stat->lastbranchvar != NULL )
833 {
834 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
835 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
836 }
837 boundchg->applied = TRUE;
838 }
839
840 return SCIP_OKAY;
841}
842
843
844/** applies single bound change */
846 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
847 BMS_BLKMEM* blkmem, /**< block memory */
848 SCIP_SET* set, /**< global SCIP settings */
849 SCIP_STAT* stat, /**< problem statistics */
850 SCIP_LP* lp, /**< current LP data */
851 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
852 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
853 int depth, /**< depth in the tree, where the bound change takes place */
854 int pos, /**< position of the bound change in its bound change array */
855 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
856 )
857{
858 SCIP_VAR* var;
859
860 assert(boundchg != NULL);
861 assert(stat != NULL);
862 assert(depth > 0);
863 assert(pos >= 0);
864 assert(cutoff != NULL);
865
866 *cutoff = FALSE;
867
868 /* ignore redundant bound changes */
869 if( boundchg->redundant )
870 return SCIP_OKAY;
871
872 if( boundchg->newboundexact != NULL)
873 return boundchgApplyExact(boundchg, blkmem, set, stat, lp, branchcand, eventqueue, depth, pos, cutoff);
874
875 var = boundchg->var;
876 assert(var != NULL);
879
880 /* apply bound change */
881 switch( boundchg->boundtype )
882 {
884 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
885 if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
886 {
887 if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
888 {
889 /* add the bound change info to the variable's bound change info array */
890 switch( boundchg->boundchgtype )
891 {
893 SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
894 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
895 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
897 stat->lastbranchvar = var;
899 stat->lastbranchvalue = boundchg->newbound;
900 break;
901
903 assert(boundchg->data.inferencedata.reason.cons != NULL);
904 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
905 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
906 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
907 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
908 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
909 boundchg->data.inferencedata.info,
911 break;
912
914 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
915 boundchg->data.inferencedata.reason.prop != NULL
916 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
917 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
918 SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
919 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
920 boundchg->data.inferencedata.info,
922 break;
923
924 default:
925 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
926 return SCIP_INVALIDDATA;
927 }
928
930 {
931 assert( var->exactdata->locdom.lbcertificateidx != -1 || SCIPsetIsInfinity(set, -var->locdom.lb) );
932 var->lbchginfos[var->nlbchginfos - 1].oldcertificateindex = var->exactdata->locdom.lbcertificateidx;
934 }
935
936 /* change local bound of variable */
937 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
938 }
939 else
940 {
941 SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
942 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
943 *cutoff = TRUE;
944 boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
945 }
946 }
947 else
948 {
949 /* mark bound change to be inactive */
950 SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
951 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
952 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
953 boundchg->redundant = TRUE;
954 }
955 break;
956
958 /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
959 if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
960 {
961 if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
962 {
963 /* add the bound change info to the variable's bound change info array */
964 switch( boundchg->boundchgtype )
965 {
967 SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
968 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
969 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
971 stat->lastbranchvar = var;
973 stat->lastbranchvalue = boundchg->newbound;
974 break;
975
977 assert(boundchg->data.inferencedata.reason.cons != NULL);
978 SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
979 SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
980 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
981 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
982 boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
983 boundchg->data.inferencedata.info,
985 break;
986
988 SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
989 boundchg->data.inferencedata.reason.prop != NULL
990 ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
991 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
992 SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
993 boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
994 boundchg->data.inferencedata.info,
996 break;
997
998 default:
999 SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
1000 return SCIP_INVALIDDATA;
1001 }
1002
1004 {
1005 assert( var->exactdata->locdom.ubcertificateidx != -1 || SCIPsetIsInfinity(set, var->locdom.ub) );
1006 var->ubchginfos[var->nubchginfos - 1].oldcertificateindex = var->exactdata->locdom.ubcertificateidx;
1008 }
1009
1010 /* change local bound of variable */
1011 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
1012 }
1013 else
1014 {
1015 SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
1016 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
1017 *cutoff = TRUE;
1018 boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
1019 }
1020 }
1021 else
1022 {
1023 /* mark bound change to be inactive */
1024 SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
1025 (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1026 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
1027 boundchg->redundant = TRUE;
1028 }
1029 break;
1030
1031 default:
1032 SCIPerrorMessage("unknown bound type\n");
1033 return SCIP_INVALIDDATA;
1034 }
1035
1036 /* update the branching and inference history */
1037 if( !boundchg->applied && !boundchg->redundant )
1038 {
1039 assert(var == boundchg->var);
1040
1042 {
1043 SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
1046 }
1047 else if( stat->lastbranchvar != NULL )
1048 {
1049 /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
1050 SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
1051 }
1052 boundchg->applied = TRUE;
1053 }
1054
1055 return SCIP_OKAY;
1056}
1057
1058/** undoes single bound change */
1060 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1061 BMS_BLKMEM* blkmem, /**< block memory */
1062 SCIP_SET* set, /**< global SCIP settings */
1063 SCIP_STAT* stat, /**< problem statistics */
1064 SCIP_LP* lp, /**< current LP data */
1065 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1066 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1067 )
1068{
1069 SCIP_VAR* var;
1070
1071 assert(boundchg != NULL);
1072 assert(stat != NULL);
1073
1074 /* ignore redundant bound changes */
1075 if( boundchg->redundant )
1076 return SCIP_OKAY;
1077
1078 var = boundchg->var;
1079 assert(var != NULL);
1081
1082 /* undo bound change: apply the previous bound change of variable */
1083 switch( boundchg->boundtype )
1084 {
1086 var->nlbchginfos--;
1087 assert(var->nlbchginfos >= 0);
1088 assert(var->lbchginfos != NULL);
1089 assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
1090 assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
1091
1092 SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
1093 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
1094 var->lbchginfos[var->nlbchginfos].bdchgidx.depth, var->lbchginfos[var->nlbchginfos].bdchgidx.pos,
1095 var->lbchginfos[var->nlbchginfos].oldbound, var->lbchginfos[var->nlbchginfos].newbound);
1096
1097 /* in case certificate is used, set back the certificate line index */
1099 && !SCIPsetIsInfinity(set, -var->lbchginfos[var->nlbchginfos].oldbound) )
1100 {
1102 var->lbchginfos[var->nlbchginfos].oldcertificateindex) );
1103 }
1104
1105 if( set->exact_enable && !SCIPrationalIsFpRepresentable(SCIPvarGetLbGlobalExact(boundchg->var))
1106 && SCIPsetIsEQ(set, var->lbchginfos[var->nlbchginfos].oldbound, SCIPvarGetLbGlobal(boundchg->var) ) )
1107 {
1108 /* reinstall the exact global bound, if necessary */
1109 SCIP_CALL( SCIPvarChgLbLocalExact(boundchg->var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue,
1110 SCIPvarGetLbGlobalExact(boundchg->var)) );
1111 }
1112 else
1113 {
1114 /* reinstall the previous local bound */
1115 SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
1116 var->lbchginfos[var->nlbchginfos].oldbound) );
1117 }
1118
1119 /* in case all bound changes are removed the local bound should match the global bound */
1120 assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
1121
1122 break;
1123
1125 var->nubchginfos--;
1126 assert(var->nubchginfos >= 0);
1127 assert(var->ubchginfos != NULL);
1128 assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
1129 assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
1130
1131 SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
1132 SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
1133 var->ubchginfos[var->nubchginfos].bdchgidx.depth, var->ubchginfos[var->nubchginfos].bdchgidx.pos,
1134 var->ubchginfos[var->nubchginfos].oldbound, var->ubchginfos[var->nubchginfos].newbound);
1135
1137 && !SCIPsetIsInfinity(set, var->ubchginfos[var->nubchginfos].oldbound) )
1138 {
1140 var->ubchginfos[var->nubchginfos].oldcertificateindex) );
1141 }
1142
1143 if( set->exact_enable && !SCIPrationalIsFpRepresentable(SCIPvarGetUbGlobalExact(boundchg->var))
1144 && SCIPsetIsEQ(set, var->ubchginfos[var->nubchginfos].oldbound, SCIPvarGetUbGlobal(boundchg->var) ) )
1145 {
1146 /* reinstall the exact global bound, if necessary */
1147 SCIP_CALL( SCIPvarChgUbLocalExact(boundchg->var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue,
1148 SCIPvarGetUbGlobalExact(boundchg->var)) );
1149 }
1150 else
1151 {
1152 /* reinstall the previous local bound */
1153 SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
1154 var->ubchginfos[var->nubchginfos].oldbound) );
1155 }
1156
1157 /* in case all bound changes are removed the local bound should match the global bound */
1158 assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
1159
1160 /* in case certificate is used, set back the certificate line index */
1161
1162 break;
1163
1164 default:
1165 SCIPerrorMessage("unknown bound type\n");
1166 return SCIP_INVALIDDATA;
1167 }
1168
1169 /* update last branching variable */
1171 {
1172 stat->lastbranchvar = NULL;
1174 }
1175
1176 return SCIP_OKAY;
1177}
1178
1179/** applies single bound change to the global problem by changing the global bound of the corresponding variable */
1180static
1182 SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
1183 BMS_BLKMEM* blkmem, /**< block memory */
1184 SCIP_SET* set, /**< global SCIP settings */
1185 SCIP_STAT* stat, /**< problem statistics */
1186 SCIP_LP* lp, /**< current LP data */
1187 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1188 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1189 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1190 SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
1191 )
1192{
1193 SCIP_VAR* var;
1194 SCIP_Real newbound;
1195 SCIP_BOUNDTYPE boundtype;
1196
1197 assert(boundchg != NULL);
1198 assert(cutoff != NULL);
1199
1200 *cutoff = FALSE;
1201
1202 /* ignore redundant bound changes */
1203 if( boundchg->redundant )
1204 return SCIP_OKAY;
1205
1206 var = SCIPboundchgGetVar(boundchg);
1207 newbound = SCIPboundchgGetNewbound(boundchg);
1208 boundtype = SCIPboundchgGetBoundtype(boundchg);
1209
1210 /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
1211 * after that bound change was applied
1212 *
1213 * @note a global bound change is not captured by the redundant member of the bound change data structure
1214 */
1215 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
1216 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
1217 {
1218 return SCIP_OKAY;
1219 }
1220
1221 SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
1223 boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
1224
1225 /* check for cutoff */
1226 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
1227 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
1228 {
1229 *cutoff = TRUE;
1230 return SCIP_OKAY;
1231 }
1232
1233 if( SCIPisCertified(set->scip) )
1234 {
1235 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1236 {
1237 var->exactdata->glbdom.lbcertificateidx = boundchg->certificateindex;
1238 var->exactdata->locdom.lbcertificateidx = boundchg->certificateindex;
1239 }
1240 else if( boundtype == SCIP_BOUNDTYPE_UPPER )
1241 {
1242 var->exactdata->glbdom.ubcertificateidx = boundchg->certificateindex;
1243 var->exactdata->locdom.ubcertificateidx = boundchg->certificateindex;
1244 }
1245#ifndef NDEBUG
1247#endif
1248 }
1249
1250 /* apply bound change */
1251 SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
1252
1253 return SCIP_OKAY;
1254}
1255
1256/** captures branching and inference data of bound change */
1257static
1259 SCIP_BOUNDCHG* boundchg /**< bound change to remove */
1260 )
1261{
1262 assert(boundchg != NULL);
1263
1264 /* capture variable associated with the bound change */
1265 assert(boundchg->var != NULL);
1266 SCIPvarCapture(boundchg->var);
1267
1268 switch( boundchg->boundchgtype )
1269 {
1272 break;
1273
1275 assert(boundchg->data.inferencedata.var != NULL);
1276 assert(boundchg->data.inferencedata.reason.cons != NULL);
1277 SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
1278 break;
1279
1280 default:
1281 SCIPerrorMessage("invalid bound change type\n");
1282 return SCIP_INVALIDDATA;
1283 }
1284
1285 return SCIP_OKAY;
1286}
1287
1288/** releases branching and inference data of bound change */
1289static
1291 SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
1292 BMS_BLKMEM* blkmem, /**< block memory */
1293 SCIP_SET* set, /**< global SCIP settings */
1294 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1295 SCIP_LP* lp /**< current LP data */
1296
1297 )
1298{
1299 assert(boundchg != NULL);
1300
1301 switch( boundchg->boundchgtype )
1302 {
1305 break;
1306
1308 assert(boundchg->data.inferencedata.var != NULL);
1309 assert(boundchg->data.inferencedata.reason.cons != NULL);
1310 SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
1311 break;
1312
1313 default:
1314 SCIPerrorMessage("invalid bound change type\n");
1315 return SCIP_INVALIDDATA;
1316 }
1317
1318 /* release variable */
1319 assert(boundchg->var != NULL);
1320 SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
1321
1322 return SCIP_OKAY;
1323}
1324
1325/** creates empty domain change data with dynamic arrays */
1326static
1328 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1329 BMS_BLKMEM* blkmem /**< block memory */
1330 )
1331{
1332 assert(domchg != NULL);
1333 assert(blkmem != NULL);
1334
1335 SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
1336 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1337 (*domchg)->domchgdyn.nboundchgs = 0;
1338 (*domchg)->domchgdyn.boundchgs = NULL;
1339 (*domchg)->domchgdyn.nholechgs = 0;
1340 (*domchg)->domchgdyn.holechgs = NULL;
1341 (*domchg)->domchgdyn.boundchgssize = 0;
1342 (*domchg)->domchgdyn.holechgssize = 0;
1343
1344 return SCIP_OKAY;
1345}
1346
1347/** frees domain change data */
1349 SCIP_DOMCHG** domchg, /**< pointer to domain change */
1350 BMS_BLKMEM* blkmem, /**< block memory */
1351 SCIP_SET* set, /**< global SCIP settings */
1352 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1353 SCIP_LP* lp /**< current LP data */
1354 )
1355{
1356 assert(domchg != NULL);
1357 assert(blkmem != NULL);
1358
1359 if( *domchg != NULL )
1360 {
1361 int i;
1362
1363 /* release variables, branching and inference data associated with the bound changes */
1364 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1365 {
1366 SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1367 if( (*domchg)->domchgbound.boundchgs[i].newboundexact != NULL )
1368 SCIPrationalFreeBlock(blkmem, &(*domchg)->domchgbound.boundchgs[i].newboundexact);
1369 }
1370
1371 /* free memory for bound and hole changes */
1372 switch( (*domchg)->domchgdyn.domchgtype )
1373 {
1375 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1376 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1377 break;
1379 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1380 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1381 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1382 break;
1384 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1385 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1386 BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1387 break;
1388 default:
1389 SCIPerrorMessage("invalid domain change type\n");
1390 return SCIP_INVALIDDATA;
1391 }
1392 }
1393
1394 return SCIP_OKAY;
1395}
1396
1397/** converts a static domain change data into a dynamic one */
1398static
1400 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1401 BMS_BLKMEM* blkmem /**< block memory */
1402 )
1403{
1404 assert(domchg != NULL);
1405 assert(blkmem != NULL);
1406
1407 SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1408
1409 if( *domchg == NULL )
1410 {
1411 SCIP_CALL( domchgCreate(domchg, blkmem) );
1412 }
1413 else
1414 {
1415 switch( (*domchg)->domchgdyn.domchgtype )
1416 {
1418 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1419 (*domchg)->domchgdyn.nholechgs = 0;
1420 (*domchg)->domchgdyn.holechgs = NULL;
1421 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1422 (*domchg)->domchgdyn.holechgssize = 0;
1423 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1424 break;
1426 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1427 (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1428 (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1429 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1430 break;
1432 break;
1433 default:
1434 SCIPerrorMessage("invalid domain change type\n");
1435 return SCIP_INVALIDDATA;
1436 }
1437 }
1438#ifndef NDEBUG
1439 {
1440 int i;
1441 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1442 assert(!SCIPvarIsIntegral((*domchg)->domchgbound.boundchgs[i].var)
1443 || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1444 }
1445#endif
1446
1447 return SCIP_OKAY;
1448}
1449
1450/** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1452 SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1453 BMS_BLKMEM* blkmem, /**< block memory */
1454 SCIP_SET* set, /**< global SCIP settings */
1455 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1456 SCIP_LP* lp /**< current LP data */
1457 )
1458{
1459 assert(domchg != NULL);
1460 assert(blkmem != NULL);
1461
1462 SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1463
1464 if( *domchg != NULL )
1465 {
1466 switch( (*domchg)->domchgdyn.domchgtype )
1467 {
1469 if( (*domchg)->domchgbound.nboundchgs == 0 )
1470 {
1471 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1472 }
1473 break;
1475 if( (*domchg)->domchgboth.nholechgs == 0 )
1476 {
1477 if( (*domchg)->domchgbound.nboundchgs == 0 )
1478 {
1479 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1480 }
1481 else
1482 {
1483 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1484 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1485 }
1486 }
1487 break;
1489 if( (*domchg)->domchgboth.nholechgs == 0 )
1490 {
1491 if( (*domchg)->domchgbound.nboundchgs == 0 )
1492 {
1493 SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1494 }
1495 else
1496 {
1497 /* shrink dynamic size arrays to their minimal sizes */
1498 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1499 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1500 BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1501
1502 /* convert into static domain change */
1503 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1504 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1505 }
1506 }
1507 else
1508 {
1509 /* shrink dynamic size arrays to their minimal sizes */
1510 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1511 (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1512 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1513 (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1514
1515 /* convert into static domain change */
1516 SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1517 (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1518 }
1519 break;
1520 default:
1521 SCIPerrorMessage("invalid domain change type\n");
1522 return SCIP_INVALIDDATA;
1523 }
1524#ifndef NDEBUG
1525 if( *domchg != NULL )
1526 {
1527 int i;
1528 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1529 assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1530 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1531 }
1532#endif
1533 }
1534
1535 return SCIP_OKAY;
1536}
1537
1538/** ensures, that boundchgs array can store at least num entries */
1539static
1541 SCIP_DOMCHG* domchg, /**< domain change data structure */
1542 BMS_BLKMEM* blkmem, /**< block memory */
1543 SCIP_SET* set, /**< global SCIP settings */
1544 int num /**< minimum number of entries to store */
1545 )
1546{
1547 assert(domchg != NULL);
1548 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1549
1550 if( num > domchg->domchgdyn.boundchgssize )
1551 {
1552 int newsize;
1553
1554 newsize = SCIPsetCalcMemGrowSize(set, num);
1555 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1556 for( int i = domchg->domchgdyn.boundchgssize; i < newsize; ++i)
1558 domchg->domchgdyn.boundchgssize = newsize;
1559 }
1560 assert(num <= domchg->domchgdyn.boundchgssize);
1561
1562 return SCIP_OKAY;
1563}
1564
1565/** ensures, that holechgs array can store at least num additional entries */
1566static
1568 SCIP_DOMCHG* domchg, /**< domain change data structure */
1569 BMS_BLKMEM* blkmem, /**< block memory */
1570 SCIP_SET* set, /**< global SCIP settings */
1571 int num /**< minimum number of additional entries to store */
1572 )
1573{
1574 assert(domchg != NULL);
1575 assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1576
1577 if( num > domchg->domchgdyn.holechgssize )
1578 {
1579 int newsize;
1580
1581 newsize = SCIPsetCalcMemGrowSize(set, num);
1582 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1583 domchg->domchgdyn.holechgssize = newsize;
1584 }
1585 assert(num <= domchg->domchgdyn.holechgssize);
1586
1587 return SCIP_OKAY;
1588}
1589
1590/** applies domain change */
1592 SCIP_DOMCHG* domchg, /**< domain change to apply */
1593 BMS_BLKMEM* blkmem, /**< block memory */
1594 SCIP_SET* set, /**< global SCIP settings */
1595 SCIP_STAT* stat, /**< problem statistics */
1596 SCIP_LP* lp, /**< current LP data */
1597 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1598 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1599 int depth, /**< depth in the tree, where the domain change takes place */
1600 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1601 )
1602{
1603 int i;
1604
1605 assert(cutoff != NULL);
1606
1607 *cutoff = FALSE;
1608
1609 SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1610
1611 if( domchg == NULL )
1612 return SCIP_OKAY;
1613
1614 /* apply bound changes */
1615 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1616 {
1617 SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1618 branchcand, eventqueue, depth, i, cutoff) );
1619 if( *cutoff )
1620 break;
1621 }
1622 SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1623
1624 /* mark all bound changes after a cutoff redundant */
1625 for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1627
1628 /* apply holelist changes */
1629 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1630 {
1631 for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1632 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1633 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1634 }
1635
1636 return SCIP_OKAY;
1637}
1638
1639/** undoes domain change */
1641 SCIP_DOMCHG* domchg, /**< domain change to remove */
1642 BMS_BLKMEM* blkmem, /**< block memory */
1643 SCIP_SET* set, /**< global SCIP settings */
1644 SCIP_STAT* stat, /**< problem statistics */
1645 SCIP_LP* lp, /**< current LP data */
1646 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1647 SCIP_EVENTQUEUE* eventqueue /**< event queue */
1648 )
1649{
1650 int i;
1651
1652 SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1653 if( domchg == NULL )
1654 return SCIP_OKAY;
1655
1656 /* undo holelist changes */
1657 if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1658 {
1659 for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1660 *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1661 SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1662 }
1663
1664 /* undo bound changes */
1665 for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1666 {
1667 SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1668 }
1669 SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1670
1671 return SCIP_OKAY;
1672}
1673
1674/** applies domain change to the global problem */
1676 SCIP_DOMCHG* domchg, /**< domain change to apply */
1677 BMS_BLKMEM* blkmem, /**< block memory */
1678 SCIP_SET* set, /**< global SCIP settings */
1679 SCIP_STAT* stat, /**< problem statistics */
1680 SCIP_LP* lp, /**< current LP data */
1681 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1682 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1683 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1684 SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1685 )
1686{
1687 int i;
1688
1689 assert(cutoff != NULL);
1690
1691 *cutoff = FALSE;
1692
1693 if( domchg == NULL )
1694 return SCIP_OKAY;
1695
1696 SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1697
1698 /* apply bound changes */
1699 for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1700 {
1701 SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1702 branchcand, eventqueue, cliquetable, cutoff) );
1703 if( *cutoff )
1704 break;
1705 }
1706 SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1707
1708 /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1709
1710 return SCIP_OKAY;
1711}
1712
1713/** adds certificate line number to domain changes */
1715 SCIP_DOMCHG* domchg, /**< pointer to domain change data structure */
1716 SCIP_CERTIFICATE* certificate /**< certificate information */
1717 )
1718{
1719 SCIP_BOUNDCHG* change;
1720
1721 if( !SCIPcertificateIsEnabled(certificate) )
1722 return;
1723
1724 change = &(domchg->domchgdyn.boundchgs[domchg->domchgdyn.nboundchgs - 1]);
1725
1726 #ifndef NDEBUG
1728 #endif
1729
1730 change->certificateindex = SCIPcertificateGetCurrentIndex(certificate) - 1;
1731}
1732
1733/** adds bound change to domain changes */
1735 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1736 BMS_BLKMEM* blkmem, /**< block memory */
1737 SCIP_SET* set, /**< global SCIP settings */
1738 SCIP_VAR* var, /**< variable to change the bounds for */
1739 SCIP_Real newbound, /**< new value for bound */
1740 SCIP_RATIONAL* newboundexact, /**< new value for exact bound, or NULL if not needed */
1741 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1742 SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1743 SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1744 SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1745 SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1746 SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1747 int inferinfo, /**< user information for inference to help resolving the conflict */
1748 SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1749 )
1750{
1751 SCIP_BOUNDCHG* boundchg;
1752
1753 assert(domchg != NULL);
1754 assert(var != NULL);
1756 assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1758 assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1759 assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1760 assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1761
1762 SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1763 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1764 newbound, var->name, (void*)domchg, (void*)*domchg);
1765
1766 /* if domain change data doesn't exist, create it;
1767 * if domain change is static, convert it into dynamic change
1768 */
1769 if( *domchg == NULL )
1770 {
1771 SCIP_CALL( domchgCreate(domchg, blkmem) );
1772 }
1773 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1774 {
1775 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1776 }
1777 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1778
1779 /* get memory for additional bound change */
1780 SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1781
1782 /* fill in the bound change data */
1783 boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1784 boundchg->var = var;
1785 switch( boundchgtype )
1786 {
1788 boundchg->data.branchingdata.lpsolval = lpsolval;
1789 break;
1791 assert(infercons != NULL);
1792 boundchg->data.inferencedata.var = infervar;
1793 boundchg->data.inferencedata.reason.cons = infercons;
1794 boundchg->data.inferencedata.info = inferinfo;
1795 break;
1797 boundchg->data.inferencedata.var = infervar;
1798 boundchg->data.inferencedata.reason.prop = inferprop;
1799 boundchg->data.inferencedata.info = inferinfo;
1800 break;
1801 default:
1802 SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1803 return SCIP_INVALIDDATA;
1804 }
1805
1806 boundchg->newbound = newbound;
1807 boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1808 boundchg->boundtype = boundtype; /*lint !e641*/
1809 boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1810 boundchg->applied = FALSE;
1811 boundchg->redundant = FALSE;
1812 (*domchg)->domchgdyn.nboundchgs++;
1813 if( newboundexact != NULL )
1814 {
1815 if( boundchg->newboundexact == NULL )
1816 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &boundchg->newboundexact, newboundexact) );
1817 else
1818 SCIPrationalSetRational(boundchg->newboundexact, newboundexact);
1819 }
1820
1821 /* capture branching and inference data associated with the bound changes */
1822 SCIP_CALL( boundchgCaptureData(boundchg) );
1823
1824#ifdef SCIP_DISABLED_CODE /* expensive debug check */
1825#ifdef SCIP_MORE_DEBUG
1826 {
1827 int i;
1828 for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1829 assert(!SCIPvarIsIntegral((*domchg)->domchgbound.boundchgs[i].var)
1830 || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1831 }
1832#endif
1833#endif
1834
1835 return SCIP_OKAY;
1836}
1837
1838/** adds hole change to domain changes */
1840 SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1841 BMS_BLKMEM* blkmem, /**< block memory */
1842 SCIP_SET* set, /**< global SCIP settings */
1843 SCIP_HOLELIST** ptr, /**< changed list pointer */
1844 SCIP_HOLELIST* newlist, /**< new value of list pointer */
1845 SCIP_HOLELIST* oldlist /**< old value of list pointer */
1846 )
1847{
1848 SCIP_HOLECHG* holechg;
1849
1850 assert(domchg != NULL);
1851 assert(ptr != NULL);
1852
1853 /* if domain change data doesn't exist, create it;
1854 * if domain change is static, convert it into dynamic change
1855 */
1856 if( *domchg == NULL )
1857 {
1858 SCIP_CALL( domchgCreate(domchg, blkmem) );
1859 }
1860 else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1861 {
1862 SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1863 }
1864 assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1865
1866 /* get memory for additional hole change */
1867 SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1868
1869 /* fill in the hole change data */
1870 holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1871 holechg->ptr = ptr;
1872 holechg->newlist = newlist;
1873 holechg->oldlist = oldlist;
1874 (*domchg)->domchgdyn.nholechgs++;
1875
1876 return SCIP_OKAY;
1877}
1878
1879
1880
1881
1882/*
1883 * methods for variables
1884 */
1885
1886/** returns adjusted lower bound value, which is rounded for integral variable types */
1887static
1889 SCIP_SET* set, /**< global SCIP settings */
1890 SCIP_Bool isintegral, /**< is variable integral? */
1891 SCIP_Real lb /**< lower bound to adjust */
1892 )
1893{
1894 if( lb < 0.0 && SCIPsetIsInfinity(set, -lb) )
1895 return -SCIPsetInfinity(set);
1896 else if( lb > 0.0 && SCIPsetIsInfinity(set, lb) )
1897 return SCIPsetInfinity(set);
1898 else if( isintegral )
1899 return SCIPsetFeasCeil(set, lb);
1900 else if( lb > 0.0 && lb < SCIPsetEpsilon(set) )
1901 return 0.0;
1902 else
1903 return lb;
1904}
1905
1906/** returns adjusted lower bound value, which is rounded for integral variable types */
1907static
1909 SCIP_Bool isintegral, /**< is variable integral? */
1910 SCIP_Real lb /**< lower bound to adjust */
1911 )
1912{
1913 if( isintegral )
1914 return ceil(lb);
1915 else
1916 return lb;
1917}
1918
1919/** returns adjusted lower bound value, which is rounded for integral variable types */
1920static
1922 SCIP_SET* set, /**< global SCIP settings */
1923 SCIP_Bool isintegral, /**< is variable integral? */
1924 SCIP_RATIONAL* lb /**< lower bound to adjust */
1925 )
1926{
1931 else if( isintegral )
1933}
1934
1935/** returns adjusted upper bound value, which is rounded for integral variable types */
1936static
1938 SCIP_SET* set, /**< global SCIP settings */
1939 SCIP_Bool isintegral, /**< is variable integral? */
1940 SCIP_Real ub /**< upper bound to adjust */
1941 )
1942{
1943 if( ub > 0.0 && SCIPsetIsInfinity(set, ub) )
1944 return SCIPsetInfinity(set);
1945 else if( ub < 0.0 && SCIPsetIsInfinity(set, -ub) )
1946 return -SCIPsetInfinity(set);
1947 else if( isintegral )
1948 return SCIPsetFeasFloor(set, ub);
1949 else if( ub < 0.0 && ub > -SCIPsetEpsilon(set) )
1950 return 0.0;
1951 else
1952 return ub;
1953}
1954
1955/** returns adjusted upperbound value, which is rounded for integral variable types */
1956static
1958 SCIP_Bool isintegral, /**< is variable integral? */
1959 SCIP_Real lb /**< lower bound to adjust */
1960 )
1961{
1962 if( isintegral )
1963 return floor(lb);
1964 else
1965 return lb;
1966}
1967
1968/** returns adjusted lower bound value, which is rounded for integral variable types */
1969static
1971 SCIP_SET* set, /**< global SCIP settings */
1972 SCIP_Bool isintegral, /**< is variable integral? */
1973 SCIP_RATIONAL* ub /**< lower bound to adjust */
1974 )
1975{
1980 else if( isintegral )
1982}
1983
1984/** writes the approximate exact multi-aggregate data in the floating-point structs */
1985static
1987 SCIP_SET* set, /**< global SCIP settings */
1988 SCIP_VAR* var /**< SCIP variable */
1989 )
1990{
1991 int i;
1992
1993 if( !set->exact_enable || SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
1994 return;
1995
1996 var->data.multaggr.constant = SCIPrationalGetReal(var->exactdata->multaggr.constant);
1997 for( i = 0; i < var->data.multaggr.nvars; i++ )
1998 {
1999 var->data.multaggr.scalars[i] = SCIPrationalGetReal(var->exactdata->multaggr.scalars[i]);
2000 }
2001}
2002
2003/** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
2004 * bounds arrays, and optionally removes them also from the variable itself
2005 */
2007 SCIP_VAR* var, /**< problem variable */
2008 BMS_BLKMEM* blkmem, /**< block memory */
2009 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
2010 SCIP_SET* set, /**< global SCIP settings */
2011 SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
2012 SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
2013 SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
2014 )
2015{
2016 SCIP_Real lb;
2017 SCIP_Real ub;
2018
2019 assert(var != NULL);
2022
2023 lb = SCIPvarGetLbGlobal(var);
2024 ub = SCIPvarGetUbGlobal(var);
2025
2026 SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
2027 onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
2028
2029 /* remove implications of (fixed) binary variable */
2030 if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
2031 {
2032 SCIP_Bool varfixing;
2033
2035
2036 varfixing = FALSE;
2037 do
2038 {
2039 SCIP_VAR** implvars;
2040 SCIP_BOUNDTYPE* impltypes;
2041 int nimpls;
2042 int i;
2043
2044 nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
2045 implvars = SCIPimplicsGetVars(var->implics, varfixing);
2046 impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
2047
2048 for( i = 0; i < nimpls; i++ )
2049 {
2050 SCIP_VAR* implvar;
2051 SCIP_BOUNDTYPE impltype;
2052
2053 implvar = implvars[i];
2054 impltype = impltypes[i];
2055 assert(implvar != var);
2056
2057 /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
2058 * the following variable bound from x's variable bounds
2059 * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
2060 * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
2061 */
2062 if( impltype == SCIP_BOUNDTYPE_UPPER )
2063 {
2064 if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2065 {
2066 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
2067 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
2068 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
2069 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
2070 implvar->closestvblpcount = -1;
2071 var->closestvblpcount = -1;
2072 }
2073 }
2074 else
2075 {
2076 if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2077 {
2078 SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
2079 SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
2080 SCIPimplicsGetBounds(var->implics, varfixing)[i]);
2081 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
2082 implvar->closestvblpcount = -1;
2083 var->closestvblpcount = -1;
2084 }
2085 }
2086 }
2087 varfixing = !varfixing;
2088 }
2089 while( varfixing == TRUE );
2090
2091 if( removefromvar )
2092 {
2093 /* free the implications data structures */
2094 SCIPimplicsFree(&var->implics, blkmem);
2095 }
2096 }
2097
2098 /* remove the (redundant) variable lower bounds */
2099 if( var->vlbs != NULL )
2100 {
2101 SCIP_VAR** vars;
2102 SCIP_Real* coefs;
2103 SCIP_Real* constants;
2104 int nvbds;
2105 int newnvbds;
2106 int i;
2107
2108 nvbds = SCIPvboundsGetNVbds(var->vlbs);
2109 vars = SCIPvboundsGetVars(var->vlbs);
2110 coefs = SCIPvboundsGetCoefs(var->vlbs);
2111 constants = SCIPvboundsGetConstants(var->vlbs);
2112
2113 /* remove for all variable bounds x >= b*z+d the following implication from z's implications
2114 * z == ub ==> x >= b*ub + d , if b > 0
2115 * z == lb ==> x >= b*lb + d , if b < 0
2116 */
2117 newnvbds = 0;
2118 for( i = 0; i < nvbds; i++ )
2119 {
2120 SCIP_VAR* implvar;
2121 SCIP_Real coef;
2122
2123 assert(newnvbds <= i);
2124
2125 implvar = vars[i];
2126 assert(implvar != NULL);
2127
2128 coef = coefs[i];
2129 assert(!SCIPsetIsZero(set, coef));
2130
2131 /* check, if we want to remove the variable bound */
2132 if( onlyredundant )
2133 {
2134 SCIP_Real vbound;
2135
2136 vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
2137 if( SCIPsetIsFeasGT(set, vbound, lb) )
2138 {
2139 /* the variable bound is not redundant: keep it */
2140 if( removefromvar )
2141 {
2142 if( newnvbds < i )
2143 {
2144 vars[newnvbds] = implvar;
2145 coefs[newnvbds] = coef;
2146 constants[newnvbds] = constants[i];
2147 }
2148 newnvbds++;
2149 }
2150 continue;
2151 }
2152 }
2153
2154 /* remove the corresponding implication */
2155 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
2156 {
2157 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
2158 SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
2159 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
2160 }
2161 if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2162 {
2163 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
2164 SCIPvarGetName(implvar), SCIPvarGetName(var));
2165 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
2166 implvar->closestvblpcount = -1;
2167 var->closestvblpcount = -1;
2168 }
2169 else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2170 {
2171 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
2172 SCIPvarGetName(implvar), SCIPvarGetName(var));
2173 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
2174 implvar->closestvblpcount = -1;
2175 var->closestvblpcount = -1;
2176 }
2177 }
2178
2179 if( removefromvar )
2180 {
2181 /* update the number of variable bounds */
2182 SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
2183 var->closestvblpcount = -1;
2184 }
2185 }
2186
2187 /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
2188 * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
2189 * cannot remove such variables x from z's implications.
2190 */
2191
2192 /* remove the (redundant) variable upper bounds */
2193 if( var->vubs != NULL )
2194 {
2195 SCIP_VAR** vars;
2196 SCIP_Real* coefs;
2197 SCIP_Real* constants;
2198 int nvbds;
2199 int newnvbds;
2200 int i;
2201
2202 nvbds = SCIPvboundsGetNVbds(var->vubs);
2203 vars = SCIPvboundsGetVars(var->vubs);
2204 coefs = SCIPvboundsGetCoefs(var->vubs);
2205 constants = SCIPvboundsGetConstants(var->vubs);
2206
2207 /* remove for all variable bounds x <= b*z+d the following implication from z's implications
2208 * z == lb ==> x <= b*lb + d , if b > 0
2209 * z == ub ==> x <= b*ub + d , if b < 0
2210 */
2211 newnvbds = 0;
2212 for( i = 0; i < nvbds; i++ )
2213 {
2214 SCIP_VAR* implvar;
2215 SCIP_Real coef;
2216
2217 assert(newnvbds <= i);
2218
2219 implvar = vars[i];
2220 assert(implvar != NULL);
2221
2222 coef = coefs[i];
2223 assert(!SCIPsetIsZero(set, coef));
2224
2225 /* check, if we want to remove the variable bound */
2226 if( onlyredundant )
2227 {
2228 SCIP_Real vbound;
2229
2230 vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
2231 if( SCIPsetIsFeasLT(set, vbound, ub) )
2232 {
2233 /* the variable bound is not redundant: keep it */
2234 if( removefromvar )
2235 {
2236 if( newnvbds < i )
2237 {
2238 vars[newnvbds] = implvar;
2239 coefs[newnvbds] = coefs[i];
2240 constants[newnvbds] = constants[i];
2241 }
2242 newnvbds++;
2243 }
2244 continue;
2245 }
2246 }
2247
2248 /* remove the corresponding implication */
2249 if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
2250 {
2251 SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
2252 SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
2253 SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
2254 }
2255 if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
2256 {
2257 SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
2258 SCIPvarGetName(implvar), SCIPvarGetName(var));
2259 SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
2260 implvar->closestvblpcount = -1;
2261 var->closestvblpcount = -1;
2262 }
2263 else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
2264 {
2265 SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
2266 SCIPvarGetName(implvar), SCIPvarGetName(var));
2267 SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
2268 implvar->closestvblpcount = -1;
2269 var->closestvblpcount = -1;
2270 }
2271 }
2272
2273 if( removefromvar )
2274 {
2275 /* update the number of variable bounds */
2276 SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
2277 var->closestvblpcount = -1;
2278 }
2279 }
2280
2281 /* remove the variable from all cliques */
2282 if( SCIPvarIsBinary(var) )
2283 SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
2284
2285 /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
2286 * z has no link (like in the binary case) to x
2287 */
2288
2289 return SCIP_OKAY;
2290}
2291
2292/** sets the variable name */
2293static
2295 SCIP_VAR* var, /**< problem variable */
2296 BMS_BLKMEM* blkmem, /**< block memory */
2297 SCIP_STAT* stat, /**< problem statistics, or NULL */
2298 const char* name /**< name of variable, or NULL for automatic name creation */
2299 )
2300{
2301 assert(blkmem != NULL);
2302 assert(var != NULL);
2303
2304 if( name == NULL )
2305 {
2306 char s[SCIP_MAXSTRLEN];
2307
2308 assert(stat != NULL);
2309
2310 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
2311 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
2312 }
2313 else
2314 {
2315 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
2316 }
2317
2318 return SCIP_OKAY;
2319}
2320
2321/** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
2322 * with bounds zero and one is automatically converted into a binary variable
2323 */
2324static
2326 SCIP_VAR** var, /**< pointer to variable data */
2327 BMS_BLKMEM* blkmem, /**< block memory */
2328 SCIP_SET* set, /**< global SCIP settings */
2329 SCIP_STAT* stat, /**< problem statistics */
2330 const char* name, /**< name of variable, or NULL for automatic name creation */
2331 SCIP_Real lb, /**< lower bound of variable */
2332 SCIP_Real ub, /**< upper bound of variable */
2333 SCIP_Real obj, /**< objective function value */
2334 SCIP_VARTYPE vartype, /**< type of variable */
2335 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2336 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2337 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2338 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2339 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2340 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2341 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2342 SCIP_VARDATA* vardata /**< user data for this specific variable */
2343 )
2344{
2345 SCIP_Bool integral;
2346 int i;
2347
2348 assert(var != NULL);
2349 assert(blkmem != NULL);
2350 assert(stat != NULL);
2352
2353 /* forbid infinite objective values */
2355 {
2356 SCIPerrorMessage("invalid objective coefficient: value is infinite\n");
2357 return SCIP_INVALIDDATA;
2358 }
2359
2360 /* exact bounds may follow later */
2361 if( !set->exact_enable )
2362 {
2363 /* adjust bounds of variable */
2364 integral = vartype != SCIP_VARTYPE_CONTINUOUS || impltype != SCIP_IMPLINTTYPE_NONE;
2365 lb = adjustedLb(set, integral, lb);
2366 ub = adjustedUb(set, integral, ub);
2367
2368 /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
2369 if( ( lb == 0.0 || lb == 1.0 ) && ( ub == 0.0 || ub == 1.0 ) ) /*lint !e777*/
2370 {
2371 if( vartype == SCIP_VARTYPE_INTEGER )
2372 vartype = SCIP_VARTYPE_BINARY;
2373 }
2374 else
2375 {
2376 if( vartype == SCIP_VARTYPE_BINARY )
2377 {
2378 SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
2379 return SCIP_INVALIDDATA;
2380 }
2381 }
2382
2383 assert(vartype != SCIP_VARTYPE_BINARY || lb == 0.0 || lb == 1.0); /*lint !e777*/
2384 assert(vartype != SCIP_VARTYPE_BINARY || ub == 0.0 || ub == 1.0); /*lint !e777*/
2386 }
2387
2389
2390 /* set variable's name */
2391 SCIP_CALL( varSetName(*var, blkmem, stat, name) );
2392
2393#ifndef NDEBUG
2394 (*var)->scip = set->scip;
2395#endif
2396 (*var)->obj = obj;
2397 (*var)->unchangedobj = obj;
2398 (*var)->branchfactor = 1.0;
2399 (*var)->rootsol = 0.0;
2400 (*var)->bestrootsol = 0.0;
2401 (*var)->bestrootredcost = 0.0;
2402 (*var)->bestrootlpobjval = SCIP_INVALID;
2403 (*var)->relaxsol = 0.0;
2404 (*var)->nlpsol = 0.0;
2405 (*var)->primsolavg = 0.5 * (lb + ub);
2406 (*var)->conflictlb = SCIP_REAL_MIN;
2407 (*var)->conflictub = SCIP_REAL_MAX;
2408 (*var)->conflictrelaxedlb = (*var)->conflictlb;
2409 (*var)->conflictrelaxedub = (*var)->conflictub;
2410 (*var)->lazylb = -SCIPsetInfinity(set);
2411 (*var)->lazyub = SCIPsetInfinity(set);
2412 (*var)->glbdom.holelist = NULL;
2413 (*var)->glbdom.lb = lb;
2414 (*var)->glbdom.ub = ub;
2415 (*var)->locdom.holelist = NULL;
2416 (*var)->locdom.lb = lb;
2417 (*var)->locdom.ub = ub;
2418 (*var)->varcopy = varcopy;
2419 (*var)->vardelorig = vardelorig;
2420 (*var)->vartrans = vartrans;
2421 (*var)->vardeltrans = vardeltrans;
2422 (*var)->vardata = vardata;
2423 (*var)->parentvars = NULL;
2424 (*var)->negatedvar = NULL;
2425 (*var)->vlbs = NULL;
2426 (*var)->vubs = NULL;
2427 (*var)->implics = NULL;
2428 (*var)->cliquelist = NULL;
2429 (*var)->eventfilter = NULL;
2430 (*var)->lbchginfos = NULL;
2431 (*var)->ubchginfos = NULL;
2432 (*var)->index = stat->nvaridx;
2433 (*var)->probindex = -1;
2434 (*var)->pseudocandindex = -1;
2435 (*var)->eventqueueindexobj = -1;
2436 (*var)->eventqueueindexlb = -1;
2437 (*var)->eventqueueindexub = -1;
2438 (*var)->parentvarssize = 0;
2439 (*var)->nparentvars = 0;
2440 (*var)->nuses = 0;
2441 (*var)->branchpriority = 0;
2442 (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
2443 (*var)->lbchginfossize = 0;
2444 (*var)->nlbchginfos = 0;
2445 (*var)->ubchginfossize = 0;
2446 (*var)->nubchginfos = 0;
2447 (*var)->conflictlbcount = 0;
2448 (*var)->conflictubcount = 0;
2449 (*var)->closestvlbidx = -1;
2450 (*var)->closestvubidx = -1;
2451 (*var)->closestvblpcount = -1;
2452 (*var)->initial = initial;
2453 (*var)->removable = removable;
2454 (*var)->deleted = FALSE;
2455 (*var)->donotaggr = FALSE;
2456 (*var)->donotmultaggr = FALSE;
2457 (*var)->vartype = (unsigned int)vartype;
2458 (*var)->varimpltype = (unsigned int)impltype;
2459 (*var)->pseudocostflag = FALSE;
2460 (*var)->eventqueueimpl = FALSE;
2461 (*var)->deletable = FALSE;
2462 (*var)->delglobalstructs = FALSE;
2463 (*var)->exactdata = NULL;
2464 (*var)->relaxationonly = FALSE;
2465
2466 for( i = 0; i < NLOCKTYPES; i++ )
2467 {
2468 (*var)->nlocksdown[i] = 0;
2469 (*var)->nlocksup[i] = 0;
2470 }
2471
2472 stat->nvaridx++;
2473
2474 /* create branching and inference history entries */
2475 SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2476 SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2477
2478 /* the value based history is only created on demand */
2479 (*var)->valuehistory = NULL;
2480
2481 return SCIP_OKAY;
2482}
2483
2484/** creates and captures an original problem variable; an integer variable with bounds
2485 * zero and one is automatically converted into a binary variable
2486 */
2488 SCIP_VAR** var, /**< pointer to variable data */
2489 BMS_BLKMEM* blkmem, /**< block memory */
2490 SCIP_SET* set, /**< global SCIP settings */
2491 SCIP_STAT* stat, /**< problem statistics */
2492 const char* name, /**< name of variable, or NULL for automatic name creation */
2493 SCIP_Real lb, /**< lower bound of variable */
2494 SCIP_Real ub, /**< upper bound of variable */
2495 SCIP_Real obj, /**< objective function value */
2496 SCIP_VARTYPE vartype, /**< type of variable */
2497 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2498 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2499 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2500 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2501 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2502 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2503 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2504 SCIP_VARDATA* vardata /**< user data for this specific variable */
2505 )
2506{
2507 assert(var != NULL);
2508 assert(blkmem != NULL);
2509 assert(stat != NULL);
2510
2511 /* create variable */
2512 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
2513 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2514
2515 /* set variable status and data */
2516 (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2517 (*var)->data.original.origdom.holelist = NULL;
2518 (*var)->data.original.origdom.lb = lb;
2519 (*var)->data.original.origdom.ub = ub;
2520 (*var)->data.original.transvar = NULL;
2521
2522 /* capture variable */
2524
2525 return SCIP_OKAY;
2526}
2527
2528/** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2529 * zero and one is automatically converted into a binary variable
2530 */
2532 SCIP_VAR** var, /**< pointer to variable data */
2533 BMS_BLKMEM* blkmem, /**< block memory */
2534 SCIP_SET* set, /**< global SCIP settings */
2535 SCIP_STAT* stat, /**< problem statistics */
2536 const char* name, /**< name of variable, or NULL for automatic name creation */
2537 SCIP_Real lb, /**< lower bound of variable */
2538 SCIP_Real ub, /**< upper bound of variable */
2539 SCIP_Real obj, /**< objective function value */
2540 SCIP_VARTYPE vartype, /**< type of variable */
2541 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
2542 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2543 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2544 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2545 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2546 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2547 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2548 SCIP_VARDATA* vardata /**< user data for this specific variable */
2549 )
2550{
2551 assert(var != NULL);
2552 assert(blkmem != NULL);
2553
2554 /* create variable */
2555 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
2556 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2557
2558 /* create event filter for transformed variable */
2559 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2560
2561 /* set variable status and data */
2562 (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2563 (*var)->data.loose.minaggrcoef = 1.0;
2564 (*var)->data.loose.maxaggrcoef = 1.0;
2565
2566 /* capture variable */
2568
2569 return SCIP_OKAY;
2570}
2571
2572/** creates and sets the exact variable bounds and objective value (using floating-point data if value pointer is NULL)
2573 *
2574 * @note an inactive integer variable with bounds zero and one is automatically converted into a binary variable
2575 *
2576 * @note if exact data is provided, the corresponding floating-point data is overwritten
2577 */
2579 SCIP_VAR* var, /**< pointer to variable data */
2580 BMS_BLKMEM* blkmem, /**< block memory */
2581 SCIP_RATIONAL* lb, /**< lower bound of variable, or NULL to use floating-point data */
2582 SCIP_RATIONAL* ub, /**< upper bound of variable, or NULL to use floating-point data */
2583 SCIP_RATIONAL* obj /**< objective function value, or NULL to use floating-point data */
2584 )
2585{
2586 assert(var != NULL);
2587 assert(blkmem != NULL);
2588
2589 assert(var->exactdata == NULL);
2590 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &(var->exactdata)) );
2591
2592 if( lb != NULL )
2593 {
2594 var->data.original.origdom.lb = SCIPrationalRoundReal(lb, SCIP_R_ROUND_DOWNWARDS);
2595 var->glbdom.lb = var->data.original.origdom.lb;
2596 var->locdom.lb = var->data.original.origdom.lb;
2597
2598 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->origdom.lb, lb) );
2599 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->glbdom.lb, lb) );
2600 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->locdom.lb, lb) );
2601 }
2602 else
2603 {
2604 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->origdom.lb) );
2605 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->glbdom.lb) );
2606 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->locdom.lb) );
2607
2608 SCIPrationalSetReal(var->exactdata->origdom.lb, var->data.original.origdom.lb);
2609 SCIPrationalSetReal(var->exactdata->glbdom.lb, var->glbdom.lb);
2610 SCIPrationalSetReal(var->exactdata->locdom.lb, var->locdom.lb);
2611 }
2612
2613 if( ub != NULL )
2614 {
2615 var->data.original.origdom.ub = SCIPrationalRoundReal(ub, SCIP_R_ROUND_UPWARDS);
2616 var->glbdom.ub = var->data.original.origdom.ub;
2617 var->locdom.ub = var->data.original.origdom.ub;
2618
2619 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->origdom.ub, ub) );
2620 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->glbdom.ub, ub) );
2621 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->locdom.ub, ub) );
2622 }
2623 else
2624 {
2625 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->origdom.ub) );
2626 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->glbdom.ub) );
2627 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->locdom.ub) );
2628
2629 SCIPrationalSetReal(var->exactdata->origdom.ub, var->data.original.origdom.ub);
2630 SCIPrationalSetReal(var->exactdata->glbdom.ub, var->glbdom.ub);
2631 SCIPrationalSetReal(var->exactdata->locdom.ub, var->locdom.ub);
2632 }
2633
2634 if( obj != NULL )
2635 {
2636 var->unchangedobj = SCIPrationalGetReal(obj);
2637 var->obj = var->unchangedobj;
2638
2639 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &var->exactdata->obj, obj) );
2640 SCIPintervalSetRational(&var->exactdata->objinterval, obj);
2641 }
2642 else
2643 {
2644 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->obj) );
2645
2646 SCIPrationalSetReal(var->exactdata->obj, var->obj);
2647 SCIPintervalSet(&var->exactdata->objinterval, var->obj);
2648 }
2649
2650 var->exactdata->glbdom.lbcertificateidx = -1;
2651 var->exactdata->glbdom.ubcertificateidx = -1;
2652 var->exactdata->locdom.lbcertificateidx = -1;
2653 var->exactdata->locdom.ubcertificateidx = -1;
2654 var->exactdata->colexact = NULL;
2655 var->exactdata->varstatusexact = SCIPvarGetStatus(var);
2656 var->exactdata->certificateindex = -1;
2657 var->exactdata->multaggr.scalars = NULL;
2658 var->exactdata->multaggr.constant = NULL;
2659 var->exactdata->aggregate.constant = NULL;
2660 var->exactdata->aggregate.scalar = NULL;
2661 var->primsolavg = 0.5 * (var->data.original.origdom.lb + var->data.original.origdom.ub);
2662
2663 /* convert inactive [0,1]-integers into binary variables and check that binary variables have correct bounds */
2664 if( ( SCIPrationalIsZero(var->exactdata->origdom.lb) || SCIPrationalIsEQReal(var->exactdata->origdom.lb, 1.0) )
2665 && ( SCIPrationalIsZero(var->exactdata->origdom.ub) || SCIPrationalIsEQReal(var->exactdata->origdom.ub, 1.0) ) )
2666 {
2667 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && var->probindex == -1 )
2668 var->vartype = (unsigned int)SCIP_VARTYPE_BINARY;
2669 }
2670 else
2671 {
2672 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_BINARY )
2673 {
2674 SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", var->data.original.origdom.lb, var->data.original.origdom.ub, var->name);
2675 return SCIP_INVALIDDATA;
2676 }
2677 }
2678
2679 return SCIP_OKAY;
2680}
2681
2682/** copies exact variable data from one variable to another
2683 *
2684 * @note This method cannot be integrated into SCIPvarCopy() because it is needed, e.g., when transforming vars.
2685 */
2687 BMS_BLKMEM* blkmem, /**< block memory */
2688 SCIP_VAR* targetvar, /**< variable that gets the exact data */
2689 SCIP_VAR* sourcevar, /**< variable the data gets copied from */
2690 SCIP_Bool negateobj /**< should the objective be negated */
2691 )
2692{
2693 assert(blkmem != NULL);
2694 assert(targetvar != NULL);
2695 assert(sourcevar != NULL);
2696
2697 if( sourcevar->exactdata == NULL )
2698 return SCIP_OKAY;
2699
2700 assert(sourcevar->exactdata != NULL);
2701
2702 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &(targetvar->exactdata)) );
2703 targetvar->exactdata->glbdom = sourcevar->exactdata->glbdom;
2704 targetvar->exactdata->locdom = sourcevar->exactdata->locdom;
2705 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->glbdom.lb, sourcevar->exactdata->glbdom.lb) );
2706 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->glbdom.ub, sourcevar->exactdata->glbdom.ub) );
2707 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->locdom.lb, sourcevar->exactdata->locdom.lb) );
2708 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->locdom.ub, sourcevar->exactdata->locdom.ub) );
2709 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->origdom.lb, sourcevar->exactdata->origdom.lb) );
2710 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->origdom.ub, sourcevar->exactdata->origdom.ub) );
2711
2712 if( sourcevar->exactdata->aggregate.scalar != NULL )
2713 {
2714 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->aggregate.scalar, sourcevar->exactdata->aggregate.scalar) );
2716 }
2717 else
2718 {
2719 targetvar->exactdata->aggregate.constant = NULL;
2720 targetvar->exactdata->aggregate.scalar = NULL;
2721 }
2722
2723 if( sourcevar->exactdata->multaggr.scalars != NULL )
2724 {
2726 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &targetvar->exactdata->multaggr.scalars, sourcevar->exactdata->multaggr.scalars, sourcevar->data.multaggr.nvars) );
2727 }
2728 else
2729 {
2730 targetvar->exactdata->multaggr.constant = NULL;
2731 targetvar->exactdata->multaggr.scalars = NULL;
2732 }
2733
2734 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &targetvar->exactdata->obj, sourcevar->exactdata->obj) );
2735 if( negateobj )
2736 {
2737 SCIPrationalNegate(targetvar->exactdata->obj, targetvar->exactdata->obj);
2738 }
2739 SCIPintervalSetRational(&(targetvar->exactdata->objinterval), targetvar->exactdata->obj);
2740 targetvar->exactdata->colexact = NULL;
2742 targetvar->exactdata->certificateindex = sourcevar->exactdata->certificateindex;
2743
2744 return SCIP_OKAY;
2745}
2746
2747/** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2748 * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2749 * copied at all
2750 */
2752 SCIP_VAR** var, /**< pointer to store the target variable */
2753 BMS_BLKMEM* blkmem, /**< block memory */
2754 SCIP_SET* set, /**< global SCIP settings */
2755 SCIP_STAT* stat, /**< problem statistics */
2756 SCIP* sourcescip, /**< source SCIP data structure */
2757 SCIP_VAR* sourcevar, /**< source variable */
2758 SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2759 * target variables */
2760 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2761 * target constraints */
2762 SCIP_Bool global /**< should global or local bounds be used? */
2763 )
2764{
2765 SCIP_VARDATA* targetdata;
2767 SCIP_Real lb;
2768 SCIP_Real ub;
2769
2770 assert(set != NULL);
2771 assert(blkmem != NULL);
2772 assert(stat != NULL);
2773 assert(sourcescip != NULL);
2774 assert(sourcevar != NULL);
2775 assert(var != NULL);
2776 assert(set->stage == SCIP_STAGE_PROBLEM);
2777 assert(varmap != NULL);
2778 assert(consmap != NULL);
2779
2780 /** @todo copy hole lists */
2781 assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2782 assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2783
2785 targetdata = NULL;
2786
2787 if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2788 {
2789 lb = SCIPvarGetLbOriginal(sourcevar);
2790 ub = SCIPvarGetUbOriginal(sourcevar);
2791 }
2792 else
2793 {
2794 lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2795 ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2796 }
2797
2798 /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2799 SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2800 lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar), SCIPvarGetImplType(sourcevar),
2801 SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2802 NULL, NULL, NULL, NULL, NULL) );
2803 assert(*var != NULL);
2804
2805 /* directly copy donot(mult)aggr flag */
2806 (*var)->donotaggr = sourcevar->donotaggr;
2807 (*var)->donotmultaggr = sourcevar->donotmultaggr;
2808
2809 /* insert variable into mapping between source SCIP and the target SCIP */
2810 assert(!SCIPhashmapExists(varmap, sourcevar));
2811 SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2812
2813 /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2814 if( sourcevar->vardata != NULL )
2815 {
2816 if( sourcevar->varcopy != NULL )
2817 {
2818 SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2819 varmap, consmap, (*var), &targetdata, &result) );
2820
2821 /* evaluate result */
2823 {
2824 SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2825 return SCIP_INVALIDRESULT;
2826 }
2827
2828 assert(targetdata == NULL || result == SCIP_SUCCESS);
2829
2830 /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2831 if( result == SCIP_SUCCESS )
2832 {
2833 (*var)->varcopy = sourcevar->varcopy;
2834 (*var)->vardelorig = sourcevar->vardelorig;
2835 (*var)->vartrans = sourcevar->vartrans;
2836 (*var)->vardeltrans = sourcevar->vardeltrans;
2837 (*var)->vardata = targetdata;
2838 }
2839 }
2840 else
2841 {
2842 /* if there is no copy callback, just copy data pointers */
2843 (*var)->vardata = sourcevar->vardata;
2844 }
2845 }
2846
2847 /* we initialize histories of the variables by copying the source variable-information */
2848 if( set->history_allowtransfer )
2849 {
2850 SCIPvarMergeHistories((*var), sourcevar, stat);
2851 }
2852
2853 /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2854 * methods
2855 */
2856 if( result == SCIP_SUCCESS )
2857 {
2858 (*var)->varcopy = sourcevar->varcopy;
2859 (*var)->vardelorig = sourcevar->vardelorig;
2860 (*var)->vartrans = sourcevar->vartrans;
2861 (*var)->vardeltrans = sourcevar->vardeltrans;
2862 (*var)->vardata = targetdata;
2863 }
2864
2865 SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2866
2867 return SCIP_OKAY;
2868}
2869
2870/** parse given string for a value */
2871static
2873 SCIP_SET* set, /**< global SCIP settings */
2874 const char* str, /**< string to parse */
2875 SCIP_Real* value, /**< pointer to store the parsed value */
2876 SCIP_RATIONAL* valueexact /**< pointer to store the parsed exact value */
2877 )
2878{
2879 assert(value == NULL || valueexact == NULL);
2880
2881 /* parse exact value */
2882 if( valueexact != NULL )
2883 {
2884 /* check for rationality */
2885 if( SCIPrationalIsString(str) )
2886 {
2887 SCIPrationalSetString(valueexact, str);
2888 SCIPrationalCanonicalize(valueexact);
2889 }
2890 else
2891 {
2892 SCIPerrorMessage("expected exact value: %s\n", str);
2893 return SCIP_READERROR;
2894 }
2895
2896 SCIPrationalDebugMessage("parsed exact value: %q\n", valueexact);
2897 }
2898 /* parse real value */
2899 else if( value != NULL )
2900 {
2901 char* endptr;
2902
2903 /* check for infinity */
2904 if( strncmp(str, "+inf", 4) == 0 )
2905 {
2906 *value = SCIPsetInfinity(set);
2907 }
2908 else if( strncmp(str, "-inf", 4) == 0 )
2909 {
2910 *value = -SCIPsetInfinity(set);
2911 }
2912 else if( !SCIPstrToRealValue(str, value, &endptr) || *endptr != '\0' )
2913 {
2914 SCIPerrorMessage("expected real value: %s\n", str);
2915 return SCIP_READERROR;
2916 }
2917
2918 SCIPsetDebugMsg(set, "parsed real value: %g\n", *value);
2919 }
2920
2921 return SCIP_OKAY;
2922}
2923
2924/** parse the characters as bounds */
2925static
2927 SCIP_SET* set, /**< global SCIP settings */
2928 const char* str, /**< string to parse */
2929 char* type, /**< bound type (global, local, or lazy) */
2930 SCIP_Real* lb, /**< pointer to store the lower bound */
2931 SCIP_Real* ub, /**< pointer to store the upper bound */
2932 SCIP_RATIONAL* lbexact, /**< pointer to store the exact lower bound */
2933 SCIP_RATIONAL* ubexact, /**< pointer to store the exact upper bound */
2934 char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2935 )
2936{
2937 char token[SCIP_MAXSTRLEN];
2938
2939 SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2940
2941 /* get bound type */
2942 SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2943 if ( *endptr == str
2944 || ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 ) )
2945 {
2946 SCIPsetDebugMsg(set, "unkown bound type\n");
2947 *endptr = NULL;
2948 return SCIP_OKAY;
2949 }
2950
2951 SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2952
2953 /* get lower bound */
2954 SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2955 SCIP_CALL( parseValue(set, token, lb, lbexact) );
2956
2957 str = *endptr - 1;
2958
2959 /* get upper bound */
2960 SCIPstrCopySection(str, ',', ']', token, SCIP_MAXSTRLEN, endptr);
2961 SCIP_CALL( parseValue(set, token, ub, ubexact) );
2962
2963 /* skip end of bounds */
2964 if( **endptr == ',' )
2965 ++(*endptr);
2966
2967 return SCIP_OKAY;
2968}
2969
2970/** parses a given string for a variable informations */
2971static
2973 SCIP_SET* set, /**< global SCIP settings */
2974 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2975 const char* str, /**< string to parse */
2976 char* name, /**< pointer to store the variable name */
2977 SCIP_Real* lb, /**< pointer to store the lower bound */
2978 SCIP_Real* ub, /**< pointer to store the upper bound */
2979 SCIP_Real* obj, /**< pointer to store the objective coefficient */
2980 SCIP_RATIONAL* lbexact, /**< pointer to store the exact lower bound */
2981 SCIP_RATIONAL* ubexact, /**< pointer to store the exact upper bound */
2982 SCIP_RATIONAL* objexact, /**< pointer to store the exact objective coefficient */
2983 SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2984 SCIP_IMPLINTTYPE* impltype, /**< pointer to store the implied integral type */
2985 SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2986 SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2987 SCIP_RATIONAL* lazylbexact, /**< pointer to store if the exact lower bound is lazy */
2988 SCIP_RATIONAL* lazyubexact, /**< pointer to store if the exact upper bound is lazy */
2989 SCIP_Bool local, /**< should the local bound be applied */
2990 char** endptr, /**< pointer to store the final string position if successfully */
2991 SCIP_Bool* success /**< pointer store if the paring process was successful */
2992 )
2993{
2994 SCIP_Bool lazyread = FALSE;
2995 char token[SCIP_MAXSTRLEN];
2996 char* strptr;
2997 int i;
2998
2999 assert(vartype != NULL);
3000 assert(success != NULL);
3001
3002 (*success) = TRUE;
3003
3004 /* copy variable type */
3005 SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
3006 assert(*endptr != str);
3007 SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
3008
3009 (*impltype) = SCIP_IMPLINTTYPE_NONE;
3010 /* get variable type */
3011 if( strncmp(token, "binary", 3) == 0 )
3012 (*vartype) = SCIP_VARTYPE_BINARY;
3013 else if( strncmp(token, "integer", 3) == 0 )
3014 (*vartype) = SCIP_VARTYPE_INTEGER;
3015 else if( strncmp(token, "implicit", 3) == 0 )
3016 {
3017 (*vartype) = SCIP_VARTYPE_CONTINUOUS;
3018 (*impltype) = SCIP_IMPLINTTYPE_WEAK;
3019 }
3020 else if( strncmp(token, "continuous", 3) == 0 )
3021 (*vartype) = SCIP_VARTYPE_CONTINUOUS;
3022 else
3023 {
3024 SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
3025 (*success) = FALSE;
3026 return SCIP_OKAY;
3027 }
3028
3029 /* move string pointer behind variable type */
3030 str = *endptr;
3031
3032 /* get variable name */
3033 SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
3034 assert(*endptr != str);
3035 SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
3036
3037 /* move string pointer behind variable name */
3038 str = *endptr;
3039
3040 /* get objective coefficient */
3041 SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
3042 SCIP_CALL( parseValue(set, token, obj, objexact) );
3043
3044 /* move string pointer behind objective coefficient */
3045 str = *endptr;
3046
3047 /* parse global/original bounds */
3048 SCIP_CALL( parseBounds(set, str, token, lb, ub, lbexact, ubexact, endptr) );
3049 if( *endptr == NULL )
3050 {
3051 SCIPerrorMessage("Expected bound type: %s.\n", token);
3052 return SCIP_READERROR;
3053 }
3054 assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
3055
3056 /* store pointer */
3057 strptr = *endptr;
3058
3059 /* possibly parse optional local and lazy bounds */
3060 for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
3061 {
3062 /* start after previous bounds */
3063 strptr = *endptr;
3064
3065 /* parse variable bounds */
3066 SCIP_CALL( parseBounds(set, strptr, token, lazylb, lazyub, lazylbexact, lazyubexact, endptr) );
3067
3068 /* set local bounds */
3069 if( strncmp(token, "local", 5) == 0 )
3070 {
3071 if( local )
3072 {
3073 if( lb != NULL )
3074 {
3075 assert(lazylb != NULL);
3076 *lb = *lazylb;
3077 }
3078
3079 if( ub != NULL )
3080 {
3081 assert(lazyub != NULL);
3082 *ub = *lazyub;
3083 }
3084
3085 if( lbexact != NULL )
3086 {
3087 assert(lazylbexact != NULL);
3088 SCIPrationalSetRational(lbexact, lazylbexact);
3089 }
3090
3091 if( ubexact != NULL )
3092 {
3093 assert(lazyubexact != NULL);
3094 SCIPrationalSetRational(ubexact, lazyubexact);
3095 }
3096 }
3097 }
3098 /* set lazy bounds */
3099 else if( strncmp(token, "lazy", 4) == 0 )
3100 {
3101 lazyread = TRUE;
3102 break;
3103 }
3104
3105 /* stop if parsing of bounds failed */
3106 if( *endptr == NULL )
3107 break;
3108 }
3109
3110 /* reset lazy bounds */
3111 if( !lazyread )
3112 {
3113 if( lazylb != NULL )
3114 *lazylb = -SCIPsetInfinity(set);
3115
3116 if( lazyub != NULL )
3117 *lazyub = SCIPsetInfinity(set);
3118
3119 if( lazylbexact != NULL )
3120 SCIPrationalSetNegInfinity(lazylbexact);
3121
3122 if( lazyubexact != NULL )
3123 SCIPrationalSetInfinity(lazyubexact);
3124 }
3125
3126 /* check bounds for binary variables */
3127 if( (*vartype) == SCIP_VARTYPE_BINARY )
3128 {
3129 if( lb != NULL && *lb < 0.0 )
3130 {
3131 SCIPerrorMessage("Parsed invalid lower bound for binary variable <%s>: %f.\n", name, *lb);
3132 return SCIP_READERROR;
3133 }
3134
3135 if( ub != NULL && *ub > 1.0 )
3136 {
3137 SCIPerrorMessage("Parsed invalid upper bound for binary variable <%s>: %f.\n", name, *ub);
3138 return SCIP_READERROR;
3139 }
3140
3141 if( lbexact != NULL && SCIPrationalIsNegative(lbexact) )
3142 {
3143 SCIPerrorMessage("Parsed invalid exact lower bound for binary variable <%s>: %f.\n",
3145 return SCIP_READERROR;
3146 }
3147
3148 if( ubexact != NULL && SCIPrationalIsGTReal(ubexact, 1.0) )
3149 {
3150 SCIPerrorMessage("Parsed invalid exact upper bound for binary variable <%s>: %f.\n",
3152 return SCIP_READERROR;
3153 }
3154
3155 if( lazyread )
3156 {
3157 if( lazylb != NULL && *lazylb < 0.0 )
3158 {
3159 SCIPerrorMessage("Parsed invalid lazy lower bound for binary variable <%s>: %f.\n", name, *lazylb);
3160 return SCIP_READERROR;
3161 }
3162
3163 if( lazyub != NULL && *lazyub > 1.0 )
3164 {
3165 SCIPerrorMessage("Parsed invalid lazy upper bound for binary variable <%s>: %f.\n", name, *lazyub);
3166 return SCIP_READERROR;
3167 }
3168
3169 if( lazylbexact != NULL && SCIPrationalIsNegative(lazylbexact) )
3170 {
3171 SCIPerrorMessage("Parsed invalid exact lazy lower bound for binary variable <%s>: %f.\n",
3172 name, SCIPrationalRoundReal(lazylbexact, SCIP_R_ROUND_DOWNWARDS));
3173 return SCIP_READERROR;
3174 }
3175
3176 if( lazyubexact != NULL && SCIPrationalIsGTReal(lazyubexact, 1.0) )
3177 {
3178 SCIPerrorMessage("Parsed invalid exact lazy upper bound for binary variable <%s>: %f.\n",
3179 name, SCIPrationalRoundReal(lazyubexact, SCIP_R_ROUND_UPWARDS));
3180 return SCIP_READERROR;
3181 }
3182 }
3183 }
3184
3185 /* update string pointer */
3186 if( *endptr != NULL )
3187 strptr = *endptr;
3188
3189 /* detect implied declaration */
3190 SCIPstrCopySection(strptr, ' ', ':', token, SCIP_MAXSTRLEN, endptr);
3191
3192 /* no further declaration */
3193 if( *endptr == strptr )
3194 return SCIP_OKAY;
3195
3196 /* get implied type */
3197 if( strncmp(token, "implied", 7) == 0 )
3198 {
3199 strptr = *endptr;
3200 SCIP_CALL( SCIPskipSpace(&strptr) );
3201
3202 if( strncmp(strptr, "strong", 6) == 0 )
3203 {
3204 (*impltype) = SCIP_IMPLINTTYPE_STRONG;
3205 *endptr = strptr + 6;
3206 }
3207 else if( strncmp(strptr, "weak", 4) == 0 )
3208 {
3209 (*impltype) = SCIP_IMPLINTTYPE_WEAK;
3210 *endptr = strptr + 4;
3211 }
3212 else if( strncmp(strptr, "none", 4) == 0 )
3213 {
3214 (*impltype) = SCIP_IMPLINTTYPE_NONE;
3215 *endptr = strptr + 4;
3216 }
3217 else
3218 {
3219 SCIPerrorMessage("Expected implied integral type 'none', 'weak', or 'strong', got: '%s'.\n", strptr);
3220 return SCIP_READERROR;
3221 }
3222 }
3223 /* keep other declarations */
3224 else
3225 *endptr = strptr;
3226
3227 return SCIP_OKAY;
3228}
3229
3230/** parses variable information (in cip format) out of a string; if the parsing process was successful an original
3231 * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
3232 * integer variable with bounds zero and one is automatically converted into a binary variable
3233 */
3235 SCIP_VAR** var, /**< pointer to variable data */
3236 BMS_BLKMEM* blkmem, /**< block memory */
3237 SCIP_SET* set, /**< global SCIP settings */
3238 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3239 SCIP_STAT* stat, /**< problem statistics */
3240 const char* str, /**< string to parse */
3241 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
3242 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
3243 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
3244 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
3245 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
3246 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
3247 SCIP_VARDATA* vardata, /**< user data for this specific variable */
3248 char** endptr, /**< pointer to store the final string position if successfully */
3249 SCIP_Bool* success /**< pointer store if the paring process was successful */
3250 )
3251{
3252 char name[SCIP_MAXSTRLEN];
3253 SCIP_VARTYPE vartype;
3254 SCIP_IMPLINTTYPE impltype;
3255
3256 assert(var != NULL);
3257 assert(blkmem != NULL);
3258 assert(stat != NULL);
3259 assert(endptr != NULL);
3260 assert(success != NULL);
3261
3262 /* parse exact variable */
3263 if( set->exact_enable )
3264 {
3265 SCIP_RATIONAL* lb;
3266 SCIP_RATIONAL* ub;
3268 SCIP_RATIONAL* lazylb;
3269 SCIP_RATIONAL* lazyub;
3270
3271 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lb) );
3272 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &ub) );
3274 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazylb) );
3275 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazyub) );
3276
3277 /* parse string in cip format for exact variable information */
3278 SCIP_CALL( varParse(set, messagehdlr, str, name, NULL, NULL, NULL, lb, ub, obj, &vartype, &impltype,
3279 NULL, NULL, lazylb, lazyub, FALSE, endptr, success) );
3280
3281 if( *success ) /*lint !e774*/
3282 {
3283 /* create variable */
3284 SCIP_CALL( varCreate(var, blkmem, set, stat, name, 0.0, 0.0, 0.0, vartype, impltype, initial, removable,
3285 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3286
3287 /* set variable status */
3290 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_ORIGINAL;
3291 (*var)->data.original.origdom.holelist = NULL;
3292 (*var)->data.original.transvar = NULL;
3293
3294 /* add exact data */
3295 SCIP_CALL( SCIPvarAddExactData(*var, blkmem, lb, ub, obj) );
3296
3297 /**@todo implement lazy bounds in exact solving mode (and adjust values before setting them) */
3298 if( !SCIPrationalIsNegInfinity(lazylb) || !SCIPrationalIsInfinity(lazyub) )
3299 {
3300 SCIPerrorMessage("exact lazy bounds not supported yet\n");
3301 return SCIP_READERROR;
3302 }
3303
3304 /* capture variable */
3306 }
3307
3308 SCIPrationalFreeBlock(blkmem, &lazyub);
3309 SCIPrationalFreeBlock(blkmem, &lazylb);
3310 SCIPrationalFreeBlock(blkmem, &obj);
3311 SCIPrationalFreeBlock(blkmem, &ub);
3312 SCIPrationalFreeBlock(blkmem, &lb);
3313 }
3314 else
3315 {
3316 SCIP_Real lb;
3317 SCIP_Real ub;
3318 SCIP_Real obj;
3319 SCIP_Real lazylb;
3320 SCIP_Real lazyub;
3321
3322 /* parse string in cip format for variable information */
3323 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, NULL, NULL, NULL, &vartype, &impltype,
3324 &lazylb, &lazyub, NULL, NULL, FALSE, endptr, success) );
3325
3326 if( *success ) /*lint !e774*/
3327 {
3328 /* create variable */
3329 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
3330 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3331
3332 /* set variable status */
3333 assert(*var != NULL);
3334 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_ORIGINAL;
3335 (*var)->data.original.origdom.holelist = NULL;
3336 (*var)->data.original.origdom.lb = (*var)->glbdom.lb;
3337 (*var)->data.original.origdom.ub = (*var)->glbdom.ub;
3338 (*var)->data.original.transvar = NULL;
3339 SCIPvarAdjustLb(*var, set, &lazylb);
3340 SCIPvarAdjustUb(*var, set, &lazyub);
3341 (*var)->lazylb = lazylb;
3342 (*var)->lazyub = lazyub;
3343
3344 /* capture variable */
3346 }
3347 }
3348
3349 return SCIP_OKAY;
3350}
3351
3352/** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
3353 * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
3354 * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
3355 * variable
3356 */
3358 SCIP_VAR** var, /**< pointer to variable data */
3359 BMS_BLKMEM* blkmem, /**< block memory */
3360 SCIP_SET* set, /**< global SCIP settings */
3361 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3362 SCIP_STAT* stat, /**< problem statistics */
3363 const char* str, /**< string to parse */
3364 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
3365 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
3366 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
3367 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
3368 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
3369 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
3370 SCIP_VARDATA* vardata, /**< user data for this specific variable */
3371 char** endptr, /**< pointer to store the final string position if successfully */
3372 SCIP_Bool* success /**< pointer store if the paring process was successful */
3373 )
3374{
3375 char name[SCIP_MAXSTRLEN];
3376 SCIP_VARTYPE vartype;
3377 SCIP_IMPLINTTYPE impltype;
3378
3379 assert(var != NULL);
3380 assert(blkmem != NULL);
3381 assert(endptr != NULL);
3382 assert(success != NULL);
3383
3384 /* parse exact variable */
3385 if( set->exact_enable )
3386 {
3387 SCIP_RATIONAL* lb;
3388 SCIP_RATIONAL* ub;
3390 SCIP_RATIONAL* lazylb;
3391 SCIP_RATIONAL* lazyub;
3392
3393 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lb) );
3394 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &ub) );
3396 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazylb) );
3397 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &lazyub) );
3398
3399 /* parse string in cip format for exact variable information */
3400 SCIP_CALL( varParse(set, messagehdlr, str, name, NULL, NULL, NULL, lb, ub, obj, &vartype, &impltype,
3401 NULL, NULL, lazylb, lazyub, TRUE, endptr, success) );
3402
3403 if( *success ) /*lint !e774*/
3404 {
3405 /* create variable */
3406 SCIP_CALL( varCreate(var, blkmem, set, stat, name, 0.0, 0.0, 0.0, vartype, impltype, initial, removable,
3407 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3408
3409 /* set variable status */
3412 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_LOOSE;
3413 (*var)->data.loose.minaggrcoef = 1.0;
3414 (*var)->data.loose.maxaggrcoef = 1.0;
3415
3416 /* add exact data */
3417 SCIP_CALL( SCIPvarAddExactData(*var, blkmem, lb, ub, obj) );
3418
3419 /**@todo implement lazy bounds in exact solving mode */
3420 if( !SCIPrationalIsNegInfinity(lazylb) || !SCIPrationalIsInfinity(lazyub) )
3421 {
3422 SCIPerrorMessage("exact lazy bounds not supported yet\n");
3423 return SCIP_READERROR;
3424 }
3425
3426 /* create event filter for transformed variable */
3427 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
3428
3429 /* capture variable */
3431 }
3432
3433 SCIPrationalFreeBlock(blkmem, &lazyub);
3434 SCIPrationalFreeBlock(blkmem, &lazylb);
3435 SCIPrationalFreeBlock(blkmem, &obj);
3436 SCIPrationalFreeBlock(blkmem, &ub);
3437 SCIPrationalFreeBlock(blkmem, &lb);
3438 }
3439 /* parse real variable */
3440 else
3441 {
3442 SCIP_Real lb;
3443 SCIP_Real ub;
3444 SCIP_Real obj;
3445 SCIP_Real lazylb;
3446 SCIP_Real lazyub;
3447
3448 /* parse string in cip format for variable information */
3449 SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, NULL, NULL, NULL, &vartype, &impltype,
3450 &lazylb, &lazyub, NULL, NULL, TRUE, endptr, success) );
3451
3452 if( *success ) /*lint !e774*/
3453 {
3454 /* create variable */
3455 SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, impltype, initial, removable,
3456 varcopy, vardelorig, vartrans, vardeltrans, vardata) );
3457
3458 /* set variable status */
3459 assert(*var != NULL);
3460 (*var)->varstatus = (unsigned int)SCIP_VARSTATUS_LOOSE;
3461 (*var)->data.loose.minaggrcoef = 1.0;
3462 (*var)->data.loose.maxaggrcoef = 1.0;
3463 (*var)->lazylb = lazylb;
3464 (*var)->lazyub = lazyub;
3465
3466 /* create event filter for transformed variable */
3467 SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
3468
3469 /* capture variable */
3471 }
3472 }
3473
3474 return SCIP_OKAY;
3475}
3476
3477/** ensures, that parentvars array of var can store at least num entries */
3478static
3480 SCIP_VAR* var, /**< problem variable */
3481 BMS_BLKMEM* blkmem, /**< block memory */
3482 SCIP_SET* set, /**< global SCIP settings */
3483 int num /**< minimum number of entries to store */
3484 )
3485{
3486 assert(var->nparentvars <= var->parentvarssize);
3487
3488 if( num > var->parentvarssize )
3489 {
3490 int newsize;
3491
3492 newsize = SCIPsetCalcMemGrowSize(set, num);
3493 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
3494 var->parentvarssize = newsize;
3495 }
3496 assert(num <= var->parentvarssize);
3497
3498 return SCIP_OKAY;
3499}
3500
3501/** adds variable to parent list of a variable and captures parent variable */
3502static
3504 SCIP_VAR* var, /**< variable to add parent to */
3505 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3506 SCIP_SET* set, /**< global SCIP settings */
3507 SCIP_VAR* parentvar /**< parent variable to add */
3508 )
3509{
3510 assert(var != NULL);
3511 assert(parentvar != NULL);
3512
3513 /* the direct original counterpart must be stored as first parent */
3514 assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
3515
3516 SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
3517 parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
3518
3519 SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
3520
3521 var->parentvars[var->nparentvars] = parentvar;
3522 var->nparentvars++;
3523
3524 SCIPvarCapture(parentvar);
3525
3526 return SCIP_OKAY;
3527}
3528
3529/** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
3530static
3532 SCIP_VAR** var, /**< pointer to variable */
3533 BMS_BLKMEM* blkmem, /**< block memory */
3534 SCIP_SET* set, /**< global SCIP settings */
3535 SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
3536 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
3537 )
3538{
3539 SCIP_VAR* parentvar;
3540 int i;
3541
3542 SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
3543
3544 /* release the parent variables and remove the link from the parent variable to the child */
3545 for( i = 0; i < (*var)->nparentvars; ++i )
3546 {
3547 assert((*var)->parentvars != NULL);
3548 parentvar = (*var)->parentvars[i];
3549 assert(parentvar != NULL);
3550
3551 switch( SCIPvarGetStatus(parentvar) )
3552 {
3554 assert(parentvar->data.original.transvar == *var);
3555 assert(&parentvar->data.original.transvar != var);
3556 parentvar->data.original.transvar = NULL;
3557 break;
3558
3560 assert(parentvar->data.aggregate.var == *var);
3561 assert(&parentvar->data.aggregate.var != var);
3562 parentvar->data.aggregate.var = NULL;
3563 break;
3564
3565#ifdef SCIP_DISABLED_CODE
3566 /* The following code is unclear: should the current variable be removed from its parents? */
3568 assert(parentvar->data.multaggr.vars != NULL);
3569 for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
3570 {}
3571 assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
3572 if( v < parentvar->data.multaggr.nvars-1 )
3573 {
3574 parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
3575 parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
3576 }
3577 parentvar->data.multaggr.nvars--;
3578 break;
3579#endif
3580
3582 assert(parentvar->negatedvar == *var);
3583 assert((*var)->negatedvar == parentvar);
3584 parentvar->negatedvar = NULL;
3585 (*var)->negatedvar = NULL;
3586 break;
3587
3588 default:
3589 SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
3590 return SCIP_INVALIDDATA;
3591 } /*lint !e788*/
3592
3593 SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
3594 }
3595
3596 /* free parentvars array */
3597 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
3598
3599 return SCIP_OKAY;
3600}
3601
3602/** free exact variable data, if it exists */
3603static
3605 SCIP_VAR* var, /**< variable */
3606 BMS_BLKMEM* blkmem, /**< block memory */
3607 SCIP_SET* set /**< global SCIP settings */
3608 )
3609{
3610 assert(blkmem != NULL);
3611 assert(var != NULL);
3612
3613 if( !set->exact_enable )
3614 {
3615 assert( var->exactdata == NULL );
3616 return SCIP_OKAY;
3617 }
3618
3619 /* free exact variable data if it was created */
3620 if( var->exactdata != NULL )
3621 {
3623 {
3624 SCIP_CALL( SCIPcolExactFree(&(var->exactdata->colexact), blkmem) );
3625 }
3626
3627 if( var->exactdata->aggregate.scalar != NULL )
3628 {
3629 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->aggregate.constant);
3630 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->aggregate.scalar);
3631 }
3632
3633 if( var->exactdata->multaggr.scalars != NULL )
3634 {
3635 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->multaggr.constant);
3636 SCIPrationalFreeBlockArray(blkmem, &(var)->exactdata->multaggr.scalars, var->data.multaggr.varssize);
3637 }
3638
3639 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->glbdom.lb);
3640 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->glbdom.ub);
3641 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->locdom.lb);
3642 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->locdom.ub);
3643 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->origdom.lb);
3644 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->origdom.ub);
3645 SCIPrationalFreeBlock(blkmem, &(var)->exactdata->obj );
3646
3647 BMSfreeBlockMemory(blkmem, &(var)->exactdata);
3648 assert((var)->exactdata == NULL);
3649 }
3650
3651 return SCIP_OKAY;
3652}
3653
3654/** frees a variable */
3655static
3657 SCIP_VAR** var, /**< pointer to variable */
3658 BMS_BLKMEM* blkmem, /**< block memory */
3659 SCIP_SET* set, /**< global SCIP settings */
3660 SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
3661 SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
3662 )
3663{
3664 assert(var != NULL);
3665 assert(*var != NULL);
3666 assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
3667 assert((*var)->nuses == 0);
3668 assert((*var)->probindex == -1);
3669 assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
3670 assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
3671
3672 SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
3673
3674 switch( SCIPvarGetStatus(*var) )
3675 {
3677 assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
3678 holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
3679 assert((*var)->data.original.origdom.holelist == NULL);
3680 break;
3682 break;
3684 SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
3685 break;
3688 break;
3690 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
3691 BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
3692 break;
3694 break;
3695 default:
3696 SCIPerrorMessage("unknown variable status\n");
3697 return SCIP_INVALIDDATA;
3698 }
3699
3700 /* release all parent variables and free the parentvars array */
3701 SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
3702
3703 /* free user data */
3705 {
3706 if( (*var)->vardelorig != NULL )
3707 {
3708 SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
3709 }
3710 }
3711 else
3712 {
3713 if( (*var)->vardeltrans != NULL )
3714 {
3715 SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
3716 }
3717 }
3718
3719 /* free event filter */
3720 if( (*var)->eventfilter != NULL )
3721 {
3722 SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
3723 }
3724 assert((*var)->eventfilter == NULL);
3725
3726 /* free hole lists */
3727 holelistFree(&(*var)->glbdom.holelist, blkmem);
3728 holelistFree(&(*var)->locdom.holelist, blkmem);
3729 assert((*var)->glbdom.holelist == NULL);
3730 assert((*var)->locdom.holelist == NULL);
3731
3732 /* free variable bounds data structures */
3733 SCIPvboundsFree(&(*var)->vlbs, blkmem);
3734 SCIPvboundsFree(&(*var)->vubs, blkmem);
3735
3736 /* free implications data structures */
3737 SCIPimplicsFree(&(*var)->implics, blkmem);
3738
3739 /* free clique list data structures */
3740 SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
3741
3742 /* free bound change information arrays */
3743 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
3744 BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
3745
3746 /* free branching and inference history entries */
3747 SCIPhistoryFree(&(*var)->history, blkmem);
3748 SCIPhistoryFree(&(*var)->historycrun, blkmem);
3749 SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
3750
3751 /* free exact data if it exists */
3752 SCIP_CALL( varFreeExactData(*var, blkmem, set) );
3753
3754 /* free variable data structure */
3755 BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
3756 BMSfreeBlockMemory(blkmem, var);
3757
3758 return SCIP_OKAY;
3759}
3760
3761/** increases usage counter of variable */
3763 SCIP_VAR* var /**< variable */
3764 )
3765{
3766 assert(var != NULL);
3767 assert(var->nuses >= 0);
3768
3769 SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
3770 var->nuses++;
3771
3772#ifdef DEBUGUSES_VARNAME
3773 if( strcmp(var->name, DEBUGUSES_VARNAME) == 0
3774#ifdef DEBUGUSES_PROBNAME
3775 && ((var->scip->transprob != NULL && strcmp(SCIPprobGetName(var->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
3776 strcmp(SCIPprobGetName(var->scip->origprob), DEBUGUSES_PROBNAME) == 0)
3777#endif
3778 )
3779 {
3780 printf("Captured variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; captured at\n", (void*)var->scip, var->nuses); /* cppcheck-suppress syntaxError */
3781 print_backtrace();
3782 }
3783#endif
3784}
3785
3786/** decreases usage counter of variable, and frees memory if necessary */
3788 SCIP_VAR** var, /**< pointer to variable */
3789 BMS_BLKMEM* blkmem, /**< block memory */
3790 SCIP_SET* set, /**< global SCIP settings */
3791 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3792 SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
3793 )
3794{
3795 assert(var != NULL);
3796 assert(*var != NULL);
3797 assert((*var)->nuses >= 1);
3798 assert(blkmem != NULL);
3799 assert((*var)->scip == set->scip);
3800
3801 SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
3802 (*var)->nuses--;
3803
3804#ifdef DEBUGUSES_VARNAME
3805 if( strcmp((*var)->name, DEBUGUSES_VARNAME) == 0
3806#ifdef DEBUGUSES_PROBNAME
3807 && (((*var)->scip->transprob != NULL && strcmp(SCIPprobGetName((*var)->scip->transprob), DEBUGUSES_PROBNAME) == 0) ||
3808 strcmp(SCIPprobGetName((*var)->scip->origprob), DEBUGUSES_PROBNAME) == 0)
3809#endif
3810 )
3811 {
3812 printf("Released variable " DEBUGUSES_VARNAME " in SCIP %p, now %d uses; released at\n", (void*)(*var)->scip, (*var)->nuses);
3813 print_backtrace();
3814 }
3815#endif
3816
3817 if( (*var)->nuses == 0 )
3818 {
3819 SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
3820 }
3821
3822 *var = NULL;
3823
3824 return SCIP_OKAY;
3825}
3826
3827/** change variable name */
3829 SCIP_VAR* var, /**< problem variable */
3830 BMS_BLKMEM* blkmem, /**< block memory */
3831 const char* name /**< name of variable */
3832 )
3833{
3834 assert(name != NULL);
3835
3836 /* remove old variable name */
3837 BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
3838
3839 /* set new variable name */
3840 SCIP_CALL( varSetName(var, blkmem, NULL, name) );
3841
3842 return SCIP_OKAY;
3843}
3844
3845/** initializes variable data structure for solving */
3847 SCIP_VAR* var /**< problem variable */
3848 )
3849{
3850 assert(var != NULL);
3851
3852 SCIPhistoryReset(var->historycrun);
3853 var->conflictlbcount = 0;
3854 var->conflictubcount = 0;
3855}
3856
3857/** outputs the given bounds into the file stream */
3858static
3860 SCIP_SET* set, /**< global SCIP settings */
3861 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3862 FILE* file, /**< output file (or NULL for standard output) */
3863 SCIP_Real lb, /**< lower bound */
3864 SCIP_Real ub, /**< upper bound */
3865 const char* name /**< bound type name */
3866 )
3867{
3868 assert(set != NULL);
3869
3870 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=[", name);
3871 if( SCIPsetIsInfinity(set, lb) )
3872 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3873 else if( SCIPsetIsInfinity(set, -lb) )
3874 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3875 else
3876 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", lb);
3877 SCIPmessageFPrintInfo(messagehdlr, file, ",");
3878 if( SCIPsetIsInfinity(set, ub) )
3879 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3880 else if( SCIPsetIsInfinity(set, -ub) )
3881 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3882 else
3883 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", ub);
3884 SCIPmessageFPrintInfo(messagehdlr, file, "]");
3885}
3886
3887/** outputs the given exact bounds into the file stream */
3888static
3890 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3891 FILE* file, /**< output file (or NULL for standard output) */
3892 SCIP_RATIONAL* lb, /**< exact lower bound */
3893 SCIP_RATIONAL* ub, /**< exact upper bound */
3894 const char* name /**< bound type name */
3895 )
3896{
3897 assert(lb != NULL);
3898 assert(ub != NULL);
3899
3900 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=[", name);
3901 if( SCIPrationalIsInfinity(lb) )
3902 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3903 else if( SCIPrationalIsNegInfinity(lb) )
3904 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3905 else
3906 SCIPrationalMessage(messagehdlr, file, lb);
3907 SCIPmessageFPrintInfo(messagehdlr, file, ",");
3908 if( SCIPrationalIsInfinity(ub) )
3909 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3910 else if( SCIPrationalIsNegInfinity(ub) )
3911 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3912 else
3913 SCIPrationalMessage(messagehdlr, file, ub);
3914 SCIPmessageFPrintInfo(messagehdlr, file, "]");
3915}
3916
3917/** prints hole list to file stream */
3918static
3920 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3921 FILE* file, /**< output file (or NULL for standard output) */
3922 SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
3923 const char* name /**< hole type name */
3924 )
3925{ /*lint --e{715}*/
3926 SCIP_Real left;
3927 SCIP_Real right;
3928
3929 if( holelist == NULL )
3930 return;
3931
3932 left = SCIPholelistGetLeft(holelist);
3933 right = SCIPholelistGetRight(holelist);
3934
3935 /* display first hole */
3936 SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
3937 holelist = SCIPholelistGetNext(holelist);
3938
3939 while(holelist != NULL )
3940 {
3941 left = SCIPholelistGetLeft(holelist);
3942 right = SCIPholelistGetRight(holelist);
3943
3944 /* display hole */
3945 SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
3946
3947 /* get next hole */
3948 holelist = SCIPholelistGetNext(holelist);
3949 }
3950}
3951
3952/** outputs variable information into file stream */
3954 SCIP_VAR* var, /**< problem variable */
3955 SCIP_SET* set, /**< global SCIP settings */
3956 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3957 FILE* file /**< output file (or NULL for standard output) */
3958 )
3959{
3960 assert(var != NULL);
3961 assert(var->scip == set->scip);
3962 assert(set != NULL);
3963 assert(set->write_implintlevel >= -2);
3964 assert(set->write_implintlevel <= 2);
3965
3966 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3968 int i;
3969
3970 /* change integrality constraints of implied integral variables based on the writing settings */
3971 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3972 {
3973 if( (int)impltype > 2 - set->write_implintlevel )
3974 vartype = SCIP_VARTYPE_INTEGER;
3975 }
3976 else
3977 {
3978 if( (int)impltype > 2 + set->write_implintlevel )
3979 vartype = SCIP_VARTYPE_CONTINUOUS;
3980 }
3981
3982 /* type of variable */
3983 switch( vartype )
3984 {
3986 SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
3987 break;
3989 SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
3990 break;
3992 SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
3993 break;
3995 default:
3996 SCIPerrorMessage("unknown variable type\n");
3997 return SCIP_INVALIDDATA;
3998 } /*lint !e788*/
3999
4000 /* name */
4001 SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
4002
4003 if( var->exactdata != NULL )
4004 {
4005 assert(set->exact_enable);
4006
4007 SCIP_RATIONAL* lb;
4008 SCIP_RATIONAL* ub;
4009
4010 /* exact objective value */
4011 assert(var->exactdata->obj != NULL);
4012 SCIPmessageFPrintInfo(messagehdlr, file, " obj=");
4013 SCIPrationalMessage(messagehdlr, file, var->exactdata->obj);
4014
4015 /* exact bounds (global bounds for transformed variables, original bounds for original variables) */
4017 {
4018 /* output exact original bounds */
4021 printBoundsExact(messagehdlr, file, lb, ub, "original bounds");
4022
4023 /**@todo get exact lazy bounds */
4024 /**@todo output exact lazy bounds */
4026 {
4027 SCIPerrorMessage("exact lazy bounds not supported yet\n");
4028 return SCIP_INVALIDDATA;
4029 }
4030
4032 }
4033 else
4034 {
4035 /* output exact global bounds */
4038 printBoundsExact(messagehdlr, file, lb, ub, "global bounds");
4039
4040 /* output exact local bounds */
4043 printBoundsExact(messagehdlr, file, lb, ub, "local bounds");
4044
4045 /**@todo get exact lazy bounds */
4046 /**@todo output exact lazy bounds */
4048 {
4049 SCIPerrorMessage("exact lazy bounds not supported yet\n");
4050 return SCIP_INVALIDDATA;
4051 }
4052
4055 }
4056 }
4057 else
4058 {
4059 assert(!set->exact_enable);
4060
4061 SCIP_Real lb;
4062 SCIP_Real ub;
4063
4064 /* objective value */
4065 SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
4066
4067 /* bounds (global bounds for transformed variables, original bounds for original variables) */
4069 {
4070 /* output original bounds */
4073 printBounds(set, messagehdlr, file, lb, ub, "original bounds");
4074
4075 /* output lazy bounds */
4076 lb = SCIPvarGetLbLazy(var);
4077 ub = SCIPvarGetUbLazy(var);
4078
4079 /* only display the lazy bounds if they are different from [-infinity,infinity] */
4080 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
4081 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
4082
4083 /* original hole list */
4084 printHolelist(messagehdlr, file, SCIPvarGetHolelistOriginal(var), "original holes");
4085 }
4086 else
4087 {
4088 /* output global bounds */
4089 lb = SCIPvarGetLbGlobal(var);
4090 ub = SCIPvarGetUbGlobal(var);
4091 printBounds(set, messagehdlr, file, lb, ub, "global bounds");
4092
4093 /* output local bounds */
4094 lb = SCIPvarGetLbLocal(var);
4095 ub = SCIPvarGetUbLocal(var);
4096 printBounds(set, messagehdlr, file, lb, ub, "local bounds");
4097
4098 /* output lazy bounds */
4099 lb = SCIPvarGetLbLazy(var);
4100 ub = SCIPvarGetUbLazy(var);
4101
4102 /* only display the lazy bounds if they are different from [-infinity,infinity] */
4103 if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
4104 printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
4105
4106 /* global hole list */
4107 printHolelist(messagehdlr, file, SCIPvarGetHolelistGlobal(var), "global holes");
4108
4109 /* local hole list */
4110 printHolelist(messagehdlr, file, SCIPvarGetHolelistLocal(var), "local holes");
4111 }
4112 }
4113
4114 /* implication of variable */
4115 switch( impltype )
4116 {
4118 break;
4120 SCIPmessageFPrintInfo(messagehdlr, file, ", implied: weak");
4121 break;
4123 SCIPmessageFPrintInfo(messagehdlr, file, ", implied: strong");
4124 break;
4125 default:
4126 SCIPerrorMessage("unknown implied type\n");
4127 return SCIP_INVALIDDATA;
4128 }
4129
4130 /* fixings and aggregations */
4131 switch( SCIPvarGetStatus(var) )
4132 {
4136 break;
4137
4139 SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
4140 if( SCIPsetIsInfinity(set, var->glbdom.lb) )
4141 SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
4142 else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4143 SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
4144 else
4145 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
4146 break;
4147
4149 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
4150 if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
4151 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
4152 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
4153 break;
4154
4156 SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
4157 if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
4158 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
4159 for( i = 0; i < var->data.multaggr.nvars; ++i )
4160 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
4161 break;
4162
4164 SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
4165 break;
4166
4167 default:
4168 SCIPerrorMessage("unknown variable status\n");
4169 return SCIP_INVALIDDATA;
4170 }
4171
4172 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
4173
4174 return SCIP_OKAY;
4175}
4176
4177/** issues a VARUNLOCKED event on the given variable */
4178static
4180 SCIP_VAR* var, /**< problem variable to change */
4181 BMS_BLKMEM* blkmem, /**< block memory */
4182 SCIP_SET* set, /**< global SCIP settings */
4183 SCIP_EVENTQUEUE* eventqueue /**< event queue */
4184 )
4185{
4186 SCIP_EVENT* event;
4187
4188 assert(var != NULL);
4189 assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
4190 assert(var->scip == set->scip);
4191
4192 /* issue VARUNLOCKED event on variable */
4193 SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
4194 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
4195
4196 return SCIP_OKAY;
4197}
4198
4199/** modifies lock numbers for rounding */
4201 SCIP_VAR* var, /**< problem variable */
4202 BMS_BLKMEM* blkmem, /**< block memory */
4203 SCIP_SET* set, /**< global SCIP settings */
4204 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4205 SCIP_LOCKTYPE locktype, /**< type of the variable locks */
4206 int addnlocksdown, /**< increase in number of rounding down locks */
4207 int addnlocksup /**< increase in number of rounding up locks */
4208 )
4209{
4210 SCIP_VAR* lockvar;
4211
4212 assert(var != NULL);
4213 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4214 assert(var->nlocksup[locktype] >= 0);
4215 assert(var->nlocksdown[locktype] >= 0);
4216 assert(var->scip == set->scip);
4217
4218 if( addnlocksdown == 0 && addnlocksup == 0 )
4219 return SCIP_OKAY;
4220
4221#ifdef SCIP_DEBUG
4222 SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
4223 addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
4224#endif
4225
4226 lockvar = var;
4227
4228 while( TRUE ) /*lint !e716 */
4229 {
4230 assert(lockvar != NULL);
4231
4232 switch( SCIPvarGetStatus(lockvar) )
4233 {
4235 if( lockvar->data.original.transvar != NULL )
4236 {
4237 lockvar = lockvar->data.original.transvar;
4238 break;
4239 }
4240 else
4241 {
4242 lockvar->nlocksdown[locktype] += addnlocksdown;
4243 lockvar->nlocksup[locktype] += addnlocksup;
4244
4245 assert(lockvar->nlocksdown[locktype] >= 0);
4246 assert(lockvar->nlocksup[locktype] >= 0);
4247
4248 return SCIP_OKAY;
4249 }
4253 lockvar->nlocksdown[locktype] += addnlocksdown;
4254 lockvar->nlocksup[locktype] += addnlocksup;
4255
4256 assert(lockvar->nlocksdown[locktype] >= 0);
4257 assert(lockvar->nlocksup[locktype] >= 0);
4258
4259 if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
4260 && lockvar->nlocksup[locktype] <= 1 )
4261 {
4262 SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
4263 }
4264
4265 return SCIP_OKAY;
4267 assert(!lockvar->donotaggr);
4268
4269 if( lockvar->data.aggregate.scalar < 0.0 )
4270 {
4271 int tmp = addnlocksup;
4272
4273 addnlocksup = addnlocksdown;
4274 addnlocksdown = tmp;
4275 }
4276
4277 lockvar = lockvar->data.aggregate.var;
4278 break;
4280 {
4281 int v;
4282
4283 assert(!lockvar->donotmultaggr);
4284
4285 lockvar->nlocksdown[locktype] += addnlocksdown;
4286 lockvar->nlocksup[locktype] += addnlocksup;
4287
4288 assert(lockvar->nlocksdown[locktype] >= 0);
4289 assert(lockvar->nlocksup[locktype] >= 0);
4290
4291 for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
4292 {
4293 if( lockvar->data.multaggr.scalars[v] > 0.0 )
4294 {
4295 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
4296 addnlocksup) );
4297 }
4298 else
4299 {
4300 SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
4301 addnlocksdown) );
4302 }
4303 }
4304 return SCIP_OKAY;
4305 }
4307 {
4308 int tmp = addnlocksup;
4309
4310 assert(lockvar->negatedvar != NULL);
4312 assert(lockvar->negatedvar->negatedvar == lockvar);
4313
4314 addnlocksup = addnlocksdown;
4315 addnlocksdown = tmp;
4316
4317 lockvar = lockvar->negatedvar;
4318 break;
4319 }
4320 default:
4321 SCIPerrorMessage("unknown variable status\n");
4322 return SCIP_INVALIDDATA;
4323 }
4324 }
4325}
4326
4327/** gets number of locks for rounding down of a special type */
4329 SCIP_VAR* var, /**< problem variable */
4330 SCIP_LOCKTYPE locktype /**< type of variable locks */
4331 )
4332{
4333 int nlocks;
4334 int i;
4335
4336 assert(var != NULL);
4337 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4338 assert(var->nlocksdown[locktype] >= 0);
4339
4340 switch( SCIPvarGetStatus(var) )
4341 {
4343 if( var->data.original.transvar != NULL )
4344 return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
4345 else
4346 return var->nlocksdown[locktype];
4347
4351 return var->nlocksdown[locktype];
4352
4354 assert(!var->donotaggr);
4355 if( var->data.aggregate.scalar > 0.0 )
4356 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
4357 else
4358 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
4359
4361 assert(!var->donotmultaggr);
4362 nlocks = 0;
4363 for( i = 0; i < var->data.multaggr.nvars; ++i )
4364 {
4365 if( var->data.multaggr.scalars[i] > 0.0 )
4366 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
4367 else
4368 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
4369 }
4370 return nlocks;
4371
4373 assert(var->negatedvar != NULL);
4375 assert(var->negatedvar->negatedvar == var);
4376 return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
4377
4378 default:
4379 SCIPerrorMessage("unknown variable status\n");
4380 SCIPABORT();
4381 return INT_MAX; /*lint !e527*/
4382 }
4383}
4384
4385/** gets number of locks for rounding up of a special type */
4387 SCIP_VAR* var, /**< problem variable */
4388 SCIP_LOCKTYPE locktype /**< type of variable locks */
4389 )
4390{
4391 int nlocks;
4392 int i;
4393
4394 assert(var != NULL);
4395 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
4396 assert(var->nlocksup[locktype] >= 0);
4397
4398 switch( SCIPvarGetStatus(var) )
4399 {
4401 if( var->data.original.transvar != NULL )
4402 return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
4403 else
4404 return var->nlocksup[locktype];
4405
4409 return var->nlocksup[locktype];
4410
4412 assert(!var->donotaggr);
4413 if( var->data.aggregate.scalar > 0.0 )
4414 return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
4415 else
4416 return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
4417
4419 assert(!var->donotmultaggr);
4420 nlocks = 0;
4421 for( i = 0; i < var->data.multaggr.nvars; ++i )
4422 {
4423 if( var->data.multaggr.scalars[i] > 0.0 )
4424 nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
4425 else
4426 nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
4427 }
4428 return nlocks;
4429
4431 assert(var->negatedvar != NULL);
4433 assert(var->negatedvar->negatedvar == var);
4434 return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
4435
4436 default:
4437 SCIPerrorMessage("unknown variable status\n");
4438 SCIPABORT();
4439 return INT_MAX; /*lint !e527*/
4440 }
4441}
4442
4443/** gets number of locks for rounding down
4444 *
4445 * @note This method will always return variable locks of type model
4446 *
4447 * @note It is recommented to use SCIPvarGetNLocksDownType()
4448 */
4450 SCIP_VAR* var /**< problem variable */
4451 )
4452{
4454}
4455
4456/** gets number of locks for rounding up
4457 *
4458 * @note This method will always return variable locks of type model
4459 *
4460 * @note It is recommented to use SCIPvarGetNLocksUpType()
4461 */
4463 SCIP_VAR* var /**< problem variable */
4464 )
4465{
4467}
4468
4469/** is it possible, to round variable down and stay feasible?
4470 *
4471 * @note This method will always check w.r.t variable locks of type model
4472 */
4474 SCIP_VAR* var /**< problem variable */
4475 )
4476{
4478}
4479
4480/** is it possible, to round variable up and stay feasible?
4481 *
4482 * @note This method will always check w.r.t. variable locks of type model
4483 */
4485 SCIP_VAR* var /**< problem variable */
4486 )
4487{
4489}
4490
4491/** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
4492 * a new transformed variable for this variable is created
4493 */
4495 SCIP_VAR* origvar, /**< original problem variable */
4496 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4497 SCIP_SET* set, /**< global SCIP settings */
4498 SCIP_STAT* stat, /**< problem statistics */
4499 SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
4500 SCIP_VAR** transvar /**< pointer to store the transformed variable */
4501 )
4502{
4503 char name[SCIP_MAXSTRLEN];
4504
4505 assert(origvar != NULL);
4506 assert(origvar->scip == set->scip);
4508 assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
4509 assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
4510 assert(origvar->vlbs == NULL);
4511 assert(origvar->vubs == NULL);
4512 assert(transvar != NULL);
4513
4514 /* check if variable is already transformed */
4515 if( origvar->data.original.transvar != NULL )
4516 {
4517 *transvar = origvar->data.original.transvar;
4518 SCIPvarCapture(*transvar);
4519 }
4520 else
4521 {
4522 int i;
4523
4524 /* create transformed variable */
4525 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
4526 SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
4527 origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
4528 SCIPvarGetType(origvar), SCIPvarGetImplType(origvar), origvar->initial, origvar->removable,
4529 origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
4530
4531 /* copy the branch factor and priority */
4532 (*transvar)->branchfactor = origvar->branchfactor;
4533 (*transvar)->branchpriority = origvar->branchpriority;
4534 (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
4535
4536 /* duplicate hole lists */
4537 SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
4538 SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
4539
4540 /* link original and transformed variable */
4541 origvar->data.original.transvar = *transvar;
4542 SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
4543
4544 /* copy rounding locks */
4545 for( i = 0; i < NLOCKTYPES; i++ )
4546 {
4547 (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
4548 (*transvar)->nlocksup[i] = origvar->nlocksup[i];
4549 assert((*transvar)->nlocksdown[i] >= 0);
4550 assert((*transvar)->nlocksup[i] >= 0);
4551 }
4552
4553 /* copy donot(mult)aggr status */
4554 (*transvar)->donotaggr = origvar->donotaggr;
4555 (*transvar)->donotmultaggr = origvar->donotmultaggr;
4556
4557 /* copy lazy bounds */
4558 (*transvar)->lazylb = origvar->lazylb;
4559 (*transvar)->lazyub = origvar->lazyub;
4560
4561 /* transfer eventual variable statistics; do not update global statistics, because this has been done
4562 * when original variable was created
4563 */
4564 SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
4565
4566 /* transform user data */
4567 if( origvar->vartrans != NULL )
4568 {
4569 SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
4570 }
4571 else
4572 (*transvar)->vardata = origvar->vardata;
4573 }
4574
4575 SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
4576
4577 return SCIP_OKAY;
4578}
4579
4580/** gets corresponding transformed variable of an original or negated original variable */
4582 SCIP_VAR* origvar, /**< original problem variable */
4583 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
4584 SCIP_SET* set, /**< global SCIP settings */
4585 SCIP_STAT* stat, /**< problem statistics */
4586 SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
4587 )
4588{
4589 assert(origvar != NULL);
4591 assert(origvar->scip == set->scip);
4592
4594 {
4595 assert(origvar->negatedvar != NULL);
4597
4598 if( origvar->negatedvar->data.original.transvar == NULL )
4599 *transvar = NULL;
4600 else
4601 {
4602 SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
4603 }
4604 }
4605 else
4606 *transvar = origvar->data.original.transvar;
4607
4608 return SCIP_OKAY;
4609}
4610
4611/** converts loose transformed variable into column variable, creates LP column */
4613 SCIP_VAR* var, /**< problem variable */
4614 BMS_BLKMEM* blkmem, /**< block memory */
4615 SCIP_SET* set, /**< global SCIP settings */
4616 SCIP_STAT* stat, /**< problem statistics */
4617 SCIP_PROB* prob, /**< problem data */
4618 SCIP_LP* lp /**< current LP data */
4619 )
4620{
4621 assert(var != NULL);
4623 assert(var->scip == set->scip);
4624
4625 SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
4626
4627 /* switch variable status */
4628 var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
4629
4630 /* create column of variable */
4631 SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
4632
4633 if( var->probindex != -1 )
4634 {
4635 /* inform problem about the variable's status change */
4636 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
4637
4638 /* inform LP, that problem variable is now a column variable and no longer loose */
4640 }
4641
4642 return SCIP_OKAY;
4643}
4644
4645/** converts loose transformed variable into column variable, creates LP column */
4647 SCIP_VAR* var, /**< problem variable */
4648 BMS_BLKMEM* blkmem, /**< block memory */
4649 SCIP_SET* set, /**< global SCIP settings */
4650 SCIP_STAT* stat, /**< problem statistics */
4651 SCIP_LPEXACT* lp /**< current LP data */
4652 )
4653{
4654 if( !set->exact_enable )
4655 return SCIP_OKAY;
4656
4657 assert(var != NULL);
4658 assert(var->exactdata->colexact == NULL);
4659 assert(var->scip == set->scip);
4660 assert(var->exactdata != NULL);
4661
4662 SCIPsetDebugMsg(set, "creating exact column for variable <%s>\n", var->name);
4663
4664 /* switch variable status */
4665 var->exactdata->varstatusexact = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
4666
4667 /* create column of variable */
4668 SCIP_CALL( SCIPcolExactCreate(&(var->exactdata->colexact), SCIPvarGetCol(var), blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
4669
4670 if( var->probindex != -1 )
4671 {
4672 /* inform LP, that problem variable is now a column variable and no longer loose */
4674 }
4675
4676 return SCIP_OKAY;
4677}
4678
4679/** converts column transformed variable back into loose variable, frees LP column */
4681 SCIP_VAR* var, /**< problem variable */
4682 BMS_BLKMEM* blkmem, /**< block memory */
4683 SCIP_SET* set, /**< global SCIP settings */
4684 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4685 SCIP_PROB* prob, /**< problem data */
4686 SCIP_LP* lp /**< current LP data */
4687 )
4688{
4689 assert(var != NULL);
4691 assert(var->scip == set->scip);
4692 assert(var->data.col != NULL);
4693 assert(var->data.col->lppos == -1);
4694 assert(var->data.col->lpipos == -1);
4695
4696 SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
4697
4698 /* free column of variable */
4699 SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
4700
4701 /* switch variable status */
4702 var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
4703
4704 if( var->probindex != -1 )
4705 {
4706 /* inform problem about the variable's status change */
4707 SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
4708
4709 /* inform LP, that problem variable is now a loose variable and no longer a column */
4711 }
4712
4713 /* initialize variable data */
4714 var->data.loose.minaggrcoef = 1.0;
4715 var->data.loose.maxaggrcoef = 1.0;
4716
4717 return SCIP_OKAY;
4718}
4719
4720/** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
4721 * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
4722 * are not informed about a fixing of an active variable they are pointing to
4723 */
4724static
4726 SCIP_VAR* var, /**< problem variable to change */
4727 BMS_BLKMEM* blkmem, /**< block memory */
4728 SCIP_SET* set, /**< global SCIP settings */
4729 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4730 int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
4731 * multi-aggregation(2)
4732 */
4733 )
4734{
4735 SCIP_EVENT* event;
4736 SCIP_VARSTATUS varstatus;
4737 int i;
4738
4739 assert(var != NULL);
4740 assert(var->scip == set->scip);
4741 assert(0 <= fixeventtype && fixeventtype <= 2);
4742
4743 /* issue VARFIXED event on variable */
4744 SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
4745 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
4746
4747#ifndef NDEBUG
4748 for( i = var->nparentvars -1; i >= 0; --i )
4749 {
4751 }
4752#endif
4753
4754 switch( fixeventtype )
4755 {
4756 case 0:
4757 /* process all parents of a fixed variable */
4758 for( i = var->nparentvars - 1; i >= 0; --i )
4759 {
4760 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4761
4762 assert(varstatus != SCIP_VARSTATUS_FIXED);
4763
4764 /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
4765 * one
4766 */
4767 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4768 {
4769 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4770 }
4771 }
4772 break;
4773 case 1:
4774 /* process all parents of a aggregated variable */
4775 for( i = var->nparentvars - 1; i >= 0; --i )
4776 {
4777 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4778
4779 assert(varstatus != SCIP_VARSTATUS_FIXED);
4780
4781 /* issue event for not aggregated parent variable, because for these and its parents the var event was already
4782 * issued(, except the original one)
4783 *
4784 * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
4785 * yet issued
4786 */
4787 if( varstatus == SCIP_VARSTATUS_AGGREGATED )
4788 continue;
4789
4790 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4791 {
4792 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4793 }
4794 }
4795 break;
4796 case 2:
4797 /* process all parents of a aggregated variable */
4798 for( i = var->nparentvars - 1; i >= 0; --i )
4799 {
4800 varstatus = SCIPvarGetStatus(var->parentvars[i]);
4801
4802 assert(varstatus != SCIP_VARSTATUS_FIXED);
4803
4804 /* issue event on all parent variables except the original one */
4805 if( varstatus != SCIP_VARSTATUS_ORIGINAL )
4806 {
4807 SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
4808 }
4809 }
4810 break;
4811 default:
4812 SCIPerrorMessage("unknown variable fixation event origin\n");
4813 return SCIP_INVALIDDATA;
4814 }
4815
4816 return SCIP_OKAY;
4817}
4818
4819/** converts variable into fixed variable */
4821 SCIP_VAR* var, /**< problem variable */
4822 BMS_BLKMEM* blkmem, /**< block memory */
4823 SCIP_SET* set, /**< global SCIP settings */
4824 SCIP_STAT* stat, /**< problem statistics */
4825 SCIP_PROB* transprob, /**< tranformed problem data */
4826 SCIP_PROB* origprob, /**< original problem data */
4827 SCIP_PRIMAL* primal, /**< primal data */
4828 SCIP_TREE* tree, /**< branch and bound tree */
4829 SCIP_REOPT* reopt, /**< reoptimization data structure */
4830 SCIP_LP* lp, /**< current LP data */
4831 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4832 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4833 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
4834 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4835 SCIP_Real fixedval, /**< value to fix variable at */
4836 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
4837 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
4838 )
4839{
4840 SCIP_Real obj;
4841 SCIP_Real childfixedval;
4842
4843 assert(var != NULL);
4844 assert(var->scip == set->scip);
4845 assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
4846 assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
4847 assert(!SCIPsetIsInfinity(set, REALABS(fixedval)));
4848 assert(infeasible != NULL);
4849 assert(fixed != NULL);
4850
4851 SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
4852
4853 *infeasible = FALSE;
4854 *fixed = FALSE;
4855
4857 {
4858 *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
4859 SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
4860 return SCIP_OKAY;
4861 }
4862 else if( ( SCIPvarIsIntegral(var) && !SCIPsetIsFeasIntegral(set, fixedval) )
4863 || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
4864 || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
4865 {
4866 SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
4867 *infeasible = TRUE;
4868 return SCIP_OKAY;
4869 }
4870
4871 switch( SCIPvarGetStatus(var) )
4872 {
4874 if( var->data.original.transvar == NULL )
4875 {
4876 SCIPerrorMessage("cannot fix an untransformed original variable\n");
4877 return SCIP_INVALIDDATA;
4878 }
4879 SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
4880 lp, branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
4881 break;
4882
4884 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4885
4886 /* set the fixed variable's objective value to 0.0 */
4887 obj = var->obj;
4888 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4889
4890 /* since we change the variable type form loose to fixed, we have to adjust the number of loose
4891 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
4892 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
4893 * objective of this variable is set to zero
4894 */
4896
4897 /* free hole lists */
4898 holelistFree(&var->glbdom.holelist, blkmem);
4899 holelistFree(&var->locdom.holelist, blkmem);
4900
4901 /* adjust fixed value */
4902 if( SCIPvarIsIntegral(var) )
4903 fixedval = SCIPsetRound(set, fixedval);
4904
4905 /* change variable bounds to fixed value */
4906 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
4907 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
4908
4909 /* explicitly set variable's bounds if the fixed value was in epsilon range of the old bound (so above call didn't set bound) */
4910 var->glbdom.lb = fixedval;
4911 var->glbdom.ub = fixedval;
4912
4913 /* ensure local domain is fixed to same value as global domain */
4914 var->locdom.lb = fixedval;
4915 var->locdom.ub = fixedval;
4916
4917 /* delete implications and variable bounds information */
4918 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
4919 assert(var->vlbs == NULL);
4920 assert(var->vubs == NULL);
4921 assert(var->implics == NULL);
4922
4923 /* clear the history of the variable */
4924 SCIPhistoryReset(var->history);
4925 SCIPhistoryReset(var->historycrun);
4926
4927 /* convert variable into fixed variable */
4928 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
4929
4930 /* inform problem about the variable's status change */
4931 if( var->probindex != -1 )
4932 {
4933 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4934 }
4935
4936 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
4937 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
4938
4939 /* issue VARFIXED event */
4940 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
4941
4942 *fixed = TRUE;
4943 break;
4944
4946 SCIPerrorMessage("cannot fix a column variable\n");
4947 return SCIP_INVALIDDATA;
4948
4950 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
4951 SCIPABORT(); /* case is already handled in earlier if condition */
4952 return SCIP_INVALIDDATA; /*lint !e527*/
4953
4955 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
4956 assert(SCIPsetIsZero(set, var->obj));
4957 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
4958 childfixedval = (fixedval - var->data.aggregate.constant) / var->data.aggregate.scalar;
4959 SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4960 branchcand, eventqueue, eventfilter, cliquetable, childfixedval, infeasible, fixed) );
4961 break;
4962
4964 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
4965 SCIPABORT();
4966 return SCIP_INVALIDDATA; /*lint !e527*/
4967
4969 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
4970 assert(SCIPsetIsZero(set, var->obj));
4971 assert(var->negatedvar != NULL);
4973 assert(var->negatedvar->negatedvar == var);
4974 SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4975 branchcand, eventqueue, eventfilter, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
4976 break;
4977
4978 default:
4979 SCIPerrorMessage("unknown variable status\n");
4980 return SCIP_INVALIDDATA;
4981 }
4982
4983 return SCIP_OKAY;
4984}
4985
4986/** converts variable into fixed variable */
4988 SCIP_VAR* var, /**< problem variable */
4989 BMS_BLKMEM* blkmem, /**< block memory */
4990 SCIP_SET* set, /**< global SCIP settings */
4991 SCIP_STAT* stat, /**< problem statistics */
4992 SCIP_PROB* transprob, /**< tranformed problem data */
4993 SCIP_PROB* origprob, /**< original problem data */
4994 SCIP_PRIMAL* primal, /**< primal data */
4995 SCIP_TREE* tree, /**< branch and bound tree */
4996 SCIP_REOPT* reopt, /**< reoptimization data structure */
4997 SCIP_LP* lp, /**< current LP data */
4998 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4999 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5000 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
5001 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5002 SCIP_RATIONAL* fixedval, /**< value to fix variable at */
5003 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
5004 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
5005 )
5006{
5008 SCIP_RATIONAL* childfixedval;
5009 SCIP_RATIONAL* tmpval;
5010
5011 assert(var != NULL);
5012 assert(var->scip == set->scip);
5013 assert(set->exact_enable);
5014
5015 *infeasible = FALSE;
5016 *fixed = FALSE;
5017
5018 if( !set->exact_enable )
5019 return SCIP_OKAY;
5020
5021 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
5022 assert(SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub));
5023 assert(infeasible != NULL);
5024 assert(fixed != NULL);
5025
5026 SCIPrationalDebugMessage("fix variable <%s>[%g,%g] to %q\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
5027
5029 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childfixedval) );
5030 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
5031
5033
5035 {
5036 *infeasible = !SCIPrationalIsEQ(fixedval, var->exactdata->locdom.lb);
5037 SCIPrationalDebugMessage(" -> variable already fixed to %q (fixedval=%q): infeasible=%u\n", var->exactdata->locdom.lb, fixedval, *infeasible);
5038 goto terminate;
5039 }
5040 else if( (SCIPvarIsIntegral(var) && !SCIPrationalIsIntegral(fixedval))
5041 || SCIPrationalIsLT(fixedval, var->exactdata->locdom.lb)
5042 || SCIPrationalIsGT(fixedval, var->exactdata->locdom.ub) )
5043 {
5044 SCIPrationalDebugMessage(" -> fixing infeasible: locdom=[%q,%q], fixedval=%q\n", var->exactdata->locdom.lb, var->exactdata->locdom.ub, fixedval);
5045 *infeasible = TRUE;
5046 goto terminate;
5047 }
5048
5049 switch( SCIPvarGetStatusExact(var) )
5050 {
5052 if( var->data.original.transvar == NULL )
5053 {
5054 SCIPerrorMessage("cannot fix an untransformed original variable\n");
5055 return SCIP_INVALIDDATA;
5056 }
5057 SCIP_CALL( SCIPvarFixExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
5058 lp, branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
5059 break;
5060
5062 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5063
5064 /* set the fixed variable's objective value to 0.0 */
5065 SCIPrationalSetRational(obj, var->exactdata->obj);
5066 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lp->lpexact, eventqueue, tmpval) );
5067
5068 /* since we change the variable type form loose to fixed, we have to adjust the number of loose
5069 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5070 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5071 * objective of this variable is set to zero
5072 */
5074
5075 /* free fole lists */
5076 holelistFree(&var->glbdom.holelist, blkmem);
5077 holelistFree(&var->locdom.holelist, blkmem);
5078
5079 /* no need to adjust fixed value as in floating-point code */
5081
5082 /* change variable bounds to fixed value */
5083 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, fixedval) );
5084 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, fixedval) );
5085
5086 /* delete implications and variable bounds information */
5087 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5088 assert(var->vlbs == NULL);
5089 assert(var->vubs == NULL);
5090 assert(var->implics == NULL);
5091 assert(var->cliquelist == NULL);
5092
5093 /* clear the history of the variable */
5094 SCIPhistoryReset(var->history);
5095 SCIPhistoryReset(var->historycrun);
5096
5097 /* convert variable into fixed variable */
5098 var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
5099 var->exactdata->varstatusexact = SCIP_VARSTATUS_FIXED; /*lint !e641*/
5100
5101 /* inform problem about the variable's status change */
5102 if( var->probindex != -1 )
5103 {
5104 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5105 }
5106
5107 /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
5108 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
5109
5110 /* issue VARFIXED event */
5111 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
5112
5113 *fixed = TRUE;
5114 break;
5115
5117 SCIPerrorMessage("cannot fix a column variable\n");
5118 return SCIP_INVALIDDATA;
5119
5121 SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
5122 SCIPABORT(); /* case is already handled in earlier if condition */
5123 return SCIP_INVALIDDATA; /*lint !e527*/
5124
5126 /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
5127 assert(SCIPsetIsZero(set, var->obj));
5128 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
5129 if( SCIPrationalIsInfinity(fixedval) || SCIPrationalIsNegInfinity(fixedval) )
5130 SCIPrationalIsNegative(var->exactdata->aggregate.scalar) ? SCIPrationalNegate(childfixedval, fixedval) : SCIPrationalSetRational(childfixedval, fixedval);
5131 else
5132 {
5133 SCIPrationalDiff(tmpval, fixedval, var->exactdata->aggregate.constant);
5134 SCIPrationalDiv(childfixedval, tmpval, var->exactdata->aggregate.scalar);
5135 }
5136 SCIP_CALL( SCIPvarFixExact(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5137 branchcand, eventqueue, eventfilter, cliquetable, childfixedval, infeasible, fixed) );
5138 break;
5139
5141 SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
5142 SCIPABORT();
5143 return SCIP_INVALIDDATA; /*lint !e527*/
5144
5146 /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
5147 assert(SCIPrationalIsZero(var->exactdata->obj));
5148 assert(var->negatedvar != NULL);
5150 assert(var->negatedvar->negatedvar == var);
5151 SCIPrationalDiffReal(fixedval, fixedval, var->data.negate.constant);
5152 SCIPrationalNegate(fixedval, fixedval);
5153 SCIP_CALL( SCIPvarFixExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5154 branchcand, eventqueue, eventfilter, cliquetable, fixedval, infeasible, fixed) );
5155 break;
5156
5157 default:
5158 SCIPerrorMessage("unknown variable status\n");
5159 return SCIP_INVALIDDATA;
5160 }
5161
5162terminate:
5163 SCIPrationalFreeBuffer(set->buffer, &tmpval);
5164 SCIPrationalFreeBuffer(set->buffer, &childfixedval);
5165 SCIPrationalFreeBuffer(set->buffer, &obj);
5166
5167 return SCIP_OKAY;
5168}
5169
5170/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
5171 *
5172 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens
5173 * except that an upper bound on the required size is stored in the variable requiredsize; otherwise, the active
5174 * variable representation is stored in the arrays.
5175 *
5176 * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been
5177 * allocated (e.g., by a C++ 'new' or SCIP functions). Note that requiredsize is an upper bound due to possible
5178 * cancelations.
5179 */
5181 SCIP_SET* set, /**< global SCIP settings */
5182 SCIP_VAR** vars, /**< variable array to get active variables */
5183 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
5184 int* nvars, /**< pointer to number of variables and values in vars and scalars array */
5185 int varssize, /**< available slots in vars and scalars array */
5186 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
5187 int* requiredsize /**< pointer to store an uppper bound on the required size for the active variables */
5188 )
5189{
5190 SCIP_VAR** activevars;
5191 SCIP_Real activeconstant;
5192 SCIP_Bool activeconstantinf;
5193 int activevarssize;
5194 int nactivevars;
5195
5196 SCIP_VAR* var;
5197 SCIP_Real scalar;
5198 int v;
5199
5200 SCIP_VAR** tmpvars;
5201 SCIP_VAR** multvars;
5202 SCIP_Real* tmpscalars;
5203 SCIP_Real* multscalars;
5204 int tmpvarssize;
5205 int ntmpvars;
5206 int nmultvars;
5207
5208 SCIP_VAR* multvar;
5209 SCIP_Real multscalar;
5210 SCIP_Real multconstant;
5211 SCIP_VARSTATUS varstatus;
5212 int ntotalvars;
5213
5214 assert(set != NULL);
5215 assert(nvars != NULL);
5216 assert(constant != NULL);
5217 assert(requiredsize != NULL);
5218 assert(*nvars <= varssize);
5219
5220 *requiredsize = 0;
5221
5222 if( *nvars == 0 )
5223 return SCIP_OKAY;
5224
5225 assert(vars != NULL);
5226 assert(scalars != NULL);
5227
5228 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
5229 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
5230 {
5231 *requiredsize = 1;
5232
5233 return SCIP_OKAY;
5234 }
5235
5236 /* allocate temporary list of variables */
5237 tmpvarssize = *nvars;
5238 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars, tmpvarssize) );
5239
5240 /* allocate memory for list of active variables */
5241 activevarssize = MAX(10, 2 * (*nvars)); /* take the maximum to avoid small reallocations */
5242 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
5243
5244 /* allocate dense array for storing scalars (to avoid checking for duplicate variables) */
5245 ntotalvars = SCIPgetNTotalVars(set->scip);
5246 SCIP_CALL( SCIPsetAllocCleanBufferArray(set, &tmpscalars, ntotalvars) );
5247
5248 /* perform one round of replacing variables by their active, fixed or multi-aggregated counterparts */
5249 activeconstant = 0.0;
5250 nactivevars = 0;
5251 ntmpvars = 0;
5252 for( v = 0; v < *nvars; ++v )
5253 {
5254 var = vars[v];
5255 assert(var != NULL);
5256 scalar = scalars[v];
5257
5258 /* Transforms variable, scalar and constant to corresponding active, fixed, or multi-aggregated variable, scalar
5259 * and constant; activeconstant collects the sum of all constants (even for variables with scalar == 0.0). */
5260 SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
5261 assert(var != NULL);
5262
5263 assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
5264 assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
5265
5266 varstatus = SCIPvarGetStatus(var);
5267 assert( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN
5268 || varstatus == SCIP_VARSTATUS_MULTAGGR || varstatus == SCIP_VARSTATUS_FIXED);
5269
5270 /* enter nonzero scalars into dense array and list */
5271 if( scalar != 0.0 )
5272 {
5273 assert(0 <= var->index && var->index < ntotalvars);
5274 if( tmpscalars[var->index] == 0.0 )
5275 {
5276 if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN )
5277 activevars[nactivevars++] = var; /* store active variables */
5278 else if( varstatus == SCIP_VARSTATUS_MULTAGGR )
5279 tmpvars[ntmpvars++] = var; /* enter mutli-aggregated variables in list to be processed below */
5280 }
5281 tmpscalars[var->index] += scalar;
5282 }
5283 }
5284 assert(ntmpvars <= *nvars);
5285 assert(nactivevars <= *nvars);
5286
5287 /* store whether the constant is infinite */
5288 activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
5289
5290 /* collect for each variable the representation in active variables */
5291 while( ntmpvars >= 1 )
5292 {
5293 --ntmpvars;
5294
5295 var = tmpvars[ntmpvars];
5296 assert(var != NULL);
5297 assert(0 <= var->index && var->index < ntotalvars);
5299
5300 scalar = tmpscalars[var->index];
5301 /* the scalar can be 0 if the variable has been treated before and is zeroed below */
5302 if( scalar == 0.0 )
5303 continue;
5304
5305 /* x = a_1*y_1 + ... + a_n*y_n + c */
5306 nmultvars = var->data.multaggr.nvars;
5307 multvars = var->data.multaggr.vars;
5308 multscalars = var->data.multaggr.scalars;
5309
5310 /* mark variable as treated */
5311 tmpscalars[var->index] = 0.0;
5312
5313 /* loop through variables of multi-aggregation */
5314 for( v = 0; v < nmultvars; ++v )
5315 {
5316 multvar = multvars[v];
5317 multscalar = multscalars[v];
5318 multconstant = 0.0;
5319
5320 assert(multvar != NULL);
5321 SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
5322 assert(multvar != NULL);
5323
5324 /* handle constant */
5325 if( !activeconstantinf )
5326 {
5327 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
5328
5329 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
5330 {
5331 assert(scalar != 0.0);
5332 if( scalar * multconstant > 0.0 )
5333 {
5334 activeconstant = SCIPsetInfinity(set);
5335 activeconstantinf = TRUE;
5336 }
5337 else
5338 {
5339 activeconstant = -SCIPsetInfinity(set);
5340 activeconstantinf = TRUE;
5341 }
5342 }
5343 else
5344 activeconstant += scalar * multconstant;
5345 }
5346#ifndef NDEBUG
5347 else
5348 {
5349 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
5350 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5351 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
5352 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5353 }
5354#endif
5355
5356 /* Note that the variable can have a nonzero constant but 0 scalar. */
5357 if( multscalar == 0.0 )
5358 continue;
5359
5360 /* enter variable into list if not already present */
5361 assert(0 <= multvar->index && multvar->index < ntotalvars);
5362 if( tmpscalars[multvar->index] == 0.0 )
5363 {
5364 varstatus = SCIPvarGetStatus(multvar);
5365 if( varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN )
5366 {
5367 /* store active variables */
5368 if( nactivevars >= activevarssize )
5369 {
5370 activevarssize *= 2;
5371 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
5372 assert(nactivevars < activevarssize);
5373 }
5374 activevars[nactivevars++] = multvar;
5375 }
5376 else if( varstatus == SCIP_VARSTATUS_MULTAGGR )
5377 {
5378 /* ensure storage */
5379 if( ntmpvars >= tmpvarssize )
5380 {
5381 tmpvarssize *= 2;
5382 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
5383 assert(ntmpvars <= tmpvarssize);
5384 }
5385 tmpvars[ntmpvars++] = multvar;
5386 }
5387 }
5388
5389 /* transfer new scalar to dense array in any case */
5390 tmpscalars[multvar->index] += scalar * multscalar;
5391 assert(scalar * multscalar != 0.0);
5392 }
5393
5394 /* handle constant of multi-aggregation */
5395 if( !activeconstantinf )
5396 {
5397 assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
5398
5399 multconstant = SCIPvarGetMultaggrConstant(var);
5400
5401 if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
5402 {
5403 assert(scalar != 0.0);
5404 if( scalar * multconstant > 0.0 )
5405 {
5406 activeconstant = SCIPsetInfinity(set);
5407 activeconstantinf = TRUE;
5408 }
5409 else
5410 {
5411 activeconstant = -SCIPsetInfinity(set);
5412 activeconstantinf = TRUE;
5413 }
5414 }
5415 else
5416 activeconstant += scalar * multconstant;
5417 }
5418#ifndef NDEBUG
5419 else
5420 {
5421 multconstant = SCIPvarGetMultaggrConstant(var);
5422 assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
5423 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5424 assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
5425 (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
5426 }
5427#endif
5428 }
5429
5430 /* Here, nactivevars is an upper bound on the required size, because of possible cancellation. We could compute the
5431 * actual size, but this would need another loop through the active variables. We therefore take the upper bound. */
5432
5433 /* return results */
5434 if( varssize >= nactivevars )
5435 {
5436 assert(vars != NULL);
5437
5438 if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
5439 {
5440 /* if activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
5441 if( activeconstantinf )
5442 *constant = activeconstant;
5443 else
5444 *constant += activeconstant;
5445 }
5446#ifndef NDEBUG
5447 else
5448 {
5449 assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
5450 assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
5451 }
5452#endif
5453
5454 /* copy active variable and scalar array to the given arrays */
5455 *nvars = 0;
5456 for( v = 0; v < nactivevars; ++v )
5457 {
5458 var = activevars[v];
5459
5461 assert(0 <= var->index && var->index < ntotalvars);
5462
5463 /* due to cancelation, the scalar could become 0 */
5464 if( tmpscalars[var->index] != 0.0 )
5465 {
5466 vars[*nvars] = var;
5467 scalars[*nvars] = tmpscalars[var->index];
5468 assert(scalars[*nvars] != 0.0);
5469 ++(*nvars);
5470 }
5471
5472 /* clean buffer again */
5473 tmpscalars[var->index] = 0.0;
5474 }
5475 /* set requiredsize to space actually needed */
5476 *requiredsize = *nvars;
5477 }
5478 else
5479 {
5480 /* clean buffer again */
5481 for( v = 0; v < nactivevars; ++v )
5482 {
5483 var = activevars[v];
5484 assert( 0 <= var->index && var->index < ntotalvars );
5485 tmpscalars[var->index] = 0.0;
5486 }
5487 *requiredsize = nactivevars;
5488 }
5489
5490 assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
5491 assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
5492
5493 SCIPsetFreeCleanBufferArray(set, &tmpscalars);
5494 SCIPsetFreeBufferArray(set, &activevars);
5495 SCIPsetFreeBufferArray(set, &tmpvars);
5496
5497 return SCIP_OKAY;
5498}
5499
5500/** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
5501 *
5502 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
5503 * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
5504 * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
5505 *
5506 * The reason for this approach is that we cannot reallocate memory, since we do not know how the
5507 * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
5508 *
5509 * @todo Reimplement this method as was done with SCIPvarGetActiveRepresentatives() using a clean buffer array for rationals.
5510 */
5512 SCIP_SET* set, /**< global SCIP settings */
5513 SCIP_VAR** vars, /**< variable array to get active variables */
5514 SCIP_RATIONAL** scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
5515 int* nvars, /**< pointer to number of variables and values in vars and vals array */
5516 int varssize, /**< available slots in vars and scalars array */
5517 SCIP_RATIONAL* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
5518 int* requiredsize, /**< pointer to store the required array size for the active variables */
5519 SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
5520 )
5521{
5522 SCIP_VAR** activevars;
5523 SCIP_RATIONAL** activescalars;
5524 int nactivevars;
5525 SCIP_RATIONAL* activeconstant;
5526 SCIP_Bool activeconstantinf;
5527 int activevarssize;
5528
5529 SCIP_VAR* var;
5530 SCIP_RATIONAL* scalar;
5531 int v;
5532 int k;
5533
5534 SCIP_VAR** tmpvars;
5535 SCIP_VAR** multvars;
5536 SCIP_RATIONAL** tmpscalars;
5537 SCIP_RATIONAL** multscalars;
5538 int tmpvarssize;
5539 int ntmpvars;
5540 int nmultvars;
5541 int ntmpvarsnew;
5542
5543 SCIP_VAR* multvar;
5544 SCIP_RATIONAL* multscalar;
5545 SCIP_RATIONAL* multconstant;
5546 int pos;
5547
5548 int noldtmpvars;
5549
5550 SCIP_VAR** tmpvars2;
5551 SCIP_RATIONAL** tmpscalars2;
5552 int tmpvarssize2;
5553 int ntmpvars2;
5554
5555 SCIP_Bool sortagain = FALSE;
5556
5557 assert(set != NULL);
5558 assert(nvars != NULL);
5559 assert(scalars != NULL || *nvars == 0);
5560 assert(constant != NULL);
5561 assert(requiredsize != NULL);
5562 assert(*nvars <= varssize);
5563
5564 *requiredsize = 0;
5565
5566 if( *nvars == 0 )
5567 return SCIP_OKAY;
5568
5569 assert(vars != NULL);
5570
5571 /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
5572 if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
5573 {
5574 *requiredsize = 1;
5575
5576 return SCIP_OKAY;
5577 }
5578
5579 nactivevars = 0;
5580 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &scalar) );
5581 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &activeconstant) );
5582 activeconstantinf = FALSE;
5583 activevarssize = (*nvars) * 2;
5584 ntmpvars = *nvars;
5585 tmpvarssize = *nvars;
5586
5587 tmpvarssize2 = 1;
5588
5589 /* allocate temporary memory */
5590 SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
5591 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &tmpscalars2, tmpvarssize2) );
5592 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
5593 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &activescalars, activevarssize) );
5594 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
5595 SCIP_CALL( SCIPrationalCopyBufferArray(set->buffer, &tmpscalars, scalars, *nvars) );
5596
5597 /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
5598 * first, first get all corresponding variables with status loose, column, multaggr or fixed
5599 */
5600 for( v = ntmpvars - 1; v >= 0; --v )
5601 {
5602 var = tmpvars[v];
5603 SCIPrationalSetRational(scalar, tmpscalars[v]);
5604
5605 assert(var != NULL);
5606 /* transforms given variable, scalar and constant to the corresponding active, fixed, or
5607 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
5608 * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
5609 */
5610 SCIP_CALL( SCIPvarGetProbvarSumExact(&var, scalar, activeconstant) );
5611 assert(var != NULL);
5612
5613 activeconstantinf = SCIPrationalIsInfinity(activeconstant) || SCIPrationalIsNegInfinity(activeconstant);
5614
5619
5620 tmpvars[v] = var;
5621 SCIPrationalSetRational(tmpscalars[v], scalar);
5622 }
5623 noldtmpvars = ntmpvars;
5624
5625 /* sort all variables to combine equal variables easily */
5626 SCIPsortPtrPtr((void**)tmpvars, (void**)tmpscalars, SCIPvarComp, noldtmpvars);
5627 ntmpvars = 0;
5628 for( v = 1; v < noldtmpvars; ++v )
5629 {
5630 /* combine same variables */
5631 if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
5632 {
5633 SCIPrationalAdd(tmpscalars[ntmpvars], tmpscalars[ntmpvars], tmpscalars[v]);
5634 }
5635 else
5636 {
5637 ++ntmpvars;
5638 if( v > ntmpvars )
5639 {
5640 SCIPrationalSetRational(tmpscalars[ntmpvars], tmpscalars[v]);
5641 tmpvars[ntmpvars] = tmpvars[v];
5642 }
5643 }
5644 }
5645 ++ntmpvars;
5646
5647#ifdef SCIP_MORE_DEBUG
5648 for( v = 1; v < ntmpvars; ++v )
5649 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5650#endif
5651
5652 /* collect for each variable the representation in active variables */
5653 while( ntmpvars >= 1 )
5654 {
5655 --ntmpvars;
5656 ntmpvars2 = 0;
5657 var = tmpvars[ntmpvars];
5658 SCIPrationalSetRational(scalar, tmpscalars[ntmpvars]);
5659
5660 assert(var != NULL);
5661
5662 /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
5663 if( SCIPrationalIsZero(scalar) )
5664 continue;
5665
5670
5671 switch( SCIPvarGetStatus(var) )
5672 {
5675 /* x = a*y + c */
5676 if( nactivevars >= activevarssize )
5677 {
5678 int newactivevarssize = activevarssize * 2;
5679 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, newactivevarssize) );
5680 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &activescalars, activevarssize, newactivevarssize) );
5681 activevarssize = newactivevarssize;
5682 assert(nactivevars < activevarssize);
5683 }
5684 activevars[nactivevars] = var;
5685 SCIPrationalSetRational(activescalars[nactivevars], scalar);
5686 nactivevars++;
5687 break;
5688
5690 /* x = a_1*y_1 + ... + a_n*y_n + c */
5691 nmultvars = var->data.multaggr.nvars;
5692 multvars = var->data.multaggr.vars;
5693 multscalars = var->exactdata->multaggr.scalars;
5694 sortagain = TRUE;
5695
5696 if( nmultvars + ntmpvars > tmpvarssize )
5697 {
5698 ntmpvarsnew = tmpvarssize;
5699 while( nmultvars + ntmpvars > ntmpvarsnew )
5700 ntmpvarsnew *= 2;
5701 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, ntmpvarsnew) );
5702 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &tmpscalars, tmpvarssize, ntmpvarsnew) );
5703 assert(nmultvars + ntmpvars <= ntmpvarsnew);
5704 tmpvarssize = ntmpvarsnew;
5705 }
5706
5707 if( nmultvars > tmpvarssize2 )
5708 {
5709 ntmpvarsnew = tmpvarssize2;
5710 while( nmultvars > ntmpvarsnew )
5711 ntmpvarsnew *= 2;
5712 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, ntmpvarsnew) );
5713 SCIP_CALL( SCIPrationalReallocBufferArray(set->buffer, &tmpscalars2, tmpvarssize2, ntmpvarsnew) );
5714 assert(nmultvars <= ntmpvarsnew);
5715 tmpvarssize2 = ntmpvarsnew;
5716 }
5717
5718 --nmultvars;
5719
5720 for( ; nmultvars >= 0; --nmultvars )
5721 {
5722 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multconstant) );
5723 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multscalar) );
5724
5725 multvar = multvars[nmultvars];
5726 SCIPrationalSetRational(multscalar, multscalars[nmultvars]);
5727
5728 assert(multvar != NULL);
5729 SCIP_CALL( SCIPvarGetProbvarSumExact(&multvar, multscalar, multconstant) );
5730 assert(multvar != NULL);
5731
5736
5737 if( !activeconstantinf )
5738 {
5740
5741 if( SCIPrationalIsAbsInfinity(multconstant) )
5742 {
5743 assert(!SCIPrationalIsZero(scalar));
5744 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign(multconstant) && !SCIPrationalIsZero(scalar) )
5745 {
5746 SCIPrationalSetInfinity(activeconstant);
5747 activeconstantinf = TRUE;
5748 }
5749 else
5750 {
5751 SCIPrationalSetNegInfinity(activeconstant);
5752 activeconstantinf = TRUE;
5753 }
5754 }
5755 else
5756 SCIPrationalAddProd(activeconstant, scalar, multconstant);
5757 }
5758
5759 if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
5760 {
5761 assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
5762 SCIPrationalAddProd(tmpscalars[pos], scalar, multscalar);
5763 }
5764 else
5765 {
5766 tmpvars2[ntmpvars2] = multvar;
5767 SCIPrationalMult(tmpscalars2[ntmpvars2], scalar, multscalar);
5768 ++(ntmpvars2);
5769 assert(ntmpvars2 <= tmpvarssize2);
5770 }
5771
5772 SCIPrationalFreeBuffer(set->buffer, &multscalar);
5773 SCIPrationalFreeBuffer(set->buffer, &multconstant);
5774 }
5775
5776 if( ntmpvars2 > 0 )
5777 {
5778 /* sort all variables to combine equal variables easily */
5779 SCIPsortPtrPtr((void**)tmpvars2, (void**)tmpscalars2, SCIPvarComp, ntmpvars2);
5780 pos = 0;
5781 for( v = 1; v < ntmpvars2; ++v )
5782 {
5783 /* combine same variables */
5784 if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
5785 {
5786 SCIPrationalAdd(tmpscalars2[pos], tmpscalars2[pos], tmpscalars2[v]);
5787 }
5788 else
5789 {
5790 ++pos;
5791 if( v > pos )
5792 {
5793 SCIPrationalSetRational(tmpscalars2[pos], tmpscalars2[v]);
5794 tmpvars2[pos] = tmpvars2[v];
5795 }
5796 }
5797 }
5798 ntmpvars2 = pos + 1;
5799#ifdef SCIP_MORE_DEBUG
5800 for( v = 1; v < ntmpvars2; ++v )
5801 {
5802 assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
5803 }
5804 for( v = 1; v < ntmpvars; ++v )
5805 {
5806 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5807 }
5808#endif
5809 v = ntmpvars - 1;
5810 k = ntmpvars2 - 1;
5811 pos = ntmpvars + ntmpvars2 - 1;
5812 ntmpvars += ntmpvars2;
5813
5814 while( v >= 0 && k >= 0 )
5815 {
5816 assert(pos >= 0);
5817 assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
5818 if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
5819 {
5820 tmpvars[pos] = tmpvars[v];
5821 SCIPrationalSetRational(tmpscalars[pos], tmpscalars[v]);
5822 --v;
5823 }
5824 else
5825 {
5826 tmpvars[pos] = tmpvars2[k];
5827 SCIPrationalSetRational(tmpscalars[pos], tmpscalars2[k]);
5828 --k;
5829 }
5830 --pos;
5831 assert(pos >= 0);
5832 }
5833 while( v >= 0 )
5834 {
5835 assert(pos >= 0);
5836 tmpvars[pos] = tmpvars[v];
5837 SCIPrationalSetRational(tmpscalars[pos], tmpscalars[v]);
5838 --v;
5839 --pos;
5840 }
5841 while( k >= 0 )
5842 {
5843 assert(pos >= 0);
5844 tmpvars[pos] = tmpvars2[k];
5845 SCIPrationalSetRational(tmpscalars[pos], tmpscalars2[k]);
5846 --k;
5847 --pos;
5848 }
5849 }
5850#ifdef SCIP_MORE_DEBUG
5851 for( v = 1; v < ntmpvars; ++v )
5852 {
5853 assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
5854 }
5855#endif
5856
5857 if( !activeconstantinf )
5858 {
5860
5861 multconstant = SCIPvarGetMultaggrConstantExact(var);
5862
5863 if( SCIPrationalIsAbsInfinity(multconstant) )
5864 {
5865 assert(!SCIPrationalIsZero(scalar));
5866 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign(multconstant) && !SCIPrationalIsZero(scalar) )
5867 {
5868 SCIPrationalSetInfinity(activeconstant);
5869 activeconstantinf = TRUE;
5870 }
5871 else
5872 {
5873 SCIPrationalSetNegInfinity(activeconstant);
5874 activeconstantinf = TRUE;
5875 }
5876 }
5877 else
5878 SCIPrationalAddProd(activeconstant, scalar, multconstant);
5879 }
5880
5881 break;
5882
5887 default:
5888 /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
5889 * fixed variables and is handled already
5890 */
5892 assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
5893 }
5894 }
5895
5896 if( mergemultiples )
5897 {
5898 if( sortagain )
5899 {
5900 /* sort variable and scalar array by variable index */
5901 SCIPsortPtrPtr((void**)activevars, (void**)activescalars, SCIPvarComp, nactivevars);
5902
5903 /* eliminate duplicates and count required size */
5904 v = nactivevars - 1;
5905 while( v > 0 )
5906 {
5907 /* combine both variable since they are the same */
5908 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
5909 {
5910 SCIPrationalNegate(scalar, activescalars[v]);
5911 if( !SCIPrationalIsEQ(activescalars[v - 1], scalar) )
5912 {
5913 SCIPrationalAdd(activescalars[v - 1], activescalars[v - 1], activescalars[v]);
5914 --nactivevars;
5915 activevars[v] = activevars[nactivevars];
5916 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5917 }
5918 else
5919 {
5920 --nactivevars;
5921 activevars[v] = activevars[nactivevars];
5922 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5923 --nactivevars;
5924 --v;
5925 activevars[v] = activevars[nactivevars];
5926 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars]);
5927 }
5928 }
5929 --v;
5930 }
5931 }
5932 /* the variables were added in reverse order, we revert the order now;
5933 * this should not be necessary, but not doing this changes the behavior sometimes
5934 */
5935 else
5936 {
5937 SCIP_VAR* tmpvar;
5938
5939 for( v = 0; v < nactivevars / 2; ++v )
5940 {
5941 tmpvar = activevars[v];
5942 SCIPrationalSetRational(scalar, activescalars[v]);
5943 activevars[v] = activevars[nactivevars - 1 - v];
5944 SCIPrationalSetRational(activescalars[v], activescalars[nactivevars - 1 - v]);
5945 activevars[nactivevars - 1 - v] = tmpvar;
5946 SCIPrationalSetRational(activescalars[nactivevars - 1 - v], scalar);
5947 }
5948 }
5949 }
5950 *requiredsize = nactivevars;
5951
5952 if( varssize >= *requiredsize )
5953 {
5954 assert(vars != NULL);
5955
5956 *nvars = *requiredsize;
5957
5958 if( !SCIPrationalIsAbsInfinity(constant) )
5959 {
5960 /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
5961 if( activeconstantinf )
5962 SCIPrationalSetRational(constant, activeconstant);
5963 else
5964 SCIPrationalAdd(constant, constant, activeconstant);
5965 }
5966
5967 /* copy active variable and scalar array to the given arrays */
5968 for( v = 0; v < *nvars; ++v )
5969 {
5970 vars[v] = activevars[v];
5971 SCIPrationalSetRational(scalars[v], activescalars[v]); /*lint !e613*/
5972 }
5973 }
5974
5975 SCIPrationalFreeBufferArray(set->buffer, &tmpscalars, tmpvarssize);
5976 SCIPsetFreeBufferArray(set, &tmpvars);
5977 SCIPrationalFreeBufferArray(set->buffer, &activescalars, activevarssize);
5978 SCIPsetFreeBufferArray(set, &activevars);
5979 SCIPrationalFreeBufferArray(set->buffer, &tmpscalars2, tmpvarssize2);
5980 SCIPsetFreeBufferArray(set, &tmpvars2);
5981
5982 SCIPrationalFreeBuffer(set->buffer, &activeconstant);
5983 SCIPrationalFreeBuffer(set->buffer, &scalar);
5984
5985 return SCIP_OKAY;
5986}
5987
5988/** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
5990 SCIP_VAR* var, /**< problem variable */
5991 BMS_BLKMEM* blkmem, /**< block memory */
5992 SCIP_SET* set, /**< global SCIP settings */
5993 SCIP_EVENTQUEUE* eventqueue /**< event queue */
5994 )
5995{
5996 int nlocksup[NLOCKTYPES];
5997 int nlocksdown[NLOCKTYPES];
5998 SCIP_Real multconstant;
5999 int multvarssize;
6000 int nmultvars;
6001 int multrequiredsize;
6002 int i;
6003
6004 assert( var != NULL );
6006 assert(var->scip == set->scip);
6007
6008 /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
6009 * on the current representation now and re-add the locks once the variable graph has been flattened, which
6010 * may lead to duplicate occurences of the same variable being merged
6011 *
6012 * Here is an example. Assume we have the multi-aggregation z = x + y.
6013 * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
6014 * When the multi-aggregation is performed, all locks are added to the active representation,
6015 * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
6016 * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
6017 * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
6018 * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
6019 * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
6020 * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
6021 * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
6022 * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
6023 * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
6024 * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
6025 * By removing the locks here, based on the old representation and adding them again after flattening,
6026 * we ensure that the locks are correct afterwards if coefficients were merged.
6027 */
6028 for( i = 0; i < NLOCKTYPES; ++i )
6029 {
6030 nlocksup[i] = var->nlocksup[i];
6031 nlocksdown[i] = var->nlocksdown[i];
6032
6033 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
6034 }
6035
6036 multconstant = var->data.multaggr.constant;
6037 nmultvars = var->data.multaggr.nvars;
6038 multvarssize = var->data.multaggr.varssize;
6039
6040 if( !set->exact_enable )
6041 {
6042 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize) );
6043
6044 if( multrequiredsize > multvarssize )
6045 {
6046 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
6047 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
6048 multvarssize = multrequiredsize;
6049 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize) );
6050
6051 assert( multrequiredsize <= multvarssize );
6052 }
6053
6054 /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
6055 * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
6056 * may loose performance hereby, since aggregated variables are easier to handle.
6057 *
6058 * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
6059 * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
6060 * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
6061 * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
6062 *
6063 * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
6064 *
6065 * The same issue appears in the SCIPvarGetProbvar...() methods.
6066 */
6067
6068 var->data.multaggr.constant = multconstant;
6069 }
6070 else
6071 {
6072 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, var->data.multaggr.vars, var->exactdata->multaggr.scalars,
6073 &nmultvars, multvarssize, var->exactdata->multaggr.constant, &multrequiredsize, TRUE) );
6074
6075 var->data.multaggr.nvars = nmultvars;
6076 var->data.multaggr.varssize = multvarssize;
6078
6079 if( multrequiredsize > multvarssize )
6080 {
6081 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
6082 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
6083 SCIP_CALL( SCIPrationalReallocBlockArray(blkmem, &(var->exactdata->multaggr.scalars), multvarssize, multrequiredsize) );
6084 multvarssize = multrequiredsize;
6085 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, var->data.multaggr.vars, var->exactdata->multaggr.scalars,
6086 &nmultvars, multvarssize, var->exactdata->multaggr.constant, &multrequiredsize, TRUE) );
6087
6088 var->data.multaggr.nvars = nmultvars;
6089 var->data.multaggr.varssize = multvarssize;
6090
6092
6093 assert( multrequiredsize <= multvarssize );
6094 }
6095 }
6096
6097 var->data.multaggr.nvars = nmultvars;
6098 var->data.multaggr.varssize = multvarssize;
6099
6100 for( i = 0; i < NLOCKTYPES; ++i )
6101 {
6102 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
6103 }
6104
6105 return SCIP_OKAY;
6106}
6107
6108/** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
6109 * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
6110 * the history merge is reasonable
6111 *
6112 * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
6113 * this corrupts the variable pseudo costs
6114 * @note Apply with care; no internal checks are performed if the two variables should be merged
6115 */
6117 SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
6118 SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
6119 SCIP_STAT* stat /**< problem statistics */
6120 )
6121{
6122 /* merge only the history of the current run into the target history */
6123 SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
6124
6125 /* apply the changes also to the global history */
6126 SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
6127}
6128
6129/** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
6130 * history over several iterations
6131 */
6133 SCIP_VAR* var, /**< variable */
6134 SCIP_HISTORY* history, /**< the history which is to set */
6135 SCIP_STAT* stat /**< problem statistics */
6136 )
6137{
6138 /* merge only the history of the current run into the target history */
6139 SCIPhistoryUnite(var->history, history, FALSE);
6140
6141 /* apply the changes also to the global history */
6142 SCIPhistoryUnite(stat->glbhistory, history, FALSE);
6143}
6144
6145/** update min/maxaggrcoef of a loose variable */
6146static
6148 SCIP_VAR* var, /**< problem variable that is used in aggregation */
6149 SCIP_VAR* aggvar, /**< variable that is aggregated */
6150 SCIP_Real aggscalar /**< coefficient that is used for var in the aggregation of aggvar */
6151 )
6152{
6153 SCIP_Real minscalar;
6154 SCIP_Real maxscalar;
6155
6156 assert(var != NULL);
6158 assert(aggvar != NULL);
6160 assert(aggscalar != 0.0); /*lint !e777*/
6161
6162 maxscalar = minscalar = REALABS(aggscalar);
6163 minscalar *= aggvar->data.loose.minaggrcoef;
6164 maxscalar *= aggvar->data.loose.maxaggrcoef;
6165 if( var->data.loose.minaggrcoef > minscalar )
6166 var->data.loose.minaggrcoef = minscalar;
6167 if( var->data.loose.maxaggrcoef < maxscalar )
6168 var->data.loose.maxaggrcoef = maxscalar;
6169}
6170
6171
6172/** tightens the bounds of both variables in aggregation x = a*y + c */
6173static
6175 SCIP_VAR* var, /**< problem variable */
6176 BMS_BLKMEM* blkmem, /**< block memory */
6177 SCIP_SET* set, /**< global SCIP settings */
6178 SCIP_STAT* stat, /**< problem statistics */
6179 SCIP_PROB* transprob, /**< tranformed problem data */
6180 SCIP_PROB* origprob, /**< original problem data */
6181 SCIP_PRIMAL* primal, /**< primal data */
6182 SCIP_TREE* tree, /**< branch and bound tree */
6183 SCIP_REOPT* reopt, /**< reoptimization data structure */
6184 SCIP_LP* lp, /**< current LP data */
6185 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6186 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6187 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6188 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6189 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
6190 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
6191 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
6192 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6193 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
6194 )
6195{
6196 SCIP_Real varlb;
6197 SCIP_Real varub;
6198 SCIP_Real aggvarlb;
6199 SCIP_Real aggvarub;
6200 SCIP_Bool aggvarbdschanged;
6201
6202 assert(var != NULL);
6203 assert(var->scip == set->scip);
6204 assert(aggvar != NULL);
6205 assert(!SCIPsetIsZero(set, scalar));
6206 assert(infeasible != NULL);
6207 assert(fixed != NULL);
6208
6209 *infeasible = FALSE;
6210 *fixed = FALSE;
6211
6212 SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
6213 SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
6214 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
6215
6216 /* loop as long additional changes may be found */
6217 do
6218 {
6219 aggvarbdschanged = FALSE;
6220
6221 /* update the bounds of the aggregated variable x in x = a*y + c */
6222 if( scalar > 0.0 )
6223 {
6224 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
6225 varlb = -SCIPsetInfinity(set);
6226 else
6227 varlb = aggvar->glbdom.lb * scalar + constant;
6228 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
6229 varub = SCIPsetInfinity(set);
6230 else
6231 varub = aggvar->glbdom.ub * scalar + constant;
6232 }
6233 else
6234 {
6235 if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
6236 varub = SCIPsetInfinity(set);
6237 else
6238 varub = aggvar->glbdom.lb * scalar + constant;
6239 if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
6240 varlb = -SCIPsetInfinity(set);
6241 else
6242 varlb = aggvar->glbdom.ub * scalar + constant;
6243 }
6244 varlb = MAX(varlb, var->glbdom.lb);
6245 varub = MIN(varub, var->glbdom.ub);
6246 SCIPvarAdjustLb(var, set, &varlb);
6247 SCIPvarAdjustUb(var, set, &varub);
6248
6249 /* check the new bounds */
6250 if( SCIPsetIsGT(set, varlb, varub) )
6251 {
6252 /* the aggregation is infeasible */
6253 *infeasible = TRUE;
6254 return SCIP_OKAY;
6255 }
6256 else if( SCIPsetIsEQ(set, varlb, varub) )
6257 {
6258 /* the aggregated variable is fixed -> fix both variables */
6259 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6260 eventqueue, eventfilter, cliquetable, varlb, infeasible, fixed) );
6261 if( !(*infeasible) )
6262 {
6263 SCIP_Bool aggfixed;
6264
6265 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6266 eventqueue, eventfilter, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
6267 assert(*fixed == aggfixed);
6268 }
6269 return SCIP_OKAY;
6270 }
6271 else
6272 {
6273 if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
6274 {
6275 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
6276 }
6277 if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
6278 {
6279 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
6280 }
6281
6282 /* update the hole list of the aggregation variable */
6283 /**@todo update hole list of aggregation variable */
6284 }
6285
6286 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
6287 if( scalar > 0.0 )
6288 {
6289 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
6290 aggvarlb = -SCIPsetInfinity(set);
6291 else
6292 aggvarlb = (var->glbdom.lb - constant) / scalar;
6293 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
6294 aggvarub = SCIPsetInfinity(set);
6295 else
6296 aggvarub = (var->glbdom.ub - constant) / scalar;
6297 }
6298 else
6299 {
6300 if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
6301 aggvarub = SCIPsetInfinity(set);
6302 else
6303 aggvarub = (var->glbdom.lb - constant) / scalar;
6304 if( SCIPsetIsInfinity(set, var->glbdom.ub) )
6305 aggvarlb = -SCIPsetInfinity(set);
6306 else
6307 aggvarlb = (var->glbdom.ub - constant) / scalar;
6308 }
6309 aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
6310 aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
6311 SCIPvarAdjustLb(aggvar, set, &aggvarlb);
6312 SCIPvarAdjustUb(aggvar, set, &aggvarub);
6313
6314 /* check the new bounds */
6315 if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
6316 {
6317 /* the aggregation is infeasible */
6318 *infeasible = TRUE;
6319 return SCIP_OKAY;
6320 }
6321 else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
6322 {
6323 /* the aggregation variable is fixed -> fix both variables */
6324 SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6325 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, fixed) );
6326 if( !(*infeasible) )
6327 {
6328 SCIP_Bool varfixed;
6329
6330 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6331 eventqueue, eventfilter, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
6332 assert(*fixed == varfixed);
6333 }
6334 return SCIP_OKAY;
6335 }
6336 else
6337 {
6338 SCIP_Real oldbd;
6339 if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
6340 {
6341 oldbd = aggvar->glbdom.lb;
6342 SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
6343 aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
6344 }
6345 if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
6346 {
6347 oldbd = aggvar->glbdom.ub;
6348 SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
6349 aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
6350 }
6351
6352 /* update the hole list of the aggregation variable */
6353 /**@todo update hole list of aggregation variable */
6354 }
6355 }
6356 while( aggvarbdschanged );
6357
6358 SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
6359 var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
6360
6361 return SCIP_OKAY;
6362}
6363
6364/** tightens the bounds of both variables in aggregation x = a*y + c */
6365static
6367 SCIP_VAR* var, /**< problem variable */
6368 BMS_BLKMEM* blkmem, /**< block memory */
6369 SCIP_SET* set, /**< global SCIP settings */
6370 SCIP_STAT* stat, /**< problem statistics */
6371 SCIP_PROB* transprob, /**< tranformed problem data */
6372 SCIP_PROB* origprob, /**< original problem data */
6373 SCIP_PRIMAL* primal, /**< primal data */
6374 SCIP_TREE* tree, /**< branch and bound tree */
6375 SCIP_REOPT* reopt, /**< reoptimization data structure */
6376 SCIP_LP* lp, /**< current LP data */
6377 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6378 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6379 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6380 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6381 SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
6382 SCIP_RATIONAL* scalar, /**< multiplier a in aggregation x = a*y + c */
6383 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a*y + c */
6384 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6385 SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
6386 )
6387{
6388 SCIP_RATIONAL* varlb;
6389 SCIP_RATIONAL* varub;
6390 SCIP_RATIONAL* aggvarlb;
6391 SCIP_RATIONAL* aggvarub;
6392 SCIP_Bool aggvarbdschanged;
6393
6394 assert(var != NULL);
6395 assert(var->scip == set->scip);
6396 assert(aggvar != NULL);
6397 assert(!SCIPrationalIsZero(scalar));
6398 assert(infeasible != NULL);
6399 assert(fixed != NULL);
6400
6401 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &varlb) );
6402 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &varub) );
6403 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &aggvarlb) );
6404 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &aggvarub) );
6405
6406 *infeasible = FALSE;
6407 *fixed = FALSE;
6408
6409 SCIPrationalDebugMessage("updating bounds of variables in aggregation <%s> == %q*<%s> %+q\n", var->name, scalar, aggvar->name, constant);
6410 SCIPrationalDebugMessage(" old bounds: <%s> [%q,%q] <%s> [%q,%q]\n",
6411 var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub);
6412
6413 /* loop as long additional changes may be found */
6414 do
6415 {
6416 aggvarbdschanged = FALSE;
6417
6418 /* update the bounds of the aggregated variable x in x = a*y + c */
6419 if( SCIPrationalIsPositive(scalar) )
6420 {
6423 else
6424 {
6425 SCIPrationalMult(varlb, aggvar->exactdata->glbdom.lb, scalar);
6426 SCIPrationalAdd(varlb, varlb, constant);
6427 }
6430 else
6431 {
6432 SCIPrationalMult(varub, aggvar->exactdata->glbdom.ub, scalar);
6433 SCIPrationalAdd(varub, varub, constant);
6434 }
6435 }
6436 else
6437 {
6440 else
6441 {
6442 SCIPrationalMult(varub, aggvar->exactdata->glbdom.lb, scalar);
6443 SCIPrationalAdd(varub, varub, constant);
6444 }
6447 else
6448 {
6449 SCIPrationalMult(varlb, aggvar->exactdata->glbdom.ub, scalar);
6450 SCIPrationalAdd(varlb, varlb, constant);
6451 }
6452 }
6453 SCIPrationalMax(varlb, varlb, var->exactdata->glbdom.lb);
6454 SCIPrationalMin(varub, varub, var->exactdata->glbdom.ub);
6455 SCIPvarAdjustLbExact(var, set, varlb);
6456 SCIPvarAdjustUbExact(var, set, varub);
6457
6458 /* check the new bounds */
6459 if( SCIPrationalIsGT(varlb, varub) )
6460 {
6461 /* the aggregation is infeasible */
6462 *infeasible = TRUE;
6463 break;
6464 }
6465 else if( SCIPrationalIsEQ(varlb, varub) )
6466 {
6467 /* the aggregated variable is fixed -> fix both variables */
6468 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6469 eventqueue, eventfilter, cliquetable, varlb, infeasible, fixed) );
6470
6471 if( !(*infeasible) )
6472 {
6473 SCIP_Bool aggfixed;
6474
6475 SCIPrationalDiff(varlb, varlb, constant);
6476 SCIPrationalDiv(varlb, varlb, scalar);
6477
6478 SCIP_CALL( SCIPvarFixExact(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6479 eventqueue, eventfilter, cliquetable, varlb, infeasible, &aggfixed) );
6480 assert(*fixed == aggfixed);
6481 }
6482 break;
6483 }
6484 else
6485 {
6486 if( SCIPrationalIsGT(varlb, var->exactdata->glbdom.lb) )
6487 {
6488 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, varlb) );
6489 }
6490 if( SCIPrationalIsLT(varub, var->exactdata->glbdom.ub) )
6491 {
6492 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, varub) );
6493 }
6494
6495 /* update the hole list of the aggregation variable */
6496 /**@todo update hole list of aggregation variable */
6497 }
6498
6499 /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
6500 if( SCIPrationalIsPositive(scalar) )
6501 {
6502 if( SCIPrationalIsNegInfinity(var->exactdata->glbdom.lb) )
6504 else
6505 {
6506 SCIPrationalDiff(aggvarlb, var->exactdata->glbdom.lb, constant);
6507 SCIPrationalDiv(aggvarlb, aggvarlb, scalar);
6508 }
6509 if( SCIPrationalIsInfinity(var->exactdata->glbdom.ub) )
6510 SCIPrationalSetInfinity(aggvarub);
6511 else
6512 {
6513 SCIPrationalDiff(aggvarub, var->exactdata->glbdom.ub, constant);
6514 SCIPrationalDiv(aggvarub, aggvarub, scalar);
6515 }
6516 }
6517 else
6518 {
6519 if( SCIPrationalIsNegInfinity(var->exactdata->glbdom.lb) )
6520 SCIPrationalSetInfinity(aggvarub);
6521 else
6522 {
6523 SCIPrationalDiff(aggvarub, var->exactdata->glbdom.lb, constant);
6524 SCIPrationalDiv(aggvarub, aggvarub, scalar);
6525 }
6526 if( SCIPrationalIsInfinity(var->exactdata->glbdom.ub) )
6528 else
6529 {
6530 SCIPrationalDiff(aggvarlb, var->exactdata->glbdom.ub, constant);
6531 SCIPrationalDiv(aggvarlb, aggvarlb, scalar);
6532 }
6533 }
6534 SCIPrationalMax(aggvarlb, aggvarlb, aggvar->exactdata->glbdom.lb);
6535 SCIPrationalMin(aggvarub, aggvarub, aggvar->exactdata->glbdom.ub);
6536 SCIPvarAdjustLbExact(aggvar, set, aggvarlb);
6537 SCIPvarAdjustUbExact(aggvar, set, aggvarub);
6538
6539 /* check the new bounds */
6540 if( SCIPrationalIsGT(aggvarlb, aggvarub) )
6541 {
6542 /* the aggregation is infeasible */
6543 *infeasible = TRUE;
6544 break;
6545 }
6546 else if( SCIPrationalIsEQ(aggvarlb, aggvarub) )
6547 {
6548 /* the aggregation variable is fixed -> fix both variables */
6549 SCIP_CALL( SCIPvarFixExact(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6550 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, fixed) );
6551
6552 if( !(*infeasible) )
6553 {
6554 SCIP_Bool varfixed;
6555
6556 SCIPrationalMult(aggvarlb, aggvarlb, scalar);
6557 SCIPrationalAdd(aggvarlb, aggvarlb, constant);
6558
6559 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6560 eventqueue, eventfilter, cliquetable, aggvarlb, infeasible, &varfixed) );
6561 assert(*fixed == varfixed);
6562 }
6563 break;
6564 }
6565 else
6566 {
6567 if( SCIPrationalIsGT(aggvarlb, aggvar->exactdata->glbdom.lb) )
6568 {
6569 SCIPrationalSetRational(varlb, aggvar->exactdata->glbdom.lb);
6570 SCIP_CALL( SCIPvarChgLbGlobalExact(aggvar, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, aggvarlb) );
6571 aggvarbdschanged = !SCIPrationalIsEQ(varlb, aggvar->exactdata->glbdom.lb);
6572 }
6573
6574 if( SCIPrationalIsLT(aggvarub, aggvar->exactdata->glbdom.ub) )
6575 {
6576 SCIPrationalSetRational(varub, aggvar->exactdata->glbdom.ub);
6577 SCIP_CALL( SCIPvarChgUbGlobalExact(aggvar, blkmem, set, stat, lp->lpexact, branchcand, eventqueue, cliquetable, aggvarub) );
6578 aggvarbdschanged = aggvarbdschanged || !SCIPrationalIsEQ(varub, aggvar->exactdata->glbdom.ub);
6579 }
6580
6581 /* update the hole list of the aggregation variable */
6582 /**@todo update hole list of aggregation variable */
6583 }
6584 }
6585 while( aggvarbdschanged );
6586
6587 SCIPrationalDebugMessage(" new bounds: <%s> [%q,%q] <%s> [%q,%q]\n",
6588 var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub);
6589
6590 SCIPrationalFreeBuffer(set->buffer, &aggvarub);
6591 SCIPrationalFreeBuffer(set->buffer, &aggvarlb);
6592 SCIPrationalFreeBuffer(set->buffer, &varub);
6593 SCIPrationalFreeBuffer(set->buffer, &varlb);
6594
6595 return SCIP_OKAY;
6596}
6597
6598/** converts loose variable into aggregated variable */
6600 SCIP_VAR* var, /**< loose problem variable */
6601 BMS_BLKMEM* blkmem, /**< block memory */
6602 SCIP_SET* set, /**< global SCIP settings */
6603 SCIP_STAT* stat, /**< problem statistics */
6604 SCIP_PROB* transprob, /**< tranformed problem data */
6605 SCIP_PROB* origprob, /**< original problem data */
6606 SCIP_PRIMAL* primal, /**< primal data */
6607 SCIP_TREE* tree, /**< branch and bound tree */
6608 SCIP_REOPT* reopt, /**< reoptimization data structure */
6609 SCIP_LP* lp, /**< current LP data */
6610 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6611 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6612 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6613 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6614 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
6615 SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
6616 SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
6617 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6618 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
6619 )
6620{
6621 SCIP_VAR** vars;
6622 SCIP_Real* coefs;
6623 SCIP_Real* constants;
6624 SCIP_Real obj;
6625 SCIP_Real branchfactor;
6626 SCIP_Bool fixed;
6627 int branchpriority;
6628 int nlocksdown[NLOCKTYPES];
6629 int nlocksup[NLOCKTYPES];
6630 int nvbds;
6631 int i;
6632 int j;
6633
6634 assert(var != NULL);
6635 assert(aggvar != NULL);
6636 assert(var->scip == set->scip);
6637 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
6638 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
6640 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
6641 assert(infeasible != NULL);
6642 assert(aggregated != NULL);
6643
6644 *infeasible = FALSE;
6645 *aggregated = FALSE;
6646
6647 /* get active problem variable of aggregation variable */
6648 SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
6649
6650 /* aggregation is a fixing, if the scalar is zero */
6651 if( SCIPsetIsZero(set, scalar) )
6652 {
6653 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
6654 eventfilter, cliquetable, constant, infeasible, aggregated) );
6655 goto TERMINATE;
6656 }
6657
6658 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
6660 return SCIP_OKAY;
6661
6662 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
6663 * should be changed in the future
6664 */
6666 return SCIP_OKAY;
6667
6668 /* if the variable is not allowed to be aggregated */
6669 if( SCIPvarDoNotAggr(var) )
6670 {
6671 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
6672 return SCIP_OKAY;
6673 }
6674
6675 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
6676 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
6678
6679 SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
6680 scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
6681
6682 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
6683 if( var == aggvar )
6684 {
6685 if( SCIPsetIsEQ(set, scalar, 1.0) )
6686 *infeasible = !SCIPsetIsZero(set, constant);
6687 else
6688 {
6689 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6690 eventqueue, eventfilter, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
6691 }
6692 goto TERMINATE;
6693 }
6694
6695 /* tighten the bounds of aggregated and aggregation variable */
6696 SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6697 branchcand, eventqueue, eventfilter, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
6698 if( *infeasible || fixed )
6699 {
6700 *aggregated = fixed;
6701 goto TERMINATE;
6702 }
6703
6704 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
6705 * aggregated variable
6706 */
6707 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
6708
6709 /* set the aggregated variable's objective value to 0.0 */
6710 obj = var->obj;
6711 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
6712
6713 /* unlock all locks */
6714 for( i = 0; i < NLOCKTYPES; i++ )
6715 {
6716 nlocksdown[i] = var->nlocksdown[i];
6717 nlocksup[i] = var->nlocksup[i];
6718
6719 var->nlocksdown[i] = 0;
6720 var->nlocksup[i] = 0;
6721 }
6722
6723 /* update aggregation bounds (argument names of varUpdateMinMaxAggrCoef are swapped) */
6724 varUpdateMinMaxAggrCoef(aggvar, var, scalar);
6725
6726 /* check, if variable should be used as NEGATED variable of the aggregation variable */
6727 if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
6728 && var->negatedvar == NULL && aggvar->negatedvar == NULL
6729 && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
6730 {
6731 /* link both variables as negation pair */
6732 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
6733 var->data.negate.constant = 1.0;
6734 var->negatedvar = aggvar;
6735 aggvar->negatedvar = var;
6736
6737 /* copy donot(mult)aggr status */
6738 aggvar->donotaggr |= var->donotaggr;
6739 aggvar->donotmultaggr |= var->donotmultaggr;
6740
6741 /* mark both variables to be non-deletable */
6744 }
6745 else
6746 {
6747 /* convert variable into aggregated variable */
6748 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
6749 var->data.aggregate.var = aggvar;
6750 var->data.aggregate.scalar = scalar;
6751 var->data.aggregate.constant = constant;
6752
6753 /* copy donot(mult)aggr status */
6754 aggvar->donotaggr |= var->donotaggr;
6755 aggvar->donotmultaggr |= var->donotmultaggr;
6756
6757 /* mark both variables to be non-deletable */
6760 }
6761
6762 /* make aggregated variable a parent of the aggregation variable */
6763 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
6764
6765 /* relock the variable, thus increasing the locks of the aggregation variable */
6766 for( i = 0; i < NLOCKTYPES; i++ )
6767 {
6768 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
6769 }
6770
6771 /* move the variable bounds to the aggregation variable:
6772 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
6773 * - free the variable bounds data structures
6774 */
6775 if( var->vlbs != NULL )
6776 {
6777 nvbds = SCIPvboundsGetNVbds(var->vlbs);
6778 vars = SCIPvboundsGetVars(var->vlbs);
6779 coefs = SCIPvboundsGetCoefs(var->vlbs);
6780 constants = SCIPvboundsGetConstants(var->vlbs);
6781 for( i = 0; i < nvbds && !(*infeasible); ++i )
6782 {
6783 SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
6784 eventqueue, eventfilter, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
6785 }
6786 }
6787 if( var->vubs != NULL )
6788 {
6789 nvbds = SCIPvboundsGetNVbds(var->vubs);
6790 vars = SCIPvboundsGetVars(var->vubs);
6791 coefs = SCIPvboundsGetCoefs(var->vubs);
6792 constants = SCIPvboundsGetConstants(var->vubs);
6793 for( i = 0; i < nvbds && !(*infeasible); ++i )
6794 {
6795 SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
6796 eventqueue, eventfilter, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
6797 }
6798 }
6799 SCIPvboundsFree(&var->vlbs, blkmem);
6800 SCIPvboundsFree(&var->vubs, blkmem);
6801
6802 /* move the implications to the aggregation variable:
6803 * - add all implications again to the variable, thus adding it to the aggregation variable
6804 * - free the implications data structures
6805 */
6806 if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(aggvar) )
6807 {
6809 for( i = 0; i < 2; ++i )
6810 {
6811 SCIP_VAR** implvars;
6812 SCIP_BOUNDTYPE* impltypes;
6813 SCIP_Real* implbounds;
6814 int nimpls;
6815
6816 nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
6817 implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
6818 impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
6819 implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
6820
6821 for( j = 0; j < nimpls && !(*infeasible); ++j )
6822 {
6823 /* @todo can't we omit transitive closure, because it should already have been done when adding the
6824 * implication to the aggregated variable?
6825 */
6826 SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
6827 branchcand, eventqueue, eventfilter, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE,
6828 infeasible, NULL) );
6829 assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
6830 }
6831 }
6832 }
6833 SCIPimplicsFree(&var->implics, blkmem);
6834
6835 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
6836 SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
6837 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
6838 SCIPhistoryReset(var->history);
6839 SCIPhistoryReset(var->historycrun);
6840
6841 /* update flags of aggregation variable */
6842 aggvar->removable &= var->removable;
6843
6844 /* update branching factors and priorities of both variables to be the maximum of both variables */
6845 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
6846 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
6847 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
6848 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
6849 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
6850 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
6851
6852 /* update branching direction of both variables to agree to a single direction */
6853 if( scalar >= 0.0 )
6854 {
6855 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
6856 {
6858 }
6860 {
6861 SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
6862 }
6863 else if( var->branchdirection != aggvar->branchdirection )
6864 {
6866 }
6867 }
6868 else
6869 {
6870 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
6871 {
6873 }
6875 {
6877 }
6878 else if( var->branchdirection != aggvar->branchdirection )
6879 {
6881 }
6882 }
6883
6884 if( var->probindex != -1 )
6885 {
6886 /* inform problem about the variable's status change */
6887 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
6888 }
6889
6890 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
6891 * variable and the problem's objective offset
6892 */
6893 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
6894
6895 /* issue VARFIXED event */
6896 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
6897
6898 *aggregated = TRUE;
6899
6900TERMINATE:
6901 /* check aggregation on debugging solution */
6902 if( *infeasible || *aggregated )
6903 SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
6904
6905 return SCIP_OKAY;
6906}
6907
6908/** converts loose variable into aggregated variable */
6910 SCIP_VAR* var, /**< loose problem variable */
6911 BMS_BLKMEM* blkmem, /**< block memory */
6912 SCIP_SET* set, /**< global SCIP settings */
6913 SCIP_STAT* stat, /**< problem statistics */
6914 SCIP_PROB* transprob, /**< tranformed problem data */
6915 SCIP_PROB* origprob, /**< original problem data */
6916 SCIP_PRIMAL* primal, /**< primal data */
6917 SCIP_TREE* tree, /**< branch and bound tree */
6918 SCIP_REOPT* reopt, /**< reoptimization data structure */
6919 SCIP_LP* lp, /**< current LP data */
6920 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6921 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6922 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6923 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
6924 SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
6925 SCIP_RATIONAL* scalar, /**< multiplier a in aggregation x = a*y + c */
6926 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a*y + c */
6927 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
6928 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
6929 )
6930{
6932 SCIP_RATIONAL* tmpval;
6933 SCIP_Real branchfactor;
6934 SCIP_Bool fixed;
6935 int branchpriority;
6936 int nlocksdown[NLOCKTYPES];
6937 int nlocksup[NLOCKTYPES];
6938 int i;
6939
6940 assert(var != NULL);
6941 assert(aggvar != NULL);
6942 assert(var->scip == set->scip);
6943 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
6944 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
6946 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
6947 assert(infeasible != NULL);
6948 assert(aggregated != NULL);
6949
6950 *infeasible = FALSE;
6951 *aggregated = FALSE;
6952
6953 /* get active problem variable of aggregation variable */
6954 SCIP_CALL( SCIPvarGetProbvarSumExact(&aggvar, scalar, constant) );
6955
6956 /* aggregation is a fixing, if the scalar is zero */
6957 if( SCIPrationalIsZero(scalar) )
6958 {
6959 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
6960 eventqueue, eventfilter, cliquetable, constant, infeasible, aggregated) );
6961 return SCIP_OKAY;
6962 }
6963
6964 /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
6966 return SCIP_OKAY;
6967
6968 /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
6969 * should be changed in the future
6970 */
6972 return SCIP_OKAY;
6973
6974 /* if the variable is not allowed to be aggregated */
6975 if( SCIPvarDoNotAggr(var) )
6976 {
6977 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
6978 return SCIP_OKAY;
6979 }
6980
6981 assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
6982 assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
6984
6985 SCIPrationalDebugMessage("aggregate variable <%s>[%q,%q] == %q*<%s>[%q,%q] +%q\n", var->name, var->exactdata->glbdom.lb, var->exactdata->glbdom.ub,
6986 scalar, aggvar->name, aggvar->exactdata->glbdom.lb, aggvar->exactdata->glbdom.ub, constant);
6987
6988 /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
6989 if( var == aggvar )
6990 {
6991 if( SCIPrationalIsEQReal(scalar, 1.0) )
6992 *infeasible = !SCIPrationalIsZero(constant);
6993 else
6994 {
6995 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
6996 /* fix to constant/(1-scalar) */
6997 SCIPrationalDiffReal(tmpval, scalar, 1.0);
6998 SCIPrationalNegate(tmpval, tmpval);
6999 SCIPrationalDiv(tmpval, constant, tmpval);
7000 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
7001 eventqueue, eventfilter, cliquetable, tmpval, infeasible, aggregated) );
7002
7003 SCIPrationalFreeBuffer(set->buffer, &tmpval);
7004 }
7005 return SCIP_OKAY;
7006 }
7007
7008 /* tighten the bounds of aggregated and aggregation variable */
7009 SCIP_CALL( varUpdateAggregationBoundsExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
7010 branchcand, eventqueue, eventfilter, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
7011 if( *infeasible || fixed )
7012 {
7013 *aggregated = fixed;
7014 return SCIP_OKAY;
7015 }
7016
7017 /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
7018 * aggregated variable
7019 */
7020 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
7021 assert(var->cliquelist == NULL);
7022
7024 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
7025
7026 /* set the aggregated variable's objective value to 0.0 */
7027 SCIPrationalSetRational(obj, var->exactdata->obj);
7028 SCIPrationalSetReal(tmpval, 0.0);
7029 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lp->lpexact, eventqueue, tmpval) );
7030
7031 SCIPrationalFreeBuffer(set->buffer, &tmpval);
7032
7033 /* unlock all locks */
7034 for( i = 0; i < NLOCKTYPES; i++ )
7035 {
7036 nlocksdown[i] = var->nlocksdown[i];
7037 nlocksup[i] = var->nlocksup[i];
7038
7039 var->nlocksdown[i] = 0;
7040 var->nlocksup[i] = 0;
7041 }
7042
7043 /* check, if variable should be used as NEGATED variable of the aggregation variable */
7044 if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
7045 && var->negatedvar == NULL && aggvar->negatedvar == NULL
7046 && SCIPrationalIsEQReal(scalar, -1.0) && SCIPrationalIsEQReal(constant, 1.0) )
7047 {
7048 /* link both variables as negation pair */
7049 var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
7050 var->exactdata->varstatusexact = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
7051 var->data.negate.constant = 1.0;
7052 var->negatedvar = aggvar;
7053 aggvar->negatedvar = var;
7054
7055 /* copy doNotMultiaggr status */
7056 aggvar->donotmultaggr |= var->donotmultaggr;
7057
7058 /* mark both variables to be non-deletable */
7061 }
7062 else
7063 {
7064 /* convert variable into aggregated variable */
7065 var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
7066 var->exactdata->varstatusexact = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
7067 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->aggregate.scalar) );
7068 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &var->exactdata->aggregate.constant) );
7069
7070 var->data.aggregate.var = aggvar;
7071 SCIPrationalSetRational(var->exactdata->aggregate.scalar, scalar);
7072 SCIPrationalSetRational(var->exactdata->aggregate.constant, constant);
7073 var->data.aggregate.scalar = SCIPrationalGetReal(scalar);
7074 var->data.aggregate.constant = SCIPrationalGetReal(constant);
7075
7076 /* copy doNotMultiaggr status */
7077 aggvar->donotmultaggr |= var->donotmultaggr;
7078
7079 /* mark both variables to be non-deletable */
7082 }
7083
7084 /* make aggregated variable a parent of the aggregation variable */
7085 SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
7086
7087 /* relock the variable, thus increasing the locks of the aggregation variable */
7088 for( i = 0; i < NLOCKTYPES; i++ )
7089 {
7090 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
7091 }
7092
7093 /* move the variable bounds to the aggregation variable:
7094 * - add all variable bounds again to the variable, thus adding it to the aggregation variable
7095 * - free the variable bounds data structures
7096 */
7097 assert(var->vlbs == NULL);
7098 assert(var->vubs == NULL);
7099
7100 /* move the implications to the aggregation variable:
7101 * - add all implications again to the variable, thus adding it to the aggregation variable
7102 * - free the implications data structures
7103 */
7104 assert(var->implics == NULL);
7105
7106 /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
7107 SCIPhistoryUnite(aggvar->history, var->history, SCIPrationalIsNegative(scalar));
7108 SCIPhistoryUnite(aggvar->historycrun, var->historycrun, SCIPrationalIsNegative(scalar));
7109 SCIPhistoryReset(var->history);
7110 SCIPhistoryReset(var->historycrun);
7111
7112 /* update flags of aggregation variable */
7113 aggvar->removable &= var->removable;
7114
7115 /* update branching factors and priorities of both variables to be the maximum of both variables */
7116 branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
7117 branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
7118 SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
7119 SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
7120 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
7121 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
7122
7123 /* update branching direction of both variables to agree to a single direction */
7124 if( !SCIPrationalIsNegative(scalar) )
7125 {
7126 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
7127 {
7129 }
7131 {
7132 SCIP_CALL( SCIPvarChgBranchDirection(aggvar, (SCIP_BRANCHDIR)var->branchdirection) );
7133 }
7134 else if( var->branchdirection != aggvar->branchdirection )
7135 {
7137 }
7138 }
7139 else
7140 {
7141 if( (SCIP_BRANCHDIR)var->branchdirection == SCIP_BRANCHDIR_AUTO )
7142 {
7144 }
7146 {
7148 }
7149 else if( var->branchdirection != aggvar->branchdirection )
7150 {
7152 }
7153 }
7154
7155 if( var->probindex != -1 )
7156 {
7157 /* inform problem about the variable's status change */
7158 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
7159 }
7160
7161 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
7162 * variable and the problem's objective offset
7163 */
7164 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
7165
7166 /* issue VARFIXED event */
7167 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
7168
7169 SCIPrationalFreeBuffer(set->buffer, &obj);
7170
7171 *aggregated = TRUE;
7172
7173 return SCIP_OKAY;
7174}
7175
7176/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
7177 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
7178 *
7179 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
7180 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7181 */
7182static
7184 SCIP_SET* set, /**< global SCIP settings */
7185 BMS_BLKMEM* blkmem, /**< block memory */
7186 SCIP_STAT* stat, /**< problem statistics */
7187 SCIP_PROB* transprob, /**< tranformed problem data */
7188 SCIP_PROB* origprob, /**< original problem data */
7189 SCIP_PRIMAL* primal, /**< primal data */
7190 SCIP_TREE* tree, /**< branch and bound tree */
7191 SCIP_REOPT* reopt, /**< reoptimization data structure */
7192 SCIP_LP* lp, /**< current LP data */
7193 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7194 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7195 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7196 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7197 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
7198 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
7199 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
7200 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
7201 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
7202 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7203 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7204 )
7205{
7206 SCIP_VAR* aggvar;
7207 char aggvarname[SCIP_MAXSTRLEN];
7208 SCIP_Longint scalarxn = 0;
7209 SCIP_Longint scalarxd = 0;
7210 SCIP_Longint scalaryn = 0;
7211 SCIP_Longint scalaryd = 0;
7215 SCIP_Longint scm;
7216 SCIP_Longint gcd;
7217 SCIP_Longint currentclass;
7218 SCIP_Longint classstep;
7219 SCIP_Longint xsol;
7220 SCIP_Longint ysol;
7221 SCIP_Bool success;
7222 SCIP_VARTYPE vartype;
7223 SCIP_IMPLINTTYPE impltypex;
7224 SCIP_IMPLINTTYPE impltypey;
7225 SCIP_IMPLINTTYPE impltype;
7226
7227#define MAXDNOM 1000000LL
7228
7229 assert(set != NULL);
7230 assert(blkmem != NULL);
7231 assert(stat != NULL);
7232 assert(transprob != NULL);
7233 assert(origprob != NULL);
7234 assert(tree != NULL);
7235 assert(lp != NULL);
7236 assert(cliquetable != NULL);
7237 assert(branchcand != NULL);
7238 assert(eventqueue != NULL);
7239 assert(varx != NULL);
7240 assert(vary != NULL);
7241 assert(varx != vary);
7242 assert(infeasible != NULL);
7243 assert(aggregated != NULL);
7249 assert(!SCIPsetIsZero(set, scalarx));
7250 assert(!SCIPsetIsZero(set, scalary));
7251
7252 *infeasible = FALSE;
7253 *aggregated = FALSE;
7254
7255 /* if the variable is not allowed to be aggregated */
7256 if( SCIPvarDoNotAggr(varx) )
7257 {
7258 SCIPsetDebugMsg(set, "variable is not allowed to be aggregated.\n");
7259 return SCIP_OKAY;
7260 }
7261
7262 /* get rational representation of coefficients */
7263 success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
7264 if( success )
7265 success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
7266 if( !success )
7267 return SCIP_OKAY;
7268 assert(scalarxd >= 1);
7269 assert(scalaryd >= 1);
7270
7271 /* multiply equality with smallest common denominator */
7272 scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
7273 a = (scm/scalarxd)*scalarxn;
7274 b = (scm/scalaryd)*scalaryn;
7275 rhs *= scm;
7276
7277 /* divide equality by the greatest common divisor of a and b */
7278 gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
7279 a /= gcd;
7280 b /= gcd;
7281 rhs /= gcd;
7282 assert(a != 0);
7283 assert(b != 0);
7284
7285 /* check, if right hand side is integral */
7286 if( !SCIPsetIsFeasIntegral(set, rhs) )
7287 {
7288 *infeasible = TRUE;
7289 return SCIP_OKAY;
7290 }
7292
7293 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
7294 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7295 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7296 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7297 {
7298 return SCIP_OKAY;
7299 }
7300
7301 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
7302 if( ( a == 1 || a == -1 ) && !SCIPvarIsImpliedIntegral(vary) )
7303 {
7304 /* aggregate x = - b/a*y + c/a */
7305 /*lint --e{653}*/
7306 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7307 branchcand, eventqueue, eventfilter, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
7308 assert(*aggregated);
7309 return SCIP_OKAY;
7310 }
7311 if( ( b == 1 || b == -1 ) && !SCIPvarIsImpliedIntegral(varx) )
7312 {
7313 /* aggregate y = - a/b*x + c/b */
7314 /*lint --e{653}*/
7315 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7316 branchcand, eventqueue, eventfilter, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
7317 assert(*aggregated);
7318 return SCIP_OKAY;
7319 }
7320
7321 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
7322 * common divisor. Let (x',y') be a solution of the equality
7323 * a*x + b*y == c -> a*x == c - b*y
7324 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
7325 */
7326
7327 /* find initial solution (x',y'):
7328 * - find y' such that c - b*y' is a multiple of a
7329 * - start in equivalence class c%a
7330 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
7331 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
7332 * - because a and b don't have a common divisor, each class is visited at most once, and at most a-1 steps are needed
7333 * - calculate x' with x' = (c - b*y')/a (which must be integral)
7334 *
7335 * Algorithm works for a > 0 only.
7336 */
7337 if( a < 0 )
7338 {
7339 a = -a;
7340 b = -b;
7341 c = -c;
7342 }
7343 assert(a > 0);
7344
7345 /* search upwards from ysol = 0 */
7346 ysol = 0;
7347 currentclass = c % a;
7348 if( currentclass < 0 )
7349 currentclass += a;
7350 assert(0 <= currentclass && currentclass < a);
7351
7352 classstep = (-b) % a;
7353
7354 if( classstep < 0 )
7355 classstep += a;
7356 assert(0 <= classstep && classstep < a);
7357
7358 while( currentclass != 0 )
7359 {
7360 assert(0 <= currentclass && currentclass < a);
7361 currentclass += classstep;
7362 if( currentclass >= a )
7363 currentclass -= a;
7364 ysol++;
7365 }
7366 assert(ysol < a);
7367 assert(((c - b*ysol) % a) == 0);
7368
7369 xsol = (c - b*ysol)/a;
7370
7371 /* determine variable type for new artificial variable:
7372 *
7373 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
7374 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
7375 * integral type
7376 */
7379 impltypex = SCIPvarGetImplType(varx);
7380 impltypey = SCIPvarGetImplType(vary);
7381 impltype = MIN(impltypex, impltypey);
7382
7383 /* feasible solutions are (x,y) = (x',y') + z * (-b,a)
7384 * - create new integer variable z with infinite bounds
7385 * - aggregate variable x = -b*z + x'
7386 * - aggregate variable y = a*z + y'
7387 * - the bounds of z are calculated automatically during aggregation
7388 */
7389 (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
7390 SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
7391 aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype, impltype,
7393 NULL, NULL, NULL, NULL, NULL) );
7394
7395 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventqueue, eventfilter, aggvar) );
7396
7397 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7398 branchcand, eventqueue, eventfilter, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
7399 assert(*aggregated || *infeasible);
7400
7401 if( !(*infeasible) )
7402 {
7403 SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7404 branchcand, eventqueue, eventfilter, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
7405 assert(*aggregated || *infeasible);
7406 }
7407
7408 /* release z */
7409 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
7410
7411 return SCIP_OKAY; /*lint !e438*/
7412}
7413
7414/** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
7415 * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
7416 *
7417 * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
7418 * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7419 */
7420static
7422 SCIP_SET* set, /**< global SCIP settings */
7423 BMS_BLKMEM* blkmem, /**< block memory */
7424 SCIP_STAT* stat, /**< problem statistics */
7425 SCIP_PROB* transprob, /**< tranformed problem data */
7426 SCIP_PROB* origprob, /**< original problem data */
7427 SCIP_PRIMAL* primal, /**< primal data */
7428 SCIP_TREE* tree, /**< branch and bound tree */
7429 SCIP_REOPT* reopt, /**< reoptimization data structure */
7430 SCIP_LP* lp, /**< current LP data */
7431 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7432 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7433 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7434 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7435 SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
7436 SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
7437 SCIP_RATIONAL* scalarx, /**< multiplier a in equality a*x + b*y == c */
7438 SCIP_RATIONAL* scalary, /**< multiplier b in equality a*x + b*y == c */
7439 SCIP_RATIONAL* rhs, /**< right hand side c in equality a*x + b*y == c */
7440 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7441 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7442 )
7443{
7444 SCIP_VAR* aggvar;
7445 SCIP_RATIONAL* tmprat1;
7446 SCIP_RATIONAL* tmprat2;
7447 SCIP_RATIONAL* tmprat3;
7448 char aggvarname[SCIP_MAXSTRLEN];
7449 SCIP_Longint scalarxn;
7450 SCIP_Longint scalarxd;
7451 SCIP_Longint scalaryn;
7452 SCIP_Longint scalaryd;
7456 SCIP_Longint scm;
7457 SCIP_Longint gcd;
7458 SCIP_Longint currentclass;
7459 SCIP_Longint classstep;
7460 SCIP_Longint xsol;
7461 SCIP_Longint ysol;
7462 SCIP_VARTYPE vartype;
7463 SCIP_IMPLINTTYPE impltypex;
7464 SCIP_IMPLINTTYPE impltypey;
7465 SCIP_IMPLINTTYPE impltype;
7466
7467 assert(set != NULL);
7468 assert(blkmem != NULL);
7469 assert(stat != NULL);
7470 assert(transprob != NULL);
7471 assert(origprob != NULL);
7472 assert(tree != NULL);
7473 assert(lp != NULL);
7474 assert(cliquetable != NULL);
7475 assert(branchcand != NULL);
7476 assert(eventqueue != NULL);
7477 assert(varx != NULL);
7478 assert(vary != NULL);
7479 assert(varx != vary);
7480 assert(infeasible != NULL);
7481 assert(aggregated != NULL);
7487 assert(!SCIPrationalIsZero(scalarx));
7488 assert(!SCIPrationalIsZero(scalary));
7489
7490 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat1) );
7491 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat2) );
7492 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmprat3) );
7493
7494 *infeasible = FALSE;
7495 *aggregated = FALSE;
7496
7497 SCIPrationalCanonicalize(scalary);
7498 SCIPrationalCanonicalize(scalarx);
7499
7500 scalarxd = SCIPrationalDenominator(scalarx);
7501 scalaryd = SCIPrationalDenominator(scalary);
7502 scalarxn = SCIPrationalNumerator(scalarx);
7503 scalaryn = SCIPrationalNumerator(scalary);
7504
7505 /* multiply equality with smallest common denominator */
7506 scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
7507 a = (scm/scalarxd)*scalarxn;
7508 b = (scm/scalaryd)*scalaryn;
7509
7510 /* divide equality by the greatest common divisor of a and b */
7511 gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
7512 a /= gcd;
7513 b /= gcd;
7514 SCIPrationalSetFraction(tmprat1, scm, gcd);
7515 SCIPrationalMult(rhs, rhs, tmprat1);
7516 assert(a != 0);
7517 assert(b != 0);
7518
7519 /* check, if right hand side is integral */
7520 if( !SCIPrationalIsIntegral(rhs) )
7521 {
7522 *infeasible = TRUE;
7523 goto FREE;
7524 }
7525
7526 /* we know rhs is integral, so check if it is in integer range */
7528 {
7529 *infeasible = TRUE;
7530 goto FREE;
7531 }
7532
7533 /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
7534 if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7535 || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
7536 || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7537 {
7538 goto FREE;
7539 }
7540
7541 /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
7542 if( ( a == 1 || a == -1 ) && !SCIPvarIsImpliedIntegral(vary) )
7543 {
7544 /* aggregate x = - b/a*y + c/a */
7545 /*lint --e{653}*/
7546 SCIPrationalSetFraction(tmprat1, -b, a);
7547 SCIPrationalSetFraction(tmprat2, c, a);
7548 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7549 branchcand, eventqueue, eventfilter, vary, tmprat1, tmprat2, infeasible, aggregated) );
7550 assert(*aggregated);
7551 goto FREE;
7552 }
7553 if( ( b == 1 || b == -1 ) && !SCIPvarIsImpliedIntegral(varx) )
7554 {
7555 /* aggregate y = - a/b*x + c/b */
7556 /*lint --e{653}*/
7557 SCIPrationalSetFraction(tmprat1, -a, b);
7558 SCIPrationalSetFraction(tmprat2, c, b);
7559 SCIP_CALL( SCIPvarAggregateExact(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7560 branchcand, eventqueue, eventfilter, varx, tmprat1, tmprat2, infeasible, aggregated) );
7561 assert(*aggregated);
7562 goto FREE;
7563 }
7564
7565 /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
7566 * common divisor. Let (x',y') be a solution of the equality
7567 * a*x + b*y == c -> a*x == c - b*y
7568 * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
7569 */
7570
7571 /* find initial solution (x',y'):
7572 * - find y' such that c - b*y' is a multiple of a
7573 * - start in equivalence class c%a
7574 * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
7575 * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
7576 * - because a and b don't have a common divisor, each class is visited at most once, and at most a-1 steps are needed
7577 * - calculate x' with x' = (c - b*y')/a (which must be integral)
7578 *
7579 * Algorithm works for a > 0 only.
7580 */
7581 if( a < 0 )
7582 {
7583 a = -a;
7584 b = -b;
7585 c = -c;
7586 }
7587 assert(a > 0);
7588
7589 /* search upwards from ysol = 0 */
7590 ysol = 0;
7591 currentclass = c % a;
7592 if( currentclass < 0 )
7593 currentclass += a;
7594 assert(0 <= currentclass && currentclass < a);
7595
7596 classstep = (-b) % a;
7597
7598 if( classstep < 0 )
7599 classstep += a;
7600 assert(0 <= classstep && classstep < a);
7601
7602 while( currentclass != 0 )
7603 {
7604 assert(0 <= currentclass && currentclass < a);
7605 currentclass += classstep;
7606 if( currentclass >= a )
7607 currentclass -= a;
7608 ysol++;
7609 }
7610 assert(ysol < a);
7611 assert(((c - b*ysol) % a) == 0);
7612
7613 xsol = (c - b*ysol)/a;
7614
7615 /* determine variable type for new artificial variable:
7616 *
7617 * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
7618 * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
7619 * integral type
7620 */
7623 impltypex = SCIPvarGetImplType(varx);
7624 impltypey = SCIPvarGetImplType(vary);
7625 impltype = MIN(impltypex, impltypey);
7626
7627 /* feasible solutions are (x,y) = (x',y') + z * (-b,a)
7628 * - create new integer variable z with infinite bounds
7629 * - aggregate variable x = -b*z + x'
7630 * - aggregate variable y = a*z + y'
7631 * - the bounds of z are calculated automatically during aggregation
7632 */
7633 (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
7634 SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
7635 aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype, impltype,
7637 NULL, NULL, NULL, NULL, NULL) );
7638
7640 SCIPrationalSetInfinity(tmprat2);
7641 SCIPrationalSetFraction(tmprat3, 0LL, 0LL);
7642
7643 SCIP_CALL( SCIPvarAddExactData(aggvar, blkmem, tmprat1, tmprat2, tmprat3) );
7644
7645 SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventqueue, eventfilter, aggvar) );
7646
7647 SCIPrationalSetFraction(tmprat1, -b, 1LL);
7648 SCIPrationalSetFraction(tmprat2, xsol, 1LL);
7649
7650 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7651 branchcand, eventqueue, eventfilter, aggvar, tmprat1, tmprat2, infeasible, aggregated) );
7652 assert(*aggregated || *infeasible);
7653
7654 if( !(*infeasible) )
7655 {
7656 SCIPrationalSetFraction(tmprat1, a, 1LL);
7657 SCIPrationalSetFraction(tmprat2, ysol, 1LL);
7658
7659 SCIP_CALL( SCIPvarAggregateExact(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7660 branchcand, eventqueue, eventfilter, aggvar, tmprat1, tmprat2, infeasible, aggregated) );
7661 assert(*aggregated || *infeasible);
7662 }
7663
7664 /* release z */
7665 SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
7666
7667FREE:
7668 SCIPrationalFreeBuffer(set->buffer, &tmprat3);
7669 SCIPrationalFreeBuffer(set->buffer, &tmprat2);
7670 SCIPrationalFreeBuffer(set->buffer, &tmprat1);
7671
7672 return SCIP_OKAY; /*lint !e438*/
7673}
7674
7675/** performs second step of SCIPaggregateVars():
7676 * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
7677 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
7678 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
7679 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
7680 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
7681 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7682 *
7683 * @todo check for fixings, infeasibility, bound changes, or domain holes:
7684 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
7685 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
7686 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
7687 */
7689 SCIP_SET* set, /**< global SCIP settings */
7690 BMS_BLKMEM* blkmem, /**< block memory */
7691 SCIP_STAT* stat, /**< problem statistics */
7692 SCIP_PROB* transprob, /**< tranformed problem data */
7693 SCIP_PROB* origprob, /**< original problem data */
7694 SCIP_PRIMAL* primal, /**< primal data */
7695 SCIP_TREE* tree, /**< branch and bound tree */
7696 SCIP_REOPT* reopt, /**< reoptimization data structure */
7697 SCIP_LP* lp, /**< current LP data */
7698 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7699 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7700 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7701 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7702 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
7703 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
7704 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
7705 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
7706 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
7707 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7708 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7709 )
7710{
7711 SCIP_Real scalar;
7712 SCIP_Real constant;
7713 SCIP_Bool easyaggr;
7714 SCIP_VARTYPE typex;
7715 SCIP_VARTYPE typey;
7716
7717 assert(set != NULL);
7718 assert(blkmem != NULL);
7719 assert(stat != NULL);
7720 assert(transprob != NULL);
7721 assert(origprob != NULL);
7722 assert(tree != NULL);
7723 assert(lp != NULL);
7724 assert(cliquetable != NULL);
7725 assert(branchcand != NULL);
7726 assert(eventqueue != NULL);
7727 assert(varx != NULL);
7728 assert(vary != NULL);
7729 assert(varx != vary);
7730 assert(infeasible != NULL);
7731 assert(aggregated != NULL);
7735 assert(scalarx != 0.0); /*lint !e777*/
7736 assert(scalary != 0.0); /*lint !e777*/
7738
7739 *infeasible = FALSE;
7740 *aggregated = FALSE;
7741
7742 /**@todo simplify the following code once SCIP_DEPRECATED_VARTYPE_IMPLINT is removed */
7745
7746 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
7747 if( typex < typey ||
7748 ( typex == typey && SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
7749 {
7750 SCIP_VAR* var;
7751 SCIP_VARTYPE type;
7752
7753 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
7754 var = vary;
7755 vary = varx;
7756 varx = var;
7757 scalar = scalary;
7758 scalary = scalarx;
7759 scalarx = scalar;
7760 type = typey;
7761 typey = typex;
7762 typex = type;
7763 }
7764
7765 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
7766 if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
7767 return SCIP_OKAY;
7768
7769 assert(typex >= typey);
7770
7771 /* figure out, which variable should be aggregated */
7772 easyaggr = FALSE;
7773
7774 /* check if it is an easy aggregation */
7775 if( typex == SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS )
7776 {
7777 easyaggr = TRUE;
7778 }
7779 else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
7780 {
7781 easyaggr = TRUE;
7782 }
7783 else if( typex == typey && SCIPsetIsFeasIntegral(set, scalarx / scalary) )
7784 {
7785 /* we have an easy aggregation if we flip the variables x and y */
7786 SCIP_VAR* var;
7787
7788 /* switch the variables, such that varx is the aggregated variable */
7789 var = vary;
7790 vary = varx;
7791 varx = var;
7792 scalar = scalary;
7793 scalary = scalarx;
7794 scalarx = scalar;
7795 easyaggr = TRUE;
7796 }
7797 else if( typex == SCIP_VARTYPE_CONTINUOUS )
7798 {
7799 /* the aggregation is still easy if both variables are continuous */
7800 assert(typey == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
7801 easyaggr = TRUE;
7802 }
7803
7804 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
7805 scalar = -scalary / scalarx;
7806 constant = rhs / scalarx;
7807
7808 /* terminate if a bound on resolved aggregation scalar becomes too small or large so that numerical cancellation may be caused */
7809 if( !SCIPvarIsAggrCoefAcceptable(set, varx, scalar) )
7810 return SCIP_OKAY;
7811
7812 /* did we find an "easy" aggregation? */
7813 if( easyaggr )
7814 {
7815 assert(typex >= typey);
7816
7817 if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
7818 return SCIP_OKAY;
7819
7820 /* check aggregation for integer feasibility */
7821 if( typex != SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS
7822 && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
7823 {
7824 *infeasible = TRUE;
7825 return SCIP_OKAY;
7826 }
7827
7828 /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
7829 * since then we would loose the corresponding divisibility property
7830 */
7832
7833 /* aggregate the variable */
7834 SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7835 branchcand, eventqueue, eventfilter, vary, scalar, constant, infeasible, aggregated) );
7836 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
7837 }
7838 else if( ( typex == SCIP_VARTYPE_INTEGER || typex == SCIP_DEPRECATED_VARTYPE_IMPLINT )
7839 && ( typey == SCIP_VARTYPE_INTEGER || typey == SCIP_DEPRECATED_VARTYPE_IMPLINT ) )
7840 {
7841 /* the variables are both integral: we have to try to find an integer aggregation */
7842 SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
7843 branchcand, eventqueue, eventfilter, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
7844 }
7845
7846 return SCIP_OKAY;
7847}
7848
7849/** performs second step of SCIPaggregateVarsExact()
7850 *
7851 * The variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
7852 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
7853 * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
7854 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
7855 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
7856 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
7857 *
7858 * @todo check for fixings, infeasibility, bound changes, or domain holes:
7859 * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
7860 * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
7861 * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
7862 */
7864 SCIP_SET* set, /**< global SCIP settings */
7865 BMS_BLKMEM* blkmem, /**< block memory */
7866 SCIP_STAT* stat, /**< problem statistics */
7867 SCIP_PROB* transprob, /**< tranformed problem data */
7868 SCIP_PROB* origprob, /**< original problem data */
7869 SCIP_PRIMAL* primal, /**< primal data */
7870 SCIP_TREE* tree, /**< branch and bound tree */
7871 SCIP_REOPT* reopt, /**< reoptimization data structure */
7872 SCIP_LP* lp, /**< current LP data */
7873 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7874 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7875 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7876 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
7877 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
7878 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
7879 SCIP_RATIONAL* scalarx, /**< multiplier a in equality a*x + b*y == c */
7880 SCIP_RATIONAL* scalary, /**< multiplier b in equality a*x + b*y == c */
7881 SCIP_RATIONAL* rhs, /**< right hand side c in equality a*x + b*y == c */
7882 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
7883 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
7884 )
7885{
7886 SCIP_Bool easyaggr;
7887 SCIP_RATIONAL* quotxy;
7888 SCIP_RATIONAL* quotyx;
7889 SCIP_Real absquot;
7890 SCIP_Real maxscalar;
7891 SCIP_VARTYPE typex;
7892 SCIP_VARTYPE typey;
7893
7894 assert(set != NULL);
7895 assert(blkmem != NULL);
7896 assert(stat != NULL);
7897 assert(transprob != NULL);
7898 assert(origprob != NULL);
7899 assert(tree != NULL);
7900 assert(lp != NULL);
7901 assert(cliquetable != NULL);
7902 assert(branchcand != NULL);
7903 assert(eventqueue != NULL);
7904 assert(varx != NULL);
7905 assert(vary != NULL);
7906 assert(varx != vary);
7907 assert(infeasible != NULL);
7908 assert(aggregated != NULL);
7912 assert(!SCIPrationalIsZero(scalarx));
7913 assert(!SCIPrationalIsZero(scalary));
7914
7915 *infeasible = FALSE;
7916 *aggregated = FALSE;
7917
7918 absquot = REALABS(SCIPrationalGetReal(scalarx) / SCIPrationalGetReal(scalary));
7919 maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
7920 maxscalar = MAX(maxscalar, 1.0);
7921
7922 if( absquot > maxscalar || absquot < 1 / maxscalar )
7923 return SCIP_OKAY;
7924
7925 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &quotxy) );
7926 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &quotyx) );
7927
7928 SCIPrationalDiv(quotxy, scalarx, scalary);
7929 SCIPrationalInvert(quotyx, quotxy);
7930
7931 /**@todo simplify the following code once SCIP_DEPRECATED_VARTYPE_IMPLINT is removed */
7934
7935 /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
7936 if( typex < typey ||
7937 ( typex == typey && SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
7938 {
7939 SCIP_VAR* var;
7940 SCIP_RATIONAL* scalar;
7941 SCIP_VARTYPE type;
7942
7943 /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
7944 var = vary;
7945 vary = varx;
7946 varx = var;
7947 scalar = scalary;
7948 scalary = scalarx;
7949 scalarx = scalar;
7950 type = typey;
7951 typey = typex;
7952 typex = type;
7953 SCIPrationalInvert(quotyx, quotyx);
7954 SCIPrationalInvert(quotxy, quotxy);
7955 }
7956
7957 /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
7958 if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
7959 return SCIP_OKAY;
7960
7961 assert(typex >= typey);
7962
7963 /* figure out, which variable should be aggregated */
7964 easyaggr = FALSE;
7965
7966 /* check if it is an easy aggregation that means:
7967 *
7968 * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
7969 */
7971 {
7972 if( typex == SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS )
7973 {
7974 easyaggr = TRUE;
7975 }
7976 else if( SCIPrationalIsIntegral(quotyx) )
7977 {
7978 easyaggr = TRUE;
7979 }
7980 else if( typex == typey && SCIPrationalIsIntegral(quotxy) )
7981 {
7982 /* we have an easy aggregation if we flip the variables x and y */
7983 SCIP_VAR* var;
7984 SCIP_RATIONAL* scalar;
7985
7986 /* switch the variables, such that varx is the aggregated variable */
7987 var = vary;
7988 vary = varx;
7989 varx = var;
7990 scalar = scalary;
7991 scalary = scalarx;
7992 scalarx = scalar;
7993 easyaggr = TRUE;
7994 SCIPrationalInvert(quotyx, quotyx);
7995 }
7996 else if( typex == SCIP_VARTYPE_CONTINUOUS )
7997 {
7998 /* the aggregation is still easy if both variables are continuous */
7999 assert(typey == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
8000 easyaggr = TRUE;
8001 }
8002 }
8003
8004 /* did we find an "easy" aggregation? */
8005 if( easyaggr )
8006 {
8007 SCIP_RATIONAL* constant;
8008
8009 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &constant) );
8010
8011 assert(typex >= typey);
8012
8013 /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
8014 SCIPrationalNegate(quotyx, quotyx);
8015 SCIPrationalDiv(constant, rhs, scalarx);
8016
8017 if( REALABS(SCIPrationalGetReal(constant)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
8018 goto FREE;
8019
8020 /* check aggregation for integer feasibility */
8021 if( typex != SCIP_VARTYPE_CONTINUOUS && typey != SCIP_VARTYPE_CONTINUOUS
8022 && SCIPrationalIsIntegral(quotyx) && !SCIPrationalIsIntegral(constant) )
8023 {
8024 *infeasible = TRUE;
8025 goto FREE;
8026 }
8027
8028 /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
8029 * since then we would loose the corresponding divisibility property
8030 */
8032
8033 /* aggregate the variable */
8034 SCIP_CALL( SCIPvarAggregateExact(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
8035 branchcand, eventqueue, eventfilter, vary, quotyx, constant, infeasible, aggregated) );
8036 assert(*aggregated || *infeasible || SCIPvarDoNotAggr(varx));
8037FREE:
8038 SCIPrationalFreeBuffer(set->buffer, &constant);
8039 }
8040 else if( (typex == SCIP_VARTYPE_INTEGER || typex == SCIP_DEPRECATED_VARTYPE_IMPLINT)
8041 && (typey == SCIP_VARTYPE_INTEGER || typey == SCIP_DEPRECATED_VARTYPE_IMPLINT) )
8042 {
8043 /* the variables are both integral: we have to try to find an integer aggregation */
8044 SCIP_CALL( tryAggregateIntVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
8045 branchcand, eventqueue, eventfilter, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
8046 }
8047
8048 SCIPrationalFreeBuffer(set->buffer, &quotyx);
8049 SCIPrationalFreeBuffer(set->buffer, &quotxy);
8050
8051 return SCIP_OKAY;
8052}
8053
8054/** converts variable into multi-aggregated variable */
8056 SCIP_VAR* var, /**< problem variable */
8057 BMS_BLKMEM* blkmem, /**< block memory */
8058 SCIP_SET* set, /**< global SCIP settings */
8059 SCIP_STAT* stat, /**< problem statistics */
8060 SCIP_PROB* transprob, /**< tranformed problem data */
8061 SCIP_PROB* origprob, /**< original problem data */
8062 SCIP_PRIMAL* primal, /**< primal data */
8063 SCIP_TREE* tree, /**< branch and bound tree */
8064 SCIP_REOPT* reopt, /**< reoptimization data structure */
8065 SCIP_LP* lp, /**< current LP data */
8066 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8067 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8068 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8069 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
8070 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8071 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8072 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8073 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8074 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8075 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8076 )
8077{
8078 SCIP_VAR** tmpvars;
8079 SCIP_Real* tmpscalars;
8080 SCIP_Real obj;
8081 SCIP_Real branchfactor;
8082 int branchpriority;
8083 SCIP_BRANCHDIR branchdirection;
8084 int nlocksdown[NLOCKTYPES];
8085 int nlocksup[NLOCKTYPES];
8086 int v;
8087 SCIP_Real tmpconstant;
8088 SCIP_Real tmpscalar;
8089 int ntmpvars;
8090 int tmpvarssize;
8091 int tmprequiredsize;
8092 int i;
8093
8094 assert(var != NULL);
8095 assert(var->scip == set->scip);
8096 assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
8097 assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
8098 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
8099 assert(naggvars == 0 || aggvars != NULL);
8100 assert(naggvars == 0 || scalars != NULL);
8101 assert(infeasible != NULL);
8102 assert(aggregated != NULL);
8103
8104 SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
8105
8106 *infeasible = FALSE;
8107 *aggregated = FALSE;
8108
8109 switch( SCIPvarGetStatus(var) )
8110 {
8112 if( var->data.original.transvar == NULL )
8113 {
8114 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
8115 return SCIP_INVALIDDATA;
8116 }
8117 SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
8118 reopt, lp, cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8119 break;
8120
8122 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
8123
8124 /* check if we would create a self-reference */
8125 ntmpvars = naggvars;
8126 tmpvarssize = naggvars;
8127 tmpconstant = constant;
8128 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
8129 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
8130
8131 /* get all active variables for multi-aggregation */
8132 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) );
8133 if( tmprequiredsize > tmpvarssize )
8134 {
8135 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
8136 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
8137 tmpvarssize = tmprequiredsize;
8138 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize) );
8139 assert( tmprequiredsize <= tmpvarssize );
8140 }
8141
8142 tmpscalar = 0.0;
8143
8144 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
8145 * possible multi-aggregated variable
8146 */
8147 for( v = ntmpvars - 1; v >= 0; --v )
8148 {
8149 assert(tmpvars[v] != NULL);
8151
8152 if( tmpvars[v]->index == var->index )
8153 {
8154 tmpscalar += tmpscalars[v];
8155 tmpvars[v] = tmpvars[ntmpvars - 1];
8156 tmpscalars[v] = tmpscalars[ntmpvars - 1];
8157 --ntmpvars;
8158 }
8159 }
8160
8161 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
8162 if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
8163 {
8164 if( ntmpvars == 0 )
8165 {
8166 if( SCIPsetIsFeasZero(set, tmpconstant) ) /* x = x */
8167 {
8168 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
8169 goto TERMINATE;
8170 }
8171 else /* 0 = c and c != 0 */
8172 {
8173 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
8174 *infeasible = TRUE;
8175 goto TERMINATE;
8176 }
8177 }
8178 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
8179 {
8180 assert(tmpscalars[0] != 0.0);
8181 assert(tmpvars[0] != NULL);
8182
8183 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
8184 SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
8185 branchcand, eventqueue, eventfilter, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
8186 goto TERMINATE;
8187 }
8188 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 */
8189 {
8190 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8191 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
8192 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
8193
8194 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
8195 cliquetable, branchcand, eventqueue, eventfilter, tmpvars[0], tmpvars[1], tmpscalars[0],
8196 tmpscalars[1], -tmpconstant, infeasible, aggregated) );
8197
8198 goto TERMINATE;
8199 }
8200 else
8201 /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
8202 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
8203 */
8204 goto TERMINATE;
8205 }
8206 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
8207 else if( tmpscalar != 0.0 ) /*lint !e777*/
8208 {
8209 tmpscalar = 1 - tmpscalar;
8210 tmpconstant /= tmpscalar;
8211 for( v = 0; v < ntmpvars; ++v )
8212 tmpscalars[v] /= tmpscalar;
8213 }
8214
8215 /* check, if we are in one of the simple cases */
8216 if( ntmpvars == 0 )
8217 {
8218 SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
8219 SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
8220 eventqueue, eventfilter, cliquetable, tmpconstant, infeasible, aggregated) );
8221 goto TERMINATE;
8222 }
8223
8224 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
8225 if( ntmpvars == 1 )
8226 {
8227 SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
8228 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
8229
8230 SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
8231 cliquetable, branchcand, eventqueue, eventfilter, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
8232 infeasible, aggregated) );
8233
8234 goto TERMINATE;
8235 }
8236
8237 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
8238 * empty hole list; this should be changed in the future */
8240 goto TERMINATE;
8241
8242 /* if the variable is not allowed to be multi-aggregated */
8244 {
8245 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
8246 goto TERMINATE;
8247 }
8248
8249 /* terminate if scalars may lead to numerical trouble */
8250 for( v = 0; v < ntmpvars; ++v )
8251 if( !SCIPvarIsAggrCoefAcceptable(set, var, tmpscalars[v]) )
8252 goto TERMINATE;
8253
8254 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
8255 * variable bound variable of another variable), we have to remove it from the other variables implications or
8256 * variable bounds
8257 */
8258 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
8259 assert(var->vlbs == NULL);
8260 assert(var->vubs == NULL);
8261 assert(var->implics == NULL);
8262
8263 /* set the aggregated variable's objective value to 0.0 */
8264 obj = var->obj;
8265 SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
8266
8267 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
8268 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
8269 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
8270 * objective of this variable is set to zero
8271 */
8273
8274 /* unlock all rounding locks */
8275 for( i = 0; i < NLOCKTYPES; i++ )
8276 {
8277 nlocksdown[i] = var->nlocksdown[i];
8278 nlocksup[i] = var->nlocksup[i];
8279
8280 var->nlocksdown[i] = 0;
8281 var->nlocksup[i] = 0;
8282 }
8283
8284 /* update aggregation bounds */
8285 for( v = 0; v < ntmpvars; ++v )
8286 varUpdateMinMaxAggrCoef(tmpvars[v], var, tmpscalars[v]);
8287
8288 /* convert variable into multi-aggregated variable */
8289 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8290 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
8291 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
8292 var->data.multaggr.constant = tmpconstant;
8293 var->data.multaggr.nvars = ntmpvars;
8294 var->data.multaggr.varssize = ntmpvars;
8295
8296 /* mark variable to be non-deletable */
8298
8299 /* relock the variable, thus increasing the locks of the aggregation variables */
8300 for( i = 0; i < NLOCKTYPES; i++ )
8301 {
8302 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
8303 }
8304
8305 /* update flags and branching factors and priorities of aggregation variables;
8306 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
8307 */
8308 branchfactor = var->branchfactor;
8309 branchpriority = var->branchpriority;
8310 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
8311
8312 for( v = 0; v < ntmpvars; ++v )
8313 {
8314 assert(tmpvars[v] != NULL);
8315 tmpvars[v]->removable &= var->removable;
8316 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
8317 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
8318
8319 /* mark variable to be non-deletable */
8320 SCIPvarMarkNotDeletable(tmpvars[v]);
8321 }
8322 for( v = 0; v < ntmpvars; ++v )
8323 {
8324 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
8325 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
8326 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
8327 {
8328 if( tmpscalars[v] >= 0.0 )
8329 {
8330 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
8331 }
8332 else
8333 {
8334 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
8335 }
8336 }
8337 }
8338 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
8339 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8340
8341 if( var->probindex != -1 )
8342 {
8343 /* inform problem about the variable's status change */
8344 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
8345 }
8346
8347 /* issue VARFIXED event */
8348 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
8349
8350 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
8351 * variables and the problem's objective offset
8352 */
8353 SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, eventfilter, obj) );
8354
8355 *aggregated = TRUE;
8356
8357 TERMINATE:
8358 BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
8359 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
8360
8361 break;
8362
8364 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
8365 return SCIP_INVALIDDATA;
8366
8368 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
8369 return SCIP_INVALIDDATA;
8370
8372 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
8373 return SCIP_INVALIDDATA;
8374
8376 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
8377 return SCIP_INVALIDDATA;
8378
8380 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
8381 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
8382 */
8383 assert(SCIPsetIsZero(set, var->obj));
8384 assert(var->negatedvar != NULL);
8386 assert(var->negatedvar->negatedvar == var);
8387
8388 /* switch the signs of the aggregation scalars */
8389 for( v = 0; v < naggvars; ++v )
8390 scalars[v] *= -1.0;
8391
8392 /* perform the multi aggregation on the negation variable */
8393 SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
8394 cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars,
8395 var->data.negate.constant - constant, infeasible, aggregated) );
8396
8397 /* switch the signs of the aggregation scalars again, to reset them to their original values */
8398 for( v = 0; v < naggvars; ++v )
8399 scalars[v] *= -1.0;
8400 break;
8401
8402 default:
8403 SCIPerrorMessage("unknown variable status\n");
8404 return SCIP_INVALIDDATA;
8405 }
8406
8407 /* check multi-aggregation on debugging solution */
8408 if( *infeasible || *aggregated )
8409 SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
8410
8411 return SCIP_OKAY;
8412}
8413
8414/** converts variable into multi-aggregated variable */
8416 SCIP_VAR* var, /**< problem variable */
8417 BMS_BLKMEM* blkmem, /**< block memory */
8418 SCIP_SET* set, /**< global SCIP settings */
8419 SCIP_STAT* stat, /**< problem statistics */
8420 SCIP_PROB* transprob, /**< tranformed problem data */
8421 SCIP_PROB* origprob, /**< original problem data */
8422 SCIP_PRIMAL* primal, /**< primal data */
8423 SCIP_TREE* tree, /**< branch and bound tree */
8424 SCIP_REOPT* reopt, /**< reoptimization data structure */
8425 SCIP_LPEXACT* lpexact, /**< current LP data */
8426 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8427 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8428 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8429 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
8430 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8431 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8432 SCIP_RATIONAL** scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8433 SCIP_RATIONAL* constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
8434 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
8435 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
8436 )
8437{
8438 SCIP_VAR** tmpvars;
8439 SCIP_RATIONAL** tmpscalars;
8441 SCIP_RATIONAL* tmpconstant;
8442 SCIP_RATIONAL* tmpscalar;
8443 SCIP_RATIONAL* tmpval;
8444 SCIP_Real branchfactor;
8445 int branchpriority;
8446 SCIP_BRANCHDIR branchdirection;
8447 int nlocksdown[NLOCKTYPES];
8448 int nlocksup[NLOCKTYPES];
8449 int v;
8450 int ntmpvars;
8451 int tmpvarssize;
8452 int tmprequiredsize;
8453 int i;
8454
8455 assert(var != NULL);
8456 assert(var->scip == set->scip);
8457 assert(set->exact_enable);
8458 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb)); /*lint !e777*/
8459 assert(SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub)); /*lint !e777*/
8460 assert(naggvars == 0 || aggvars != NULL);
8461 assert(naggvars == 0 || scalars != NULL);
8462 assert(infeasible != NULL);
8463 assert(aggregated != NULL);
8464
8465 SCIPrationalDebugMessage("trying exact multi-aggregating variable <%s> == ...%d vars... %+q\n", var->name, naggvars, constant);
8466
8467 *infeasible = FALSE;
8468 *aggregated = FALSE;
8469
8470 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpconstant) );
8471 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpscalar) );
8473 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
8474
8475 switch( SCIPvarGetStatusExact(var) )
8476 {
8478 if( var->data.original.transvar == NULL )
8479 {
8480 SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
8481 return SCIP_INVALIDDATA;
8482 }
8483 SCIP_CALL( SCIPvarMultiaggregateExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
8484 reopt, lpexact, cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
8485 break;
8486
8488 assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
8489
8490 /* check if we would create a self-reference */
8491 ntmpvars = naggvars;
8492 tmpvarssize = naggvars;
8493 SCIPrationalSetRational(tmpconstant, constant);
8494 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
8495 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &tmpscalars, scalars, ntmpvars) );
8496
8497 /* get all active variables for multi-aggregation */
8498 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, tmpconstant, &tmprequiredsize, FALSE) );
8499 if( tmprequiredsize > tmpvarssize )
8500 {
8501 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
8502 SCIP_CALL( SCIPrationalReallocBlockArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
8503 tmpvarssize = tmprequiredsize;
8504 SCIP_CALL( SCIPvarGetActiveRepresentativesExact(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, tmpconstant, &tmprequiredsize, FALSE) );
8505 assert( tmprequiredsize <= tmpvarssize );
8506 }
8507
8508 SCIPrationalSetReal(tmpscalar, 0.0);
8509
8510 /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
8511 * possible multi-aggregated variable
8512 */
8513 for( v = ntmpvars - 1; v >= 0; --v )
8514 {
8515 assert(tmpvars[v] != NULL);
8517
8518 if( tmpvars[v]->index == var->index )
8519 {
8520 SCIPrationalAdd(tmpscalar, tmpscalar, tmpscalars[v]);
8521 tmpvars[v] = tmpvars[ntmpvars - 1];
8522 SCIPrationalSetRational(tmpscalars[v], tmpscalars[ntmpvars - 1]);
8523 --ntmpvars;
8524 }
8525 }
8526
8527 /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
8528 if( SCIPrationalIsEQReal(tmpscalar, 1.0) )
8529 {
8530 if( ntmpvars == 0 )
8531 {
8532 if( SCIPrationalIsZero(tmpconstant) ) /* x = x */
8533 {
8534 SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
8535 goto TERMINATE;
8536 }
8537 else /* 0 = c and c != 0 */
8538 {
8539 SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
8540 *infeasible = TRUE;
8541 goto TERMINATE;
8542 }
8543 }
8544 else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
8545 {
8546 assert(!SCIPrationalIsZero(tmpscalars[0]));
8547 assert(tmpvars[0] != NULL);
8548
8549 SCIPrationalDiv(tmpval, constant, tmpscalars[0]);
8550 SCIPrationalNegate(tmpval, tmpval);
8551
8552 SCIPrationalDebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %q.\n", SCIPvarGetName(tmpvars[0]), tmpval);
8553 SCIP_CALL( SCIPvarFixExact(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8554 branchcand, eventqueue, eventfilter, cliquetable, tmpval, infeasible, aggregated) );
8555 goto TERMINATE;
8556 }
8557 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 */
8558 {
8559 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
8560
8561 SCIPrationalNegate(tmpconstant, tmpconstant);
8562 SCIPrationalDebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %q and %q and constant %q.\n",
8563 SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], tmpconstant);
8564
8565 SCIP_CALL( SCIPvarTryAggregateVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8566 cliquetable, branchcand, eventqueue, eventfilter, tmpvars[0], tmpvars[1], tmpscalars[0],
8567 tmpscalars[1], tmpconstant, infeasible, aggregated) );
8568
8569 goto TERMINATE;
8570 }
8571 else
8572 /** @todo: it is possible to multi-aggregate another variable, does it make sense?,
8573 * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
8574 */
8575 goto TERMINATE;
8576 }
8577 /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
8578 else if( !SCIPrationalIsZero(tmpscalar) )
8579 {
8580 SCIPrationalDiffReal(tmpscalar, tmpscalar, 1.0);
8581 SCIPrationalNegate(tmpscalar, tmpscalar);
8582 SCIPrationalDiv(tmpconstant, tmpconstant, tmpscalar);
8583 for( v = ntmpvars - 1; v >= 0; --v )
8584 SCIPrationalDiv(tmpscalars[v], tmpscalars[v], tmpscalar);
8585 }
8586
8587 /* check, if we are in one of the simple cases */
8588 if( ntmpvars == 0 )
8589 {
8590 SCIPrationalDebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %q.\n", SCIPvarGetName(var), tmpconstant);
8591 SCIP_CALL( SCIPvarFixExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp, branchcand,
8592 eventqueue, eventfilter, cliquetable, tmpconstant, infeasible, aggregated) );
8593 goto TERMINATE;
8594 }
8595
8596 /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
8597 if( ntmpvars == 1 )
8598 {
8599 SCIPrationalNegate(tmpscalars[0], tmpscalars[0]);
8600 SCIPrationalSetReal(tmpval, 1.0);
8601 SCIPrationalDebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %f and %q and constant %q.\n",
8602 SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, tmpscalars[0], tmpconstant);
8603
8604 SCIP_CALL( SCIPvarTryAggregateVarsExact(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp,
8605 cliquetable, branchcand, eventqueue, eventfilter, var, tmpvars[0], tmpval, tmpscalars[0], tmpconstant,
8606 infeasible, aggregated) );
8607
8608 goto TERMINATE;
8609 }
8610
8611 /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
8612 * empty hole list; this should be changed in the future */
8614 goto TERMINATE;
8615
8616 /* if the variable is not allowed to be multi-aggregated */
8618 {
8619 SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
8620 goto TERMINATE;
8621 }
8622
8623 /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
8624 * variable bound variable of another variable), we have to remove it from the other variables implications or
8625 * variable bounds
8626 */
8627 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
8628 assert(var->vlbs == NULL);
8629 assert(var->vubs == NULL);
8630 assert(var->implics == NULL);
8631 assert(var->cliquelist == NULL);
8632
8633 /* set the aggregated variable's objective value to 0.0 */
8634 SCIPrationalSetRational(obj, var->exactdata->obj);
8635 SCIPrationalSetReal(tmpval, 0.0);
8636 SCIP_CALL( SCIPvarChgObjExact(var, blkmem, set, transprob, primal, lpexact, eventqueue, tmpval) );
8637
8638 /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
8639 * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
8640 * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
8641 * objective of this variable is set to zero
8642 */
8643 SCIPlpDecNLoosevars(lpexact->fplp);
8644 SCIPlpExactDecNLoosevars(lpexact);
8645
8646 /* unlock all rounding locks */
8647 for( i = 0; i < NLOCKTYPES; i++ )
8648 {
8649 nlocksdown[i] = var->nlocksdown[i];
8650 nlocksup[i] = var->nlocksup[i];
8651
8652 var->nlocksdown[i] = 0;
8653 var->nlocksup[i] = 0;
8654 }
8655
8656 /* convert variable into multi-aggregated variable */
8657 var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8658 var->exactdata->varstatusexact = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
8659 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
8660 SCIP_CALL( SCIPrationalCopyBlockArray(blkmem, &(var->exactdata->multaggr.scalars), tmpscalars, ntmpvars) );
8661 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &var->data.multaggr.scalars, ntmpvars) );
8662 for( i = 0; i < ntmpvars; ++i )
8663 var->data.multaggr.scalars[i] = SCIPrationalGetReal(tmpscalars[i]);
8664 SCIP_CALL( SCIPrationalCopyBlock(blkmem, &(var->exactdata->multaggr.constant), tmpconstant) );
8665 var->data.multaggr.constant = SCIPrationalGetReal(tmpconstant);
8666 var->data.multaggr.nvars = ntmpvars;
8667 var->data.multaggr.varssize = ntmpvars;
8668
8669 /* mark variable to be non-deletable */
8671
8672 /* relock the variable, thus increasing the locks of the aggregation variables */
8673 for( i = 0; i < NLOCKTYPES; i++ )
8674 {
8675 SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
8676 }
8677
8678 /* update flags and branching factors and priorities of aggregation variables;
8679 * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
8680 */
8681 branchfactor = var->branchfactor;
8682 branchpriority = var->branchpriority;
8683 branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
8684
8685 for( v = 0; v < ntmpvars; ++v )
8686 {
8687 assert(tmpvars[v] != NULL);
8688 tmpvars[v]->removable &= var->removable;
8689 branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
8690 branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
8691
8692 /* mark variable to be non-deletable */
8693 SCIPvarMarkNotDeletable(tmpvars[v]);
8694 }
8695 for( v = 0; v < ntmpvars; ++v )
8696 {
8697 SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
8698 SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
8699 if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
8700 {
8701 if( !SCIPrationalIsNegative(tmpscalars[v]) )
8702 {
8703 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
8704 }
8705 else
8706 {
8707 SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
8708 }
8709 }
8710 }
8711 SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
8712 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
8713
8714 if( var->probindex != -1 )
8715 {
8716 /* inform problem about the variable's status change */
8717 SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
8718 }
8719
8720 /* issue VARFIXED event */
8721 SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
8722
8723 /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
8724 * variables and the problem's objective offset
8725 */
8726 SCIP_CALL( SCIPvarAddObjExact(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact->fplp, eventqueue, eventfilter, obj) );
8727
8728 *aggregated = TRUE;
8729
8730 TERMINATE:
8731 SCIPrationalFreeBlockArray(blkmem, &tmpscalars, tmpvarssize);
8732 BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
8733 break;
8734
8736 SCIPerrorMessage("cannot multi-aggregate a column variable\n");
8737 return SCIP_INVALIDDATA;
8738
8740 SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
8741 return SCIP_INVALIDDATA;
8742
8744 SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
8745 return SCIP_INVALIDDATA;
8746
8748 SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
8749 return SCIP_INVALIDDATA;
8750
8752 /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
8753 * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
8754 */
8755 assert(SCIPrationalIsZero(var->exactdata->obj));
8756 assert(var->negatedvar != NULL);
8758 assert(var->negatedvar->negatedvar == var);
8759
8760 /* switch the signs of the aggregation scalars */
8761 for( v = 0; v < naggvars; ++v )
8763
8764 SCIPrationalDiffReal(tmpval, constant, var->data.negate.constant);
8765 SCIPrationalNegate(tmpval, tmpval);
8766 /* perform the multi aggregation on the negation variable */
8767 SCIP_CALL( SCIPvarMultiaggregateExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lpexact,
8768 cliquetable, branchcand, eventqueue, eventfilter, naggvars, aggvars, scalars,
8769 tmpval, infeasible, aggregated) );
8770
8771 /* switch the signs of the aggregation scalars again, to reset them to their original values */
8772 for( v = 0; v < naggvars; ++v )
8774
8775 break;
8776
8777 default:
8778 SCIPerrorMessage("unknown variable status\n");
8779 return SCIP_INVALIDDATA;
8780 }
8781
8782 SCIPrationalFreeBuffer(set->buffer, &tmpval);
8783 SCIPrationalFreeBuffer(set->buffer, &obj);
8784 SCIPrationalFreeBuffer(set->buffer, &tmpscalar);
8785 SCIPrationalFreeBuffer(set->buffer, &tmpconstant);
8786
8787 return SCIP_OKAY;
8788}
8789
8790/** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
8791 * or for original variables the same variable is returned
8792 */
8793static
8795 SCIP_VAR* var /**< problem variable */
8796 )
8797{
8798 SCIP_VAR* retvar;
8799
8800 assert(var != NULL);
8801
8802 retvar = var;
8803
8804 SCIPdebugMessage("get active variable of <%s>\n", var->name);
8805
8806 while( TRUE ) /*lint !e716 */
8807 {
8808 assert(retvar != NULL);
8809
8810 switch( SCIPvarGetStatus(retvar) )
8811 {
8816 return retvar;
8817
8819 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
8820 if ( retvar->data.multaggr.nvars == 1 )
8821 retvar = retvar->data.multaggr.vars[0];
8822 else
8823 return retvar;
8824 break;
8825
8827 retvar = retvar->data.aggregate.var;
8828 break;
8829
8831 retvar = retvar->negatedvar;
8832 break;
8833
8834 default:
8835 SCIPerrorMessage("unknown variable status\n");
8836 SCIPABORT();
8837 return NULL; /*lint !e527*/
8838 }
8839 }
8840}
8841
8842/** returns whether variable is not allowed to be aggregated */
8844 SCIP_VAR* var /**< problem variable */
8845 )
8846{
8847 SCIP_VAR* retvar;
8848
8849 assert(var != NULL);
8850
8851 retvar = varGetActiveVar(var);
8852 assert(retvar != NULL);
8853
8854 switch( SCIPvarGetStatus(retvar) )
8855 {
8860 return retvar->donotaggr;
8861
8863 return FALSE;
8864
8867 default:
8868 /* aggregated and negated variables should be resolved by varGetActiveVar() */
8869 SCIPerrorMessage("wrong variable status\n");
8870 SCIPABORT();
8871 return FALSE; /*lint !e527 */
8872 }
8873}
8874
8875/** returns whether variable is not allowed to be multi-aggregated */
8877 SCIP_VAR* var /**< problem variable */
8878 )
8879{
8880 SCIP_VAR* retvar;
8881
8882 assert(var != NULL);
8883
8884 retvar = varGetActiveVar(var);
8885 assert(retvar != NULL);
8886
8887 switch( SCIPvarGetStatus(retvar) )
8888 {
8893 return retvar->donotmultaggr;
8894
8896 return FALSE;
8897
8900 default:
8901 /* aggregated and negated variables should be resolved by varGetActiveVar() */
8902 SCIPerrorMessage("wrong variable status\n");
8903 SCIPABORT();
8904 return FALSE; /*lint !e527 */
8905 }
8906}
8907
8908/** checks whether a loose variable can be used in a new aggregation with given coefficient */
8910 SCIP_SET* set, /**< global SCIP settings */
8911 SCIP_VAR* var, /**< problem variable */
8912 SCIP_Real scalar /**< aggregation scalar */
8913 )
8914{
8915 assert(set != NULL);
8916 assert(var != NULL);
8917 assert(scalar != 0.0); /*lint !e777*/
8921
8923 return FALSE;
8924
8925 if( SCIPsetIsSumZero(set, 1.0 / (SCIPvarGetMaxAggrCoef(var) * scalar)) )
8926 return FALSE;
8927
8928 return TRUE;
8929}
8930
8931/** adds correct bound-data to negated variable */
8932static
8934 SCIP_VAR* negvar, /**< the negated variable */
8935 SCIP_VAR* origvar, /**< the original variable */
8936 BMS_BLKMEM* blkmem /**< block memory of transformed problem */
8937 )
8938{
8939 SCIP_Real constant;
8940
8941 if( origvar->exactdata == NULL )
8942 return SCIP_OKAY;
8943
8944 assert(negvar != NULL);
8945 assert(origvar != NULL);
8946 assert(origvar->exactdata != NULL);
8947 assert(negvar->exactdata == NULL);
8948
8949 constant = negvar->data.negate.constant;
8950
8951 SCIP_CALL( SCIPvarCopyExactData(blkmem, negvar, origvar, FALSE) );
8952
8953 SCIPrationalDiffReal(negvar->exactdata->glbdom.ub, origvar->exactdata->glbdom.lb, constant);
8955
8956 SCIPrationalDiffReal(negvar->exactdata->glbdom.lb, origvar->exactdata->glbdom.ub, constant);
8958
8959 SCIPrationalDiffReal(negvar->exactdata->locdom.ub, origvar->exactdata->locdom.lb, constant);
8961
8962 SCIPrationalDiffReal(negvar->exactdata->locdom.lb, origvar->exactdata->locdom.ub, constant);
8964
8966
8971
8972 return SCIP_OKAY;
8973}
8974
8975/** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
8976 * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
8977 * negated variable is created
8978 */
8980 SCIP_VAR* var, /**< problem variable to negate */
8981 BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
8982 SCIP_SET* set, /**< global SCIP settings */
8983 SCIP_STAT* stat, /**< problem statistics */
8984 SCIP_VAR** negvar /**< pointer to store the negated variable */
8985 )
8986{
8987 assert(var != NULL);
8988 assert(var->scip == set->scip);
8989 assert(negvar != NULL);
8990
8991 /* check, if we already created the negated variable */
8992 if( var->negatedvar == NULL )
8993 {
8994 char negvarname[SCIP_MAXSTRLEN];
8995
8997
8998 SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
8999
9000 /* negation is only possible for bounded variables */
9001 if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
9002 {
9003 SCIPerrorMessage("cannot negate unbounded variable\n");
9004 return SCIP_INVALIDDATA;
9005 }
9006
9007 (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
9008
9009 /* create negated variable */
9010 SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
9011 SCIPvarGetType(var), SCIPvarGetImplType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
9012 (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
9013 if( SCIPvarIsBinary(var) )
9014 (*negvar)->data.negate.constant = 1.0;
9015 else
9016 (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
9017
9018 /* create event filter for transformed variable */
9020 {
9021 SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
9022 }
9023
9024 /* set the bounds corresponding to the negation variable */
9025 (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
9026 (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
9027 (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
9028 (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
9029
9030 SCIP_CALL( varNegateExactData(*negvar, var, blkmem) );
9031 /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
9032
9033 /* link the variables together */
9034 var->negatedvar = *negvar;
9035 (*negvar)->negatedvar = var;
9036
9037 /* mark both variables to be non-deletable */
9039 SCIPvarMarkNotDeletable(*negvar);
9040
9041 /* copy the branch factor and priority, and use the negative preferred branching direction */
9042 (*negvar)->branchfactor = var->branchfactor;
9043 (*negvar)->branchpriority = var->branchpriority;
9044 (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
9045
9046 /* copy donot(mult)aggr status */
9047 (*negvar)->donotaggr = var->donotaggr;
9048 (*negvar)->donotmultaggr = var->donotmultaggr;
9049
9050 /* copy lazy bounds (they have to be flipped) */
9051 (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
9052 (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
9053
9054 /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
9055 SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
9056 assert((*negvar)->nuses == 1);
9057 }
9058 assert(var->negatedvar != NULL);
9059
9060 /* return the negated variable */
9061 *negvar = var->negatedvar;
9062
9063 /* exactly one variable of the negation pair has to be marked as negated variable */
9065
9066 return SCIP_OKAY;
9067}
9068
9069/** informs variable that its position in problem's vars array changed */
9070static
9072 SCIP_VAR* var, /**< problem variable */
9073 int probindex /**< new problem index of variable (-1 for removal) */
9074 )
9075{
9076 assert(var != NULL);
9077
9078 var->probindex = probindex;
9080 {
9081 assert(var->data.col != NULL);
9082 var->data.col->var_probindex = probindex;
9083 }
9084}
9085
9086/** informs variable that its position in problem's vars array changed */
9088 SCIP_VAR* var, /**< problem variable */
9089 int probindex /**< new problem index of variable */
9090 )
9091{
9092 assert(var != NULL);
9093 assert(probindex >= 0);
9094
9095 varSetProbindex(var, probindex);
9096}
9097
9098/** gives the variable a new name
9099 *
9100 * @note the old pointer is overwritten, which might result in a memory leakage
9101 */
9103 SCIP_VAR* var, /**< problem variable */
9104 const char* name /**< new name of variable */
9105 )
9106{
9107 assert(var != NULL);
9108 assert(name != NULL);
9109
9110 var->name = (char*)name;
9111}
9112
9113/** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
9114 * implication graph;
9115 * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
9116 * variable bounds and implication data structures of the variable are freed. Since in the final removal
9117 * of all variables from the transformed problem, this deletes the implication graph completely and is faster
9118 * than removing the variables one by one, each time updating all lists of the other variables.
9119 * If 'keepimplics' is TRUE, the implications, variable bounds and cliques are kept. This should be used when the
9120 * variable type is upgraded, i.e. when it gains (implied) integrality, so that existing implications are not lost.
9121 */
9123 SCIP_VAR* var, /**< problem variable */
9124 BMS_BLKMEM* blkmem, /**< block memory buffer */
9125 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9126 SCIP_SET* set, /**< global SCIP settings */
9127 SCIP_Bool final, /**< is this the final removal of all problem variables? */
9128 SCIP_Bool keepimplics /**< should the implications be kept? */
9129 )
9130{
9132 assert(var->scip == set->scip);
9133
9134 /* if the variable is active in the transformed problem, remove it from the implication graph */
9137 {
9138 if( final )
9139 {
9140 /* just destroy the data structures */
9141 SCIPvboundsFree(&var->vlbs, blkmem);
9142 SCIPvboundsFree(&var->vubs, blkmem);
9143 SCIPimplicsFree(&var->implics, blkmem);
9144 }
9145 else if( !keepimplics )
9146 {
9147 /* unlink the variable from all other variables' lists and free the data structures */
9148 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
9149 }
9150 }
9151
9152 /* mark the variable to be no longer a member of the problem */
9153 varSetProbindex(var, -1);
9154
9155 return SCIP_OKAY;
9156}
9157
9158/** marks the variable to be deleted from the problem */
9160 SCIP_VAR* var /**< problem variable */
9161 )
9162{
9163 assert(var != NULL);
9164 assert(var->probindex != -1);
9165
9166 var->deleted = TRUE;
9167}
9168
9169/** marks the variable to not to be aggregated */
9171 SCIP_VAR* var /**< problem variable */
9172 )
9173{
9174 SCIP_VAR* retvar;
9175
9176 assert(var != NULL);
9177
9178 retvar = varGetActiveVar(var);
9179 assert(retvar != NULL);
9180
9181 switch( SCIPvarGetStatus(retvar) )
9182 {
9187 retvar->donotaggr = TRUE;
9188 break;
9189
9191 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be aggregated.\n");
9192 return SCIP_INVALIDDATA;
9193
9196 default:
9197 /* aggregated and negated variables should be resolved by varGetActiveVar() */
9198 SCIPerrorMessage("wrong variable status\n");
9199 return SCIP_INVALIDDATA;
9200 }
9201
9202 return SCIP_OKAY;
9203}
9204
9205/** marks the variable to not to be multi-aggregated */
9207 SCIP_VAR* var /**< problem variable */
9208 )
9209{
9210 SCIP_VAR* retvar;
9211
9212 assert(var != NULL);
9213
9214 retvar = varGetActiveVar(var);
9215 assert(retvar != NULL);
9216
9217 switch( SCIPvarGetStatus(retvar) )
9218 {
9223 retvar->donotmultaggr = TRUE;
9224 break;
9225
9227 SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
9228 return SCIP_INVALIDDATA;
9229
9232 default:
9233 /* aggregated and negated variables should be resolved by varGetActiveVar() */
9234 SCIPerrorMessage("wrong variable status\n");
9235 return SCIP_INVALIDDATA;
9236 }
9237
9238 return SCIP_OKAY;
9239}
9240
9241/** changes type of variable; cannot be called, if var belongs to a problem */
9243 SCIP_VAR* var, /**< variable to change */
9244 BMS_BLKMEM* blkmem, /**< block memory */
9245 SCIP_SET* set, /**< global SCIP settings */
9246 SCIP_PRIMAL* primal, /**< primal data */
9247 SCIP_LP* lp, /**< current LP data */
9248 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9249 SCIP_VARTYPE vartype /**< new type of variable */
9250 )
9251{
9252 SCIP_EVENT* event;
9253 SCIP_VARTYPE oldtype;
9254
9255 assert(var != NULL);
9256
9257 SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
9258
9259 if( var->probindex >= 0 )
9260 {
9261 SCIPerrorMessage("cannot change type of variable already in the problem\n");
9262 return SCIP_INVALIDDATA;
9263 }
9264
9265 if( vartype == SCIP_DEPRECATED_VARTYPE_IMPLINT )
9266 {
9268 {
9269 SCIP_CALL( SCIPvarChgImplType(var, blkmem, set, primal, lp, eventqueue, SCIP_IMPLINTTYPE_WEAK) );
9270 }
9271 return SCIP_OKAY;
9272 }
9273
9274 oldtype = (SCIP_VARTYPE)var->vartype;
9275 var->vartype = vartype; /*lint !e641*/
9276
9278 {
9279 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
9280 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9281 }
9282
9283 if( var->negatedvar != NULL )
9284 {
9285 assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
9286 || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
9287
9288 var->negatedvar->vartype = vartype; /*lint !e641*/
9289
9291 {
9292 SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
9293 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9294 }
9295 }
9296
9297 return SCIP_OKAY;
9298}
9299
9300/** changes implied integral type of variable; cannot be called, if var belongs to a problem */
9302 SCIP_VAR* var, /**< variable to change */
9303 BMS_BLKMEM* blkmem, /**< block memory */
9304 SCIP_SET* set, /**< global SCIP settings */
9305 SCIP_PRIMAL* primal, /**< primal data */
9306 SCIP_LP* lp, /**< current LP data */
9307 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9308 SCIP_IMPLINTTYPE impltype /**< new implied integral type of variable */
9309 )
9310{
9311 SCIP_EVENT* event;
9312 SCIP_IMPLINTTYPE oldtype;
9313
9314 assert(var != NULL);
9315
9316 SCIPdebugMessage("change implied integral type of <%s> from %d to %d\n", var->name, SCIPvarGetImplType(var), impltype);
9317
9318 if( var->probindex >= 0 )
9319 {
9320 SCIPerrorMessage("cannot change type of variable already in the problem\n");
9321 return SCIP_INVALIDDATA;
9322 }
9323
9324 oldtype = (SCIP_IMPLINTTYPE) var->varimpltype;
9325 var->varimpltype = impltype; /*lint !e641*/
9326
9328 {
9329 SCIP_CALL( SCIPeventCreateImplTypeChanged(&event, blkmem, var, oldtype, impltype) );
9330 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9331 }
9332
9333 if( var->negatedvar != NULL )
9334 {
9335 var->negatedvar->varimpltype = impltype; /*lint !e641*/
9336
9338 {
9339 SCIP_CALL( SCIPeventCreateImplTypeChanged(&event, blkmem, var->negatedvar, oldtype, impltype) );
9340 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9341 }
9342 }
9343
9344 return SCIP_OKAY;
9345}
9346
9347/** appends OBJCHANGED event to the event queue */
9348static
9350 SCIP_VAR* var, /**< problem variable to change */
9351 BMS_BLKMEM* blkmem, /**< block memory */
9352 SCIP_SET* set, /**< global SCIP settings */
9353 SCIP_PRIMAL* primal, /**< primal data */
9354 SCIP_LP* lp, /**< current LP data */
9355 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9356 SCIP_Real oldobj, /**< old objective value for variable */
9357 SCIP_Real newobj /**< new objective value for variable */
9358 )
9359{
9360 SCIP_EVENT* event;
9361
9362 assert(var != NULL);
9363 assert(var->scip == set->scip);
9364 assert(var->eventfilter != NULL);
9367
9368 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
9369 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
9370 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
9371 * that make comparison with values close to epsilon inaccurate.
9372 */
9375 (set->exact_enable && oldobj != newobj)); /*lint !e777*/
9376
9377 SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
9378 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9379
9380 return SCIP_OKAY;
9381}
9382
9383/** appends OBJCHANGED event to the event queue */
9384static
9386 SCIP_VAR* var, /**< problem variable to change */
9387 BMS_BLKMEM* blkmem, /**< block memory */
9388 SCIP_SET* set, /**< global SCIP settings */
9389 SCIP_PRIMAL* primal, /**< primal data */
9390 SCIP_LP* lp, /**< current LP data */
9391 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9392 SCIP_RATIONAL* oldobj, /**< old objective value for variable */
9393 SCIP_RATIONAL* newobj /**< new objective value for variable */
9394 )
9395{
9396 SCIP_EVENT* event;
9397
9398 assert(var != NULL);
9399 assert(var->scip == set->scip);
9400 assert(var->eventfilter != NULL);
9403
9404 /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
9405 * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
9406 * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
9407 * that make comparison with values close to epsilon inaccurate.
9408 */
9410
9412 SCIP_CALL( SCIPeventAddExactObjChg(event, blkmem, oldobj, newobj) );
9413 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
9414
9415 return SCIP_OKAY;
9416}
9417
9418/** changes objective value of variable */
9420 SCIP_VAR* var, /**< variable to change */
9421 BMS_BLKMEM* blkmem, /**< block memory */
9422 SCIP_SET* set, /**< global SCIP settings */
9423 SCIP_PROB* prob, /**< problem data */
9424 SCIP_PRIMAL* primal, /**< primal data */
9425 SCIP_LP* lp, /**< current LP data */
9426 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9427 SCIP_Real newobj /**< new objective value for variable */
9428 )
9429{
9431
9432 assert(var != NULL);
9433 assert(set != NULL);
9434 assert(var->scip == set->scip);
9435
9436 SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
9437
9438 if( !SCIPsetIsEQ(set, var->obj, newobj) )
9439 {
9440 switch( SCIPvarGetStatus(var) )
9441 {
9443 if( var->data.original.transvar != NULL )
9444 {
9446
9447 SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
9448 (SCIP_Real) prob->objsense * newobj/prob->objscale) );
9449 }
9450 else
9451 assert(set->stage == SCIP_STAGE_PROBLEM);
9452
9453 var->obj = newobj;
9454 var->unchangedobj = newobj;
9455
9456 break;
9457
9460 oldobj = var->obj;
9461 var->obj = newobj;
9462
9463 /* update unchanged objective value of variable */
9464 if( !lp->divingobjchg )
9465 var->unchangedobj = newobj;
9466
9467 /* update the number of variables with non-zero objective coefficient;
9468 * we only want to do the update, if the variable is added to the problem;
9469 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9470 */
9471 if( SCIPvarIsActive(var) )
9472 SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
9473
9474 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
9475 break;
9476
9481 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
9482 return SCIP_INVALIDDATA;
9483
9484 default:
9485 SCIPerrorMessage("unknown variable status\n");
9486 return SCIP_INVALIDDATA;
9487 }
9488 }
9489
9490 return SCIP_OKAY;
9491}
9492
9493/** changes rational objective value of variable */
9495 SCIP_VAR* var, /**< variable to change */
9496 BMS_BLKMEM* blkmem, /**< block memory */
9497 SCIP_SET* set, /**< global SCIP settings */
9498 SCIP_PROB* prob, /**< problem data */
9499 SCIP_PRIMAL* primal, /**< primal data */
9500 SCIP_LPEXACT* lp, /**< current LP data */
9501 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9502 SCIP_RATIONAL* newobj /**< new objective value for variable */
9503 )
9504{
9505 SCIP_Real newobjreal;
9507 SCIP_RATIONAL* tmp;
9508
9509 assert(var != NULL);
9510 assert(set != NULL);
9511
9512 if( !set->exact_enable )
9513 return SCIP_OKAY;
9514
9515 assert(var->exactdata != NULL);
9516 assert(var->scip == set->scip);
9517
9518 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
9520 newobjreal = SCIPrationalGetReal(newobj);
9521
9522 SCIPrationalDebugMessage("changing exact objective value of <%s> from %q to %q\n", var->name, var->exactdata->obj, newobj);
9523
9524 if( !SCIPrationalIsEQ(var->exactdata->obj, newobj) )
9525 {
9526 switch( SCIPvarGetStatusExact(var) )
9527 {
9529 if( var->data.original.transvar != NULL )
9530 {
9532
9534
9535 SCIP_CALL( SCIPvarChgObjExact(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
9536 tmp) );
9537 }
9538 else
9539 assert(set->stage == SCIP_STAGE_PROBLEM);
9540
9541 SCIPrationalSetRational(var->exactdata->obj, newobj);
9542 SCIPintervalSetRational(&(var->exactdata->objinterval), newobj);
9543 var->obj = newobjreal;
9544 var->unchangedobj = newobjreal;
9545 break;
9546
9549 SCIPrationalSetRational(oldobj, var->exactdata->obj);
9550 SCIPrationalSetRational(var->exactdata->obj, newobj);
9551 SCIPintervalSetRational(&(var->exactdata->objinterval), newobj);
9552 var->obj = newobjreal;
9553
9554 /* update unchanged objective value of variable */
9555 if( !lp->fplp->divingobjchg )
9556 var->unchangedobj = newobjreal;
9557
9558 /* update the number of variables with non-zero objective coefficient;
9559 * we only want to do the update, if the variable is added to the problem;
9560 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9561 */
9562 if( SCIPvarIsActive(var) )
9564
9565 SCIP_CALL( varEventObjChangedExact(var, blkmem, set, primal, lp->fplp, eventqueue, oldobj, var->exactdata->obj) );
9566
9567 break;
9568
9573 SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
9574 return SCIP_INVALIDDATA;
9575
9576 default:
9577 SCIPerrorMessage("unknown variable status\n");
9578 return SCIP_INVALIDDATA;
9579 }
9580 }
9581
9583 SCIPrationalFreeBuffer(set->buffer, &tmp);
9584
9585 return SCIP_OKAY;
9586}
9587
9588/** adds value to objective value of variable */
9590 SCIP_VAR* var, /**< variable to change */
9591 BMS_BLKMEM* blkmem, /**< block memory */
9592 SCIP_SET* set, /**< global SCIP settings */
9593 SCIP_STAT* stat, /**< problem statistics */
9594 SCIP_PROB* transprob, /**< transformed problem data */
9595 SCIP_PROB* origprob, /**< original problem data */
9596 SCIP_PRIMAL* primal, /**< primal data */
9597 SCIP_TREE* tree, /**< branch and bound tree */
9598 SCIP_REOPT* reopt, /**< reoptimization data structure */
9599 SCIP_LP* lp, /**< current LP data */
9600 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9601 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9602 SCIP_Real addobj /**< additional objective value for variable */
9603 )
9604{
9605 assert(var != NULL);
9606 assert(set != NULL);
9607 assert(var->scip == set->scip);
9609
9610 SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
9611
9612 if( !SCIPsetIsZero(set, addobj) )
9613 {
9615 int i;
9616
9617 switch( SCIPvarGetStatus(var) )
9618 {
9620 if( var->data.original.transvar != NULL )
9621 {
9622 SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
9623 reopt, lp, eventqueue, eventfilter, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
9624 }
9625 else
9626 assert(set->stage == SCIP_STAGE_PROBLEM);
9627
9628 var->obj += addobj;
9629 var->unchangedobj += addobj;
9630 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
9631
9632 break;
9633
9636 oldobj = var->obj;
9637 var->obj += addobj;
9638
9639 /* update unchanged objective value of variable */
9640 if( !lp->divingobjchg )
9641 {
9642 var->unchangedobj += addobj;
9643 assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
9644 }
9645
9646 /* update the number of variables with non-zero objective coefficient;
9647 * we only want to do the update, if the variable is added to the problem;
9648 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9649 */
9650 if( SCIPvarIsActive(var) )
9651 SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
9652
9653 SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
9654 break;
9655
9657 assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
9658 SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
9659 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9660 break;
9661
9663 assert(!var->donotaggr);
9664 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
9665 SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
9666 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9667 SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
9668 lp, eventqueue, eventfilter, var->data.aggregate.scalar * addobj) );
9669 break;
9670
9672 assert(!var->donotmultaggr);
9673 /* 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 */
9674 SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
9675 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9676 for( i = 0; i < var->data.multaggr.nvars; ++i )
9677 {
9678 SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
9679 reopt, lp, eventqueue, eventfilter, var->data.multaggr.scalars[i] * addobj) );
9680 }
9681 break;
9682
9684 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
9685 assert(var->negatedvar != NULL);
9687 assert(var->negatedvar->negatedvar == var);
9688 SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
9689 SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9690 SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
9691 eventqueue, eventfilter, -addobj) );
9692 break;
9693
9694 default:
9695 SCIPerrorMessage("unknown variable status\n");
9696 return SCIP_INVALIDDATA;
9697 }
9698 }
9699
9700 return SCIP_OKAY;
9701}
9702
9703/** adds exact value to objective value of variable */
9705 SCIP_VAR* var, /**< variable to change */
9706 BMS_BLKMEM* blkmem, /**< block memory */
9707 SCIP_SET* set, /**< global SCIP settings */
9708 SCIP_STAT* stat, /**< problem statistics */
9709 SCIP_PROB* transprob, /**< transformed problem data */
9710 SCIP_PROB* origprob, /**< original problem data */
9711 SCIP_PRIMAL* primal, /**< primal data */
9712 SCIP_TREE* tree, /**< branch and bound tree */
9713 SCIP_REOPT* reopt, /**< reoptimization data structure */
9714 SCIP_LP* lp, /**< current LP data */
9715 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9716 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9717 SCIP_RATIONAL* addobj /**< additional objective value for variable */
9718 )
9719{
9720 SCIP_RATIONAL* tmpobj;
9722 SCIP_RATIONAL* multaggrobj;
9723 SCIP_Real oldobjreal;
9724
9725 assert(var != NULL);
9726 assert(set != NULL);
9727 assert(var->scip == set->scip);
9729
9730 SCIPrationalDebugMessage("adding %q to objective value %q of <%s>\n", addobj, var->exactdata->obj, var->name);
9731
9733 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpobj) );
9734
9735 if( !SCIPrationalIsZero(addobj) )
9736 {
9737 int i;
9738
9739 switch( SCIPvarGetStatusExact(var) )
9740 {
9742 if( var->data.original.transvar != NULL )
9743 {
9744 SCIPrationalMultReal(tmpobj, addobj, (SCIP_Real)transprob->objsense/transprob->objscale);
9745 SCIP_CALL( SCIPvarAddObjExact(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
9746 reopt, lp, eventqueue, eventfilter, tmpobj) );
9747 }
9748 else
9749 assert(set->stage == SCIP_STAGE_PROBLEM);
9750
9751 SCIPrationalAdd(var->exactdata->obj, var->exactdata->obj, addobj);
9752 SCIPintervalSetRational(&(var->exactdata->objinterval), var->exactdata->obj);
9753 var->obj = SCIPrationalGetReal(var->exactdata->obj);
9754 var->unchangedobj = var->obj;
9755
9756 break;
9757
9760 SCIPrationalSetRational(oldobj, var->exactdata->obj);
9761 oldobjreal = var->obj;
9762 SCIPrationalAdd(var->exactdata->obj, var->exactdata->obj, addobj);
9763 SCIPintervalSetRational(&(var->exactdata->objinterval), var->exactdata->obj);
9764 var->obj = SCIPrationalGetReal(var->exactdata->obj);
9765
9766 /* update unchanged objective value of variable */
9767 if( !lp->divingobjchg )
9768 {
9769 var->unchangedobj = var->obj;
9770 }
9771
9772 /* update the number of variables with non-zero objective coefficient;
9773 * we only want to do the update, if the variable is added to the problem;
9774 * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
9775 */
9776 if( SCIPvarIsActive(var) )
9777 SCIPprobUpdateNObjVars(transprob, set, oldobjreal, var->obj);
9778
9779 SCIP_CALL( varEventObjChangedExact(var, blkmem, set, primal, lp, eventqueue, oldobj, var->exactdata->obj) );
9780 break;
9781
9783 assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
9784 SCIPrationalMult(tmpobj, var->exactdata->locdom.lb, addobj);
9785 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9786 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9787 break;
9788
9790 /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
9791 SCIPrationalMult(tmpobj, var->exactdata->aggregate.constant, addobj);
9792 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9793 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9794
9795 SCIPrationalMult(tmpobj, var->exactdata->aggregate.scalar, addobj);
9796
9797 SCIP_CALL( SCIPvarAddObjExact(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
9798 lp, eventqueue, eventfilter, tmpobj) );
9799 break;
9800
9802 assert(!var->donotmultaggr);
9803 /* 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 */
9804 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &multaggrobj) );
9805
9806 SCIPrationalMult(tmpobj, var->exactdata->multaggr.constant, addobj);
9807 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9808 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9809
9810 for( i = 0; i < var->data.multaggr.nvars; ++i )
9811 {
9812 SCIPrationalMult(multaggrobj, addobj, var->exactdata->multaggr.scalars[i]);
9813 SCIP_CALL( SCIPvarAddObjExact(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
9814 reopt, lp, eventqueue, eventfilter, multaggrobj) );
9815 }
9816 SCIPrationalFreeBuffer(set->buffer, &multaggrobj);
9817 break;
9818
9820 /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
9821 assert(var->negatedvar != NULL);
9823 assert(var->negatedvar->negatedvar == var);
9824
9825 SCIPrationalMultReal(tmpobj, addobj, var->data.negate.constant);
9826 SCIPprobAddObjoffsetExact(transprob, tmpobj);
9827 SCIP_CALL( SCIPprimalUpdateObjoffsetExact(primal, blkmem, set, stat, eventqueue, eventfilter, transprob, origprob, tree, reopt, lp) );
9828
9829 SCIPrationalNegate(tmpobj, addobj);
9830 SCIP_CALL( SCIPvarAddObjExact(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
9831 eventqueue, eventfilter, tmpobj) );
9832 break;
9833
9834 default:
9835 SCIPerrorMessage("unknown variable status\n");
9836 return SCIP_INVALIDDATA;
9837 }
9838 }
9839
9840 SCIPrationalFreeBuffer(set->buffer, &tmpobj);
9842
9843 return SCIP_OKAY;
9844}
9845
9846/** changes objective value of variable in current dive */
9848 SCIP_VAR* var, /**< problem variable to change */
9849 SCIP_SET* set, /**< global SCIP settings */
9850 SCIP_LP* lp, /**< current LP data */
9851 SCIP_Real newobj /**< new objective value for variable */
9852 )
9853{
9854 assert(var != NULL);
9855 assert(set != NULL);
9856 assert(var->scip == set->scip);
9857 assert(lp != NULL);
9858
9859 SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
9860
9861 if( SCIPsetIsZero(set, newobj) )
9862 newobj = 0.0;
9863
9864 /* change objective value of attached variables */
9865 switch( SCIPvarGetStatus(var) )
9866 {
9868 assert(var->data.original.transvar != NULL);
9869 SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
9870 break;
9871
9873 assert(var->data.col != NULL);
9874 SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
9875 break;
9876
9879 /* nothing to do here: only the constant shift in objective function would change */
9880 break;
9881
9882 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
9883 assert(var->data.aggregate.var != NULL);
9884 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
9885 SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
9886 /* the constant can be ignored, because it would only affect the objective shift */
9887 break;
9888
9890 SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
9891 return SCIP_INVALIDDATA;
9892
9893 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9894 assert(var->negatedvar != NULL);
9896 assert(var->negatedvar->negatedvar == var);
9897 SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
9898 /* the offset can be ignored, because it would only affect the objective shift */
9899 break;
9900
9901 default:
9902 SCIPerrorMessage("unknown variable status\n");
9903 return SCIP_INVALIDDATA;
9904 }
9905
9906 return SCIP_OKAY;
9907}
9908
9909/** adjust lower bound to integral value, if variable is integral */
9911 SCIP_VAR* var, /**< problem variable */
9912 SCIP_SET* set, /**< global SCIP settings */
9913 SCIP_Real* lb /**< pointer to lower bound to adjust */
9914 )
9915{
9916 assert(var != NULL);
9917 assert(set != NULL);
9918 assert(var->scip == set->scip);
9919 assert(lb != NULL);
9920
9921 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
9922
9923 *lb = adjustedLb(set, SCIPvarIsIntegral(var), *lb);
9924}
9925
9926/** adjust lower bound to integral value, if variable is integral */
9928 SCIP_VAR* var, /**< problem variable */
9929 SCIP_SET* set, /**< global SCIP settings */
9930 SCIP_RATIONAL* lb /**< pointer to lower bound to adjust */
9931 )
9932{
9933 assert(var != NULL);
9934 assert(set != NULL);
9935 assert(var->scip == set->scip);
9936 assert(lb != NULL);
9937
9938 SCIPrationalDebugMessage("adjust lower bound %q of <%s>\n", lb, var->name);
9939
9941}
9942
9943/** adjust lower bound to integral value, if variable is integral */
9945 SCIP_VAR* var, /**< problem variable */
9946 SCIP_SET* set, /**< global SCIP settings */
9947 SCIP_Real* lb /**< pointer to lower bound to adjust */
9948 )
9949{
9950 assert(var != NULL);
9951 assert(set != NULL);
9952 assert(var->scip == set->scip);
9953 assert(lb != NULL);
9954
9955 SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
9956
9958}
9959
9960/** adjust upper bound to integral value, if variable is integral */
9962 SCIP_VAR* var, /**< problem variable */
9963 SCIP_SET* set, /**< global SCIP settings */
9964 SCIP_Real* ub /**< pointer to upper bound to adjust */
9965 )
9966{
9967 assert(var != NULL);
9968 assert(set != NULL);
9969 assert(var->scip == set->scip);
9970 assert(ub != NULL);
9971
9972 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
9973
9974 *ub = adjustedUb(set, SCIPvarIsIntegral(var), *ub);
9975}
9976
9977/** adjust lower bound to integral value, if variable is integral */
9979 SCIP_VAR* var, /**< problem variable */
9980 SCIP_SET* set, /**< global SCIP settings */
9981 SCIP_RATIONAL* ub /**< pointer to lower bound to adjust */
9982 )
9983{
9984 assert(var != NULL);
9985 assert(set != NULL);
9986 assert(var->scip == set->scip);
9987 assert(ub != NULL);
9988
9989 SCIPrationalDebugMessage("adjust upper bound %q of <%s>\n", ub, var->name);
9990
9992}
9993
9994/** adjust lower bound to integral value, if variable is integral */
9996 SCIP_VAR* var, /**< problem variable */
9997 SCIP_SET* set, /**< global SCIP settings */
9998 SCIP_Real* ub /**< pointer to lower bound to adjust */
9999 )
10000{
10001 assert(var != NULL);
10002 assert(set != NULL);
10003 assert(var->scip == set->scip);
10004 assert(ub != NULL);
10005
10006 SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
10007
10009}
10010
10011/** adjust lower or upper bound to integral value, if variable is integral */
10013 SCIP_VAR* var, /**< problem variable */
10014 SCIP_SET* set, /**< global SCIP settings */
10015 SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
10016 SCIP_Real* bd /**< pointer to bound to adjust */
10017 )
10018{
10019 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
10020
10021 if( boundtype == SCIP_BOUNDTYPE_LOWER )
10022 SCIPvarAdjustLb(var, set, bd);
10023 else
10024 SCIPvarAdjustUb(var, set, bd);
10025}
10026
10027/** changes lower bound of original variable in original problem */
10029 SCIP_VAR* var, /**< problem variable to change */
10030 SCIP_SET* set, /**< global SCIP settings */
10031 SCIP_Real newbound /**< new bound for variable */
10032 )
10033{
10034 int i;
10035
10036 assert(var != NULL);
10039 assert(set != NULL);
10040 assert(var->scip == set->scip);
10041 assert(set->stage == SCIP_STAGE_PROBLEM);
10042
10043 /* check that the bound is feasible */
10045 /* adjust bound to integral value if variable is of integral type */
10046 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
10047
10048 if( SCIPsetIsZero(set, newbound) )
10049 newbound = 0.0;
10050
10051 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10053 {
10054 SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
10055 var->name, var->data.original.origdom.lb, newbound);
10056
10057 if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
10058 return SCIP_OKAY;
10059
10060 /* change the bound */
10061 var->data.original.origdom.lb = newbound;
10062 }
10064 {
10065 assert( var->negatedvar != NULL );
10066 SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
10067 }
10068
10069 /* process parent variables */
10070 for( i = 0; i < var->nparentvars; ++i )
10071 {
10072 SCIP_VAR* parentvar;
10073
10074 parentvar = var->parentvars[i];
10075 assert(parentvar != NULL);
10077 assert(parentvar->negatedvar == var);
10078 assert(var->negatedvar == parentvar);
10079
10080 SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
10081 }
10082
10083 return SCIP_OKAY;
10084}
10085
10086/** changes exact lower bound of original variable in original problem */
10088 SCIP_VAR* var, /**< problem variable to change */
10089 SCIP_SET* set, /**< global SCIP settings */
10090 SCIP_RATIONAL* newbound /**< new bound for variable */
10091 )
10092{
10093 SCIP_RATIONAL* tmpval;
10094 int i;
10095
10096 assert(var != NULL);
10099 assert(set != NULL);
10100 assert(var->scip == set->scip);
10101 assert(set->stage == SCIP_STAGE_PROBLEM);
10102
10103 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
10104 SCIPrationalSetRational(tmpval, newbound);
10105
10106 /* check that the bound is feasible */
10108
10109 /* adjust bound to integral value if variable is of integral type */
10111
10112 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10114 {
10115 SCIPrationalDebugMessage("changing original lower bound of <%s> from %q to %q\n",
10116 var->name, var->exactdata->origdom.lb, newbound);
10117
10118 if( SCIPrationalIsEQ(var->exactdata->origdom.lb, newbound) )
10119 {
10120 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10121 return SCIP_OKAY;
10122 }
10123
10124 /* change the bound */
10125 SCIPrationalSetRational(var->exactdata->origdom.lb, newbound);
10126 var->data.original.origdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
10127 }
10129 {
10130 assert( var->negatedvar != NULL );
10131
10132 SCIPrationalSetReal(tmpval, var->data.negate.constant);
10133 SCIPrationalDiff(tmpval, tmpval, newbound);
10134
10135 SCIP_CALL( SCIPvarChgUbOriginalExact(var->negatedvar, set, tmpval) );
10136 }
10137
10138 /* process parent variables */
10139 for( i = 0; i < var->nparentvars; ++i )
10140 {
10141 SCIP_VAR* parentvar;
10142
10143 parentvar = var->parentvars[i];
10144 assert(parentvar != NULL);
10146 assert(parentvar->negatedvar == var);
10147 assert(var->negatedvar == parentvar);
10148
10149 SCIPrationalSetReal(tmpval, parentvar->data.negate.constant);
10150 SCIPrationalDiff(tmpval, tmpval, newbound);
10151
10152 SCIP_CALL( SCIPvarChgUbOriginalExact(parentvar, set, tmpval) );
10153 }
10154
10155 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10156
10157 return SCIP_OKAY;
10158}
10159
10160/** changes upper bound of original variable in original problem */
10162 SCIP_VAR* var, /**< problem variable to change */
10163 SCIP_SET* set, /**< global SCIP settings */
10164 SCIP_Real newbound /**< new bound for variable */
10165 )
10166{
10167 int i;
10168
10169 assert(var != NULL);
10172 assert(set != NULL);
10173 assert(var->scip == set->scip);
10174 assert(set->stage == SCIP_STAGE_PROBLEM);
10175
10176 /* check that the bound is feasible */
10178 /* adjust bound to integral value if variable is of integral type */
10179 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
10180
10181 if( SCIPsetIsZero(set, newbound) )
10182 newbound = 0.0;
10183
10184 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10186 {
10187 SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
10188 var->name, var->data.original.origdom.ub, newbound);
10189
10190 if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
10191 return SCIP_OKAY;
10192
10193 /* change the bound */
10194 var->data.original.origdom.ub = newbound;
10195 }
10197 {
10198 assert( var->negatedvar != NULL );
10199 SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
10200 }
10201
10202 /* process parent variables */
10203 for( i = 0; i < var->nparentvars; ++i )
10204 {
10205 SCIP_VAR* parentvar;
10206
10207 parentvar = var->parentvars[i];
10208 assert(parentvar != NULL);
10210 assert(parentvar->negatedvar == var);
10211 assert(var->negatedvar == parentvar);
10212
10213 SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
10214 }
10215
10216 return SCIP_OKAY;
10217}
10218
10219/** changes exact upper bound of original variable in original problem */
10221 SCIP_VAR* var, /**< problem variable to change */
10222 SCIP_SET* set, /**< global SCIP settings */
10223 SCIP_RATIONAL* newbound /**< new bound for variable */
10224 )
10225{
10226 SCIP_RATIONAL* tmpval;
10227 int i;
10228
10229 assert(var != NULL);
10232 assert(set != NULL);
10233 assert(var->scip == set->scip);
10234 assert(set->stage == SCIP_STAGE_PROBLEM);
10235
10236 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmpval) );
10237
10238 /* check that the bound is feasible */
10240
10241 /* adjust bound to integral value if variable is of integral type */
10243
10244 /* original domains are only stored for ORIGINAL variables, not for NEGATED */
10246 {
10247 SCIPrationalDebugMessage("changing original upper bound of <%s> from %q to %q\n",
10248 var->name, var->exactdata->origdom.ub, newbound);
10249
10250 if( SCIPrationalIsEQ(var->exactdata->origdom.ub, newbound) )
10251 {
10252 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10253 return SCIP_OKAY;
10254 }
10255
10256 /* change the bound */
10257 SCIPrationalSetRational(var->exactdata->origdom.ub, newbound);
10258 var->data.original.origdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
10259 }
10261 {
10262 assert( var->negatedvar != NULL );
10263
10264 SCIPrationalSetReal(tmpval, var->data.negate.constant);
10265 SCIPrationalDiff(tmpval, tmpval, newbound);
10266
10267 SCIP_CALL( SCIPvarChgLbOriginalExact(var->negatedvar, set, tmpval) );
10268 }
10269
10270 /* process parent variables */
10271 for( i = 0; i < var->nparentvars; ++i )
10272 {
10273 SCIP_VAR* parentvar;
10274
10275 parentvar = var->parentvars[i];
10276 assert(parentvar != NULL);
10278 assert(parentvar->negatedvar == var);
10279 assert(var->negatedvar == parentvar);
10280
10281 SCIPrationalSetReal(tmpval, parentvar->data.negate.constant);
10282 SCIPrationalDiff(tmpval, tmpval, newbound);
10283
10284 SCIP_CALL( SCIPvarChgLbOriginalExact(parentvar, set, tmpval) );
10285 }
10286
10287 SCIPrationalFreeBuffer(set->buffer, &tmpval);
10288
10289 return SCIP_OKAY;
10290}
10291
10292/** appends GLBCHANGED event to the event queue */
10293static
10295 SCIP_VAR* var, /**< problem variable to change */
10296 BMS_BLKMEM* blkmem, /**< block memory */
10297 SCIP_SET* set, /**< global SCIP settings */
10298 SCIP_LP* lp, /**< current LP data */
10299 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10300 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10301 SCIP_Real oldbound, /**< old lower bound for variable */
10302 SCIP_Real newbound /**< new lower bound for variable */
10303 )
10304{
10305 assert(var != NULL);
10306 assert(var->eventfilter != NULL);
10308 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
10309 assert(set != NULL);
10310 assert(var->scip == set->scip);
10311
10312 /* check, if the variable is being tracked for bound changes
10313 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10314 */
10315 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
10318 {
10319 SCIP_EVENT* event;
10320
10321 SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
10322
10323 SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
10324 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10325 }
10326
10327 return SCIP_OKAY;
10328}
10329
10330/** appends GLBCHANGED event to the event queue */
10331static
10333 SCIP_VAR* var, /**< problem variable to change */
10334 BMS_BLKMEM* blkmem, /**< block memory */
10335 SCIP_SET* set, /**< global SCIP settings */
10336 SCIP_LP* lp, /**< current LP data */
10337 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10338 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10339 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
10340 SCIP_RATIONAL* newbound /**< new lower bound for variable */
10341 )
10342{
10343 assert(var != NULL);
10344 assert(var->eventfilter != NULL);
10346 assert(!SCIPrationalIsEQ(oldbound, newbound));
10347 assert(set != NULL);
10348 assert(var->scip == set->scip);
10349
10350 /* check, if the variable is being tracked for bound changes
10351 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10352 */
10353 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
10356 {
10357 SCIP_EVENT* event;
10358
10359 SCIPrationalDebugMessage("issue exact GLBCHANGED event for variable <%s>: %q -> %q\n", var->name, oldbound, newbound);
10360
10362 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
10363 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10364 }
10365
10366 return SCIP_OKAY;
10367}
10368
10369/** appends GUBCHANGED event to the event queue */
10370static
10372 SCIP_VAR* var, /**< problem variable to change */
10373 BMS_BLKMEM* blkmem, /**< block memory */
10374 SCIP_SET* set, /**< global SCIP settings */
10375 SCIP_LP* lp, /**< current LP data */
10376 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10377 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10378 SCIP_Real oldbound, /**< old lower bound for variable */
10379 SCIP_Real newbound /**< new lower bound for variable */
10380 )
10381{
10382 assert(var != NULL);
10383 assert(var->eventfilter != NULL);
10385 assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
10386 assert(set != NULL);
10387 assert(var->scip == set->scip);
10388
10389 /* check, if the variable is being tracked for bound changes
10390 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10391 */
10392 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
10395 {
10396 SCIP_EVENT* event;
10397
10398 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
10399
10400 SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
10401 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10402 }
10403
10404 return SCIP_OKAY;
10405}
10406
10407/** appends exact GUBCHANGED event to the event queue */
10408static
10410 SCIP_VAR* var, /**< problem variable to change */
10411 BMS_BLKMEM* blkmem, /**< block memory */
10412 SCIP_SET* set, /**< global SCIP settings */
10413 SCIP_LP* lp, /**< current LP data */
10414 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10415 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10416 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
10417 SCIP_RATIONAL* newbound /**< new lower bound for variable */
10418 )
10419{
10420 assert(var != NULL);
10421 assert(var->eventfilter != NULL);
10423 assert(!SCIPrationalIsEQ(oldbound, newbound));
10424 assert(set != NULL);
10425 assert(var->scip == set->scip);
10426
10427 /* check, if the variable is being tracked for bound changes
10428 * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
10429 */
10430 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
10433 {
10434 SCIP_EVENT* event;
10435
10436 SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, SCIPrationalGetReal(oldbound), SCIPrationalGetReal(newbound));
10437
10439 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
10440 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
10441 }
10442
10443 return SCIP_OKAY;
10444}
10445
10446/** appends GHOLEADDED event to the event queue */
10447static
10449 SCIP_VAR* var, /**< problem variable to change */
10450 BMS_BLKMEM* blkmem, /**< block memory */
10451 SCIP_SET* set, /**< global SCIP settings */
10452 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10453 SCIP_Real left, /**< left bound of open interval in new hole */
10454 SCIP_Real right /**< right bound of open interval in new hole */
10455 )
10456{
10457 assert(var != NULL);
10458 assert(var->eventfilter != NULL);
10460 assert(set != NULL);
10461 assert(var->scip == set->scip);
10462 assert(SCIPsetIsLT(set, left, right));
10463
10464 /* check, if the variable is being tracked for bound changes */
10465 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
10466 {
10467 SCIP_EVENT* event;
10468
10469 SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
10470
10471 SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
10472 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
10473 }
10474
10475 return SCIP_OKAY;
10476}
10477
10478/** increases root bound change statistics after a global bound change */
10479static
10481 SCIP_VAR* var, /**< problem variable to change */
10482 SCIP_SET* set, /**< global SCIP settings */
10483 SCIP_STAT* stat /**< problem statistics */
10484 )
10485{
10486 assert(var != NULL);
10487 assert(set != NULL);
10488 assert(var->scip == set->scip);
10489 assert(stat != NULL);
10490
10492 {
10493 stat->nrootboundchgs++;
10494 stat->nrootboundchgsrun++;
10496 {
10497 stat->nrootintfixings++;
10498 stat->nrootintfixingsrun++;
10499 }
10500 }
10501}
10502
10503/* forward declaration, because both methods call each other recursively */
10504
10505/* performs the current change in upper bound, changes all parents accordingly */
10506static
10508 SCIP_VAR* var, /**< problem variable to change */
10509 BMS_BLKMEM* blkmem, /**< block memory */
10510 SCIP_SET* set, /**< global SCIP settings */
10511 SCIP_STAT* stat, /**< problem statistics */
10512 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10513 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10514 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10515 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10516 SCIP_Real newbound /**< new bound for variable */
10517 );
10518
10519/** performs the current change in lower bound, changes all parents accordingly */
10520static
10522 SCIP_VAR* var, /**< problem variable to change */
10523 BMS_BLKMEM* blkmem, /**< block memory */
10524 SCIP_SET* set, /**< global SCIP settings */
10525 SCIP_STAT* stat, /**< problem statistics */
10526 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10527 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10528 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10529 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10530 SCIP_Real newbound /**< new bound for variable */
10531 )
10532{
10533 SCIP_VAR* parentvar;
10534 SCIP_Real oldbound;
10535 int i;
10536
10537 assert(var != NULL);
10538 /* local domains can violate global bounds but not more than feasibility epsilon */
10539 assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
10540 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
10541 assert(blkmem != NULL);
10542 assert(set != NULL);
10543 assert(var->scip == set->scip);
10544 assert(stat != NULL);
10545
10546 /* adjust bound to integral value if variable is of integral type */
10547 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
10548
10549 /* check that the bound is feasible */
10550 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
10551 {
10552 /* due to numerics we only want to be feasible in feasibility tolerance */
10553 assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
10554 newbound = var->glbdom.ub;
10555 }
10557
10558 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
10559
10560 SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
10561
10562 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
10563 return SCIP_OKAY;
10564
10565 /* check bound on debugging solution */
10566 SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
10567
10568 /* change the bound */
10569 oldbound = var->glbdom.lb;
10570 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
10571 var->glbdom.lb = newbound;
10572 if( set->exact_enable && SCIPrationalIsLTReal(SCIPvarGetLbGlobalExact(var), newbound) )
10573 SCIPrationalSetReal(var->exactdata->glbdom.lb, newbound);
10574 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
10575 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
10576
10578 {
10579 /* merges overlapping holes into single holes, moves bounds respectively */
10580 domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
10581 }
10582
10583 /* update the root bound changes counters */
10584 varIncRootboundchgs(var, set, stat);
10585
10586 /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
10587 * redundant bound changes to be branching decisions
10588 */
10589 for( i = 0; i < var->nlbchginfos; ++i )
10590 {
10591 assert(var->lbchginfos[i].var == var);
10592
10593 if( var->lbchginfos[i].oldbound < var->glbdom.lb )
10594 {
10595 SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
10596 SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
10597 var->lbchginfos[i].oldbound = var->glbdom.lb;
10598 if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
10599 {
10600 /* this bound change is redundant due to the new global bound */
10601 var->lbchginfos[i].newbound = var->glbdom.lb;
10602 var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
10603 var->lbchginfos[i].redundant = TRUE;
10604 }
10605 else
10606 break; /* from now on, the remaining local bound changes are not redundant */
10607 }
10608 else
10609 break; /* from now on, the remaining local bound changes are not redundant */
10610 }
10611
10612 /* remove redundant implications and variable bounds */
10614 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
10615 {
10616 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
10617 }
10618
10619 /* issue bound change event */
10620 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10621 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
10622 {
10623 SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
10624 }
10625
10626 /* process parent variables */
10627 for( i = 0; i < var->nparentvars; ++i )
10628 {
10629 parentvar = var->parentvars[i];
10630 assert(parentvar != NULL);
10631
10632 switch( SCIPvarGetStatus(parentvar) )
10633 {
10635 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
10636 break;
10637
10642 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10643 return SCIP_INVALIDDATA;
10644
10645 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10646 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
10647 {
10648 SCIP_Real parentnewbound;
10649 assert(parentvar->data.aggregate.var == var);
10650
10651 if( parentvar->data.aggregate.scalar > 0 )
10652 {
10653 /* a > 0 -> change lower bound of y */
10654 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
10655 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
10656 || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
10657
10658 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10659 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10660 else
10661 parentnewbound = newbound;
10662 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10663 }
10664 else
10665 {
10666 /* a < 0 -> change upper bound of y */
10668 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
10669 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
10670 || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
10671
10672 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10673 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10674 else
10675 parentnewbound = -newbound;
10676 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10677 }
10678 break;
10679 }
10680
10681 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
10682 assert(parentvar->negatedvar != NULL);
10684 assert(parentvar->negatedvar->negatedvar == parentvar);
10685 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
10686 parentvar->data.negate.constant - newbound) );
10687 break;
10688
10689 default:
10690 SCIPerrorMessage("unknown variable status\n");
10691 return SCIP_INVALIDDATA;
10692 }
10693 }
10694
10695 return SCIP_OKAY;
10696}
10697
10698/** performs the current change in upper bound, changes all parents accordingly */
10699static
10701 SCIP_VAR* var, /**< problem variable to change */
10702 BMS_BLKMEM* blkmem, /**< block memory */
10703 SCIP_SET* set, /**< global SCIP settings */
10704 SCIP_STAT* stat, /**< problem statistics */
10705 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
10706 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10707 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10708 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10709 SCIP_Real newbound /**< new bound for variable */
10710 )
10711{
10712 SCIP_VAR* parentvar;
10713 SCIP_Real oldbound;
10714 int i;
10715
10716 assert(var != NULL);
10717 /* local domains can violate global bounds but not more than feasibility epsilon */
10718 assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
10719 assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
10720 assert(blkmem != NULL);
10721 assert(set != NULL);
10722 assert(var->scip == set->scip);
10723 assert(stat != NULL);
10724
10725 /* adjust bound to integral value if variable is of integral type */
10726 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
10727
10728 /* check that the bound is feasible */
10729 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
10730 {
10731 /* due to numerics we only want to be feasible in feasibility tolerance */
10732 assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
10733 newbound = var->glbdom.lb;
10734 }
10736
10737 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
10738
10739 SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
10740
10741 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
10742 return SCIP_OKAY;
10743
10744 /* check bound on debugging solution */
10745 SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
10746
10747 /* change the bound */
10748 oldbound = var->glbdom.ub;
10749 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
10750 var->glbdom.ub = newbound;
10751 if( set->exact_enable && SCIPrationalIsGTReal(SCIPvarGetUbGlobalExact(var), newbound) )
10752 SCIPrationalSetReal(var->exactdata->glbdom.ub, newbound);
10753
10754 assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
10755 assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
10756
10758 {
10759 /* merges overlapping holes into single holes, moves bounds respectively */
10760 domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
10761 }
10762
10763 /* update the root bound changes counters */
10764 varIncRootboundchgs(var, set, stat);
10765
10766 /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
10767 * redundant bound changes to be branching decisions
10768 */
10769 for( i = 0; i < var->nubchginfos; ++i )
10770 {
10771 assert(var->ubchginfos[i].var == var);
10772 if( var->ubchginfos[i].oldbound > var->glbdom.ub )
10773 {
10774 SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
10775 SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
10776 var->ubchginfos[i].oldbound = var->glbdom.ub;
10777 if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
10778 {
10779 /* this bound change is redundant due to the new global bound */
10780 var->ubchginfos[i].newbound = var->glbdom.ub;
10781 var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
10782 var->ubchginfos[i].redundant = TRUE;
10783 }
10784 else
10785 break; /* from now on, the remaining local bound changes are not redundant */
10786 }
10787 else
10788 break; /* from now on, the remaining local bound changes are not redundant */
10789 }
10790
10791 /* remove redundant implications and variable bounds */
10793 && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
10794 {
10795 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
10796 }
10797
10798 /* issue bound change event */
10799 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10800 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
10801 {
10802 SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
10803 }
10804
10805 /* process parent variables */
10806 for( i = 0; i < var->nparentvars; ++i )
10807 {
10808 parentvar = var->parentvars[i];
10809 assert(parentvar != NULL);
10810
10811 switch( SCIPvarGetStatus(parentvar) )
10812 {
10814 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
10815 break;
10816
10821 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10822 return SCIP_INVALIDDATA;
10823
10824 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10825 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
10826 {
10827 SCIP_Real parentnewbound;
10828 assert(parentvar->data.aggregate.var == var);
10829
10830 if( parentvar->data.aggregate.scalar > 0 )
10831 {
10832 /* a > 0 -> change upper bound of y */
10833 assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
10834 || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
10835 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
10836 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10837 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10838 else
10839 parentnewbound = newbound;
10840 SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10841 }
10842 else
10843 {
10844 /* a < 0 -> change lower bound of y */
10846 assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
10847 || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
10848 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
10849 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
10850 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
10851 else
10852 parentnewbound = -newbound;
10853 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
10854 }
10855 break;
10856 }
10857
10858 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
10859 assert(parentvar->negatedvar != NULL);
10861 assert(parentvar->negatedvar->negatedvar == parentvar);
10862 SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
10863 parentvar->data.negate.constant - newbound) );
10864 break;
10865
10866 default:
10867 SCIPerrorMessage("unknown variable status\n");
10868 return SCIP_INVALIDDATA;
10869 }
10870 }
10871
10872 return SCIP_OKAY;
10873}
10874
10875/* forward declaration, because both methods call each other recursively */
10876
10877/* performs the current change in upper bound, changes all parents accordingly */
10878static
10880 SCIP_VAR* var, /**< problem variable to change */
10881 BMS_BLKMEM* blkmem, /**< block memory */
10882 SCIP_SET* set, /**< global SCIP settings */
10883 SCIP_STAT* stat, /**< problem statistics */
10884 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
10885 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10886 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10887 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10888 SCIP_RATIONAL* newbound /**< new bound for variable */
10889 );
10890
10891/** performs the current change in lower bound, changes all parents accordingly */
10892static
10894 SCIP_VAR* var, /**< problem variable to change */
10895 BMS_BLKMEM* blkmem, /**< block memory */
10896 SCIP_SET* set, /**< global SCIP settings */
10897 SCIP_STAT* stat, /**< problem statistics */
10898 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
10899 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
10900 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
10901 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10902 SCIP_RATIONAL* newbound /**< new bound for variable */
10903 )
10904{
10905 SCIP_VAR* parentvar;
10906 SCIP_RATIONAL* oldbound;
10907 SCIP_RATIONAL* parentnewbound;
10908 int i;
10909
10910 assert(var != NULL);
10911 assert(SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
10912 assert(SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub));
10913 assert(blkmem != NULL);
10914 assert(set != NULL);
10915 assert(var->scip == set->scip);
10916 assert(stat != NULL);
10917
10918 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
10919
10920 /* adjust bound to integral value if variable is of integral type */
10922
10923 /* check that the bound is feasible */
10924 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub) )
10925 {
10926 /* due to numerics we only want to be feasible in feasibility tolerance */
10927 assert(SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
10928 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
10929 }
10931
10932 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPrationalIsEQReal(newbound, 0.0) || SCIPrationalIsEQReal(newbound, 1.0)); /*lint !e641*/
10933
10934 SCIPrationalDebugMessage("process changing exact global lower bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
10935
10936 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.lb) )
10937 {
10938 SCIPrationalFreeBuffer(set->buffer, &oldbound);
10939 return SCIP_OKAY;
10940 }
10941
10942 /* change the bound */
10943 SCIPrationalSetRational(oldbound, var->exactdata->glbdom.lb);
10944 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
10945 SCIPrationalSetRational(var->exactdata->glbdom.lb, newbound);
10946 var->glbdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
10947 assert( SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) );
10948 assert( SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub) );
10949
10950 /* update the root bound changes counters */
10951 varIncRootboundchgs(var, set, stat);
10952
10953 /* issue bound change event */
10954 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
10955 if( var->eventfilter != NULL )
10956 {
10957 SCIP_CALL( varEventGlbChangedExact(var, blkmem, set, lpexact->fplp, branchcand, eventqueue, oldbound, newbound) );
10958 }
10959
10960 /* process parent variables */
10961 for( i = 0; i < var->nparentvars; ++i )
10962 {
10963 parentvar = var->parentvars[i];
10964 assert(parentvar != NULL);
10965
10966 switch( SCIPvarGetStatus(parentvar) )
10967 {
10969 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
10970 break;
10971
10976 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10977 return SCIP_INVALIDDATA;
10978
10979 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
10980 assert(parentvar->data.aggregate.var == var);
10982 {
10983 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
10984 /* a > 0 -> change lower bound of y */
10985 if( !SCIPrationalIsAbsInfinity(newbound) )
10986 {
10987 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
10988 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
10989 }
10990 else
10991 SCIPrationalSetRational(parentnewbound, newbound);
10992 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
10993 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
10994 }
10995 else
10996 {
10997 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
10998 /* a < 0 -> change upper bound of y */
10999 if( !SCIPrationalIsAbsInfinity(newbound) )
11000 {
11001 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11002 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11003 }
11004 else
11005 SCIPrationalNegate(parentnewbound, newbound);
11006 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11007 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11008 }
11009 break;
11010
11011 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11012 assert(parentvar->negatedvar != NULL);
11014 assert(parentvar->negatedvar->negatedvar == parentvar);
11015 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11016 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
11017 SCIPrationalNegate(parentnewbound, parentnewbound);
11018 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11019 parentnewbound) );
11020 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11021 break;
11022
11023 default:
11024 SCIPerrorMessage("unknown variable status\n");
11025 return SCIP_INVALIDDATA;
11026 }
11027 }
11028 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11029
11030 return SCIP_OKAY;
11031}
11032
11033/** performs the current change in exact upper bound, changes all parents accordingly */
11034static
11036 SCIP_VAR* var, /**< problem variable to change */
11037 BMS_BLKMEM* blkmem, /**< block memory */
11038 SCIP_SET* set, /**< global SCIP settings */
11039 SCIP_STAT* stat, /**< problem statistics */
11040 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11041 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11042 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11043 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11044 SCIP_RATIONAL* newbound /**< new bound for variable */
11045 )
11046{
11047 SCIP_VAR* parentvar;
11048 SCIP_RATIONAL* oldbound;
11049 SCIP_RATIONAL* parentnewbound;
11050 int i;
11051
11052 assert(var != NULL);
11053 assert(SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb));
11054 assert(SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub));
11055 assert(blkmem != NULL);
11056 assert(set != NULL);
11057 assert(var->scip == set->scip);
11058 assert(stat != NULL);
11059
11060 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
11061
11062 /* adjust bound to integral value if variable is of integral type */
11064
11065 /* check that the bound is feasible */
11066 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb) )
11067 {
11068 /* due to numerics we only want to be feasible in feasibility tolerance */
11069 assert(SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
11070 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
11071 }
11073
11074 assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPrationalIsEQReal(newbound, 0.0) || SCIPrationalIsEQReal(newbound, 1.0)); /*lint !e641*/
11075
11076 SCIPrationalDebugMessage("process changing exact global upper bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
11077
11078 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.ub) )
11079 {
11080 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11081 return SCIP_OKAY;
11082 }
11083
11084 /* change the bound */
11085 SCIPrationalSetRational(oldbound, var->exactdata->glbdom.ub);
11086 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
11087 SCIPrationalSetRational(var->exactdata->glbdom.ub, newbound);
11088 var->glbdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
11089 assert( SCIPrationalIsLE(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) );
11090 assert( SCIPrationalIsLE(var->exactdata->locdom.ub, var->exactdata->glbdom.ub) );
11091
11092 /* update the root bound changes counters */
11093 varIncRootboundchgs(var, set, stat);
11094
11095 /* issue bound change event */
11096 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
11097 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
11098 {
11099 SCIP_CALL( varEventGubChangedExact(var, blkmem, set, lpexact->fplp, branchcand, eventqueue, oldbound, newbound) );
11100 }
11101
11102 /* process parent variables */
11103 for( i = 0; i < var->nparentvars; ++i )
11104 {
11105 parentvar = var->parentvars[i];
11106 assert(parentvar != NULL);
11107
11108 switch( SCIPvarGetStatus(parentvar) )
11109 {
11111 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11112 break;
11113
11118 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11119 return SCIP_INVALIDDATA;
11120
11121 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11122 assert(parentvar->data.aggregate.var == var);
11124 {
11125 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11126 /* a > 0 -> change lower bound of y */
11127 if( !SCIPrationalIsAbsInfinity(newbound) )
11128 {
11129 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11130 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11131 }
11132 else
11133 SCIPrationalSetRational(parentnewbound, newbound);
11134 SCIP_CALL( varProcessChgUbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11135 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11136 }
11137 else
11138 {
11139 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11140 /* a < 0 -> change upper bound of y */
11141 if( !SCIPrationalIsAbsInfinity(newbound) )
11142 {
11143 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
11144 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
11145 }
11146 else
11147 SCIPrationalNegate(parentnewbound, newbound);
11148 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, parentnewbound) );
11149 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11150 }
11151 break;
11152
11153 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11154 assert(parentvar->negatedvar != NULL);
11156 assert(parentvar->negatedvar->negatedvar == parentvar);
11157 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
11158 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
11159 SCIPrationalNegate(parentnewbound, parentnewbound);
11160 SCIP_CALL( varProcessChgLbGlobalExact(parentvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11161 parentnewbound) );
11162 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
11163 break;
11164
11165 default:
11166 SCIPerrorMessage("unknown variable status\n");
11167 return SCIP_INVALIDDATA;
11168 }
11169 }
11170 SCIPrationalFreeBuffer(set->buffer, &oldbound);
11171
11172 return SCIP_OKAY;
11173}
11174
11175/** changes global lower bound of variable; if possible, adjusts bound to integral value;
11176 * updates local lower bound if the global bound is tighter
11177 */
11179 SCIP_VAR* var, /**< problem variable to change */
11180 BMS_BLKMEM* blkmem, /**< block memory */
11181 SCIP_SET* set, /**< global SCIP settings */
11182 SCIP_STAT* stat, /**< problem statistics */
11183 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11184 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11185 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11186 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11187 SCIP_Real newbound /**< new bound for variable */
11188 )
11189{
11190 assert(var != NULL);
11191 assert(blkmem != NULL);
11192 assert(set != NULL);
11193 assert(var->scip == set->scip);
11194
11195 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11196 * of the domain within feastol
11197 */
11198 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
11199
11200 /* adjust bound to integral value if variable is of integral type */
11201 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
11202
11203 /* check that the adjusted bound is feasible
11204 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11205 * here because we reset bounds to their original value!
11206 */
11207 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
11208
11210 {
11211 /* we do not want to exceed the upperbound, which could have happened due to numerics */
11212 newbound = MIN(newbound, var->glbdom.ub);
11213 }
11215
11216 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11217 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11218 */
11219 assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11220
11221 SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
11222
11223 if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
11224 return SCIP_OKAY;
11225
11226 /* change bounds of attached variables */
11227 switch( SCIPvarGetStatus(var) )
11228 {
11230 if( var->data.original.transvar != NULL )
11231 {
11232 SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
11233 cliquetable, newbound) );
11234 }
11235 else
11236 {
11237 assert(set->stage == SCIP_STAGE_PROBLEM);
11238 if( newbound > SCIPvarGetLbLocal(var) )
11239 {
11240 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11241 }
11242 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11243 }
11244 break;
11245
11248 if( newbound > SCIPvarGetLbLocal(var) )
11249 {
11250 /* ensure that the local bound change is not blocked */
11251 if( newbound > SCIPvarGetUbLocal(var) )
11252 {
11253 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11254 }
11255 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11256 }
11257 SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11258 break;
11259
11261 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11262 return SCIP_INVALIDDATA;
11263
11264 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11265 {
11266 SCIP_Real childnewbound;
11267 assert(var->data.aggregate.var != NULL);
11268
11269 if( var->data.aggregate.scalar > 0 )
11270 {
11271 /* a > 0 -> change lower bound of y */
11272 assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
11273 || SCIPsetIsFeasEQ(set, var->glbdom.lb,
11274 var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
11275 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11276 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11277 else
11278 childnewbound = newbound;
11279 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11280 childnewbound) );
11281 }
11282 else
11283 {
11284 /* a < 0 -> change upper bound of y */
11285 assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
11286 || SCIPsetIsFeasEQ(set, var->glbdom.lb,
11287 var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
11288 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11289 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11290 else
11291 childnewbound = -newbound;
11292 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11293 childnewbound) );
11294 }
11295 break;
11296 }
11297
11299 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11300 return SCIP_INVALIDDATA;
11301
11302 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11303 assert(var->negatedvar != NULL);
11305 assert(var->negatedvar->negatedvar == var);
11306 SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11307 var->data.negate.constant - newbound) );
11308 break;
11309
11310 default:
11311 SCIPerrorMessage("unknown variable status\n");
11312 return SCIP_INVALIDDATA;
11313 }
11314
11315 return SCIP_OKAY;
11316}
11317
11318/** changes global lower bound of variable; if possible, adjusts bound to integral value;
11319 * updates local lower bound if the global bound is tighter
11320 */
11322 SCIP_VAR* var, /**< problem variable to change */
11323 BMS_BLKMEM* blkmem, /**< block memory */
11324 SCIP_SET* set, /**< global SCIP settings */
11325 SCIP_STAT* stat, /**< problem statistics */
11326 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11327 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11328 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11329 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11330 SCIP_RATIONAL* newbound /**< new bound for variable */
11331 )
11332{
11333 SCIP_RATIONAL* childnewbound;
11334
11335 assert(var != NULL);
11336 assert(blkmem != NULL);
11337 assert(set != NULL);
11338 assert(var->scip == set->scip);
11339
11340 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11341 * of the domain within feastol
11342 */
11343 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub));
11344
11345 /* adjust bound to integral value if variable is of integral type */
11347
11348 /* check that the adjusted bound is feasible
11349 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11350 * here because we reset bounds to their original value!
11351 */
11352 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->glbdom.ub));
11353
11355 {
11356 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11357 SCIPrationalMin(newbound, newbound, var->exactdata->glbdom.ub);
11358 }
11360
11361 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11362 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11363 */
11364 assert(lpexact == NULL || SCIPrationalIsLE(var->exactdata->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11365
11366 SCIPrationalDebugMessage("changing global lower bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.lb, newbound);
11367
11368 /* change bounds of attached variables */
11369 switch( SCIPvarGetStatus(var) )
11370 {
11372 if( var->data.original.transvar != NULL )
11373 {
11374 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11375 newbound) );
11376 }
11377 else
11378 {
11379 assert(set->stage == SCIP_STAGE_PROBLEM);
11381 {
11382 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11383 }
11384 SCIP_CALL( varProcessChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11385 }
11386 break;
11387
11391 {
11393 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11394 }
11395 SCIP_CALL( varProcessChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11396 break;
11397
11399 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11400 return SCIP_INVALIDDATA;
11401
11402 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11403 assert(var->data.aggregate.var != NULL);
11404 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
11405 {
11406 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11407
11408 /* a > 0 -> change lower bound of y */
11409 if( !SCIPrationalIsAbsInfinity(newbound) )
11410 {
11411 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11412 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11413 }
11414 else
11415 SCIPrationalSetRational(childnewbound, newbound);
11416
11417 SCIP_CALL( SCIPvarChgLbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11418 childnewbound) );
11419
11420 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11421 }
11422 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
11423 {
11424 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11425
11426 /* a < 0 -> change upper bound of y */
11427 if( !SCIPrationalIsAbsInfinity(newbound) )
11428 {
11429 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11430 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11431 }
11432 else
11433 SCIPrationalSetRational(childnewbound, newbound);
11434
11435 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11436 childnewbound) );
11437
11438 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11439 }
11440 else
11441 {
11442 SCIPerrorMessage("scalar is zero in aggregation\n");
11443 return SCIP_INVALIDDATA;
11444 }
11445 break;
11446
11448 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11449 return SCIP_INVALIDDATA;
11450
11451 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11452 assert(var->negatedvar != NULL);
11454 assert(var->negatedvar->negatedvar == var);
11455
11456 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11457 SCIPrationalDiffReal(childnewbound, newbound, var->data.negate.constant);
11458 SCIPrationalNegate(childnewbound, childnewbound);
11459 SCIP_CALL( SCIPvarChgUbGlobalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11460 childnewbound) );
11461 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11462 break;
11463
11464 default:
11465 SCIPerrorMessage("unknown variable status\n");
11466 return SCIP_INVALIDDATA;
11467 }
11468
11469 return SCIP_OKAY;
11470}
11471
11472/** changes global upper bound of variable; if possible, adjusts bound to integral value;
11473 * updates local upper bound if the global bound is tighter
11474 */
11476 SCIP_VAR* var, /**< problem variable to change */
11477 BMS_BLKMEM* blkmem, /**< block memory */
11478 SCIP_SET* set, /**< global SCIP settings */
11479 SCIP_STAT* stat, /**< problem statistics */
11480 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11481 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11482 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11483 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11484 SCIP_Real newbound /**< new bound for variable */
11485 )
11486{
11487 assert(var != NULL);
11488 assert(blkmem != NULL);
11489 assert(set != NULL);
11490 assert(var->scip == set->scip);
11491
11492 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11493 * of the domain within feastol
11494 */
11495 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
11496
11497 /* adjust bound to integral value if variable is of integral type */
11498 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
11499
11500 /* check that the adjusted bound is feasible
11501 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11502 * here because we reset bounds to their original value!
11503 */
11504 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
11505
11507 {
11508 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11509 newbound = MAX(newbound, var->glbdom.lb);
11510 }
11512
11513 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11514 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11515 */
11516 assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11517
11518 SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
11519
11520 if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
11521 return SCIP_OKAY;
11522
11523 /* change bounds of attached variables */
11524 switch( SCIPvarGetStatus(var) )
11525 {
11527 if( var->data.original.transvar != NULL )
11528 {
11529 SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11530 newbound) );
11531 }
11532 else
11533 {
11534 assert(set->stage == SCIP_STAGE_PROBLEM);
11535 if( newbound < SCIPvarGetUbLocal(var) )
11536 {
11537 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11538 }
11539 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11540 }
11541 break;
11542
11545 if( newbound < SCIPvarGetUbLocal(var) )
11546 {
11547 /* ensure that the local bound change is not blocked */
11548 if( newbound < SCIPvarGetLbLocal(var) )
11549 {
11550 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11551 }
11552 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
11553 }
11554 SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
11555 break;
11556
11558 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11559 return SCIP_INVALIDDATA;
11560
11561 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11562 {
11563 SCIP_Real childnewbound;
11564 assert(var->data.aggregate.var != NULL);
11565
11566 if( var->data.aggregate.scalar > 0 )
11567 {
11568 /* a > 0 -> change lower bound of y */
11569 assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
11570 || SCIPsetIsFeasEQ(set, var->glbdom.ub,
11571 var->data.aggregate.var->glbdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
11572 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11573 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11574 else
11575 childnewbound = newbound;
11576 SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11577 childnewbound) );
11578 }
11579 else
11580 {
11581 /* a < 0 -> change upper bound of y */
11582 assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
11583 || SCIPsetIsFeasEQ(set, var->glbdom.ub,
11584 var->data.aggregate.var->glbdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
11585 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
11586 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
11587 else
11588 childnewbound = -newbound;
11589 SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11590 childnewbound) );
11591 }
11592 break;
11593 }
11594
11596 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11597 return SCIP_INVALIDDATA;
11598
11599 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11600 assert(var->negatedvar != NULL);
11602 assert(var->negatedvar->negatedvar == var);
11603 SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
11604 var->data.negate.constant - newbound) );
11605 break;
11606
11607 default:
11608 SCIPerrorMessage("unknown variable status\n");
11609 return SCIP_INVALIDDATA;
11610 }
11611
11612 return SCIP_OKAY;
11613}
11614
11615/** changes global upper bound of variable; if possible, adjusts bound to integral value;
11616 * updates local upper bound if the global bound is tighter
11617 */
11619 SCIP_VAR* var, /**< problem variable to change */
11620 BMS_BLKMEM* blkmem, /**< block memory */
11621 SCIP_SET* set, /**< global SCIP settings */
11622 SCIP_STAT* stat, /**< problem statistics */
11623 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
11624 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11625 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11626 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11627 SCIP_RATIONAL* newbound /**< new bound for variable */
11628 )
11629{
11630 SCIP_RATIONAL* childnewbound;
11631
11632 assert(var != NULL);
11633 assert(blkmem != NULL);
11634 assert(set != NULL);
11635 assert(var->scip == set->scip);
11636
11637 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
11638 * of the domain within feastol
11639 */
11640 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb));
11641
11642 /* adjust bound to integral value if variable is of integral type */
11644
11645 /* check that the adjusted bound is feasible
11646 * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
11647 * here because we reset bounds to their original value!
11648 */
11649 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->glbdom.lb));
11650
11652 {
11653 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
11654 SCIPrationalMax(newbound, newbound, var->exactdata->glbdom.lb);
11655 }
11657
11658 /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
11659 * SCIPvarFix() allows fixings that are outside of the domain within feastol
11660 */
11661 assert(lpexact == NULL || SCIPrationalIsGE(var->exactdata->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
11662
11663 SCIPrationalDebugMessage("changing global upper bound of <%s> from %q to %q\n", var->name, var->exactdata->glbdom.ub, newbound);
11664
11665 /* change bounds of attached variables */
11666 switch( SCIPvarGetStatus(var) )
11667 {
11669 if( var->data.original.transvar != NULL )
11670 {
11671 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11672 newbound) );
11673 }
11674 else
11675 {
11676 assert(set->stage == SCIP_STAGE_PROBLEM);
11678 {
11679 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11680 }
11681
11682 SCIP_CALL( varProcessChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11683 }
11684 break;
11685
11689 {
11691 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
11692 }
11693 SCIP_CALL( varProcessChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound) );
11694 break;
11695
11697 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
11698 return SCIP_INVALIDDATA;
11699
11700 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
11701 assert(var->data.aggregate.var != NULL);
11702 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
11703 {
11704 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11705
11706 /* a > 0 -> change lower bound of y */
11707 if( !SCIPrationalIsAbsInfinity(newbound) )
11708 {
11709 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
11710 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
11711 }
11712 else
11713 SCIPrationalSetRational(childnewbound, newbound);
11714
11715 SCIP_CALL( SCIPvarChgUbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11716 childnewbound) );
11717
11718 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11719 }
11720 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
11721 {
11722 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11723
11724 /* a < 0 -> change upper 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( SCIPvarChgLbGlobalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11734 childnewbound) );
11735
11736 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11737 }
11738 else
11739 {
11740 SCIPerrorMessage("scalar is zero in aggregation\n");
11741 return SCIP_INVALIDDATA;
11742 }
11743 break;
11744
11746 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
11747 return SCIP_INVALIDDATA;
11748
11749 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11750 assert(var->negatedvar != NULL);
11752 assert(var->negatedvar->negatedvar == var);
11753
11754 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
11755 SCIPrationalDiffReal(childnewbound, newbound, var->data.negate.constant);
11756 SCIPrationalNegate(childnewbound, childnewbound);
11757 SCIP_CALL( SCIPvarChgLbGlobalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable,
11758 childnewbound) );
11759 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
11760 break;
11761
11762 default:
11763 SCIPerrorMessage("unknown variable status\n");
11764 return SCIP_INVALIDDATA;
11765 }
11766
11767 return SCIP_OKAY;
11768}
11769
11770/** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
11772 SCIP_VAR* var, /**< problem variable */
11773 SCIP_SET* set, /**< global SCIP settings */
11774 SCIP_Real lazylb /**< the lazy lower bound to be set */
11775 )
11776{
11777 assert(var != NULL);
11778 assert(var->probindex != -1);
11779 assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
11780 assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
11781 assert(set != NULL);
11782 assert(var->scip == set->scip);
11783
11784 /* variable should not be in the LP */
11786 return SCIP_INVALIDCALL;
11787
11788 var->lazylb = lazylb;
11789
11790 return SCIP_OKAY;
11791}
11792
11793/** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
11795 SCIP_VAR* var, /**< problem variable */
11796 SCIP_SET* set, /**< global SCIP settings */
11797 SCIP_Real lazyub /**< the lazy upper bound to be set */
11798 )
11799{
11800 assert(var != NULL);
11801 assert(var->probindex != -1);
11802 assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
11803 assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
11804 assert(set != NULL);
11805 assert(var->scip == set->scip);
11806
11807 /* variable should not be in the LP */
11809 return SCIP_INVALIDCALL;
11810
11811 var->lazyub = lazyub;
11812
11813 return SCIP_OKAY;
11814}
11815
11816/** changes global bound of variable; if possible, adjusts bound to integral value;
11817 * updates local bound if the global bound is tighter
11818 */
11820 SCIP_VAR* var, /**< problem variable to change */
11821 BMS_BLKMEM* blkmem, /**< block memory */
11822 SCIP_SET* set, /**< global SCIP settings */
11823 SCIP_STAT* stat, /**< problem statistics */
11824 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
11825 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11826 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11827 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11828 SCIP_Real newbound, /**< new bound for variable */
11829 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
11830 )
11831{
11832 /* apply bound change to the LP data */
11833 switch( boundtype )
11834 {
11836 return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
11838 return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
11839 default:
11840 SCIPerrorMessage("unknown bound type\n");
11841 return SCIP_INVALIDDATA;
11842 }
11843}
11844
11845/** changes exact global bound of variable; if possible, adjusts bound to integral value;
11846 * updates local bound if the global bound is tighter
11847 */
11849 SCIP_VAR* var, /**< problem variable to change */
11850 BMS_BLKMEM* blkmem, /**< block memory */
11851 SCIP_SET* set, /**< global SCIP settings */
11852 SCIP_STAT* stat, /**< problem statistics */
11853 SCIP_LPEXACT* lpexact, /**< current LP data, may be NULL for original variables */
11854 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
11855 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
11856 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11857 SCIP_RATIONAL* newbound, /**< new bound for variable */
11858 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
11859 )
11860{
11861 /* apply bound change to the LP data */
11862 switch( boundtype )
11863 {
11865 return SCIPvarChgLbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound);
11867 return SCIPvarChgUbGlobalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, cliquetable, newbound);
11868 default:
11869 SCIPerrorMessage("unknown bound type\n");
11870 return SCIP_INVALIDDATA;
11871 }
11872}
11873
11874/** appends LBTIGHTENED or LBRELAXED event to the event queue */
11875static
11877 SCIP_VAR* var, /**< problem variable to change */
11878 BMS_BLKMEM* blkmem, /**< block memory */
11879 SCIP_SET* set, /**< global SCIP settings */
11880 SCIP_LP* lp, /**< current LP data */
11881 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11882 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11883 SCIP_Real oldbound, /**< old lower bound for variable */
11884 SCIP_Real newbound /**< new lower bound for variable */
11885 )
11886{
11887 assert(var != NULL);
11888 assert(var->eventfilter != NULL);
11890 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
11891 assert(set != NULL);
11892 assert(var->scip == set->scip);
11893
11894 /* check, if the variable is being tracked for bound changes
11895 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11896 */
11897 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
11900 {
11901 SCIP_EVENT* event;
11902
11903 SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
11904
11905 SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
11906 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
11907 }
11908
11909 return SCIP_OKAY;
11910}
11911
11912/** appends LBTIGHTENED or LBRELAXED event to the event queue */
11913static
11915 SCIP_VAR* var, /**< problem variable to change */
11916 BMS_BLKMEM* blkmem, /**< block memory */
11917 SCIP_SET* set, /**< global SCIP settings */
11918 SCIP_LPEXACT* lp, /**< current LP data */
11919 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11920 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11921 SCIP_RATIONAL* oldbound, /**< old lower bound for variable */
11922 SCIP_RATIONAL* newbound /**< new lower bound for variable */
11923 )
11924{
11925 assert(var != NULL);
11926 assert(var->eventfilter != NULL);
11928 assert(set != NULL);
11929 assert(var->scip == set->scip);
11930
11931 /* check, if the variable is being tracked for bound changes
11932 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11933 */
11934 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
11937 {
11938 SCIP_EVENT* event;
11939
11940 SCIPrationalDebugMessage("issue exact LBCHANGED event for variable <%s>: %q -> %q\n", var->name, oldbound, newbound);
11941
11943 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
11944 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp->fplp, branchcand, NULL, &event) );
11945 }
11946
11947 return SCIP_OKAY;
11948}
11949
11950/** appends UBTIGHTENED or UBRELAXED event to the event queue */
11951static
11953 SCIP_VAR* var, /**< problem variable to change */
11954 BMS_BLKMEM* blkmem, /**< block memory */
11955 SCIP_SET* set, /**< global SCIP settings */
11956 SCIP_LP* lp, /**< current LP data */
11957 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11958 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11959 SCIP_Real oldbound, /**< old upper bound for variable */
11960 SCIP_Real newbound /**< new upper bound for variable */
11961 )
11962{
11963 assert(var != NULL);
11964 assert(var->eventfilter != NULL);
11966 assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
11967 assert(set != NULL);
11968 assert(var->scip == set->scip);
11969
11970 /* check, if the variable is being tracked for bound changes
11971 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
11972 */
11973 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
11976 {
11977 SCIP_EVENT* event;
11978
11979 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
11980
11981 SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
11982 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
11983 }
11984
11985 return SCIP_OKAY;
11986}
11987
11988/** appends exact UBTIGHTENED or UBRELAXED event to the event queue */
11989static
11991 SCIP_VAR* var, /**< problem variable to change */
11992 BMS_BLKMEM* blkmem, /**< block memory */
11993 SCIP_SET* set, /**< global SCIP settings */
11994 SCIP_LPEXACT* lp, /**< current LP data */
11995 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11996 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11997 SCIP_RATIONAL* oldbound, /**< old upper bound for variable */
11998 SCIP_RATIONAL* newbound /**< new upper bound for variable */
11999 )
12000{
12001 assert(var != NULL);
12002 assert(var->eventfilter != NULL);
12004 assert(set != NULL);
12005 assert(var->scip == set->scip);
12006
12007 /* check, if the variable is being tracked for bound changes
12008 * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
12009 */
12010 if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
12013 {
12014 SCIP_EVENT* event;
12015
12016 SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, SCIPrationalGetReal(oldbound), SCIPrationalGetReal(newbound));
12017
12019 SCIP_CALL( SCIPeventAddExactBdChg(event, blkmem, oldbound, newbound) );
12020 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp->fplp, branchcand, NULL, &event) );
12021 }
12022
12023 return SCIP_OKAY;
12024}
12025
12026/* forward declaration, because both methods call each other recursively */
12027
12028/* performs the current change in upper bound, changes all parents accordingly */
12029static
12031 SCIP_VAR* var, /**< problem variable to change */
12032 BMS_BLKMEM* blkmem, /**< block memory */
12033 SCIP_SET* set, /**< global SCIP settings */
12034 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12035 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12036 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12037 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12038 SCIP_Real newbound /**< new bound for variable */
12039 );
12040
12041/** performs the current change in lower bound, changes all parents accordingly */
12042static
12044 SCIP_VAR* var, /**< problem variable to change */
12045 BMS_BLKMEM* blkmem, /**< block memory */
12046 SCIP_SET* set, /**< global SCIP settings */
12047 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12048 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12049 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12050 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12051 SCIP_Real newbound /**< new bound for variable */
12052 )
12053{
12054 SCIP_VAR* parentvar;
12055 SCIP_Real oldbound;
12056 int i;
12057
12058 assert(var != NULL);
12059 assert(set != NULL);
12060 assert(var->scip == set->scip);
12061 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
12062 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
12063 || (SCIPvarIsIntegral(var) && (SCIPsetIsIntegral(set, newbound)
12064 || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
12065 || !SCIPvarIsIntegral(var));
12066
12067 /* check that the bound is feasible */
12068 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
12069 /* adjust bound to integral value if variable is of integral type */
12070 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
12071
12073 {
12074 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12075 newbound = MIN(newbound, var->locdom.ub);
12076
12077 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12078 newbound = MAX(newbound, var->glbdom.lb);
12079 }
12081
12082 SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
12083
12084 if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
12085 newbound = var->glbdom.lb;
12086 else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
12087 return SCIP_OKAY;
12088
12089 /* change the bound */
12090 oldbound = var->locdom.lb;
12091 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
12092 var->locdom.lb = newbound;
12093 /* adjust the exact bound as well */
12094 if( set->exact_enable )
12095 {
12096 SCIPrationalSetReal(var->exactdata->locdom.lb, var->locdom.lb);
12097 SCIPrationalMax(var->exactdata->locdom.lb, var->exactdata->locdom.lb, var->exactdata->glbdom.lb);
12098 }
12099
12100 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12101 * once update the statistic
12102 */
12103 if( stat != NULL )
12104 SCIPstatIncrement(stat, set, domchgcount);
12105
12107 {
12108 /* merges overlapping holes into single holes, moves bounds respectively */
12109 domMerge(&var->locdom, blkmem, set, &newbound, NULL);
12110 }
12111
12114
12115 /* issue bound change event */
12116 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12117 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12118 {
12119 SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
12120 }
12121
12122 /* process parent variables */
12123 for( i = 0; i < var->nparentvars; ++i )
12124 {
12125 parentvar = var->parentvars[i];
12126 assert(parentvar != NULL);
12127
12128 switch( SCIPvarGetStatus(parentvar) )
12129 {
12131 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
12132 break;
12133
12138 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12139 return SCIP_INVALIDDATA;
12140
12141 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12142 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
12143 {
12144 SCIP_Real parentnewbound;
12145 assert(parentvar->data.aggregate.var == var);
12146
12147 if (!set->exact_enable)
12148 {
12149 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
12150 }
12151 else
12152 {
12153 SCIP_INTERVAL parentboundinterval;
12154 SCIPintervalSet(&parentboundinterval, newbound);
12155 SCIPintervalMulScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.scalar);
12156 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.constant);
12157 parentnewbound = parentvar->data.aggregate.scalar > 0 ? parentboundinterval.inf : parentboundinterval.sup;
12158 }
12159
12160 if( parentvar->data.aggregate.scalar > 0 )
12161 {
12162 /* a > 0 -> change lower bound of y */
12163 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
12164 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
12165 || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
12166
12167 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12168 {
12169 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
12170 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
12171 * as a result, the parent's lower bound is set to it's upper bound, and not above
12172 */
12173 if( parentnewbound > parentvar->glbdom.ub )
12174 {
12175 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12176 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
12177 parentnewbound = parentvar->glbdom.ub;
12178 }
12179 }
12180 else
12181 parentnewbound = newbound;
12182 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12183 }
12184 else
12185 {
12186 /* a < 0 -> change upper bound of y */
12188 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
12189 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
12190 || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
12191
12192 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12193 {
12194 /* 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
12195 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
12196 * as a result, the parent's upper bound is set to it's lower bound, and not below
12197 */
12198 if( parentnewbound < parentvar->glbdom.lb )
12199 {
12200 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12201 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
12202 parentnewbound = parentvar->glbdom.lb;
12203 }
12204 }
12205 else
12206 parentnewbound = -newbound;
12207 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12208 }
12209 break;
12210 }
12211 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12212 assert(parentvar->negatedvar != NULL);
12214 assert(parentvar->negatedvar->negatedvar == parentvar);
12215 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
12216 parentvar->data.negate.constant - newbound) );
12217 break;
12218
12219 default:
12220 SCIPerrorMessage("unknown variable status\n");
12221 return SCIP_INVALIDDATA;
12222 }
12223 }
12224
12225 return SCIP_OKAY;
12226}
12227
12228/** performs the current change in upper bound, changes all parents accordingly */
12229static
12231 SCIP_VAR* var, /**< problem variable to change */
12232 BMS_BLKMEM* blkmem, /**< block memory */
12233 SCIP_SET* set, /**< global SCIP settings */
12234 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12235 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12236 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12237 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12238 SCIP_Real newbound /**< new bound for variable */
12239 )
12240{
12241 SCIP_VAR* parentvar;
12242 SCIP_Real oldbound;
12243 int i;
12244
12245 assert(var != NULL);
12246 assert(set != NULL);
12247 assert(var->scip == set->scip);
12248 assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
12249 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
12250 || (SCIPvarIsIntegral(var) && (SCIPsetIsIntegral(set, newbound)
12251 || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
12252 || !SCIPvarIsIntegral(var));
12253
12254 /* check that the bound is feasible */
12255 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
12256 /* adjust bound to integral value if variable is of integral type */
12257 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
12258
12260 {
12261 /* we do not want to undercut the lower bound, which could have happened due to numerics */
12262 newbound = MAX(newbound, var->locdom.lb);
12263
12264 /* we do not want to exceed the global upper bound, which could have happened due to numerics */
12265 newbound = MIN(newbound, var->glbdom.ub);
12266 }
12268
12269 SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
12270
12271 if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
12272 newbound = var->glbdom.ub;
12273 else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
12274 return SCIP_OKAY;
12275
12276 /* change the bound */
12277 oldbound = var->locdom.ub;
12278 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
12279 var->locdom.ub = newbound;
12280 /* adjust the exact bound as well */
12281 if( set->exact_enable )
12282 {
12283 SCIPrationalSetReal(var->exactdata->locdom.ub, var->locdom.ub);
12284 SCIPrationalMin(var->exactdata->locdom.ub, var->exactdata->locdom.ub, var->exactdata->glbdom.ub);
12285 }
12286
12287 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12288 * once update the statistic
12289 */
12290 if( stat != NULL )
12291 SCIPstatIncrement(stat, set, domchgcount);
12292
12294 {
12295 /* merges overlapping holes into single holes, moves bounds respectively */
12296 domMerge(&var->locdom, blkmem, set, NULL, &newbound);
12297 }
12298
12301
12302 /* issue bound change event */
12303 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12304 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12305 {
12306 SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
12307 }
12308
12309 /* process parent variables */
12310 for( i = 0; i < var->nparentvars; ++i )
12311 {
12312 parentvar = var->parentvars[i];
12313 assert(parentvar != NULL);
12314
12315 switch( SCIPvarGetStatus(parentvar) )
12316 {
12318 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
12319 break;
12320
12325 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12326 return SCIP_INVALIDDATA;
12327
12328 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12329 /* this change does not affect the behavior in floating-point SCIP although it looks like it at first glance */
12330 {
12331 SCIP_Real parentnewbound;
12332 assert(parentvar->data.aggregate.var == var);
12333
12334 if( !set->exact_enable )
12335 {
12336 parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
12337 }
12338 else
12339 {
12340 SCIP_INTERVAL parentboundinterval;
12341 SCIPintervalSet(&parentboundinterval, newbound);
12342 SCIPintervalMulScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.scalar);
12343 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &parentboundinterval, parentboundinterval, parentvar->data.aggregate.constant);
12344 parentnewbound = parentvar->data.aggregate.scalar > 0 ? parentboundinterval.sup : parentboundinterval.inf;
12345 }
12346 if( parentvar->data.aggregate.scalar > 0 )
12347 {
12348 /* a > 0 -> change upper bound of x */
12349 assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
12350 || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
12351 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
12352 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12353 {
12354 /* 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
12355 * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
12356 * as a result, the parent's upper bound is set to it's lower bound, and not below
12357 */
12358 if( parentnewbound < parentvar->glbdom.lb )
12359 {
12360 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12361 assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
12362 parentnewbound = parentvar->glbdom.lb;
12363 }
12364 }
12365 else
12366 parentnewbound = newbound;
12367 SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12368 }
12369 else
12370 {
12371 /* a < 0 -> change lower bound of x */
12373 assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
12374 || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
12375 oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
12376 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12377 {
12378 /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
12379 * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
12380 * as a result, the parent's lower bound is set to it's upper bound, and not above
12381 */
12382 if( parentnewbound > parentvar->glbdom.ub )
12383 {
12384 /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
12385 assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
12386 parentnewbound = parentvar->glbdom.ub;
12387 }
12388 }
12389 else
12390 parentnewbound = -newbound;
12391 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
12392 }
12393 break;
12394 }
12395
12396 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12397 assert(parentvar->negatedvar != NULL);
12399 assert(parentvar->negatedvar->negatedvar == parentvar);
12400 SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
12401 parentvar->data.negate.constant - newbound) );
12402 break;
12403
12404 default:
12405 SCIPerrorMessage("unknown variable status\n");
12406 return SCIP_INVALIDDATA;
12407 }
12408 }
12409
12410 return SCIP_OKAY;
12411}
12412
12413/* forward declaration, because both methods call each other recursively */
12414
12415/* performs the current change in upper bound, changes all parents accordingly */
12416static
12418 SCIP_VAR* var, /**< problem variable to change */
12419 BMS_BLKMEM* blkmem, /**< block memory */
12420 SCIP_SET* set, /**< global SCIP settings */
12421 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12422 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12423 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12424 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12425 SCIP_RATIONAL* newbound /**< new bound for variable */
12426 );
12427
12428/** performs the current change in lower bound, changes all parents accordingly */
12429static
12431 SCIP_VAR* var, /**< problem variable to change */
12432 BMS_BLKMEM* blkmem, /**< block memory */
12433 SCIP_SET* set, /**< global SCIP settings */
12434 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12435 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12436 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12437 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12438 SCIP_RATIONAL* newbound /**< new bound for variable */
12439 )
12440{
12441 SCIP_VAR* parentvar;
12442 SCIP_RATIONAL* oldbound;
12443 SCIP_RATIONAL* parentnewbound;
12444 int i;
12445
12446 assert(var != NULL);
12447 assert(set != NULL);
12448 assert(var->scip == set->scip);
12450 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12452 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12453 || !SCIPvarIsIntegral(var));
12454
12455 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
12456
12457 /* check that the bound is feasible */
12458 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->glbdom.ub));
12459 /* adjust bound to integral value if variable is of integral type */
12461
12463 {
12464 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12465 SCIPrationalMin(newbound, newbound, var->exactdata->locdom.ub);
12466
12467 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12468 SCIPrationalMax(newbound, newbound, var->exactdata->glbdom.lb);
12469 }
12471
12472 SCIPrationalDebugMessage("process changing lower bound of <%s> from %q to %q\n", var->name, var->exactdata->locdom.lb, newbound);
12473
12474 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.lb) && !SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb) ) /*lint !e777*/
12475 SCIPrationalSetRational(newbound, var->exactdata->glbdom.lb);
12476
12477 /* change the bound */
12478 SCIPrationalSetRational(oldbound, var->exactdata->locdom.lb);
12479 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsLE(newbound, var->exactdata->locdom.ub));
12480 SCIPrationalSetRational(var->exactdata->locdom.lb, newbound);
12481 var->locdom.lb = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_DOWNWARDS);
12482
12483 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12484 * once update the statistic
12485 */
12486 if( stat != NULL )
12487 SCIPstatIncrement(stat, set, domchgcount);
12488
12489 /* issue bound change event */
12490 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12491 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12492 {
12493 SCIP_CALL( varEventLbChangedExact(var, blkmem, set, lpexact, branchcand, eventqueue, oldbound, newbound) );
12494 }
12495
12496 /* process parent variables */
12497 for( i = 0; i < var->nparentvars; ++i )
12498 {
12499 parentvar = var->parentvars[i];
12500 assert(parentvar != NULL);
12501
12502 switch( SCIPvarGetStatus(parentvar) )
12503 {
12505 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, newbound) );
12506 break;
12507
12512 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12513 return SCIP_INVALIDDATA;
12514
12515 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12516 assert(parentvar->data.aggregate.var == var);
12517 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12519 {
12520 /* a > 0 -> change lower bound of y */
12521 if( !SCIPrationalIsAbsInfinity(newbound) )
12522 {
12523 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12524 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12525 }
12526 else
12527 SCIPrationalSetRational(parentnewbound, newbound);
12528
12529 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12530 }
12531 else
12532 {
12533 /* a < 0 -> change upper bound of y */
12534 if( !SCIPrationalIsAbsInfinity(newbound) )
12535 {
12536 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12537 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12538 }
12539 else
12540 SCIPrationalNegate(parentnewbound, newbound);
12541
12542 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12543 }
12544 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12545 break;
12546
12547 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12548 assert(parentvar->negatedvar != NULL);
12550 assert(parentvar->negatedvar->negatedvar == parentvar);
12551 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12552 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
12553 SCIPrationalNegate(parentnewbound, parentnewbound);
12554 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue,
12555 parentnewbound) );
12556 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12557 break;
12558
12559 default:
12560 SCIPerrorMessage("unknown variable status\n");
12561 return SCIP_INVALIDDATA;
12562 }
12563 }
12564
12565 SCIPrationalFreeBuffer(set->buffer, &oldbound);
12566
12567 return SCIP_OKAY;
12568}
12569
12570/** performs the current change in upper bound, changes all parents accordingly */
12571static
12573 SCIP_VAR* var, /**< problem variable to change */
12574 BMS_BLKMEM* blkmem, /**< block memory */
12575 SCIP_SET* set, /**< global SCIP settings */
12576 SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
12577 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12578 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12579 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12580 SCIP_RATIONAL* newbound /**< new bound for variable */
12581 )
12582{
12583 SCIP_VAR* parentvar;
12584 SCIP_RATIONAL* oldbound;
12585 SCIP_RATIONAL* parentnewbound;
12586 int i;
12587
12588 assert(var != NULL);
12589 assert(set != NULL);
12590 assert(var->scip == set->scip);
12592 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12594 || SCIPrationalIsEQ(newbound, var->exactdata->locdom.ub)))
12595 || !SCIPvarIsIntegral(var));
12596
12597 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &oldbound) );
12598
12599 /* check that the bound is feasible */
12600 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->glbdom.lb));
12601 /* adjust bound to integral value if variable is of integral type */
12603
12605 {
12606 /* we do not want to exceed the upper bound, which could have happened due to numerics */
12607 SCIPrationalMax(newbound, newbound, var->exactdata->locdom.lb);
12608
12609 /* we do not want to undercut the global lower bound, which could have happened due to numerics */
12610 SCIPrationalMin(newbound, newbound, var->exactdata->glbdom.ub);
12611 }
12613
12614 SCIPrationalDebugMessage("process changing exact upper bound of <%s> from %q to %q\n", var->name, var->exactdata->locdom.ub, newbound);
12615
12616 if( SCIPrationalIsEQ(newbound, var->exactdata->glbdom.ub) && !SCIPrationalIsEQ(var->exactdata->glbdom.ub, var->exactdata->locdom.ub) ) /*lint !e777*/
12617 SCIPrationalSetRational(newbound, var->exactdata->glbdom.ub);
12618
12619 /* change the bound */
12620 SCIPrationalSetRational(oldbound, var->exactdata->locdom.ub);
12621 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPrationalIsGE(newbound, var->exactdata->locdom.lb));
12622 SCIPrationalSetRational(var->exactdata->locdom.ub, newbound);
12623 var->locdom.ub = SCIPrationalRoundReal(newbound, SCIP_R_ROUND_UPWARDS);
12624
12625 /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
12626 * once update the statistic
12627 */
12628 if( stat != NULL )
12629 SCIPstatIncrement(stat, set, domchgcount);
12630
12631 /* issue bound change event */
12632 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
12633 if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && var->eventfilter != NULL )
12634 {
12635 SCIP_CALL( varEventUbChangedExact(var, blkmem, set, lpexact, branchcand, eventqueue, oldbound, newbound) );
12636 }
12637
12638 /* process parent variables */
12639 for( i = 0; i < var->nparentvars; ++i )
12640 {
12641 parentvar = var->parentvars[i];
12642 assert(parentvar != NULL);
12643
12644 switch( SCIPvarGetStatus(parentvar) )
12645 {
12647 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, newbound) );
12648 break;
12649
12654 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12655 return SCIP_INVALIDDATA;
12656
12657 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12658 assert(parentvar->data.aggregate.var == var);
12659 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12661 {
12662 /* a > 0 -> change upper bound of y */
12663 if( !SCIPrationalIsAbsInfinity(newbound) )
12664 {
12665 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12666 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12667 }
12668 else
12669 SCIPrationalSetRational(parentnewbound, newbound);
12670
12671 SCIP_CALL( varProcessChgUbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12672 }
12673 else
12674 {
12675 /* a < 0 -> change lower bound of y */
12676 if( !SCIPrationalIsAbsInfinity(newbound) )
12677 {
12678 SCIPrationalMult(parentnewbound, parentvar->exactdata->aggregate.scalar, newbound);
12679 SCIPrationalAdd(parentnewbound, parentnewbound, parentvar->exactdata->aggregate.constant);
12680 }
12681 else
12682 SCIPrationalNegate(parentnewbound, newbound);
12683
12684 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue, parentnewbound) );
12685 }
12686 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12687 break;
12688
12689 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
12690 assert(parentvar->negatedvar != NULL);
12692 assert(parentvar->negatedvar->negatedvar == parentvar);
12693 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &parentnewbound) );
12694 SCIPrationalDiffReal(parentnewbound, newbound, parentvar->data.negate.constant);
12695 SCIPrationalNegate(parentnewbound, parentnewbound);
12696 SCIP_CALL( varProcessChgLbLocalExact(parentvar, blkmem, set, NULL, lpexact, branchcand, eventqueue,
12697 parentnewbound) );
12698 SCIPrationalFreeBuffer(set->buffer, &parentnewbound);
12699 break;
12700
12701 default:
12702 SCIPerrorMessage("unknown variable status\n");
12703 return SCIP_INVALIDDATA;
12704 }
12705 }
12706
12707 SCIPrationalFreeBuffer(set->buffer, &oldbound);
12708
12709 return SCIP_OKAY;
12710}
12711
12712/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
12713 * information in variable
12714 */
12716 SCIP_VAR* var, /**< problem variable to change */
12717 BMS_BLKMEM* blkmem, /**< block memory */
12718 SCIP_SET* set, /**< global SCIP settings */
12719 SCIP_STAT* stat, /**< problem statistics */
12720 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12721 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12722 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12723 SCIP_Real newbound /**< new bound for variable */
12724 )
12725{
12726 assert(var != NULL);
12727 assert(blkmem != NULL);
12728 assert(set != NULL);
12729 assert(var->scip == set->scip);
12730
12731 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
12732 * of the domain within feastol
12733 */
12734 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
12735
12736 /* adjust bound to integral value if variable is of integral type */
12737 newbound = adjustedLb(set, SCIPvarIsIntegral(var), newbound);
12738
12739 /* check that the adjusted bound is feasible */
12740 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
12741
12743 {
12744 /* we do not want to exceed the upperbound, which could have happened due to numerics */
12745 newbound = MIN(newbound, var->locdom.ub);
12746 }
12748
12749 SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
12750
12751 if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
12752 && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
12753 return SCIP_OKAY;
12754
12757
12758 /* change bounds of attached variables */
12759 switch( SCIPvarGetStatus(var) )
12760 {
12762 if( var->data.original.transvar != NULL )
12763 {
12764 SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
12765 newbound) );
12766 }
12767 else
12768 {
12769 assert(set->stage == SCIP_STAGE_PROBLEM);
12770 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
12771 }
12772 break;
12773
12776 SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
12777 break;
12778
12780 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
12781 return SCIP_INVALIDDATA;
12782
12783 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12784 {
12785 SCIP_Real childnewbound;
12786 assert(var->data.aggregate.var != NULL);
12787
12788 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
12789 {
12790 /* a > 0 -> change lower bound of y */
12791 assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
12792 || SCIPsetIsFeasEQ(set, var->locdom.lb,
12793 var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
12794 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12795 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
12796 else
12797 childnewbound = newbound;
12798 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
12799 childnewbound) );
12800 }
12801 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
12802 {
12803 /* a < 0 -> change upper bound of y */
12804 assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
12805 || SCIPsetIsFeasEQ(set, var->locdom.lb,
12806 var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
12807 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
12808 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
12809 else
12810 childnewbound = -newbound;
12811 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
12812 childnewbound) );
12813 }
12814 else
12815 {
12816 SCIPerrorMessage("scalar is zero in aggregation\n");
12817 return SCIP_INVALIDDATA;
12818 }
12819 break;
12820 }
12821
12823 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
12824 return SCIP_INVALIDDATA;
12825
12826 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12827 assert(var->negatedvar != NULL);
12829 assert(var->negatedvar->negatedvar == var);
12830 SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
12831 var->data.negate.constant - newbound) );
12832 break;
12833
12834 default:
12835 SCIPerrorMessage("unknown variable status\n");
12836 return SCIP_INVALIDDATA;
12837 }
12838
12839 return SCIP_OKAY;
12840}
12841
12842/** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
12843 * information in variable
12844 */
12846 SCIP_VAR* var, /**< problem variable to change */
12847 BMS_BLKMEM* blkmem, /**< block memory */
12848 SCIP_SET* set, /**< global SCIP settings */
12849 SCIP_STAT* stat, /**< problem statistics */
12850 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
12851 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12852 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12853 SCIP_RATIONAL* newbound /**< new bound for variable */
12854 )
12855{
12856 assert(var != NULL);
12857 assert(blkmem != NULL);
12858 assert(set != NULL);
12859 assert(var->scip == set->scip);
12860
12861 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
12862 * of the domain within feastol
12863 */
12864 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->locdom.ub));
12865
12866 /* adjust bound to integral value if variable is of integral type */
12868
12869 /* check that the adjusted bound is feasible */
12870 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsGT(newbound, var->exactdata->locdom.ub));
12871
12873 {
12874 /* we do not want to exceed the upperbound, which could have happened due to numerics */
12875 SCIPrationalMin(newbound, newbound, var->exactdata->locdom.ub);
12876 }
12878
12879 SCIPrationalDebugMessage("changing lower bound of <%s>[%q,%q] to %q\n", var->name, var->exactdata->locdom.lb, var->exactdata->locdom.ub, newbound);
12880
12883
12884 /* change bounds of attached variables */
12885 switch( SCIPvarGetStatusExact(var) )
12886 {
12888 if( var->data.original.transvar != NULL )
12889 {
12890 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
12891 newbound) );
12892 }
12893 else
12894 {
12895 assert(set->stage == SCIP_STAGE_PROBLEM);
12896 SCIP_CALL( varProcessChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
12897 }
12898 break;
12899
12902 SCIP_CALL( varProcessChgLbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
12903 break;
12904
12906 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
12907 return SCIP_INVALIDDATA;
12908
12909 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12910 assert(var->data.aggregate.var != NULL);
12911 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
12912 {
12913 SCIP_RATIONAL* childnewbound;
12914
12915 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
12916
12917 /* a > 0 -> change lower bound of y */
12918 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
12919 {
12920 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
12921 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
12922 }
12923 else
12924 SCIPrationalSetRational(childnewbound, newbound);
12925
12926 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
12927 childnewbound) );
12928
12929 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
12930 }
12931 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
12932 {
12933 SCIP_RATIONAL* childnewbound;
12934
12935 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
12936
12937 /* a < 0 -> change upper bound of y */
12938 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
12939 {
12940 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
12941 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
12942 }
12943 else
12944 SCIPrationalNegate(childnewbound, newbound);
12945
12946 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
12947 childnewbound) );
12948
12949 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
12950 }
12951 else
12952 {
12953 SCIPerrorMessage("scalar is zero in aggregation\n");
12954 return SCIP_INVALIDDATA;
12955 }
12956 break;
12957
12959 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
12960 return SCIP_INVALIDDATA;
12961
12962 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12963 assert(var->negatedvar != NULL);
12965 assert(var->negatedvar->negatedvar == var);
12966 SCIPrationalDiffReal(newbound, newbound, var->data.negate.constant);
12967 SCIPrationalNegate(newbound, newbound);
12968 SCIP_CALL( SCIPvarChgUbLocalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
12969 newbound) );
12970 break;
12971
12972 default:
12973 SCIPerrorMessage("unknown variable status\n");
12974 return SCIP_INVALIDDATA;
12975 }
12976
12977 return SCIP_OKAY;
12978}
12979
12980/** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
12981 * information in variable
12982 */
12984 SCIP_VAR* var, /**< problem variable to change */
12985 BMS_BLKMEM* blkmem, /**< block memory */
12986 SCIP_SET* set, /**< global SCIP settings */
12987 SCIP_STAT* stat, /**< problem statistics */
12988 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
12989 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
12990 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
12991 SCIP_Real newbound /**< new bound for variable */
12992 )
12993{
12994 assert(var != NULL);
12995 assert(blkmem != NULL);
12996 assert(set != NULL);
12997 assert(var->scip == set->scip);
12998
12999 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
13000 * of the domain within feastol
13001 */
13002 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
13003
13004 /* adjust bound to integral value if variable is of integral type */
13005 newbound = adjustedUb(set, SCIPvarIsIntegral(var), newbound);
13006
13007 /* check that the adjusted bound is feasible */
13008 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
13009
13011 {
13012 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
13013 newbound = MAX(newbound, var->locdom.lb);
13014 }
13016
13017 SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
13018
13019 if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
13020 && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
13021 return SCIP_OKAY;
13022
13025
13026 /* change bounds of attached variables */
13027 switch( SCIPvarGetStatus(var) )
13028 {
13030 if( var->data.original.transvar != NULL )
13031 {
13032 SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13033 }
13034 else
13035 {
13036 assert(set->stage == SCIP_STAGE_PROBLEM);
13037 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13038 }
13039 break;
13040
13043 SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
13044 break;
13045
13047 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13048 return SCIP_INVALIDDATA;
13049
13050 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13051 {
13052 SCIP_Real childnewbound;
13053 assert(var->data.aggregate.var != NULL);
13054
13055 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13056 {
13057 /* a > 0 -> change upper bound of y */
13058 assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
13059 || SCIPsetIsFeasEQ(set, var->locdom.ub,
13060 var->data.aggregate.var->locdom.ub * var->data.aggregate.scalar + var->data.aggregate.constant));
13061 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13062 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13063 else
13064 childnewbound = newbound;
13065 SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
13066 childnewbound) );
13067 }
13068 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13069 {
13070 /* a < 0 -> change lower bound of y */
13071 assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
13072 || SCIPsetIsFeasEQ(set, var->locdom.ub,
13073 var->data.aggregate.var->locdom.lb * var->data.aggregate.scalar + var->data.aggregate.constant));
13074 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13075 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13076 else
13077 childnewbound = -newbound;
13078 SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
13079 childnewbound) );
13080 }
13081 else
13082 {
13083 SCIPerrorMessage("scalar is zero in aggregation\n");
13084 return SCIP_INVALIDDATA;
13085 }
13086 break;
13087 }
13088
13090 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13091 return SCIP_INVALIDDATA;
13092
13093 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13094 assert(var->negatedvar != NULL);
13096 assert(var->negatedvar->negatedvar == var);
13097 SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
13098 var->data.negate.constant - newbound) );
13099 break;
13100
13101 default:
13102 SCIPerrorMessage("unknown variable status\n");
13103 return SCIP_INVALIDDATA;
13104 }
13105
13106 return SCIP_OKAY;
13107}
13108
13109/** changes current exact local upper bound of variable; if possible, adjusts bound to integral value; stores inference
13110 * information in variable
13111 */
13113 SCIP_VAR* var, /**< problem variable to change */
13114 BMS_BLKMEM* blkmem, /**< block memory */
13115 SCIP_SET* set, /**< global SCIP settings */
13116 SCIP_STAT* stat, /**< problem statistics */
13117 SCIP_LPEXACT* lpexact, /**< current exact LP data, may be NULL for original variables */
13118 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
13119 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
13120 SCIP_RATIONAL* newbound /**< new bound for variable */
13121 )
13122{
13123 assert(var != NULL);
13124 assert(blkmem != NULL);
13125 assert(set != NULL);
13126 assert(var->scip == set->scip);
13127
13128 /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
13129 * of the domain within feastol
13130 */
13131 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->locdom.lb));
13132
13133 /* adjust bound to integral value if variable is of integral type */
13135
13136 /* check that the adjusted bound is feasible */
13137 assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPrationalIsLT(newbound, var->exactdata->locdom.lb));
13138
13140 {
13141 /* we do not want to undercut the lowerbound, which could have happened due to numerics */
13142 SCIPrationalMax(newbound, newbound, var->exactdata->locdom.lb);
13143 }
13145
13146 SCIPrationalDebugMessage("changing upper bound of <%s>[%q,%q] to %q\n", var->name, var->exactdata->locdom.lb, var->exactdata->locdom.ub, newbound);
13147
13150
13151 /* change bounds of attached variables */
13152 switch( SCIPvarGetStatusExact(var) )
13153 {
13155 if( var->data.original.transvar != NULL )
13156 {
13157 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.original.transvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
13158 newbound) );
13159 }
13160 else
13161 {
13162 assert(set->stage == SCIP_STAGE_PROBLEM);
13163 SCIP_CALL( varProcessChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
13164 }
13165 break;
13166
13169 SCIP_CALL( varProcessChgUbLocalExact(var, blkmem, set, stat, lpexact, branchcand, eventqueue, newbound) );
13170 break;
13171
13173 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13174 return SCIP_INVALIDDATA;
13175
13176 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13177 assert(var->data.aggregate.var != NULL);
13178 if( SCIPrationalIsPositive(var->exactdata->aggregate.scalar) )
13179 {
13180 SCIP_RATIONAL* childnewbound;
13181
13182 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
13183
13184 /* a > 0 -> change upper bound of y */
13185 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
13186 {
13187 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
13188 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
13189 }
13190 else
13191 SCIPrationalSetRational(childnewbound, newbound);
13192 SCIP_CALL( SCIPvarChgUbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
13193 childnewbound) );
13194
13195 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
13196 }
13197 else if( SCIPrationalIsNegative(var->exactdata->aggregate.scalar) )
13198 {
13199 SCIP_RATIONAL* childnewbound;
13200
13201 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &childnewbound) );
13202
13203 /* a < 0 -> change lower bound of y */
13204 if( !SCIPrationalIsNegInfinity(newbound) && !SCIPrationalIsInfinity(newbound) )
13205 {
13206 SCIPrationalDiff(childnewbound, newbound, var->exactdata->aggregate.constant);
13207 SCIPrationalDiv(childnewbound, childnewbound, var->exactdata->aggregate.scalar);
13208 }
13209 else
13210 SCIPrationalNegate(childnewbound, newbound);
13211
13212 SCIP_CALL( SCIPvarChgLbLocalExact(var->data.aggregate.var, blkmem, set, stat, lpexact, branchcand, eventqueue,
13213 childnewbound) );
13214
13215 SCIPrationalFreeBuffer(set->buffer, &childnewbound);
13216 }
13217 else
13218 {
13219 SCIPerrorMessage("scalar is zero in aggregation\n");
13220 return SCIP_INVALIDDATA;
13221 }
13222 break;
13223
13225 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13226 return SCIP_INVALIDDATA;
13227
13228 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13229 assert(var->negatedvar != NULL);
13231 assert(var->negatedvar->negatedvar == var);
13232 SCIPrationalDiffReal(newbound, newbound, var->data.negate.constant);
13233 SCIPrationalNegate(newbound, newbound);
13234 SCIP_CALL( SCIPvarChgLbLocalExact(var->negatedvar, blkmem, set, stat, lpexact, branchcand, eventqueue,
13235 newbound) );
13236 break;
13237
13238 default:
13239 SCIPerrorMessage("unknown variable status\n");
13240 return SCIP_INVALIDDATA;
13241 }
13242
13243 return SCIP_OKAY;
13244}
13245
13246/** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
13247 * information in variable
13248 */
13250 SCIP_VAR* var, /**< problem variable to change */
13251 BMS_BLKMEM* blkmem, /**< block memory */
13252 SCIP_SET* set, /**< global SCIP settings */
13253 SCIP_STAT* stat, /**< problem statistics */
13254 SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
13255 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
13256 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
13257 SCIP_Real newbound, /**< new bound for variable */
13258 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13259 )
13260{
13261 /* apply bound change to the LP data */
13262 switch( boundtype )
13263 {
13265 return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
13267 return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
13268 default:
13269 SCIPerrorMessage("unknown bound type\n");
13270 return SCIP_INVALIDDATA;
13271 }
13272}
13273
13274/** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
13276 SCIP_VAR* var, /**< problem variable to change */
13277 SCIP_SET* set, /**< global SCIP settings */
13278 SCIP_LP* lp, /**< current LP data */
13279 SCIP_Real newbound /**< new bound for variable */
13280 )
13281{
13282 assert(var != NULL);
13283 assert(set != NULL);
13284 assert(var->scip == set->scip);
13285 assert(lp != NULL);
13286 assert(SCIPlpDiving(lp));
13287
13288 /* adjust bound for integral variables */
13289 SCIPvarAdjustLb(var, set, &newbound);
13290
13291 SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
13292
13293 /* change bounds of attached variables */
13294 switch( SCIPvarGetStatus(var) )
13295 {
13297 assert(var->data.original.transvar != NULL);
13298 SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
13299 break;
13300
13302 assert(var->data.col != NULL);
13303 SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
13304 break;
13305
13307 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13308 return SCIP_INVALIDDATA;
13309
13311 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13312 return SCIP_INVALIDDATA;
13313
13314 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13315 assert(var->data.aggregate.var != NULL);
13316 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13317 {
13318 SCIP_Real childnewbound;
13319
13320 /* a > 0 -> change lower bound of y */
13321 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13322 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13323 else
13324 childnewbound = newbound;
13325 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
13326 }
13327 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13328 {
13329 SCIP_Real childnewbound;
13330
13331 /* a < 0 -> change upper bound of y */
13332 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13333 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13334 else
13335 childnewbound = -newbound;
13336 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
13337 }
13338 else
13339 {
13340 SCIPerrorMessage("scalar is zero in aggregation\n");
13341 return SCIP_INVALIDDATA;
13342 }
13343 break;
13344
13346 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13347 return SCIP_INVALIDDATA;
13348
13349 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13350 assert(var->negatedvar != NULL);
13352 assert(var->negatedvar->negatedvar == var);
13353 SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
13354 break;
13355
13356 default:
13357 SCIPerrorMessage("unknown variable status\n");
13358 return SCIP_INVALIDDATA;
13359 }
13360
13361 return SCIP_OKAY;
13362}
13363
13364/** changes lower bound of variable in current exact dive */
13366 SCIP_VAR* var, /**< problem variable to change */
13367 SCIP_SET* set, /**< global SCIP settings */
13368 SCIP_LPEXACT* lpexact, /**< current exact LP data */
13369 SCIP_RATIONAL* newbound /**< new bound for variable */
13370 )
13371{
13372 assert(var != NULL);
13373 assert(set != NULL);
13374 assert(var->scip == set->scip);
13375 assert(lpexact != NULL);
13376 assert(SCIPlpExactDiving(lpexact));
13377
13378 SCIPrationalDebugMessage("changing lower bound of <%s> to %q in current exact dive\n", var->name, newbound);
13379
13380 /* change bounds of attached variables */
13381 switch( SCIPvarGetStatusExact(var) )
13382 {
13384 assert(var->data.original.transvar != NULL);
13385 SCIP_CALL( SCIPvarChgLbExactDive(var->data.original.transvar, set, lpexact, newbound) );
13386 break;
13387
13389 assert(var->data.col != NULL);
13390 SCIP_CALL( SCIPcolExactChgLb(var->exactdata->colexact, set, lpexact, newbound) );
13391 break;
13392
13394 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13395 return SCIP_INVALIDDATA;
13396
13398 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13399 return SCIP_INVALIDDATA;
13400
13401 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13402 SCIPerrorMessage("cannot change the bounds of an aggregated variable\n");
13403 return SCIP_INVALIDDATA;
13404
13406 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable\n");
13407 return SCIP_INVALIDDATA;
13408
13409 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13410 SCIPerrorMessage("cannot change the bounds of a negated variable\n");
13411 return SCIP_INVALIDDATA;
13412
13413 default:
13414 SCIPerrorMessage("unknown variable status\n");
13415 return SCIP_INVALIDDATA;
13416 }
13417
13418 return SCIP_OKAY;
13419}
13420
13421/** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
13423 SCIP_VAR* var, /**< problem variable to change */
13424 SCIP_SET* set, /**< global SCIP settings */
13425 SCIP_LP* lp, /**< current LP data */
13426 SCIP_Real newbound /**< new bound for variable */
13427 )
13428{
13429 assert(var != NULL);
13430 assert(set != NULL);
13431 assert(var->scip == set->scip);
13432 assert(lp != NULL);
13433 assert(SCIPlpDiving(lp));
13434
13435 /* adjust bound for integral variables */
13436 SCIPvarAdjustUb(var, set, &newbound);
13437
13438 SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
13439
13440 /* change bounds of attached variables */
13441 switch( SCIPvarGetStatus(var) )
13442 {
13444 assert(var->data.original.transvar != NULL);
13445 SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
13446 break;
13447
13449 assert(var->data.col != NULL);
13450 SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
13451 break;
13452
13454 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13455 return SCIP_INVALIDDATA;
13456
13458 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13459 return SCIP_INVALIDDATA;
13460
13461 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13462 assert(var->data.aggregate.var != NULL);
13463 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
13464 {
13465 SCIP_Real childnewbound;
13466
13467 /* a > 0 -> change upper bound of y */
13468 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13469 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13470 else
13471 childnewbound = newbound;
13472 SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
13473 }
13474 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
13475 {
13476 SCIP_Real childnewbound;
13477
13478 /* a < 0 -> change lower bound of y */
13479 if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
13480 childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
13481 else
13482 childnewbound = -newbound;
13483 SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
13484 }
13485 else
13486 {
13487 SCIPerrorMessage("scalar is zero in aggregation\n");
13488 return SCIP_INVALIDDATA;
13489 }
13490 break;
13491
13493 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13494 return SCIP_INVALIDDATA;
13495
13496 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13497 assert(var->negatedvar != NULL);
13499 assert(var->negatedvar->negatedvar == var);
13500 SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
13501 break;
13502
13503 default:
13504 SCIPerrorMessage("unknown variable status\n");
13505 return SCIP_INVALIDDATA;
13506 }
13507
13508 return SCIP_OKAY;
13509}
13510
13511/** changes upper bound of variable in current exact dive */
13513 SCIP_VAR* var, /**< problem variable to change */
13514 SCIP_SET* set, /**< global SCIP settings */
13515 SCIP_LPEXACT* lpexact, /**< current exact LP data */
13516 SCIP_RATIONAL* newbound /**< new bound for variable */
13517 )
13518{
13519 assert(var != NULL);
13520 assert(set != NULL);
13521 assert(var->scip == set->scip);
13522 assert(lpexact != NULL);
13523 assert(SCIPlpExactDiving(lpexact));
13524
13525 SCIPrationalDebugMessage("changing upper bound of <%s> to %d in current dive\n", var->name, newbound);
13526
13527 /* change bounds of attached variables */
13528 switch( SCIPvarGetStatusExact(var) )
13529 {
13531 assert(var->data.original.transvar != NULL);
13532 SCIP_CALL( SCIPvarChgUbExactDive(var->data.original.transvar, set, lpexact, newbound) );
13533 break;
13534
13536 assert(var->data.col != NULL);
13537 SCIP_CALL( SCIPcolExactChgUb(var->exactdata->colexact, set, lpexact, newbound) );
13538 break;
13539
13541 SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
13542 return SCIP_INVALIDDATA;
13543
13545 SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
13546 return SCIP_INVALIDDATA;
13547
13548 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
13549 SCIPerrorMessage("cannot change the bounds of an aggregated variable\n");
13550 return SCIP_INVALIDDATA;
13551
13553 SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
13554 return SCIP_INVALIDDATA;
13555
13556 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13557 SCIPerrorMessage("cannot change the bounds of a negated variable\n");
13558 return SCIP_INVALIDDATA;
13559
13560 default:
13561 SCIPerrorMessage("unknown variable status\n");
13562 return SCIP_INVALIDDATA;
13563 }
13564
13565 return SCIP_OKAY;
13566}
13567
13568/** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
13569 * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
13570 * not updated if bounds of aggregation variables are changing
13571 *
13572 * calling this function for a non-multi-aggregated variable is not allowed
13573 */
13575 SCIP_VAR* var, /**< problem variable */
13576 SCIP_SET* set /**< global SCIP settings */
13577 )
13578{
13579 int i;
13580 SCIP_Real lb;
13581 SCIP_Real bnd;
13582 SCIP_VAR* aggrvar;
13583 SCIP_Bool posinf;
13584 SCIP_Bool neginf;
13585
13586 assert(var != NULL);
13587 assert(set != NULL);
13588 assert(var->scip == set->scip);
13590
13591 posinf = FALSE;
13592 neginf = FALSE;
13593 lb = var->data.multaggr.constant;
13594 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13595 {
13596 aggrvar = var->data.multaggr.vars[i];
13597 if( var->data.multaggr.scalars[i] > 0.0 )
13598 {
13600
13601 if( SCIPsetIsInfinity(set, bnd) )
13602 posinf = TRUE;
13603 else if( SCIPsetIsInfinity(set, -bnd) )
13604 neginf = TRUE;
13605 else
13606 lb += var->data.multaggr.scalars[i] * bnd;
13607 }
13608 else
13609 {
13611
13612 if( SCIPsetIsInfinity(set, -bnd) )
13613 posinf = TRUE;
13614 else if( SCIPsetIsInfinity(set, bnd) )
13615 neginf = TRUE;
13616 else
13617 lb += var->data.multaggr.scalars[i] * bnd;
13618 }
13619
13620 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13621 * variable
13622 */
13623 if( neginf )
13624 return SCIPvarGetLbLocal(var);
13625 }
13626
13627 /* if positive infinity flag was set to true return infinity */
13628 if( posinf )
13629 return SCIPsetInfinity(set);
13630
13631 return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
13632}
13633
13634/** for a multi-aggregated variable, gives the exact local lower bound computed by adding the local bounds from all aggregation variables
13635 * this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is not updated if bounds of aggregation variables are changing
13636 * calling this function for a non-multi-aggregated variable is not allowed
13637 */
13639 SCIP_VAR* var, /**< problem variable */
13640 SCIP_SET* set, /**< global SCIP settings */
13641 SCIP_RATIONAL* result /**< the resulting bound */
13642 )
13643{
13644 int i;
13645 SCIP_RATIONAL* lb;
13646 SCIP_RATIONAL* bnd;
13647 SCIP_VAR* aggrvar;
13648 SCIP_Bool posinf;
13649 SCIP_Bool neginf;
13650
13651 assert(var != NULL);
13652 assert(set != NULL);
13653 assert(var->scip == set->scip);
13655
13656 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lb) );
13657 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &bnd) );
13658
13659 posinf = FALSE;
13660 neginf = FALSE;
13661 SCIPrationalSetRational(lb, var->exactdata->multaggr.constant);
13662 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13663 {
13664 aggrvar = var->data.multaggr.vars[i];
13665 if( SCIPrationalIsPositive(var->exactdata->multaggr.scalars[i]) )
13666 {
13669 else
13671
13672 if( SCIPrationalIsInfinity(bnd) )
13673 posinf = TRUE;
13674 else if( SCIPrationalIsNegInfinity(bnd) )
13675 neginf = TRUE;
13676 else
13677 SCIPrationalAddProd(lb, var->exactdata->multaggr.scalars[i], bnd);
13678 }
13679 else
13680 {
13683 else
13685
13686 if( SCIPrationalIsNegInfinity(bnd) )
13687 posinf = TRUE;
13688 else if( SCIPrationalIsInfinity(bnd) )
13689 neginf = TRUE;
13690 else
13691 SCIPrationalAddProd(lb, var->exactdata->multaggr.scalars[i], bnd);
13692 }
13693
13694 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13695 * variable
13696 */
13697 if( neginf )
13698 {
13700 break;
13701 }
13702 }
13703
13704 /* if positive infinity flag was set to true return infinity */
13705 if( posinf && !neginf )
13707 else
13709
13710 SCIPrationalFreeBuffer(set->buffer, &bnd);
13711 SCIPrationalFreeBuffer(set->buffer, &lb);
13712
13713 return SCIP_OKAY;
13714}
13715
13716/** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
13717 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
13718 * not updated if bounds of aggregation variables are changing
13719 *
13720 * calling this function for a non-multi-aggregated variable is not allowed
13721 */
13723 SCIP_VAR* var, /**< problem variable */
13724 SCIP_SET* set /**< global SCIP settings */
13725 )
13726{
13727 int i;
13728 SCIP_Real ub;
13729 SCIP_Real bnd;
13730 SCIP_VAR* aggrvar;
13731 SCIP_Bool posinf;
13732 SCIP_Bool neginf;
13733
13734 assert(var != NULL);
13735 assert(set != NULL);
13736 assert(var->scip == set->scip);
13738
13739 posinf = FALSE;
13740 neginf = FALSE;
13741 ub = var->data.multaggr.constant;
13742 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13743 {
13744 aggrvar = var->data.multaggr.vars[i];
13745 if( var->data.multaggr.scalars[i] > 0.0 )
13746 {
13748
13749 if( SCIPsetIsInfinity(set, bnd) )
13750 posinf = TRUE;
13751 else if( SCIPsetIsInfinity(set, -bnd) )
13752 neginf = TRUE;
13753 else
13754 ub += var->data.multaggr.scalars[i] * bnd;
13755 }
13756 else
13757 {
13759
13760 if( SCIPsetIsInfinity(set, -bnd) )
13761 posinf = TRUE;
13762 else if( SCIPsetIsInfinity(set, bnd) )
13763 neginf = TRUE;
13764 else
13765 ub += var->data.multaggr.scalars[i] * bnd;
13766 }
13767
13768 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
13769 * variable
13770 */
13771 if( posinf )
13772 return SCIPvarGetUbLocal(var);
13773 }
13774
13775 /* if negative infinity flag was set to true return -infinity */
13776 if( neginf )
13777 return -SCIPsetInfinity(set);
13778
13779 return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
13780}
13781
13782/** for a multi-aggregated variable, gives the exact local upper bound computed by adding the local bounds from all aggregation variables
13783 * 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
13784 * calling this function for a non-multi-aggregated variable is not allowed
13785 */
13787 SCIP_VAR* var, /**< problem variable */
13788 SCIP_SET* set, /**< global SCIP settings */
13789 SCIP_RATIONAL* result /**< the resulting bound */
13790 )
13791{
13792 int i;
13793 SCIP_RATIONAL* ub;
13794 SCIP_RATIONAL* bnd;
13795 SCIP_VAR* aggrvar;
13796 SCIP_Bool posinf;
13797 SCIP_Bool neginf;
13798
13799 assert(var != NULL);
13800 assert(set != NULL);
13801 assert(var->scip == set->scip);
13803
13804 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &ub) );
13805 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &bnd) );
13806
13807 posinf = FALSE;
13808 neginf = FALSE;
13809 SCIPrationalSetRational(ub, var->exactdata->multaggr.constant);
13810 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13811 {
13812 aggrvar = var->data.multaggr.vars[i];
13813 if( SCIPrationalIsPositive(var->exactdata->multaggr.scalars[i]) )
13814 {
13817 else
13819
13820 if( SCIPrationalIsInfinity(bnd) )
13821 posinf = TRUE;
13822 else if( SCIPrationalIsNegInfinity(bnd) )
13823 neginf = TRUE;
13824 else
13825 SCIPrationalAddProd(ub, var->exactdata->multaggr.scalars[i], bnd);
13826 }
13827 else
13828 {
13831 else
13833
13834 if( SCIPrationalIsNegInfinity(bnd) )
13835 posinf = TRUE;
13836 else if( SCIPrationalIsInfinity(bnd) )
13837 neginf = TRUE;
13838 else
13839 SCIPrationalAddProd(ub, var->exactdata->multaggr.scalars[i], bnd);
13840 }
13841
13842 /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
13843 * variable
13844 */
13845 if( posinf )
13846 {
13848 break;
13849 }
13850 }
13851
13852 /* if positive infinity flag was set to true return infinity */
13853 if( !posinf && neginf )
13855 else
13857
13858 SCIPrationalFreeBuffer(set->buffer, &bnd);
13859 SCIPrationalFreeBuffer(set->buffer, &ub);
13860
13861 return SCIP_OKAY;
13862}
13863
13864/** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
13865 * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
13866 * not updated if bounds of aggregation variables are changing
13867 *
13868 * calling this function for a non-multi-aggregated variable is not allowed
13869 */
13871 SCIP_VAR* var, /**< problem variable */
13872 SCIP_SET* set /**< global SCIP settings */
13873 )
13874{
13875 int i;
13876 SCIP_Real lb;
13877 SCIP_Real bnd;
13878 SCIP_VAR* aggrvar;
13879 SCIP_Bool posinf;
13880 SCIP_Bool neginf;
13881
13882 assert(var != NULL);
13883 assert(set != NULL);
13884 assert(var->scip == set->scip);
13886
13887 posinf = FALSE;
13888 neginf = FALSE;
13889 lb = var->data.multaggr.constant;
13890 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13891 {
13892 aggrvar = var->data.multaggr.vars[i];
13893 if( var->data.multaggr.scalars[i] > 0.0 )
13894 {
13896
13897 if( SCIPsetIsInfinity(set, bnd) )
13898 posinf = TRUE;
13899 else if( SCIPsetIsInfinity(set, -bnd) )
13900 neginf = TRUE;
13901 else
13902 lb += var->data.multaggr.scalars[i] * bnd;
13903 }
13904 else
13905 {
13907
13908 if( SCIPsetIsInfinity(set, -bnd) )
13909 posinf = TRUE;
13910 else if( SCIPsetIsInfinity(set, bnd) )
13911 neginf = TRUE;
13912 else
13913 lb += var->data.multaggr.scalars[i] * bnd;
13914 }
13915
13916 /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
13917 * variable
13918 */
13919 if( neginf )
13920 return SCIPvarGetLbGlobal(var);
13921 }
13922
13923 /* if positive infinity flag was set to true return infinity */
13924 if( posinf )
13925 return SCIPsetInfinity(set);
13926
13927 return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
13928}
13929
13930/** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
13931 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
13932 * not updated if bounds of aggregation variables are changing
13933 *
13934 * calling this function for a non-multi-aggregated variable is not allowed
13935 */
13937 SCIP_VAR* var, /**< problem variable */
13938 SCIP_SET* set /**< global SCIP settings */
13939 )
13940{
13941 int i;
13942 SCIP_Real ub;
13943 SCIP_Real bnd;
13944 SCIP_VAR* aggrvar;
13945 SCIP_Bool posinf;
13946 SCIP_Bool neginf;
13947
13948 assert(var != NULL);
13949 assert(set != NULL);
13950 assert(var->scip == set->scip);
13952
13953 posinf = FALSE;
13954 neginf = FALSE;
13955 ub = var->data.multaggr.constant;
13956 for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
13957 {
13958 aggrvar = var->data.multaggr.vars[i];
13959 if( var->data.multaggr.scalars[i] > 0.0 )
13960 {
13962
13963 if( SCIPsetIsInfinity(set, bnd) )
13964 posinf = TRUE;
13965 else if( SCIPsetIsInfinity(set, -bnd) )
13966 neginf = TRUE;
13967 else
13968 ub += var->data.multaggr.scalars[i] * bnd;
13969 }
13970 else
13971 {
13973
13974 if( SCIPsetIsInfinity(set, -bnd) )
13975 posinf = TRUE;
13976 else if( SCIPsetIsInfinity(set, bnd) )
13977 neginf = TRUE;
13978 else
13979 ub += var->data.multaggr.scalars[i] * bnd;
13980 }
13981
13982 /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
13983 * variable
13984 */
13985 if( posinf )
13986 return SCIPvarGetUbGlobal(var);
13987 }
13988
13989 /* if negative infinity flag was set to true return -infinity */
13990 if( neginf )
13991 return -SCIPsetInfinity(set);
13992
13993 return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
13994}
13995
13996/** adds a hole to the original domain of the variable */
13998 SCIP_VAR* var, /**< problem variable */
13999 BMS_BLKMEM* blkmem, /**< block memory */
14000 SCIP_SET* set, /**< global SCIP settings */
14001 SCIP_Real left, /**< left bound of open interval in new hole */
14002 SCIP_Real right /**< right bound of open interval in new hole */
14003 )
14004{
14005 SCIP_Bool added;
14006
14007 assert(var != NULL);
14011 assert(set != NULL);
14012 assert(var->scip == set->scip);
14013 assert(set->stage == SCIP_STAGE_PROBLEM);
14014
14015 SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
14016
14017 if( SCIPsetIsEQ(set, left, right) )
14018 return SCIP_OKAY;
14019
14020 /* the interval should not be empty */
14021 assert(SCIPsetIsLT(set, left, right));
14022
14023 /* the the interval bound should already be adjusted */
14026
14027 /* the the interval should lay between the lower and upper bound */
14030
14031 /* add domain hole */
14032 SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
14033
14034 /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
14035 if( added )
14036 {
14037 domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
14038 }
14039
14040 /**@todo add hole in parent and child variables (just like with bound changes);
14041 * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
14042 */
14043
14044 return SCIP_OKAY;
14045}
14046
14047/** performs the current add of domain, changes all parents accordingly */
14048static
14050 SCIP_VAR* var, /**< problem variable */
14051 BMS_BLKMEM* blkmem, /**< block memory */
14052 SCIP_SET* set, /**< global SCIP settings */
14053 SCIP_STAT* stat, /**< problem statistics */
14054 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14055 SCIP_Real left, /**< left bound of open interval in new hole */
14056 SCIP_Real right, /**< right bound of open interval in new hole */
14057 SCIP_Bool* added /**< pointer to store whether the hole was added */
14058 )
14059{
14060 SCIP_VAR* parentvar;
14061 SCIP_Real newlb;
14062 SCIP_Real newub;
14063 int i;
14064
14065 assert(var != NULL);
14066 assert(added != NULL);
14067 assert(blkmem != NULL);
14068
14069 /* the interval should not be empty */
14070 assert(SCIPsetIsLT(set, left, right));
14071
14072 /* the interval bound should already be adjusted */
14075
14076 /* the interval should lay between the lower and upper bound */
14079
14080 /* @todo add debugging mechanism for holes when using a debugging solution */
14081
14082 /* add hole to hole list */
14083 SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
14084
14085 /* check if the hole is redundant */
14086 if( !(*added) )
14087 return SCIP_OKAY;
14088
14089 /* current bounds */
14090 newlb = var->glbdom.lb;
14091 newub = var->glbdom.ub;
14092
14093 /* merge domain holes */
14094 domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
14095
14096 /* the bound should not be changed */
14097 assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
14098 assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
14099
14100 /* issue bound change event */
14101 assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
14102 if( var->eventfilter != NULL )
14103 {
14104 SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
14105 }
14106
14107 /* process parent variables */
14108 for( i = 0; i < var->nparentvars; ++i )
14109 {
14110 SCIP_Real parentnewleft;
14111 SCIP_Real parentnewright;
14112 SCIP_Bool localadded;
14113
14114 parentvar = var->parentvars[i];
14115 assert(parentvar != NULL);
14116
14117 switch( SCIPvarGetStatus(parentvar) )
14118 {
14120 parentnewleft = left;
14121 parentnewright = right;
14122 break;
14123
14128 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
14129 return SCIP_INVALIDDATA;
14130
14131 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14132 assert(parentvar->data.aggregate.var == var);
14133
14134 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
14135 {
14136 /* a > 0 -> change upper bound of x */
14137 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14138 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14139 }
14140 else
14141 {
14142 /* a < 0 -> change lower bound of x */
14144
14145 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14146 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14147 }
14148 break;
14149
14150 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
14151 assert(parentvar->negatedvar != NULL);
14153 assert(parentvar->negatedvar->negatedvar == parentvar);
14154
14155 parentnewright = -left + parentvar->data.negate.constant;
14156 parentnewleft = -right + parentvar->data.negate.constant;
14157 break;
14158
14159 default:
14160 SCIPerrorMessage("unknown variable status\n");
14161 return SCIP_INVALIDDATA;
14162 }
14163
14164 SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
14165
14166 /* perform hole added for parent variable */
14167 assert(blkmem != NULL);
14168 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
14169 SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
14170 parentnewleft, parentnewright, &localadded) );
14171 assert(localadded);
14172 }
14173
14174 return SCIP_OKAY;
14175}
14176
14177/** adds a hole to the variable's global and local domain */
14179 SCIP_VAR* var, /**< problem variable */
14180 BMS_BLKMEM* blkmem, /**< block memory */
14181 SCIP_SET* set, /**< global SCIP settings */
14182 SCIP_STAT* stat, /**< problem statistics */
14183 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14184 SCIP_Real left, /**< left bound of open interval in new hole */
14185 SCIP_Real right, /**< right bound of open interval in new hole */
14186 SCIP_Bool* added /**< pointer to store whether the hole was added */
14187 )
14188{
14189 SCIP_Real childnewleft;
14190 SCIP_Real childnewright;
14191
14192 assert(var != NULL);
14194 assert(blkmem != NULL);
14195 assert(added != NULL);
14196
14197 SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
14198
14199 /* the interval should not be empty */
14200 assert(SCIPsetIsLT(set, left, right));
14201
14202 /* the the interval bound should already be adjusted */
14205
14206 /* the the interval should lay between the lower and upper bound */
14209
14210 /* change bounds of attached variables */
14211 switch( SCIPvarGetStatus(var) )
14212 {
14214 if( var->data.original.transvar != NULL )
14215 {
14216 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
14217 left, right, added) );
14218 }
14219 else
14220 {
14221 assert(set->stage == SCIP_STAGE_PROBLEM);
14222
14223 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
14224 if( *added )
14225 {
14226 SCIP_Bool localadded;
14227
14228 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
14229 }
14230 }
14231 break;
14232
14235 SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
14236 if( *added )
14237 {
14238 SCIP_Bool localadded;
14239
14240 SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
14241 }
14242 break;
14243
14245 SCIPerrorMessage("cannot add hole of a fixed variable\n");
14246 return SCIP_INVALIDDATA;
14247
14248 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14249 assert(var->data.aggregate.var != NULL);
14250
14251 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
14252 {
14253 /* a > 0 -> change lower bound of y */
14254 childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14255 childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14256 }
14257 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
14258 {
14259 childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14260 childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14261 }
14262 else
14263 {
14264 SCIPerrorMessage("scalar is zero in aggregation\n");
14265 return SCIP_INVALIDDATA;
14266 }
14267 SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
14268 childnewleft, childnewright, added) );
14269 break;
14270
14272 SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
14273 return SCIP_INVALIDDATA;
14274
14275 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14276 assert(var->negatedvar != NULL);
14278 assert(var->negatedvar->negatedvar == var);
14279
14280 childnewright = -left + var->data.negate.constant;
14281 childnewleft = -right + var->data.negate.constant;
14282
14283 SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
14284 childnewleft, childnewright, added) );
14285 break;
14286
14287 default:
14288 SCIPerrorMessage("unknown variable status\n");
14289 return SCIP_INVALIDDATA;
14290 }
14291
14292 return SCIP_OKAY;
14293}
14294
14295/** performs the current add of domain, changes all parents accordingly */
14296static
14298 SCIP_VAR* var, /**< problem variable */
14299 BMS_BLKMEM* blkmem, /**< block memory */
14300 SCIP_SET* set, /**< global SCIP settings */
14301 SCIP_STAT* stat, /**< problem statistics */
14302 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14303 SCIP_Real left, /**< left bound of open interval in new hole */
14304 SCIP_Real right, /**< right bound of open interval in new hole */
14305 SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
14306 )
14307{
14308 SCIP_VAR* parentvar;
14309 SCIP_Real newlb;
14310 SCIP_Real newub;
14311 int i;
14312
14313 assert(var != NULL);
14314 assert(added != NULL);
14315 assert(blkmem != NULL);
14316
14317 /* the interval should not be empty */
14318 assert(SCIPsetIsLT(set, left, right));
14319
14320 /* the the interval bound should already be adjusted */
14323
14324 /* the the interval should lay between the lower and upper bound */
14327
14328 /* add hole to hole list */
14329 SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
14330
14331 /* check if the hole is redundant */
14332 if( !(*added) )
14333 return SCIP_OKAY;
14334
14335 /* current bounds */
14336 newlb = var->locdom.lb;
14337 newub = var->locdom.ub;
14338
14339 /* merge domain holes */
14340 domMerge(&var->locdom, blkmem, set, &newlb, &newub);
14341
14342 /* the bound should not be changed */
14343 assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
14344 assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
14345
14346#ifdef SCIP_DISABLED_CODE
14347 /* issue LHOLEADDED event */
14348 SCIP_EVENT event;
14349 assert(var->eventfilter != NULL);
14351 SCIP_CALL( SCIPeventProcess(&event, set, NULL, NULL, NULL, var->eventfilter) );
14352#endif
14353
14354 /* process parent variables */
14355 for( i = 0; i < var->nparentvars; ++i )
14356 {
14357 SCIP_Real parentnewleft;
14358 SCIP_Real parentnewright;
14359 SCIP_Bool localadded;
14360
14361 parentvar = var->parentvars[i];
14362 assert(parentvar != NULL);
14363
14364 switch( SCIPvarGetStatus(parentvar) )
14365 {
14367 parentnewleft = left;
14368 parentnewright = right;
14369 break;
14370
14375 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
14376 return SCIP_INVALIDDATA;
14377
14378 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14379 assert(parentvar->data.aggregate.var == var);
14380
14381 if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
14382 {
14383 /* a > 0 -> change upper bound of x */
14384 parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14385 parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14386 }
14387 else
14388 {
14389 /* a < 0 -> change lower bound of x */
14391
14392 parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
14393 parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
14394 }
14395 break;
14396
14397 case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
14398 assert(parentvar->negatedvar != NULL);
14400 assert(parentvar->negatedvar->negatedvar == parentvar);
14401
14402 parentnewright = -left + parentvar->data.negate.constant;
14403 parentnewleft = -right + parentvar->data.negate.constant;
14404 break;
14405
14406 default:
14407 SCIPerrorMessage("unknown variable status\n");
14408 return SCIP_INVALIDDATA;
14409 }
14410
14411 SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
14412
14413 /* perform hole added for parent variable */
14414 assert(blkmem != NULL);
14415 assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
14416 SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
14417 parentnewleft, parentnewright, &localadded) );
14418 assert(localadded);
14419 }
14420
14421 return SCIP_OKAY;
14422}
14423
14424/** adds a hole to the variable's current local domain */
14426 SCIP_VAR* var, /**< problem variable */
14427 BMS_BLKMEM* blkmem, /**< block memory */
14428 SCIP_SET* set, /**< global SCIP settings */
14429 SCIP_STAT* stat, /**< problem statistics */
14430 SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
14431 SCIP_Real left, /**< left bound of open interval in new hole */
14432 SCIP_Real right, /**< right bound of open interval in new hole */
14433 SCIP_Bool* added /**< pointer to store whether the hole was added */
14434 )
14435{
14436 SCIP_Real childnewleft;
14437 SCIP_Real childnewright;
14438
14439 assert(var != NULL);
14440
14441 SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
14442
14443 assert(set != NULL);
14444 assert(var->scip == set->scip);
14446 assert(blkmem != NULL);
14447 assert(added != NULL);
14448
14449 /* the interval should not be empty */
14450 assert(SCIPsetIsLT(set, left, right));
14451
14452 /* the the interval bound should already be adjusted */
14455
14456 /* the the interval should lay between the lower and upper bound */
14459
14460 /* change bounds of attached variables */
14461 switch( SCIPvarGetStatus(var) )
14462 {
14464 if( var->data.original.transvar != NULL )
14465 {
14466 SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
14467 left, right, added) );
14468 }
14469 else
14470 {
14471 assert(set->stage == SCIP_STAGE_PROBLEM);
14472 SCIPstatIncrement(stat, set, domchgcount);
14473 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
14474 }
14475 break;
14476
14479 SCIPstatIncrement(stat, set, domchgcount);
14480 SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
14481 break;
14482
14484 SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
14485 return SCIP_INVALIDDATA;
14486
14487 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
14488 assert(var->data.aggregate.var != NULL);
14489
14490 if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
14491 {
14492 /* a > 0 -> change lower bound of y */
14493 childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14494 childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14495 }
14496 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
14497 {
14498 childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
14499 childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
14500 }
14501 else
14502 {
14503 SCIPerrorMessage("scalar is zero in aggregation\n");
14504 return SCIP_INVALIDDATA;
14505 }
14506 SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
14507 childnewleft, childnewright, added) );
14508 break;
14509
14511 SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
14512 return SCIP_INVALIDDATA;
14513
14514 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14515 assert(var->negatedvar != NULL);
14517 assert(var->negatedvar->negatedvar == var);
14518
14519 childnewright = -left + var->data.negate.constant;
14520 childnewleft = -right + var->data.negate.constant;
14521
14522 SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
14523 break;
14524
14525 default:
14526 SCIPerrorMessage("unknown variable status\n");
14527 return SCIP_INVALIDDATA;
14528 }
14529
14530 return SCIP_OKAY;
14531}
14532
14533/** resets the global and local bounds of original variable to their original values */
14535 SCIP_VAR* var, /**< problem variable */
14536 BMS_BLKMEM* blkmem, /**< block memory */
14537 SCIP_SET* set, /**< global SCIP settings */
14538 SCIP_STAT* stat /**< problem statistics */
14539 )
14540{
14541 assert(var != NULL);
14542 assert(set != NULL);
14543 assert(var->scip == set->scip);
14545 /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
14546 * the transformed variable has been fixed */
14548
14549 /* copy the original bounds back to the global and local bounds */
14550 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
14551 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
14552 SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
14553 SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
14554
14555 if( var->exactdata != NULL )
14556 {
14557 SCIP_CALL( SCIPvarChgLbGlobalExact(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->exactdata->origdom.lb) );
14558 SCIP_CALL( SCIPvarChgUbGlobalExact(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->exactdata->origdom.ub) );
14559 SCIP_CALL( SCIPvarChgLbLocalExact(var, blkmem, set, stat, NULL, NULL, NULL, var->exactdata->origdom.lb) );
14560 SCIP_CALL( SCIPvarChgUbLocalExact(var, blkmem, set, stat, NULL, NULL, NULL, var->exactdata->origdom.ub) );
14561 }
14562
14563 /* free the global and local holelists and duplicate the original ones */
14564 /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
14565 holelistFree(&var->glbdom.holelist, blkmem);
14566 holelistFree(&var->locdom.holelist, blkmem);
14567 SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
14568 SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
14569
14570 return SCIP_OKAY;
14571}
14572
14573/** issues a IMPLADDED event on the given variable */
14574static
14576 SCIP_VAR* var, /**< problem variable to change */
14577 BMS_BLKMEM* blkmem, /**< block memory */
14578 SCIP_SET* set, /**< global SCIP settings */
14579 SCIP_EVENTQUEUE* eventqueue /**< event queue */
14580 )
14581{
14582 SCIP_EVENT* event;
14583
14584 assert(var != NULL);
14585
14586 /* issue IMPLADDED event on variable */
14587 SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
14588 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
14589
14590 return SCIP_OKAY;
14591}
14592
14593/** actually performs the addition of a variable bound to the variable's vbound arrays */
14594static
14596 SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
14597 BMS_BLKMEM* blkmem, /**< block memory */
14598 SCIP_SET* set, /**< global SCIP settings */
14599 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14600 SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
14601 SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
14602 SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
14603 SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
14604 )
14605{
14606 SCIP_Bool added;
14607
14608 /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
14609 * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
14610 * variable of the aggregated variable might be the same as the one its gets aggregated too.
14611 *
14612 * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
14613 * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
14614 * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
14615 * variable bound can be ignored.
14616 *
14617 * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
14618 * equivalence of the variables should be checked here.
14619 */
14620 if( var == vbvar )
14621 {
14622 /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
14623 * can be checked via the global bounds of the variable */
14624#ifndef NDEBUG
14625 SCIP_Real lb;
14626 SCIP_Real ub;
14627
14628 lb = SCIPvarGetLbGlobal(var);
14629 ub = SCIPvarGetUbGlobal(var);
14630
14631 if(vbtype == SCIP_BOUNDTYPE_LOWER)
14632 {
14633 if( vbcoef > 0.0 )
14634 {
14635 assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
14636 assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
14637 }
14638 else
14639 {
14640 assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
14641 assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
14642 }
14643 }
14644 else
14645 {
14646 assert(vbtype == SCIP_BOUNDTYPE_UPPER);
14647 if( vbcoef > 0.0 )
14648 {
14649 assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
14650 assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
14651 }
14652 else
14653 {
14654 assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
14655 assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
14656 }
14657 }
14658#endif
14659 SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
14660 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
14661
14662 return SCIP_OKAY;
14663 }
14664
14665 SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
14666 SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
14667
14668 /* check variable bound on debugging solution */
14669 SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
14670
14671 /* perform the addition */
14672 if( vbtype == SCIP_BOUNDTYPE_LOWER )
14673 {
14674 SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
14675 }
14676 else
14677 {
14678 SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
14679 }
14680 var->closestvblpcount = -1;
14681
14682 if( added )
14683 {
14684 /* issue IMPLADDED event */
14685 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
14686 }
14687
14688 return SCIP_OKAY;
14689}
14690
14691/** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
14692static
14694 SCIP_SET* set, /**< global SCIP settings */
14695 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14696 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14697 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14698 SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
14699 SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
14700 )
14701{
14702 SCIP_Real impllb;
14703 SCIP_Real implub;
14704
14705 assert(redundant != NULL);
14706 assert(infeasible != NULL);
14707
14708 impllb = SCIPvarGetLbGlobal(implvar);
14709 implub = SCIPvarGetUbGlobal(implvar);
14710 if( impltype == SCIP_BOUNDTYPE_LOWER )
14711 {
14712 *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
14713 *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
14714 }
14715 else
14716 {
14717 *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
14718 *redundant = SCIPsetIsFeasGE(set, implbound, implub);
14719 }
14720}
14721
14722/** applies the given implication, if it is not redundant */
14723static
14725 BMS_BLKMEM* blkmem, /**< block memory */
14726 SCIP_SET* set, /**< global SCIP settings */
14727 SCIP_STAT* stat, /**< problem statistics */
14728 SCIP_PROB* transprob, /**< transformed problem */
14729 SCIP_PROB* origprob, /**< original problem */
14730 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
14731 SCIP_REOPT* reopt, /**< reoptimization data structure */
14732 SCIP_LP* lp, /**< current LP data */
14733 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
14734 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14735 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14736 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
14737 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14738 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14739 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14740 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
14741 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
14742 )
14743{
14744 SCIP_Real implub;
14745 SCIP_Real impllb;
14746
14747 assert(infeasible != NULL);
14748
14749 *infeasible = FALSE;
14750
14751 implub = SCIPvarGetUbGlobal(implvar);
14752 impllb = SCIPvarGetLbGlobal(implvar);
14753 if( impltype == SCIP_BOUNDTYPE_LOWER )
14754 {
14755 if( SCIPsetIsFeasGT(set, implbound, implub) )
14756 {
14757 /* the implication produces a conflict: the problem is infeasible */
14758 *infeasible = TRUE;
14759 }
14760 else if( SCIPsetIsFeasGT(set, implbound, impllb) )
14761 {
14762 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14763 * with the local bound, in this case we need to store the bound change as pending bound change
14764 */
14766 {
14767 assert(tree != NULL);
14768 assert(transprob != NULL);
14769 assert(SCIPprobIsTransformed(transprob));
14770
14771 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14772 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
14773 }
14774 else
14775 {
14776 SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
14777 }
14778
14779 if( nbdchgs != NULL )
14780 (*nbdchgs)++;
14781 }
14782 }
14783 else
14784 {
14785 if( SCIPsetIsFeasLT(set, implbound, impllb) )
14786 {
14787 /* the implication produces a conflict: the problem is infeasible */
14788 *infeasible = TRUE;
14789 }
14790 else if( SCIPsetIsFeasLT(set, implbound, implub) )
14791 {
14792 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14793 * with the local bound, in this case we need to store the bound change as pending bound change
14794 */
14796 {
14797 assert(tree != NULL);
14798 assert(transprob != NULL);
14799 assert(SCIPprobIsTransformed(transprob));
14800
14801 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14802 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
14803 }
14804 else
14805 {
14806 SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
14807 }
14808
14809 if( nbdchgs != NULL )
14810 (*nbdchgs)++;
14811 }
14812 }
14813
14814 return SCIP_OKAY;
14815}
14816
14817/** actually performs the addition of an implication to the variable's implication arrays,
14818 * and adds the corresponding implication or variable bound to the implied variable;
14819 * if the implication is conflicting, the variable is fixed to the opposite value;
14820 * if the variable is already fixed to the given value, the implication is performed immediately;
14821 * if the implication is redundant with respect to the variables' global bounds, it is ignored
14822 */
14823static
14825 SCIP_VAR* var, /**< problem variable */
14826 BMS_BLKMEM* blkmem, /**< block memory */
14827 SCIP_SET* set, /**< global SCIP settings */
14828 SCIP_STAT* stat, /**< problem statistics */
14829 SCIP_PROB* transprob, /**< transformed problem */
14830 SCIP_PROB* origprob, /**< original problem */
14831 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
14832 SCIP_REOPT* reopt, /**< reoptimization data structure */
14833 SCIP_LP* lp, /**< current LP data */
14834 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
14835 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
14836 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14837 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
14838 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
14839 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
14840 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
14841 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
14842 SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
14843 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
14844 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
14845 SCIP_Bool* added /**< pointer to store whether an implication was added */
14846 )
14847{
14848 SCIP_Bool redundant;
14849 SCIP_Bool conflict;
14850
14851 assert(var != NULL);
14856 assert(infeasible != NULL);
14857 assert(added != NULL);
14858
14859 /* check implication on debugging solution */
14860 SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
14861
14862 *infeasible = FALSE;
14863 *added = FALSE;
14864
14865 /* check, if the implication is redundant or infeasible */
14866 checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
14867 assert(!redundant || !conflict);
14868 if( redundant )
14869 return SCIP_OKAY;
14870
14871 if( var == implvar )
14872 {
14873 /* special cases appear were a bound to a variable implies itself to be outside the bounds:
14874 * x == varfixing => x < 0 or x > 1
14875 */
14876 if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
14877 conflict = TRUE;
14878 else
14879 {
14880 /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
14881 assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
14882 assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
14883 assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
14884 conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
14885 if( !conflict )
14886 return SCIP_OKAY;
14887 }
14888 }
14889
14890 /* check, if the variable is already fixed */
14891 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
14892 {
14893 /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
14894 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
14895 {
14896 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
14897 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
14898 }
14899 return SCIP_OKAY;
14900 }
14901
14902 assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
14903 || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
14904
14905 if( !conflict )
14906 {
14907 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
14908
14909 if( SCIPvarIsBinary(implvar) )
14910 {
14911 SCIP_VAR* vars[2];
14912 SCIP_Bool vals[2];
14913
14914 assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
14915 assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
14916
14917 vars[0] = var;
14918 vars[1] = implvar;
14919 vals[0] = varfixing;
14920 vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
14921
14922 /* add the clique to the clique table */
14923 SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
14924 eventqueue, eventfilter, vars, vals, 2, FALSE, &conflict, nbdchgs) );
14925
14926 if( !conflict )
14927 return SCIP_OKAY;
14928 }
14929 else
14930 {
14931 /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
14932 SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
14933 SCIPvarGetName(var), varfixing,
14934 SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
14935 SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
14936 isshortcut, &conflict, added) );
14937 }
14938 }
14939 assert(!conflict || !(*added));
14940
14941 /* on conflict, fix the variable to the opposite value */
14942 if( conflict )
14943 {
14944 SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
14945
14946 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
14947 * with the local bound, in this case we need to store the bound change as pending bound change
14948 */
14950 {
14951 assert(tree != NULL);
14952 assert(transprob != NULL);
14953 assert(SCIPprobIsTransformed(transprob));
14954
14955 if( varfixing )
14956 {
14957 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14958 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
14959 }
14960 else
14961 {
14962 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
14963 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
14964 }
14965 }
14966 else
14967 {
14968 if( varfixing )
14969 {
14970 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
14971 }
14972 else
14973 {
14974 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
14975 }
14976 }
14977 if( nbdchgs != NULL )
14978 (*nbdchgs)++;
14979
14980 return SCIP_OKAY;
14981 }
14982 else if( *added )
14983 {
14984 /* issue IMPLADDED event */
14985 SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
14986 }
14987 else
14988 {
14989 /* the implication was redundant: the inverse is also redundant */
14990 return SCIP_OKAY;
14991 }
14992
14993 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
14994
14995 /* check, whether implied variable is binary */
14996 if( !SCIPvarIsBinary(implvar) )
14997 {
14998 SCIP_Real lb;
14999 SCIP_Real ub;
15000
15001 /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
15002 * x == 0 -> y <= b <-> y <= (ub - b)*x + b
15003 * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
15004 * x == 0 -> y >= b <-> y >= (lb - b)*x + b
15005 * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
15006 * for numerical reasons, ignore variable bounds with large absolute coefficient
15007 */
15008 lb = SCIPvarGetLbGlobal(implvar);
15009 ub = SCIPvarGetUbGlobal(implvar);
15010 if( impltype == SCIP_BOUNDTYPE_UPPER )
15011 {
15012 if( REALABS(implbound - ub) <= MAXABSVBCOEF )
15013 {
15014 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
15015 varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
15016 }
15017 }
15018 else
15019 {
15020 if( REALABS(implbound - lb) <= MAXABSVBCOEF )
15021 {
15022 SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
15023 varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
15024 }
15025 }
15026 }
15027
15028 return SCIP_OKAY;
15029}
15030
15031/** adds transitive closure for binary implication x = a -> y = b */
15032static
15034 SCIP_VAR* var, /**< problem variable */
15035 BMS_BLKMEM* blkmem, /**< block memory */
15036 SCIP_SET* set, /**< global SCIP settings */
15037 SCIP_STAT* stat, /**< problem statistics */
15038 SCIP_PROB* transprob, /**< transformed problem */
15039 SCIP_PROB* origprob, /**< original problem */
15040 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15041 SCIP_REOPT* reopt, /**< reoptimization data structure */
15042 SCIP_LP* lp, /**< current LP data */
15043 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15044 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15045 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15046 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15047 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
15048 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
15049 SCIP_Bool implvarfixing, /**< fixing b in implication */
15050 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15051 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
15052 )
15053{
15054 SCIP_VAR** implvars;
15055 SCIP_BOUNDTYPE* impltypes;
15056 SCIP_Real* implbounds;
15057 int nimpls;
15058 int i;
15059
15060 *infeasible = FALSE;
15061
15062 /* binary variable: implications of implvar */
15063 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
15064 implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
15065 impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
15066 implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
15067
15068 /* if variable has too many implications, the implication graph may become too dense */
15069 i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
15070
15071 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15072 * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
15073 * array over which we currently iterate; the only thing that can happen, is that elements of the array are
15074 * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
15075 * only thing that can happen is that we add the same implication twice - this does no harm
15076 */
15077 while ( i >= 0 && !(*infeasible) )
15078 {
15079 SCIP_Bool added;
15080
15081 assert(implvars[i] != implvar);
15082
15083 /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
15084 * add implication x == varfixing -> z <= b / z >= b to the implications list of x
15085 */
15086 if( SCIPvarIsActive(implvars[i]) )
15087 {
15088 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
15089 eventqueue, eventfilter, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
15090 assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
15091 nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
15092 i = MIN(i, nimpls); /* some elements from the array could have been removed */
15093 }
15094 --i;
15095 }
15096
15097 return SCIP_OKAY;
15098}
15099
15100/** adds given implication to the variable's implication list, and adds all implications directly implied by this
15101 * implication to the variable's implication list;
15102 * if the implication is conflicting, the variable is fixed to the opposite value;
15103 * if the variable is already fixed to the given value, the implication is performed immediately;
15104 * if the implication is redundant with respect to the variables' global bounds, it is ignored
15105 */
15106static
15108 SCIP_VAR* var, /**< problem variable */
15109 BMS_BLKMEM* blkmem, /**< block memory */
15110 SCIP_SET* set, /**< global SCIP settings */
15111 SCIP_STAT* stat, /**< problem statistics */
15112 SCIP_PROB* transprob, /**< transformed problem */
15113 SCIP_PROB* origprob, /**< original problem */
15114 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15115 SCIP_REOPT* reopt, /**< reoptimization data structure */
15116 SCIP_LP* lp, /**< current LP data */
15117 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15118 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15119 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15120 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15121 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
15122 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
15123 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
15124 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
15125 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15126 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15127 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
15128 )
15129{
15130 SCIP_Bool added;
15131
15132 assert(var != NULL);
15135 assert(implvar != NULL);
15137 assert(infeasible != NULL);
15138
15139 /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
15140 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
15141 eventqueue, eventfilter, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
15142
15143 if( *infeasible || var == implvar || !transitive || !added )
15144 return SCIP_OKAY;
15145
15146 assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
15147
15148 /* add transitive closure */
15149 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(implvar) )
15150 {
15151 SCIP_Bool implvarfixing;
15152
15153 implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
15154
15155 /* binary variable: implications of implvar */
15156 SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15157 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
15158
15159 /* inverse implication */
15160 if( !(*infeasible) )
15161 {
15162 SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15163 cliquetable, branchcand, eventqueue, eventfilter, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
15164 }
15165 }
15166 else
15167 {
15168 /* non-binary variable: variable lower bounds of implvar */
15169 if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
15170 {
15171 SCIP_VAR** vlbvars;
15172 SCIP_Real* vlbcoefs;
15173 SCIP_Real* vlbconstants;
15174 int nvlbvars;
15175 int i;
15176
15177 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
15178 vlbvars = SCIPvboundsGetVars(implvar->vlbs);
15179 vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
15180 vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
15181
15182 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15183 * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
15184 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
15185 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
15186 * is that we add the same implication twice - this does no harm
15187 */
15188 i = nvlbvars-1;
15189 while ( i >= 0 && !(*infeasible) )
15190 {
15191 assert(vlbvars[i] != implvar);
15192 assert(!SCIPsetIsZero(set, vlbcoefs[i]));
15193
15194 /* we have x == varfixing -> y <= b and y >= c*z + d:
15195 * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
15196 * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
15197 *
15198 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
15199 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
15200 * aggregation variable (the one which will stay active);
15201 *
15202 * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
15203 * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
15204 * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
15205 * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
15206 * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
15207 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
15208 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
15209 * have to explicitly check that the active variable has not a variable status
15210 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
15211 */
15213 {
15214 SCIP_Real vbimplbound;
15215
15216 vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
15217 if( vlbcoefs[i] >= 0.0 )
15218 {
15219 vbimplbound = adjustedUb(set, SCIPvarIsIntegral(vlbvars[i]), vbimplbound);
15220 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15221 branchcand, eventqueue, eventfilter, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
15222 infeasible, nbdchgs, &added) );
15223 }
15224 else
15225 {
15226 vbimplbound = adjustedLb(set, SCIPvarIsIntegral(vlbvars[i]), vbimplbound);
15227 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15228 branchcand, eventqueue, eventfilter, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
15229 infeasible, nbdchgs, &added) );
15230 }
15231 nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
15232 i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
15233 }
15234 --i;
15235 }
15236 }
15237
15238 /* non-binary variable: variable upper bounds of implvar */
15239 if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
15240 {
15241 SCIP_VAR** vubvars;
15242 SCIP_Real* vubcoefs;
15243 SCIP_Real* vubconstants;
15244 int nvubvars;
15245 int i;
15246
15247 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
15248 vubvars = SCIPvboundsGetVars(implvar->vubs);
15249 vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
15250 vubconstants = SCIPvboundsGetConstants(implvar->vubs);
15251
15252 /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
15253 * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
15254 * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
15255 * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
15256 * is that we add the same implication twice - this does no harm
15257 */
15258 i = nvubvars-1;
15259 while ( i >= 0 && !(*infeasible) )
15260 {
15261 assert(vubvars[i] != implvar);
15262 assert(!SCIPsetIsZero(set, vubcoefs[i]));
15263
15264 /* we have x == varfixing -> y >= b and y <= c*z + d:
15265 * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
15266 * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
15267 *
15268 * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
15269 * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
15270 * aggregation variable (the one which will stay active);
15271 *
15272 * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
15273 * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
15274 * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
15275 * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
15276 * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
15277 * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
15278 * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
15279 * have to explicitly check that the active variable has not a variable status
15280 * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
15281 */
15283 {
15284 SCIP_Real vbimplbound;
15285
15286 vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
15287 if( vubcoefs[i] >= 0.0 )
15288 {
15289 vbimplbound = adjustedLb(set, SCIPvarIsIntegral(vubvars[i]), vbimplbound);
15290 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15291 branchcand, eventqueue, eventfilter, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
15292 infeasible, nbdchgs, &added) );
15293 }
15294 else
15295 {
15296 vbimplbound = adjustedUb(set, SCIPvarIsIntegral(vubvars[i]), vbimplbound);
15297 SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15298 branchcand, eventqueue, eventfilter, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
15299 infeasible, nbdchgs, &added) );
15300 }
15301 nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
15302 i = MIN(i, nvubvars); /* some elements from the array could have been removed */
15303 }
15304 --i;
15305 }
15306 }
15307 }
15308
15309 return SCIP_OKAY;
15310}
15311
15312/** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
15313 * if z is binary, the corresponding valid implication for z is also added;
15314 * improves the global bounds of the variable and the vlb variable if possible
15315 */
15317 SCIP_VAR* var, /**< problem variable */
15318 BMS_BLKMEM* blkmem, /**< block memory */
15319 SCIP_SET* set, /**< global SCIP settings */
15320 SCIP_STAT* stat, /**< problem statistics */
15321 SCIP_PROB* transprob, /**< transformed problem */
15322 SCIP_PROB* origprob, /**< original problem */
15323 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15324 SCIP_REOPT* reopt, /**< reoptimization data structure */
15325 SCIP_LP* lp, /**< current LP data */
15326 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15327 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15328 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15329 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15330 SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
15331 SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
15332 SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
15333 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15334 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15335 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
15336 )
15337{
15338 assert(var != NULL);
15339 assert(set != NULL);
15340 assert(var->scip == set->scip);
15341 assert(SCIPvarIsIntegral(vlbvar));
15342 assert(infeasible != NULL);
15343
15344 SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
15345
15346 *infeasible = FALSE;
15347 if( nbdchgs != NULL )
15348 *nbdchgs = 0;
15349
15350 switch( SCIPvarGetStatus(var) )
15351 {
15353 assert(var->data.original.transvar != NULL);
15354 SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15355 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
15356 break;
15357
15361 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15362 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
15363 SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n",
15364 SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
15365
15366 /* if the variables are the same, just update the corresponding bound */
15367 if( var == vlbvar )
15368 {
15369 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15370 if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
15371 {
15372 if( SCIPsetIsFeasPositive(set, vlbconstant) )
15373 *infeasible = TRUE;
15374 }
15375 else
15376 {
15379
15380 /* the variable bound constraint defines a new upper bound */
15381 if( SCIPsetIsGT(set, vlbcoef, 1.0) )
15382 {
15383 /* bound might be adjusted due to integrality condition */
15384 SCIP_Real newub = adjustedUb(set, SCIPvarIsIntegral(var), vlbconstant / (1.0 - vlbcoef));
15385
15386 /* check bounds for feasibility */
15387 if( SCIPsetIsFeasLT(set, newub, lb) )
15388 {
15389 *infeasible = TRUE;
15390 return SCIP_OKAY;
15391 }
15392
15393 /* improve global upper bound of variable */
15394 if( SCIPsetIsFeasLT(set, newub, ub) )
15395 {
15396 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15397 * with the local bound, in this case we need to store the bound change as pending bound change
15398 */
15400 {
15401 assert(tree != NULL);
15402 assert(transprob != NULL);
15403 assert(SCIPprobIsTransformed(transprob));
15404
15405 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15406 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15407 }
15408 else
15409 {
15410 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
15411 }
15412
15413 if( nbdchgs != NULL )
15414 (*nbdchgs)++;
15415 }
15416 }
15417 /* the variable bound constraint defines a new lower bound */
15418 else
15419 {
15420 assert(SCIPsetIsLT(set, vlbcoef, 1.0));
15421
15422 /* bound might be adjusted due to integrality condition */
15423 SCIP_Real newlb = adjustedLb(set, SCIPvarIsIntegral(var), vlbconstant / (1.0 - vlbcoef));
15424
15425 /* check bounds for feasibility */
15426 if( SCIPsetIsFeasGT(set, newlb, ub) )
15427 {
15428 *infeasible = TRUE;
15429 return SCIP_OKAY;
15430 }
15431
15432 /* improve global lower bound of variable */
15433 if( SCIPsetIsFeasGT(set, newlb, lb) )
15434 {
15435 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15436 * with the local bound, in this case we need to store the bound change as pending bound change
15437 */
15439 {
15440 assert(tree != NULL);
15441 assert(transprob != NULL);
15442 assert(SCIPprobIsTransformed(transprob));
15443
15444 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15445 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15446 }
15447 else
15448 {
15449 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
15450 }
15451
15452 if( nbdchgs != NULL )
15453 (*nbdchgs)++;
15454 }
15455 }
15456 }
15457 }
15458 /* if the vlb coefficient is zero, just update the lower bound of the variable */
15459 else if( SCIPsetIsZero(set, vlbcoef) )
15460 {
15461 /* bound might be adjusted due to integrality condition */
15462 vlbconstant = adjustedLb(set, SCIPvarIsIntegral(var), vlbconstant);
15463
15464 /* check bounds for feasibility */
15465 if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
15466 *infeasible = TRUE;
15467 /* improve global lower bound of variable */
15468 else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
15469 {
15470 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15471 * with the local bound, in this case we need to store the bound change as pending bound change
15472 */
15474 {
15475 assert(tree != NULL);
15476 assert(transprob != NULL);
15477 assert(SCIPprobIsTransformed(transprob));
15478
15479 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15480 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
15481 }
15482 else
15483 {
15484 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
15485 }
15486
15487 if( nbdchgs != NULL )
15488 (*nbdchgs)++;
15489 }
15490 }
15491 else if( SCIPvarIsActive(vlbvar) )
15492 {
15493 SCIP_Real xlb;
15494 SCIP_Real xub;
15495 SCIP_Real zlb;
15496 SCIP_Real zub;
15497 SCIP_Real minvlb;
15498 SCIP_Real maxvlb;
15499
15501 assert(vlbcoef != 0.0);
15502
15503 minvlb = -SCIPsetInfinity(set);
15504 maxvlb = SCIPsetInfinity(set);
15505
15506 xlb = SCIPvarGetLbGlobal(var);
15507 xub = SCIPvarGetUbGlobal(var);
15508 zlb = SCIPvarGetLbGlobal(vlbvar);
15509 zub = SCIPvarGetUbGlobal(vlbvar);
15510
15511 /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
15512 if( vlbcoef >= 0.0 )
15513 {
15514 if( !SCIPsetIsInfinity(set, xub) )
15515 {
15516 /* x >= b*z + d -> z <= (x-d)/b */
15517 SCIP_Real newzub = adjustedUb(set, SCIPvarIsIntegral(vlbvar), (xub - vlbconstant) / vlbcoef);
15518
15519 /* check bounds for feasibility */
15520 if( SCIPsetIsFeasLT(set, newzub, zlb) )
15521 {
15522 *infeasible = TRUE;
15523 return SCIP_OKAY;
15524 }
15525
15526 /* improve global upper bound of variable */
15527 if( SCIPsetIsFeasLT(set, newzub, zub) )
15528 {
15529 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15530 * with the local bound, in this case we need to store the bound change as pending bound change
15531 */
15533 {
15534 assert(tree != NULL);
15535 assert(transprob != NULL);
15536 assert(SCIPprobIsTransformed(transprob));
15537
15538 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15539 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15540 }
15541 else
15542 {
15543 SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
15544 }
15545 zub = newzub;
15546
15547 if( nbdchgs != NULL )
15548 (*nbdchgs)++;
15549 }
15550 maxvlb = vlbcoef * zub + vlbconstant;
15551 if( !SCIPsetIsInfinity(set, -zlb) )
15552 minvlb = vlbcoef * zlb + vlbconstant;
15553 }
15554 else
15555 {
15556 if( !SCIPsetIsInfinity(set, zub) )
15557 maxvlb = vlbcoef * zub + vlbconstant;
15558 if( !SCIPsetIsInfinity(set, -zlb) )
15559 minvlb = vlbcoef * zlb + vlbconstant;
15560 }
15561 }
15562 else
15563 {
15564 if( !SCIPsetIsInfinity(set, xub) )
15565 {
15566 /* x >= b*z + d -> z >= (x-d)/b */
15567 SCIP_Real newzlb = adjustedLb(set, SCIPvarIsIntegral(vlbvar), (xub - vlbconstant) / vlbcoef);
15568
15569 /* check bounds for feasibility */
15570 if( SCIPsetIsFeasGT(set, newzlb, zub) )
15571 {
15572 *infeasible = TRUE;
15573 return SCIP_OKAY;
15574 }
15575
15576 /* improve global lower bound of variable */
15577 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
15578 {
15579 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15580 * with the local bound, in this case we need to store the bound change as pending bound change
15581 */
15583 {
15584 assert(tree != NULL);
15585 assert(transprob != NULL);
15586 assert(SCIPprobIsTransformed(transprob));
15587
15588 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15589 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15590 }
15591 else
15592 {
15593 SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
15594 }
15595 zlb = newzlb;
15596
15597 if( nbdchgs != NULL )
15598 (*nbdchgs)++;
15599 }
15600 maxvlb = vlbcoef * zlb + vlbconstant;
15601 if( !SCIPsetIsInfinity(set, zub) )
15602 minvlb = vlbcoef * zub + vlbconstant;
15603 }
15604 else
15605 {
15606 if( !SCIPsetIsInfinity(set, -zlb) )
15607 maxvlb = vlbcoef * zlb + vlbconstant;
15608 if( !SCIPsetIsInfinity(set, zub) )
15609 minvlb = vlbcoef * zub + vlbconstant;
15610 }
15611 }
15612 if( maxvlb < minvlb )
15613 maxvlb = minvlb;
15614
15615 /* adjust bounds due to integrality of variable */
15616 minvlb = adjustedLb(set, SCIPvarIsIntegral(var), minvlb);
15617 maxvlb = adjustedLb(set, SCIPvarIsIntegral(var), maxvlb);
15618
15619 /* check bounds for feasibility */
15620 if( SCIPsetIsFeasGT(set, minvlb, xub) )
15621 {
15622 *infeasible = TRUE;
15623 return SCIP_OKAY;
15624 }
15625
15626 /* improve global lower bound of variable */
15627 if( SCIPsetIsFeasGT(set, minvlb, xlb) )
15628 {
15629 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15630 * with the local bound, in this case we need to store the bound change as pending bound change
15631 */
15633 {
15634 assert(tree != NULL);
15635 assert(transprob != NULL);
15636 assert(SCIPprobIsTransformed(transprob));
15637
15638 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15639 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15640 }
15641 else
15642 {
15643 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
15644 }
15645 xlb = minvlb;
15646
15647 if( nbdchgs != NULL )
15648 (*nbdchgs)++;
15649 }
15650 minvlb = xlb;
15651
15652 /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
15654 {
15655 /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
15656 * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
15657 */
15658
15659 assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
15660
15661 if( vlbcoef >= 0.0 )
15662 {
15663 vlbcoef = maxvlb - minvlb;
15664 vlbconstant = minvlb;
15665 }
15666 else
15667 {
15668 vlbcoef = minvlb - maxvlb;
15669 vlbconstant = maxvlb;
15670 }
15671 }
15672
15673 /* add variable bound to the variable bounds list */
15674 if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
15675 {
15677 assert(!SCIPsetIsZero(set, vlbcoef));
15678
15679 /* if one of the variables is binary, add the corresponding implication to the variable's implication
15680 * list, thereby also adding the variable bound (or implication) to the other variable
15681 */
15683 {
15684 /* add corresponding implication:
15685 * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
15686 * b < 0, x >= b*z + d <-> z == 0 -> x >= d
15687 */
15688 SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15689 cliquetable, branchcand, eventqueue, eventfilter, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
15690 infeasible, nbdchgs) );
15691 }
15693 {
15694 /* add corresponding implication:
15695 * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
15696 * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
15697 */
15698 SCIP_Real implbound;
15699 implbound = -vlbconstant/vlbcoef;
15700
15701 /* tighten the implication bound if the variable is integer */
15702 if( SCIPvarIsIntegral(vlbvar) )
15703 {
15704 if( vlbcoef >= 0 )
15705 implbound = SCIPsetFloor(set, implbound);
15706 else
15707 implbound = SCIPsetCeil(set, implbound);
15708 }
15709 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15710 cliquetable, branchcand, eventqueue, eventfilter, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
15711 implbound, transitive, infeasible, nbdchgs) );
15712 }
15713 else
15714 {
15715 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
15716 }
15717 }
15718 }
15719 break;
15720
15722 /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
15723 * y <= b/a * z + (d-c)/a, if a < 0
15724 */
15725
15726 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15727 SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
15728
15729 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15730 assert(var->data.aggregate.var != NULL);
15731 if( var->data.aggregate.var == vlbvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vlbcoef) )
15732 {
15733 if( SCIPsetIsFeasLT(set, var->data.aggregate.constant, vlbconstant) )
15734 *infeasible = TRUE;
15735 }
15736 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
15737 {
15738 /* a > 0 -> add variable lower bound */
15739 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15740 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef/var->data.aggregate.scalar,
15741 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
15742 }
15743 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
15744 {
15745 /* a < 0 -> add variable upper bound */
15746 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15747 cliquetable, branchcand, eventqueue, eventfilter, vlbvar, vlbcoef/var->data.aggregate.scalar,
15748 (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
15749 }
15750 else
15751 {
15752 SCIPerrorMessage("scalar is zero in aggregation\n");
15753 return SCIP_INVALIDDATA;
15754 }
15755 break;
15756
15758 /* nothing to do here */
15759 break;
15760
15762 /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
15763 assert(var->negatedvar != NULL);
15765 assert(var->negatedvar->negatedvar == var);
15766 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
15767 branchcand, eventqueue, eventfilter, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
15768 nbdchgs) );
15769 break;
15770
15771 default:
15772 SCIPerrorMessage("unknown variable status\n");
15773 return SCIP_INVALIDDATA;
15774 }
15775
15776 return SCIP_OKAY;
15777}
15778
15779/** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
15780 * if z is binary, the corresponding valid implication for z is also added;
15781 * updates the global bounds of the variable and the vub variable correspondingly
15782 */
15784 SCIP_VAR* var, /**< problem variable */
15785 BMS_BLKMEM* blkmem, /**< block memory */
15786 SCIP_SET* set, /**< global SCIP settings */
15787 SCIP_STAT* stat, /**< problem statistics */
15788 SCIP_PROB* transprob, /**< transformed problem */
15789 SCIP_PROB* origprob, /**< original problem */
15790 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
15791 SCIP_REOPT* reopt, /**< reoptimization data structure */
15792 SCIP_LP* lp, /**< current LP data */
15793 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
15794 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
15795 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15796 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15797 SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
15798 SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
15799 SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
15800 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
15801 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
15802 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
15803 )
15804{
15805 assert(var != NULL);
15806 assert(set != NULL);
15807 assert(var->scip == set->scip);
15808 assert(SCIPvarIsIntegral(vubvar));
15809 assert(infeasible != NULL);
15810
15811 SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
15812
15813 *infeasible = FALSE;
15814 if( nbdchgs != NULL )
15815 *nbdchgs = 0;
15816
15817 switch( SCIPvarGetStatus(var) )
15818 {
15820 assert(var->data.original.transvar != NULL);
15821 SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
15822 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
15823 break;
15824
15828 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
15829 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
15830 SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
15831 SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
15832
15833 /* if the variables are the same, just update the corresponding bound */
15834 if( var == vubvar )
15835 {
15836 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
15837 if( SCIPsetIsEQ(set, vubcoef, 1.0) )
15838 {
15839 if( SCIPsetIsFeasNegative(set, vubconstant) )
15840 *infeasible = TRUE;
15841 }
15842 else
15843 {
15846
15847 /* the variable bound constraint defines a new lower bound */
15848 if( SCIPsetIsGT(set, vubcoef, 1.0) )
15849 {
15850 /* bound might be adjusted due to integrality condition */
15851 SCIP_Real newlb = adjustedLb(set, SCIPvarIsIntegral(var), vubconstant / (1.0 - vubcoef));
15852
15853 /* check bounds for feasibility */
15854 if( SCIPsetIsFeasGT(set, newlb, ub) )
15855 {
15856 *infeasible = TRUE;
15857 return SCIP_OKAY;
15858 }
15859
15860 /* improve global lower bound of variable */
15861 if( SCIPsetIsFeasGT(set, newlb, lb) )
15862 {
15863 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15864 * with the local bound, in this case we need to store the bound change as pending bound change
15865 */
15867 {
15868 assert(tree != NULL);
15869 assert(transprob != NULL);
15870 assert(SCIPprobIsTransformed(transprob));
15871
15872 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15873 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
15874 }
15875 else
15876 {
15877 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
15878 }
15879
15880 if( nbdchgs != NULL )
15881 (*nbdchgs)++;
15882 }
15883 }
15884 /* the variable bound constraint defines a new upper bound */
15885 else
15886 {
15887 assert(SCIPsetIsLT(set, vubcoef, 1.0));
15888
15889 /* bound might be adjusted due to integrality condition */
15890 SCIP_Real newub = adjustedUb(set, SCIPvarIsIntegral(var), vubconstant / (1.0 - vubcoef));
15891
15892 /* check bounds for feasibility */
15893 if( SCIPsetIsFeasLT(set, newub, lb) )
15894 {
15895 *infeasible = TRUE;
15896 return SCIP_OKAY;
15897 }
15898
15899 /* improve global upper bound of variable */
15900 if( SCIPsetIsFeasLT(set, newub, ub) )
15901 {
15902 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15903 * with the local bound, in this case we need to store the bound change as pending bound change
15904 */
15906 {
15907 assert(tree != NULL);
15908 assert(transprob != NULL);
15909 assert(SCIPprobIsTransformed(transprob));
15910
15911 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15912 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
15913 }
15914 else
15915 {
15916 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
15917 }
15918
15919 if( nbdchgs != NULL )
15920 (*nbdchgs)++;
15921 }
15922 }
15923 }
15924 }
15925 /* if the vub coefficient is zero, just update the upper bound of the variable */
15926 else if( SCIPsetIsZero(set, vubcoef) )
15927 {
15928 /* bound might be adjusted due to integrality condition */
15929 vubconstant = adjustedUb(set, SCIPvarIsIntegral(var), vubconstant);
15930
15931 /* check bounds for feasibility */
15932 if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
15933 *infeasible = TRUE;
15934 /* improve global upper bound of variable */
15935 else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
15936 {
15937 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15938 * with the local bound, in this case we need to store the bound change as pending bound change
15939 */
15941 {
15942 assert(tree != NULL);
15943 assert(transprob != NULL);
15944 assert(SCIPprobIsTransformed(transprob));
15945
15946 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
15947 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
15948 }
15949 else
15950 {
15951 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
15952 }
15953
15954 if( nbdchgs != NULL )
15955 (*nbdchgs)++;
15956 }
15957 }
15958 else if( SCIPvarIsActive(vubvar) )
15959 {
15960 SCIP_Real xlb;
15961 SCIP_Real xub;
15962 SCIP_Real zlb;
15963 SCIP_Real zub;
15964 SCIP_Real minvub;
15965 SCIP_Real maxvub;
15966
15968 assert(vubcoef != 0.0);
15969
15970 minvub = -SCIPsetInfinity(set);
15971 maxvub = SCIPsetInfinity(set);
15972
15973 xlb = SCIPvarGetLbGlobal(var);
15974 xub = SCIPvarGetUbGlobal(var);
15975 zlb = SCIPvarGetLbGlobal(vubvar);
15976 zub = SCIPvarGetUbGlobal(vubvar);
15977
15978 /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
15979 if( vubcoef >= 0.0 )
15980 {
15981 if( !SCIPsetIsInfinity(set, -xlb) )
15982 {
15983 /* x <= b*z + d -> z >= (x-d)/b */
15984 SCIP_Real newzlb = adjustedLb(set, SCIPvarIsIntegral(vubvar), (xlb - vubconstant) / vubcoef);
15985
15986 /* check bounds for feasibility */
15987 if( SCIPsetIsFeasGT(set, newzlb, zub) )
15988 {
15989 *infeasible = TRUE;
15990 return SCIP_OKAY;
15991 }
15992
15993 /* improve global lower bound of variable */
15994 if( SCIPsetIsFeasGT(set, newzlb, zlb) )
15995 {
15996 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
15997 * with the local bound, in this case we need to store the bound change as pending bound change
15998 */
16000 {
16001 assert(tree != NULL);
16002 assert(transprob != NULL);
16003 assert(SCIPprobIsTransformed(transprob));
16004
16005 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16006 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
16007 }
16008 else
16009 {
16010 SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
16011 }
16012 zlb = newzlb;
16013
16014 if( nbdchgs != NULL )
16015 (*nbdchgs)++;
16016 }
16017 minvub = vubcoef * zlb + vubconstant;
16018 if( !SCIPsetIsInfinity(set, zub) )
16019 maxvub = vubcoef * zub + vubconstant;
16020 }
16021 else
16022 {
16023 if( !SCIPsetIsInfinity(set, zub) )
16024 maxvub = vubcoef * zub + vubconstant;
16025 if( !SCIPsetIsInfinity(set, -zlb) )
16026 minvub = vubcoef * zlb + vubconstant;
16027 }
16028 }
16029 else
16030 {
16031 if( !SCIPsetIsInfinity(set, -xlb) )
16032 {
16033 /* x <= b*z + d -> z <= (x-d)/b */
16034 SCIP_Real newzub = adjustedUb(set, SCIPvarIsIntegral(vubvar), (xlb - vubconstant) / vubcoef);
16035
16036 /* check bounds for feasibility */
16037 if( SCIPsetIsFeasLT(set, newzub, zlb) )
16038 {
16039 *infeasible = TRUE;
16040 return SCIP_OKAY;
16041 }
16042
16043 /* improve global upper bound of variable */
16044 if( SCIPsetIsFeasLT(set, newzub, zub) )
16045 {
16046 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16047 * with the local bound, in this case we need to store the bound change as pending bound change
16048 */
16050 {
16051 assert(tree != NULL);
16052 assert(transprob != NULL);
16053 assert(SCIPprobIsTransformed(transprob));
16054
16055 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16056 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
16057 }
16058 else
16059 {
16060 SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
16061 }
16062 zub = newzub;
16063
16064 if( nbdchgs != NULL )
16065 (*nbdchgs)++;
16066 }
16067 minvub = vubcoef * zub + vubconstant;
16068 if( !SCIPsetIsInfinity(set, -zlb) )
16069 maxvub = vubcoef * zlb + vubconstant;
16070 }
16071 else
16072 {
16073 if( !SCIPsetIsInfinity(set, zub) )
16074 minvub = vubcoef * zub + vubconstant;
16075 if( !SCIPsetIsInfinity(set, -zlb) )
16076 maxvub = vubcoef * zlb + vubconstant;
16077 }
16078 }
16079 if( minvub > maxvub )
16080 minvub = maxvub;
16081
16082 /* adjust bounds due to integrality of vub variable */
16083 minvub = adjustedUb(set, SCIPvarIsIntegral(var), minvub);
16084 maxvub = adjustedUb(set, SCIPvarIsIntegral(var), maxvub);
16085
16086 /* check bounds for feasibility */
16087 if( SCIPsetIsFeasLT(set, maxvub, xlb) )
16088 {
16089 *infeasible = TRUE;
16090 return SCIP_OKAY;
16091 }
16092
16093 /* improve global upper bound of variable */
16094 if( SCIPsetIsFeasLT(set, maxvub, xub) )
16095 {
16096 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16097 * with the local bound, in this case we need to store the bound change as pending bound change
16098 */
16100 {
16101 assert(tree != NULL);
16102 assert(transprob != NULL);
16103 assert(SCIPprobIsTransformed(transprob));
16104
16105 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16106 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
16107 }
16108 else
16109 {
16110 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
16111 }
16112 xub = maxvub;
16113
16114 if( nbdchgs != NULL )
16115 (*nbdchgs)++;
16116 }
16117 maxvub = xub;
16118
16119 /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
16120 if( SCIPvarIsBinary(vubvar) )
16121 {
16122 /* b > 0: x <= (maxvub - minvub) * z + minvub
16123 * b < 0: x <= (minvub - maxvub) * z + maxvub
16124 */
16125
16126 assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
16127
16128 if( vubcoef >= 0.0 )
16129 {
16130 vubcoef = maxvub - minvub;
16131 vubconstant = minvub;
16132 }
16133 else
16134 {
16135 vubcoef = minvub - maxvub;
16136 vubconstant = maxvub;
16137 }
16138 }
16139
16140 /* add variable bound to the variable bounds list */
16141 if( SCIPsetIsFeasLT(set, minvub, xub) )
16142 {
16144 assert(!SCIPsetIsZero(set, vubcoef));
16145
16146 /* if one of the variables is binary, add the corresponding implication to the variable's implication
16147 * list, thereby also adding the variable bound (or implication) to the other variable
16148 */
16150 {
16151 /* add corresponding implication:
16152 * b > 0, x <= b*z + d <-> z == 0 -> x <= d
16153 * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
16154 */
16155 SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16156 cliquetable, branchcand, eventqueue, eventfilter, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
16157 infeasible, nbdchgs) );
16158 }
16160 {
16161 /* add corresponding implication:
16162 * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
16163 * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
16164 */
16165 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16166 cliquetable, branchcand, eventqueue, eventfilter, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
16167 (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
16168 }
16169 else
16170 {
16171 SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
16172 }
16173 }
16174 }
16175 break;
16176
16178 /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
16179 * y >= b/a * z + (d-c)/a, if a < 0
16180 */
16181
16182 /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
16183 SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
16184
16185 /* if the variables cancel out, the variable bound constraint is redundant or proves global infeasibility */
16186 assert(var->data.aggregate.var != NULL);
16187 if( var->data.aggregate.var == vubvar && SCIPsetIsEQ(set, var->data.aggregate.scalar, vubcoef) )
16188 {
16189 if( SCIPsetIsFeasGT(set, var->data.aggregate.constant, vubconstant) )
16190 *infeasible = TRUE;
16191 }
16192 else if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
16193 {
16194 /* a > 0 -> add variable upper bound */
16195 SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16196 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef/var->data.aggregate.scalar,
16197 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
16198 }
16199 else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
16200 {
16201 /* a < 0 -> add variable lower bound */
16202 SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16203 cliquetable, branchcand, eventqueue, eventfilter, vubvar, vubcoef/var->data.aggregate.scalar,
16204 (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
16205 }
16206 else
16207 {
16208 SCIPerrorMessage("scalar is zero in aggregation\n");
16209 return SCIP_INVALIDDATA;
16210 }
16211 break;
16212
16214 /* nothing to do here */
16215 break;
16216
16218 /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
16219 assert(var->negatedvar != NULL);
16221 assert(var->negatedvar->negatedvar == var);
16222 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16223 branchcand, eventqueue, eventfilter, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
16224 nbdchgs) );
16225 break;
16226
16227 default:
16228 SCIPerrorMessage("unknown variable status\n");
16229 return SCIP_INVALIDDATA;
16230 }
16231
16232 return SCIP_OKAY;
16233}
16234
16235/** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
16236 * also adds the corresponding implication or variable bound to the implied variable;
16237 * if the implication is conflicting, the variable is fixed to the opposite value;
16238 * if the variable is already fixed to the given value, the implication is performed immediately;
16239 * if the implication is redundant with respect to the variables' global bounds, it is ignored
16240 */
16242 SCIP_VAR* var, /**< problem variable */
16243 BMS_BLKMEM* blkmem, /**< block memory */
16244 SCIP_SET* set, /**< global SCIP settings */
16245 SCIP_STAT* stat, /**< problem statistics */
16246 SCIP_PROB* transprob, /**< transformed problem */
16247 SCIP_PROB* origprob, /**< original problem */
16248 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16249 SCIP_REOPT* reopt, /**< reoptimization data structure */
16250 SCIP_LP* lp, /**< current LP data */
16251 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16252 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16253 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16254 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16255 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
16256 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
16257 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
16258 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
16259 SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
16260 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16261 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
16262 )
16263{
16264 assert(var != NULL);
16265 assert(set != NULL);
16266 assert(var->scip == set->scip);
16268 assert(infeasible != NULL);
16269
16270 *infeasible = FALSE;
16271 if( nbdchgs != NULL )
16272 *nbdchgs = 0;
16273
16274 switch( SCIPvarGetStatus(var) )
16275 {
16277 assert(var->data.original.transvar != NULL);
16278 SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16279 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible,
16280 nbdchgs) );
16281 break;
16282
16285 /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
16286 * the variable, the implication can be applied directly;
16287 * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
16288 */
16289 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
16290 {
16291 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
16292 {
16293 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
16294 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
16295 }
16296 }
16297 else
16298 {
16299 SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
16300 SCIPvarAdjustBd(implvar, set, impltype, &implbound);
16301 if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
16302 {
16303 SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16304 branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
16305 }
16306 }
16307 break;
16308
16310 /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
16311 if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
16312 {
16313 SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
16314 eventfilter, cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
16315 }
16316 break;
16317
16319 /* implication added for x == 1:
16320 * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16321 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16322 * implication added for x == 0:
16323 * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16324 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16325 *
16326 * use only binary variables z
16327 */
16328 assert(var->data.aggregate.var != NULL);
16329 if( SCIPvarIsBinary(var->data.aggregate.var) )
16330 {
16331 assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
16332 || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
16333
16334 if( var->data.aggregate.scalar > 0 )
16335 {
16336 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16337 cliquetable, branchcand, eventqueue, eventfilter, varfixing, implvar, impltype, implbound, transitive, infeasible,
16338 nbdchgs) );
16339 }
16340 else
16341 {
16342 SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16343 cliquetable, branchcand, eventqueue, eventfilter, !varfixing, implvar, impltype, implbound, transitive, infeasible,
16344 nbdchgs) );
16345 }
16346 }
16347 break;
16348
16350 /* nothing to do here */
16351 break;
16352
16354 /* implication added for x == 1:
16355 * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
16356 * implication added for x == 0:
16357 * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
16358 */
16359 assert(var->negatedvar != NULL);
16361 assert(var->negatedvar->negatedvar == var);
16362 assert(SCIPvarIsBinary(var->negatedvar));
16363
16364 if( SCIPvarGetType(var->negatedvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(var->negatedvar) )
16365 {
16366 SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16367 cliquetable, branchcand, eventqueue, eventfilter, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
16368 }
16369 /* in case one both variables are not of binary type we have to add the implication as variable bounds */
16370 else
16371 {
16372 /* if the implied variable is of binary type exchange the variables */
16373 if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
16374 {
16375 SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16376 branchcand, eventqueue, eventfilter, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
16377 varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
16378 infeasible, nbdchgs) );
16379 }
16380 else
16381 {
16382 /* both variables are not of binary type but are implicit binary; in that case we can only add this
16383 * implication as variable bounds
16384 */
16385
16386 /* add variable lower bound on the negation of var */
16387 if( varfixing )
16388 {
16389 /* (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
16390 * as variable lower bound
16391 */
16392 SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16393 cliquetable, branchcand, eventqueue, eventfilter, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
16394 (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
16395 }
16396 else
16397 {
16398 /* (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
16399 * as variable upper bound
16400 */
16401 SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
16402 cliquetable, branchcand, eventqueue, eventfilter, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
16403 (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
16404 }
16405
16406 /* add variable bound on implvar */
16407 if( impltype == SCIP_BOUNDTYPE_UPPER )
16408 {
16409 /* (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
16410 * as variable upper bound
16411 */
16412 SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16413 branchcand, eventqueue, eventfilter, var->negatedvar, (varfixing) ? 1.0 : -1.0,
16414 (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
16415 }
16416 else
16417 {
16418 /* (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
16419 * as variable upper bound
16420 */
16421 SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
16422 branchcand, eventqueue, eventfilter, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
16423 transitive, infeasible, nbdchgs) );
16424 }
16425 }
16426 }
16427 break;
16428
16429 default:
16430 SCIPerrorMessage("unknown variable status\n");
16431 return SCIP_INVALIDDATA;
16432 }
16433
16434 return SCIP_OKAY;
16435}
16436
16437/** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
16438 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
16439 * both variables must be active, variable x must be binary
16440 */
16442 SCIP_VAR* var, /**< problem variable x */
16443 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16444 SCIP_VAR* implvar, /**< variable y to search for */
16445 SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
16446 )
16447{
16448 assert(var != NULL);
16449 assert(implvar != NULL);
16451 assert(SCIPvarIsActive(implvar));
16453
16454 return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
16455}
16456
16457/** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
16458 * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
16459 * both variables must be active binary variables
16460 */
16462 SCIP_VAR* var, /**< problem variable x */
16463 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16464 SCIP_VAR* implvar, /**< variable y to search for */
16465 SCIP_Bool implvarfixing /**< value of the implied variable to search for */
16466 )
16467{
16468 assert(SCIPvarIsBinary(implvar));
16469
16470 return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
16471}
16472
16473/** gets the values of b in implications x == varfixing -> y <= b or y >= b in the implication graph;
16474 * the values are set to SCIP_INVALID if there is no implied bound
16475 */
16477 SCIP_VAR* var, /**< problem variable x */
16478 SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
16479 SCIP_VAR* implvar, /**< variable y to search for */
16480 SCIP_Real* lb, /**< buffer to store the value of the implied lower bound */
16481 SCIP_Real* ub /**< buffer to store the value of the implied upper bound */
16482 )
16483{
16484 int lowerpos;
16485 int upperpos;
16486 SCIP_Real* bounds;
16487
16488 assert(lb != NULL);
16489 assert(ub != NULL);
16490
16491 *lb = SCIP_INVALID;
16492 *ub = SCIP_INVALID;
16493
16494 if( var->implics == NULL )
16495 return;
16496
16497 SCIPimplicsGetVarImplicPoss(var->implics, varfixing, implvar, &lowerpos, &upperpos);
16498 bounds = SCIPvarGetImplBounds(var, varfixing);
16499
16500 if( bounds == NULL )
16501 return;
16502
16503 if( lowerpos >= 0 )
16504 *lb = bounds[lowerpos];
16505
16506 if( upperpos >= 0 )
16507 *ub = bounds[upperpos];
16508}
16509
16510
16511/** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
16513 SCIP_VAR* var, /**< problem variable */
16514 BMS_BLKMEM* blkmem, /**< block memory */
16515 SCIP_SET* set, /**< global SCIP settings */
16516 SCIP_STAT* stat, /**< problem statistics */
16517 SCIP_PROB* transprob, /**< transformed problem */
16518 SCIP_PROB* origprob, /**< original problem */
16519 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16520 SCIP_REOPT* reopt, /**< reoptimization data structure */
16521 SCIP_LP* lp, /**< current LP data */
16522 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16523 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16524 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16525 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16526 SCIP_Bool value, /**< value to fix variable to */
16527 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16528 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
16529 )
16530{
16531 assert(var != NULL);
16532 assert(set != NULL);
16533 assert(var->scip == set->scip);
16534 assert(infeasible != NULL);
16535
16536 *infeasible = FALSE;
16537
16538 if( value == FALSE )
16539 {
16540 if( var->glbdom.lb > 0.5 )
16541 *infeasible = TRUE;
16542 else if( var->glbdom.ub > 0.5 )
16543 {
16544 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16545 * with the local bound, in this case we need to store the bound change as pending bound change
16546 */
16548 {
16549 assert(tree != NULL);
16550 assert(transprob != NULL);
16551 assert(SCIPprobIsTransformed(transprob));
16552
16553 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16554 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
16555 }
16556 else
16557 {
16558 SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
16559 }
16560
16561 if( nbdchgs != NULL )
16562 (*nbdchgs)++;
16563 }
16564 }
16565 else
16566 {
16567 if( var->glbdom.ub < 0.5 )
16568 *infeasible = TRUE;
16569 else if( var->glbdom.lb < 0.5 )
16570 {
16571 /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
16572 * with the local bound, in this case we need to store the bound change as pending bound change
16573 */
16575 {
16576 assert(tree != NULL);
16577 assert(transprob != NULL);
16578 assert(SCIPprobIsTransformed(transprob));
16579
16580 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
16581 tree, reopt, lp, branchcand, eventqueue, eventfilter, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
16582 }
16583 else
16584 {
16585 SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
16586 }
16587
16588 if( nbdchgs != NULL )
16589 (*nbdchgs)++;
16590 }
16591 }
16592
16593 return SCIP_OKAY;
16594}
16595
16596/** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
16597 * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
16598 * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
16599 * the opposite of the value they take in the clique
16600 */
16602 SCIP_VAR* var, /**< problem variable */
16603 BMS_BLKMEM* blkmem, /**< block memory */
16604 SCIP_SET* set, /**< global SCIP settings */
16605 SCIP_STAT* stat, /**< problem statistics */
16606 SCIP_PROB* transprob, /**< transformed problem */
16607 SCIP_PROB* origprob, /**< original problem */
16608 SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
16609 SCIP_REOPT* reopt, /**< reoptimization data structure */
16610 SCIP_LP* lp, /**< current LP data */
16611 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
16612 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16613 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16614 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16615 SCIP_Bool value, /**< value of the variable in the clique */
16616 SCIP_CLIQUE* clique, /**< clique the variable should be added to */
16617 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
16618 int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
16619 )
16620{
16621 assert(var != NULL);
16622 assert(set != NULL);
16623 assert(var->scip == set->scip);
16625 assert(infeasible != NULL);
16626
16627 *infeasible = FALSE;
16628
16629 /* get corresponding active problem variable */
16636
16637 /* only column and loose variables may be member of a clique */
16639 {
16640 SCIP_Bool doubleentry;
16641 SCIP_Bool oppositeentry;
16642
16643 /* add variable to clique */
16644 SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
16645
16646 /* add clique to variable's clique list */
16647 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
16648
16649 /* check consistency of cliquelist */
16650 SCIPcliquelistCheck(var->cliquelist, var);
16651
16652 /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
16653 if( doubleentry )
16654 {
16655 SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
16656 eventqueue, eventfilter, cliquetable, !value, infeasible, nbdchgs) );
16657 }
16658
16659 /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
16660 * to the opposite of the value they take in the clique
16661 */
16662 if( oppositeentry )
16663 {
16664 SCIP_VAR** vars;
16665 SCIP_Bool* values;
16666 int nvars;
16667 int i;
16668
16669 nvars = SCIPcliqueGetNVars(clique);
16670 vars = SCIPcliqueGetVars(clique);
16671 values = SCIPcliqueGetValues(clique);
16672 for( i = 0; i < nvars && !(*infeasible); ++i )
16673 {
16674 if( vars[i] == var )
16675 continue;
16676
16677 SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
16678 eventqueue, eventfilter, cliquetable, !values[i], infeasible, nbdchgs) );
16679 }
16680 }
16681 }
16682
16683 return SCIP_OKAY;
16684}
16685
16686/** adds a filled clique to the cliquelists of all corresponding variables */
16688 SCIP_VAR** vars, /**< problem variables */
16689 SCIP_Bool* values, /**< values of the variables in the clique */
16690 int nvars, /**< number of problem variables */
16691 BMS_BLKMEM* blkmem, /**< block memory */
16692 SCIP_SET* set, /**< global SCIP settings */
16693 SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
16694 )
16695{
16696 SCIP_VAR* var;
16697 int v;
16698
16699 assert(vars != NULL);
16700 assert(values != NULL);
16701 assert(nvars > 0);
16702 assert(set != NULL);
16703 assert(blkmem != NULL);
16704 assert(clique != NULL);
16705
16706 for( v = nvars - 1; v >= 0; --v )
16707 {
16708 var = vars[v];
16711
16712 /* add clique to variable's clique list */
16713 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
16714
16715 /* check consistency of cliquelist */
16716 SCIPcliquelistCheck(var->cliquelist, var);
16717 }
16718
16719 return SCIP_OKAY;
16720}
16721
16722/** adds a clique to the list of cliques of the given binary variable, but does not change the clique
16723 * itself
16724 */
16726 SCIP_VAR* var, /**< problem variable */
16727 BMS_BLKMEM* blkmem, /**< block memory */
16728 SCIP_SET* set, /**< global SCIP settings */
16729 SCIP_Bool value, /**< value of the variable in the clique */
16730 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
16731 )
16732{
16733 assert(var != NULL);
16736
16737 /* add clique to variable's clique list */
16738 SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
16739
16740 return SCIP_OKAY;
16741}
16742
16743
16744/** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
16745 * itself
16746 */
16748 SCIP_VAR* var, /**< problem variable */
16749 BMS_BLKMEM* blkmem, /**< block memory */
16750 SCIP_Bool value, /**< value of the variable in the clique */
16751 SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
16752 )
16753{
16754 assert(var != NULL);
16756
16757 /* delete clique from variable's clique list */
16758 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
16759
16760 return SCIP_OKAY;
16761}
16762
16763/** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
16765 SCIP_VAR* var, /**< problem variable */
16766 BMS_BLKMEM* blkmem, /**< block memory */
16767 SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
16768 SCIP_Bool value, /**< value of the variable in the clique */
16769 SCIP_CLIQUE* clique /**< clique the variable should be removed from */
16770 )
16771{
16772 assert(var != NULL);
16774
16775 /* get corresponding active problem variable */
16782
16783 /* only column and loose variables may be member of a clique */
16785 {
16786 /* delete clique from variable's clique list */
16787 SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
16788
16789 /* delete variable from clique */
16790 SCIPcliqueDelVar(clique, cliquetable, var, value);
16791
16792 /* check consistency of cliquelist */
16793 SCIPcliquelistCheck(var->cliquelist, var);
16794 }
16795
16796 return SCIP_OKAY;
16797}
16798
16799/** returns whether there is a clique that contains both given variable/value pairs;
16800 * the variables must be active binary variables;
16801 * if regardimplics is FALSE, only the cliques in the clique table are looked at;
16802 * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
16803 *
16804 * @note a variable with it's negated variable are NOT! in a clique
16805 * @note a variable with itself are in a clique
16806 */
16808 SCIP_VAR* var1, /**< first variable */
16809 SCIP_Bool value1, /**< value of first variable */
16810 SCIP_VAR* var2, /**< second variable */
16811 SCIP_Bool value2, /**< value of second variable */
16812 SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
16813 )
16814{
16815 assert(var1 != NULL);
16816 assert(var2 != NULL);
16817 assert(SCIPvarIsActive(var1));
16818 assert(SCIPvarIsActive(var2));
16819 assert(SCIPvarIsBinary(var1));
16820 assert(SCIPvarIsBinary(var2));
16821
16822 return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
16823 || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
16824}
16825
16826/** actually changes the branch factor of the variable and of all parent variables */
16827static
16829 SCIP_VAR* var, /**< problem variable */
16830 SCIP_SET* set, /**< global SCIP settings */
16831 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
16832 )
16833{
16834 SCIP_VAR* parentvar;
16835 SCIP_Real eps;
16836 int i;
16837
16838 assert(var != NULL);
16839 assert(set != NULL);
16840 assert(var->scip == set->scip);
16841
16842 /* only use positive values */
16844 branchfactor = MAX(branchfactor, eps);
16845
16846 SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
16847
16848 if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
16849 return SCIP_OKAY;
16850
16851 /* change the branch factor */
16852 var->branchfactor = branchfactor;
16853
16854 /* process parent variables */
16855 for( i = 0; i < var->nparentvars; ++i )
16856 {
16857 parentvar = var->parentvars[i];
16858 assert(parentvar != NULL);
16859
16860 switch( SCIPvarGetStatus(parentvar) )
16861 {
16863 /* do not change priorities across the border between transformed and original problem */
16864 break;
16865
16870 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
16871 SCIPABORT();
16872 return SCIP_INVALIDDATA; /*lint !e527*/
16873
16876 SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
16877 break;
16878
16879 default:
16880 SCIPerrorMessage("unknown variable status\n");
16881 SCIPABORT();
16882 return SCIP_ERROR; /*lint !e527*/
16883 }
16884 }
16885
16886 return SCIP_OKAY;
16887}
16888
16889/** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
16890 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
16891 */
16893 SCIP_VAR* var, /**< problem variable */
16894 SCIP_SET* set, /**< global SCIP settings */
16895 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
16896 )
16897{
16898 int v;
16899
16900 assert(var != NULL);
16901 assert(set != NULL);
16902 assert(var->scip == set->scip);
16903 assert(branchfactor >= 0.0);
16904
16905 SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
16906
16907 if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
16908 return SCIP_OKAY;
16909
16910 /* change priorities of attached variables */
16911 switch( SCIPvarGetStatus(var) )
16912 {
16914 if( var->data.original.transvar != NULL )
16915 {
16916 SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
16917 }
16918 else
16919 {
16920 assert(set->stage == SCIP_STAGE_PROBLEM);
16921 var->branchfactor = branchfactor;
16922 }
16923 break;
16924
16928 SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
16929 break;
16930
16932 assert(!var->donotaggr);
16933 assert(var->data.aggregate.var != NULL);
16934 SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
16935 break;
16936
16938 assert(!var->donotmultaggr);
16939 for( v = 0; v < var->data.multaggr.nvars; ++v )
16940 {
16941 SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
16942 }
16943 break;
16944
16946 assert(var->negatedvar != NULL);
16948 assert(var->negatedvar->negatedvar == var);
16949 SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
16950 break;
16951
16952 default:
16953 SCIPerrorMessage("unknown variable status\n");
16954 SCIPABORT();
16955 return SCIP_ERROR; /*lint !e527*/
16956 }
16957
16958 return SCIP_OKAY;
16959}
16960
16961/** actually changes the branch priority of the variable and of all parent variables */
16962static
16964 SCIP_VAR* var, /**< problem variable */
16965 int branchpriority /**< branching priority of the variable */
16966 )
16967{
16968 SCIP_VAR* parentvar;
16969 int i;
16970
16971 assert(var != NULL);
16972
16973 SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
16974 var->name, var->branchpriority, branchpriority);
16975
16976 if( branchpriority == var->branchpriority )
16977 return SCIP_OKAY;
16978
16979 /* change the branch priority */
16980 var->branchpriority = branchpriority;
16981
16982 /* process parent variables */
16983 for( i = 0; i < var->nparentvars; ++i )
16984 {
16985 parentvar = var->parentvars[i];
16986 assert(parentvar != NULL);
16987
16988 switch( SCIPvarGetStatus(parentvar) )
16989 {
16991 /* do not change priorities across the border between transformed and original problem */
16992 break;
16993
16998 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
16999 SCIPABORT();
17000 return SCIP_INVALIDDATA; /*lint !e527*/
17001
17004 SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
17005 break;
17006
17007 default:
17008 SCIPerrorMessage("unknown variable status\n");
17009 return SCIP_ERROR;
17010 }
17011 }
17012
17013 return SCIP_OKAY;
17014}
17015
17016/** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
17017 * with lower priority in selection of branching variable
17018 */
17020 SCIP_VAR* var, /**< problem variable */
17021 int branchpriority /**< branching priority of the variable */
17022 )
17023{
17024 int v;
17025
17026 assert(var != NULL);
17027
17028 SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
17029
17030 if( var->branchpriority == branchpriority )
17031 return SCIP_OKAY;
17032
17033 /* change priorities of attached variables */
17034 switch( SCIPvarGetStatus(var) )
17035 {
17037 if( var->data.original.transvar != NULL )
17038 {
17039 SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
17040 }
17041 else
17042 var->branchpriority = branchpriority;
17043 break;
17044
17048 SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
17049 break;
17050
17052 assert(!var->donotaggr);
17053 assert(var->data.aggregate.var != NULL);
17054 SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
17055 break;
17056
17058 assert(!var->donotmultaggr);
17059 for( v = 0; v < var->data.multaggr.nvars; ++v )
17060 {
17061 SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
17062 }
17063 break;
17064
17066 assert(var->negatedvar != NULL);
17068 assert(var->negatedvar->negatedvar == var);
17069 SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
17070 break;
17071
17072 default:
17073 SCIPerrorMessage("unknown variable status\n");
17074 SCIPABORT();
17075 return SCIP_ERROR; /*lint !e527*/
17076 }
17077
17078 return SCIP_OKAY;
17079}
17080
17081/** actually changes the branch direction of the variable and of all parent variables */
17082static
17084 SCIP_VAR* var, /**< problem variable */
17085 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
17086 )
17087{
17088 SCIP_VAR* parentvar;
17089 int i;
17090
17091 assert(var != NULL);
17092
17093 SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
17094 var->name, var->branchdirection, branchdirection);
17095
17096 if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
17097 return SCIP_OKAY;
17098
17099 /* change the branch direction */
17100 var->branchdirection = branchdirection; /*lint !e641*/
17101
17102 /* process parent variables */
17103 for( i = 0; i < var->nparentvars; ++i )
17104 {
17105 parentvar = var->parentvars[i];
17106 assert(parentvar != NULL);
17107
17108 switch( SCIPvarGetStatus(parentvar) )
17109 {
17111 /* do not change directions across the border between transformed and original problem */
17112 break;
17113
17118 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
17119 SCIPABORT();
17120 return SCIP_INVALIDDATA; /*lint !e527*/
17121
17123 if( parentvar->data.aggregate.scalar > 0.0 )
17124 {
17125 SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
17126 }
17127 else
17128 {
17129 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
17130 }
17131 break;
17132
17134 SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
17135 break;
17136
17137 default:
17138 SCIPerrorMessage("unknown variable status\n");
17139 SCIPABORT();
17140 return SCIP_ERROR; /*lint !e527*/
17141 }
17142 }
17143
17144 return SCIP_OKAY;
17145}
17146
17147/** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
17148 * with lower direction in selection of branching variable
17149 */
17151 SCIP_VAR* var, /**< problem variable */
17152 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
17153 )
17154{
17155 int v;
17156
17157 assert(var != NULL);
17158
17159 SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
17160
17161 if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
17162 return SCIP_OKAY;
17163
17164 /* change directions of attached variables */
17165 switch( SCIPvarGetStatus(var) )
17166 {
17168 if( var->data.original.transvar != NULL )
17169 {
17170 SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
17171 }
17172 else
17173 var->branchdirection = branchdirection; /*lint !e641*/
17174 break;
17175
17179 SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
17180 break;
17181
17183 assert(!var->donotaggr);
17184 assert(var->data.aggregate.var != NULL);
17185 if( var->data.aggregate.scalar > 0.0 )
17186 {
17187 SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
17188 }
17189 else
17190 {
17191 SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, SCIPbranchdirOpposite(branchdirection)) );
17192 }
17193 break;
17194
17196 assert(!var->donotmultaggr);
17197 for( v = 0; v < var->data.multaggr.nvars; ++v )
17198 {
17199 /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
17200 assert(var->data.multaggr.vars[v] != NULL);
17201 if( (SCIP_BRANCHDIR)var->data.multaggr.vars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
17202 {
17203 if( var->data.multaggr.scalars[v] > 0.0 )
17204 {
17205 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
17206 }
17207 else
17208 {
17209 SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], SCIPbranchdirOpposite(branchdirection)) );
17210 }
17211 }
17212 }
17213 break;
17214
17216 assert(var->negatedvar != NULL);
17218 assert(var->negatedvar->negatedvar == var);
17219 SCIP_CALL( SCIPvarChgBranchDirection(var->negatedvar, SCIPbranchdirOpposite(branchdirection)) );
17220 break;
17221
17222 default:
17223 SCIPerrorMessage("unknown variable status\n");
17224 SCIPABORT();
17225 return SCIP_ERROR; /*lint !e527*/
17226 }
17227
17228 return SCIP_OKAY;
17229}
17230
17231/** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
17232 * is negated then the index of the corresponding active variable is taken, returns -1 if first is
17233 * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
17234 * are equal, which means both variables are equal
17235 */
17237 SCIP_VAR* var1, /**< first problem variable */
17238 SCIP_VAR* var2 /**< second problem variable */
17239 )
17240{
17241 assert(var1 != NULL);
17242 assert(var2 != NULL);
17245
17247 var1 = SCIPvarGetNegatedVar(var1);
17249 var2 = SCIPvarGetNegatedVar(var2);
17250
17251 assert(var1 != NULL);
17252 assert(var2 != NULL);
17253
17254 if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
17255 return -1;
17256 else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
17257 return +1;
17258
17259 assert(var1 == var2);
17260 return 0;
17261}
17262
17263/** comparison method for sorting active and negated variables by non-decreasing index, active and negated
17264 * variables are handled as the same variables
17265 */
17266SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
17267{
17268 return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
17269}
17270
17271/** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
17272 * variable index; returns 0 if both indices are equal, which means both variables are equal
17273 */
17275 SCIP_VAR* var1, /**< first problem variable */
17276 SCIP_VAR* var2 /**< second problem variable */
17277 )
17278{
17279 assert(var1 != NULL);
17280 assert(var2 != NULL);
17281
17282 if( var1->index < var2->index )
17283 return -1;
17284 else if( var1->index > var2->index )
17285 return +1;
17286 else
17287 {
17288 assert(var1 == var2);
17289 return 0;
17290 }
17291}
17292
17293/** comparison method for sorting variables by non-decreasing index */
17295{
17296 return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
17297}
17298
17299/** comparison method for sorting variables by non-decreasing objective coefficient */
17301{
17302 SCIP_Real obj1;
17303 SCIP_Real obj2;
17304
17305 obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
17306 obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
17307
17308 if( obj1 < obj2 )
17309 return -1;
17310 else if( obj1 > obj2 )
17311 return +1;
17312 else
17313 return 0;
17314}
17315
17316/** hash key retrieval function for variables */
17317SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
17318{ /*lint --e{715}*/
17319 return elem;
17320}
17321
17322/** returns TRUE iff the indices of both variables are equal */
17323SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
17324{ /*lint --e{715}*/
17325 if( key1 == key2 )
17326 return TRUE;
17327 return FALSE;
17328}
17329
17330/** returns the hash value of the key */
17331SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
17332{ /*lint --e{715}*/
17333 assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
17334 return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
17335}
17336
17337/** return for given variables all their active counterparts; all active variables will be pairwise different */
17339 SCIP_SET* set, /**< global SCIP settings */
17340 SCIP_VAR** vars, /**< variable array with given variables and as output all active
17341 * variables, if enough slots exist
17342 */
17343 int* nvars, /**< number of given variables, and as output number of active variables,
17344 * if enough slots exist
17345 */
17346 int varssize, /**< available slots in vars array */
17347 int* requiredsize /**< pointer to store the required array size for the active variables */
17348 )
17349{
17350 SCIP_VAR** activevars;
17351 int nactivevars;
17352 int activevarssize;
17353
17354 SCIP_VAR* var;
17355 int v;
17356
17357 SCIP_VAR** tmpvars;
17358 SCIP_VAR** multvars;
17359 int tmpvarssize;
17360 int ntmpvars;
17361 int noldtmpvars;
17362 int nmultvars;
17363
17364 assert(set != NULL);
17365 assert(nvars != NULL);
17366 assert(vars != NULL || *nvars == 0);
17367 assert(varssize >= *nvars);
17368 assert(requiredsize != NULL);
17369
17370 *requiredsize = 0;
17371
17372 if( *nvars == 0 )
17373 return SCIP_OKAY;
17374
17375 nactivevars = 0;
17376 activevarssize = *nvars;
17377 ntmpvars = *nvars;
17378 tmpvarssize = *nvars;
17379
17380 /* temporary memory */
17381 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
17382 /* coverity[copy_paste_error] */
17383 SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
17384
17385 noldtmpvars = ntmpvars;
17386
17387 /* sort all variables to combine equal variables easily */
17388 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17389 for( v = ntmpvars - 1; v > 0; --v )
17390 {
17391 /* combine same variables */
17392 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
17393 {
17394 --ntmpvars;
17395 tmpvars[v] = tmpvars[ntmpvars];
17396 }
17397 }
17398 /* sort all variables again to combine equal variables later on */
17399 if( noldtmpvars > ntmpvars )
17400 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17401
17402 /* collect for each variable the representation in active variables */
17403 while( ntmpvars >= 1 )
17404 {
17405 --ntmpvars;
17406 var = tmpvars[ntmpvars];
17407 assert( var != NULL );
17408
17409 switch( SCIPvarGetStatus(var) )
17410 {
17412 if( var->data.original.transvar == NULL )
17413 {
17414 SCIPerrorMessage("original variable has no transformed variable attached\n");
17415 SCIPABORT();
17416 return SCIP_INVALIDDATA; /*lint !e527*/
17417 }
17418 tmpvars[ntmpvars] = var->data.original.transvar;
17419 ++ntmpvars;
17420 break;
17421
17423 tmpvars[ntmpvars] = var->data.aggregate.var;
17424 ++ntmpvars;
17425 break;
17426
17428 tmpvars[ntmpvars] = var->negatedvar;
17429 ++ntmpvars;
17430 break;
17431
17434 /* check for space in temporary memory */
17435 if( nactivevars >= activevarssize )
17436 {
17437 activevarssize *= 2;
17438 SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
17439 assert(nactivevars < activevarssize);
17440 }
17441 activevars[nactivevars] = var;
17442 nactivevars++;
17443 break;
17444
17446 /* x = a_1*y_1 + ... + a_n*y_n + c */
17447 nmultvars = var->data.multaggr.nvars;
17448 multvars = var->data.multaggr.vars;
17449
17450 /* check for space in temporary memory */
17451 if( nmultvars + ntmpvars > tmpvarssize )
17452 {
17453 while( nmultvars + ntmpvars > tmpvarssize )
17454 tmpvarssize *= 2;
17455 SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
17456 assert(nmultvars + ntmpvars <= tmpvarssize);
17457 }
17458
17459 /* copy all multi-aggregation variables into our working array */
17460 BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
17461
17462 /* get active, fixed or multi-aggregated corresponding variables for all new ones */
17463 SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
17464
17465 ntmpvars += nmultvars;
17466 noldtmpvars = ntmpvars;
17467
17468 /* sort all variables to combine equal variables easily */
17469 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17470 for( v = ntmpvars - 1; v > 0; --v )
17471 {
17472 /* combine same variables */
17473 if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
17474 {
17475 --ntmpvars;
17476 tmpvars[v] = tmpvars[ntmpvars];
17477 }
17478 }
17479 /* sort all variables again to combine equal variables later on */
17480 if( noldtmpvars > ntmpvars )
17481 SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
17482
17483 break;
17484
17486 /* no need for memorizing fixed variables */
17487 break;
17488
17489 default:
17490 SCIPerrorMessage("unknown variable status\n");
17491 SCIPABORT();
17492 return SCIP_INVALIDDATA; /*lint !e527*/
17493 }
17494 }
17495
17496 /* sort variable array by variable index */
17497 SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
17498
17499 /* eliminate duplicates and count required size */
17500 v = nactivevars - 1;
17501 while( v > 0 )
17502 {
17503 /* combine both variable since they are the same */
17504 if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
17505 {
17506 --nactivevars;
17507 activevars[v] = activevars[nactivevars];
17508 }
17509 --v;
17510 }
17511 *requiredsize = nactivevars;
17512
17513 if( varssize >= *requiredsize )
17514 {
17515 assert(vars != NULL);
17516
17517 *nvars = *requiredsize;
17518 BMScopyMemoryArray(vars, activevars, nactivevars);
17519 }
17520
17521 SCIPsetFreeBufferArray(set, &tmpvars);
17522 SCIPsetFreeBufferArray(set, &activevars);
17523
17524 return SCIP_OKAY;
17525}
17526
17527/** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
17528 * @note the content of the given array will/might change
17529 */
17531 SCIP_VAR** vars, /**< array of problem variables */
17532 int nvars /**< number of variables */
17533 )
17534{
17535 int v;
17536
17537 assert(vars != NULL || nvars == 0);
17538
17539 for( v = nvars - 1; v >= 0; --v )
17540 {
17541 assert(vars != NULL);
17542 assert(vars[v] != NULL);
17543
17544 vars[v] = SCIPvarGetProbvar(vars[v]);
17545 assert(vars[v] != NULL);
17546 }
17547}
17548
17549/** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
17551 SCIP_VAR* var /**< problem variable */
17552 )
17553{
17554 SCIP_VAR* retvar;
17555
17556 assert(var != NULL);
17557
17558 retvar = var;
17559
17560 SCIPdebugMessage("get problem variable of <%s>\n", var->name);
17561
17562 while( TRUE ) /*lint !e716 */
17563 {
17564 assert(retvar != NULL);
17565
17566 switch( SCIPvarGetStatus(retvar) )
17567 {
17569 if( retvar->data.original.transvar == NULL )
17570 {
17571 SCIPerrorMessage("original variable has no transformed variable attached\n");
17572 SCIPABORT();
17573 return NULL; /*lint !e527 */
17574 }
17575 retvar = retvar->data.original.transvar;
17576 break;
17577
17581 return retvar;
17582
17584 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17585 if ( retvar->data.multaggr.nvars == 1 )
17586 retvar = retvar->data.multaggr.vars[0];
17587 else
17588 return retvar;
17589 break;
17590
17592 retvar = retvar->data.aggregate.var;
17593 break;
17594
17596 retvar = retvar->negatedvar;
17597 break;
17598
17599 default:
17600 SCIPerrorMessage("unknown variable status\n");
17601 SCIPABORT();
17602 return NULL; /*lint !e527*/
17603 }
17604 }
17605}
17606
17607/** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
17608 * negation status of each variable
17609 */
17611 SCIP_VAR*** vars, /**< pointer to binary problem variables */
17612 SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
17613 int nvars /**< number of variables and values in vars and negated array */
17614 )
17615{
17616 SCIP_VAR** var;
17617 SCIP_Bool* negated;
17618 int v;
17619
17620 assert(vars != NULL);
17621 assert(*vars != NULL || nvars == 0);
17622 assert(negatedarr != NULL);
17623 assert(*negatedarr != NULL || nvars == 0);
17624
17625 for( v = nvars - 1; v >= 0; --v )
17626 {
17627 var = &((*vars)[v]);
17628 negated = &((*negatedarr)[v]);
17629
17630 /* get problem variable */
17632 }
17633
17634 return SCIP_OKAY;
17635}
17636
17637
17638/** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
17639 * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
17640 * FALSE is used)
17641 */
17643 SCIP_VAR** var, /**< pointer to binary problem variable */
17644 SCIP_Bool* negated /**< pointer to update the negation status */
17645 )
17646{
17648#ifndef NDEBUG
17649 SCIP_Real constant = 0.0;
17650 SCIP_Bool orignegated;
17651#endif
17652
17653 assert(var != NULL);
17654 assert(*var != NULL);
17655 assert(negated != NULL);
17657
17658#ifndef NDEBUG
17659 orignegated = *negated;
17660#endif
17661
17662 while( !active && *var != NULL )
17663 {
17664 switch( SCIPvarGetStatus(*var) )
17665 {
17667 if( (*var)->data.original.transvar == NULL )
17668 return SCIP_OKAY;
17669 *var = (*var)->data.original.transvar;
17670 break;
17671
17675 active = TRUE;
17676 break;
17677
17679 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17680 if ( (*var)->data.multaggr.nvars == 1 )
17681 {
17682 assert( (*var)->data.multaggr.vars != NULL );
17683 assert( (*var)->data.multaggr.scalars != NULL );
17684 assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
17685 assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
17686
17687 /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
17688 * another variable which needs to be fixed
17689 *
17690 * e.g. x = y - 1 => (x = 0 && y = 1)
17691 * e.g. x = y + 1 => (x = 1 && y = 0)
17692 *
17693 * is this special case we need to return the muti-aggregation
17694 */
17695 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)) )
17696 {
17697 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
17698 }
17699 else
17700 {
17701 /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
17702 * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
17703 * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
17704 * we will return the aggregated variable;
17705 */
17706 if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
17707 {
17708 active = TRUE;
17709 break;
17710 }
17711
17712 /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
17713 * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
17714 * so if this is the case, we will return the aggregated variable
17715 */
17716 assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
17717 || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
17718 || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
17719
17720 if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
17721 {
17722 active = TRUE;
17723 break;
17724 }
17725
17726 assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
17727
17728 if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
17729 {
17730 /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
17731 * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
17732 * variable itself is multi-aggregated again?
17733 */
17734 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
17735 ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
17736 SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
17737 }
17738 else
17739 {
17740 assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
17741#ifndef NDEBUG
17742 constant += (*negated) != orignegated ? -1.0 : 1.0;
17743#endif
17744
17745 *negated = !(*negated);
17746 }
17747 *var = (*var)->data.multaggr.vars[0];
17748 break;
17749 }
17750 }
17751 active = TRUE; /*lint !e838*/
17752 break;
17753
17754 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17755 assert((*var)->data.aggregate.var != NULL);
17756 assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
17757 assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
17758#ifndef NDEBUG
17759 constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
17760#endif
17761
17762 *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
17763 *var = (*var)->data.aggregate.var;
17764 break;
17765
17766 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17767 assert((*var)->negatedvar != NULL);
17768#ifndef NDEBUG
17769 constant += (*negated) != orignegated ? -1.0 : 1.0;
17770#endif
17771
17772 *negated = !(*negated);
17773 *var = (*var)->negatedvar;
17774 break;
17775
17776 default:
17777 SCIPerrorMessage("unknown variable status\n");
17778 return SCIP_INVALIDDATA;
17779 }
17780 }
17781 assert(active == (*var != NULL));
17782
17783 if( active )
17784 {
17786 assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
17787 assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
17788
17789 return SCIP_OKAY;
17790 }
17791 else
17792 {
17793 SCIPerrorMessage("active variable path leads to NULL pointer\n");
17794 return SCIP_INVALIDDATA;
17795 }
17796}
17797
17798/** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
17799 * values
17800 */
17802 SCIP_VAR** var, /**< pointer to problem variable */
17803 SCIP_Real* bound, /**< pointer to bound value to transform */
17804 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
17805 )
17806{
17807 assert(var != NULL);
17808 assert(*var != NULL);
17809 assert(bound != NULL);
17810 assert(boundtype != NULL);
17811
17812 SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
17813
17814 switch( SCIPvarGetStatus(*var) )
17815 {
17817 if( (*var)->data.original.transvar == NULL )
17818 {
17819 SCIPerrorMessage("original variable has no transformed variable attached\n");
17820 return SCIP_INVALIDDATA;
17821 }
17822 *var = (*var)->data.original.transvar;
17823 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17824 break;
17825
17829 break;
17830
17832 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17833 if ( (*var)->data.multaggr.nvars == 1 )
17834 {
17835 assert( (*var)->data.multaggr.vars != NULL );
17836 assert( (*var)->data.multaggr.scalars != NULL );
17837 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
17838
17839 (*bound) /= (*var)->data.multaggr.scalars[0];
17840 (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
17841 if ( (*var)->data.multaggr.scalars[0] < 0.0 )
17842 {
17843 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
17844 *boundtype = SCIP_BOUNDTYPE_UPPER;
17845 else
17846 *boundtype = SCIP_BOUNDTYPE_LOWER;
17847 }
17848 *var = (*var)->data.multaggr.vars[0];
17849 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17850 }
17851 break;
17852
17853 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
17854 assert((*var)->data.aggregate.var != NULL);
17855 assert((*var)->data.aggregate.scalar != 0.0);
17856
17857 (*bound) /= (*var)->data.aggregate.scalar;
17858 (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
17859 if( (*var)->data.aggregate.scalar < 0.0 )
17860 {
17861 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17862 *boundtype = SCIP_BOUNDTYPE_UPPER;
17863 else
17864 *boundtype = SCIP_BOUNDTYPE_LOWER;
17865 }
17866 *var = (*var)->data.aggregate.var;
17867 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17868 break;
17869
17870 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
17871 assert((*var)->negatedvar != NULL);
17872 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
17873 assert((*var)->negatedvar->negatedvar == *var);
17874 (*bound) = (*var)->data.negate.constant - *bound;
17875 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17876 *boundtype = SCIP_BOUNDTYPE_UPPER;
17877 else
17878 *boundtype = SCIP_BOUNDTYPE_LOWER;
17879 *var = (*var)->negatedvar;
17880 SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
17881 break;
17882
17883 default:
17884 SCIPerrorMessage("unknown variable status\n");
17885 return SCIP_INVALIDDATA;
17886 }
17887
17888 return SCIP_OKAY;
17889}
17890
17891/** transforms given variable, boundtype and exact bound to the corresponding active, fixed, or multi-aggregated variable
17892 * values
17893 */
17895 SCIP_VAR** var, /**< pointer to problem variable */
17896 SCIP_RATIONAL* bound, /**< pointer to bound value to transform */
17897 SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
17898 )
17899{
17900 assert(var != NULL);
17901 assert(*var != NULL);
17902 assert(bound != NULL);
17903 assert(boundtype != NULL);
17904
17905 SCIPrationalDebugMessage("get probvar bound %q of type %d of variable <%s>\n", bound, *boundtype, (*var)->name);
17906
17907 switch( SCIPvarGetStatusExact(*var) )
17908 {
17910 if( (*var)->data.original.transvar == NULL )
17911 {
17912 SCIPerrorMessage("original variable has no transformed variable attached\n");
17913 return SCIP_INVALIDDATA;
17914 }
17915 *var = (*var)->data.original.transvar;
17917 break;
17918
17922 break;
17923
17925 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17926 if( (*var)->data.multaggr.nvars == 1 )
17927 {
17928 assert( (*var)->data.multaggr.vars != NULL );
17929 assert( (*var)->data.multaggr.scalars != NULL );
17930 assert( (*var)->data.multaggr.scalars[0] != 0.0 );
17931
17932 SCIPrationalDiff(bound, bound, (*var)->exactdata->multaggr.constant);
17933 SCIPrationalDiv(bound, bound, (*var)->exactdata->multaggr.scalars[0]);
17934
17935 if( SCIPrationalIsNegative((*var)->exactdata->multaggr.scalars[0]) )
17936 {
17937 if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
17938 *boundtype = SCIP_BOUNDTYPE_UPPER;
17939 else
17940 *boundtype = SCIP_BOUNDTYPE_LOWER;
17941 }
17942 *var = (*var)->data.multaggr.vars[0];
17944 }
17945 break;
17946
17947 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
17948 assert((*var)->data.aggregate.var != NULL);
17949 assert((*var)->data.aggregate.scalar != 0.0);
17950
17951 SCIPrationalDiff(bound, bound, (*var)->exactdata->aggregate.constant);
17952 SCIPrationalDiv(bound, bound, (*var)->exactdata->aggregate.scalar);
17953
17954 if( SCIPrationalIsNegative((*var)->exactdata->aggregate.scalar) )
17955 {
17956 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17957 *boundtype = SCIP_BOUNDTYPE_UPPER;
17958 else
17959 *boundtype = SCIP_BOUNDTYPE_LOWER;
17960 }
17961 *var = (*var)->data.aggregate.var;
17963 break;
17964
17965 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
17966 assert((*var)->negatedvar != NULL);
17967 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
17968 assert((*var)->negatedvar->negatedvar == *var);
17969 SCIPrationalDiffReal(bound, bound, (*var)->data.negate.constant);
17971 if( *boundtype == SCIP_BOUNDTYPE_LOWER )
17972 *boundtype = SCIP_BOUNDTYPE_UPPER;
17973 else
17974 *boundtype = SCIP_BOUNDTYPE_LOWER;
17975 *var = (*var)->negatedvar;
17977 break;
17978
17979 default:
17980 SCIPerrorMessage("unknown variable status\n");
17981 return SCIP_INVALIDDATA;
17982 }
17983
17984 return SCIP_OKAY;
17985}
17986
17987/** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
17988 * values
17989 */
17991 SCIP_VAR** var, /**< pointer to problem variable */
17992 SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
17993 SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
17994 )
17995{
17996 assert(var != NULL);
17997 assert(*var != NULL);
17998 assert(left != NULL);
17999 assert(right != NULL);
18000
18001 SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
18002
18003 switch( SCIPvarGetStatus(*var) )
18004 {
18006 if( (*var)->data.original.transvar == NULL )
18007 {
18008 SCIPerrorMessage("original variable has no transformed variable attached\n");
18009 return SCIP_INVALIDDATA;
18010 }
18011 *var = (*var)->data.original.transvar;
18012 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
18013 break;
18014
18019 break;
18020
18021 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
18022 assert((*var)->data.aggregate.var != NULL);
18023 assert((*var)->data.aggregate.scalar != 0.0);
18024
18025 /* scale back */
18026 (*left) /= (*var)->data.aggregate.scalar;
18027 (*right) /= (*var)->data.aggregate.scalar;
18028
18029 /* shift back */
18030 (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
18031 (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
18032
18033 *var = (*var)->data.aggregate.var;
18034
18035 /* check if the interval bounds have to swapped */
18036 if( (*var)->data.aggregate.scalar < 0.0 )
18037 {
18038 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
18039 }
18040 else
18041 {
18042 SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
18043 }
18044 break;
18045
18046 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18047 assert((*var)->negatedvar != NULL);
18048 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18049 assert((*var)->negatedvar->negatedvar == *var);
18050
18051 /* shift and scale back */
18052 (*left) = (*var)->data.negate.constant - (*left);
18053 (*right) = (*var)->data.negate.constant - (*right);
18054
18055 *var = (*var)->negatedvar;
18056
18057 /* through the negated variable the left and right interval bound have to swapped */
18058 SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
18059 break;
18060
18061 default:
18062 SCIPerrorMessage("unknown variable status\n");
18063 return SCIP_INVALIDDATA;
18064 }
18065
18066 return SCIP_OKAY;
18067}
18068
18069/** transforms given variable, scalar and constant to the corresponding active, fixed, or
18070 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
18071 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
18072 * with only one active variable (this can happen due to fixings after the multi-aggregation),
18073 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
18074 */
18076 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18077 SCIP_SET* set, /**< global SCIP settings */
18078 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
18079 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
18080 )
18081{
18082 assert(var != NULL);
18083 assert(scalar != NULL);
18084 assert(constant != NULL);
18085
18086 while( *var != NULL )
18087 {
18088 switch( SCIPvarGetStatus(*var) )
18089 {
18091 if( (*var)->data.original.transvar == NULL )
18092 {
18093 SCIPerrorMessage("original variable has no transformed variable attached\n");
18094 return SCIP_INVALIDDATA;
18095 }
18096 *var = (*var)->data.original.transvar;
18097 break;
18098
18101 return SCIP_OKAY;
18102
18103 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
18104 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18105 {
18106 if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
18107 {
18108 assert(*scalar != 0.0);
18109 if( (*scalar) * (*var)->glbdom.lb > 0.0 )
18110 (*constant) = SCIPsetInfinity(set);
18111 else
18112 (*constant) = -SCIPsetInfinity(set);
18113 }
18114 else
18115 (*constant) += *scalar * (*var)->glbdom.lb;
18116 }
18117#ifndef NDEBUG
18118 else
18119 {
18120 assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
18121 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
18122 assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
18123 (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
18124 }
18125#endif
18126 *scalar = 0.0;
18127 return SCIP_OKAY;
18128
18130 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
18131 if ( (*var)->data.multaggr.nvars == 1 )
18132 {
18133 assert((*var)->data.multaggr.vars != NULL);
18134 assert((*var)->data.multaggr.scalars != NULL);
18135 assert((*var)->data.multaggr.vars[0] != NULL);
18136 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18137 {
18138 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
18139 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
18140 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
18141 */
18142 if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
18143 || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
18144 {
18145 if( (*scalar) * (*var)->data.multaggr.constant > 0 )
18146 {
18147 assert(!SCIPsetIsInfinity(set, -(*constant)));
18148 (*constant) = SCIPsetInfinity(set);
18149 }
18150 else
18151 {
18152 assert(!SCIPsetIsInfinity(set, *constant));
18153 (*constant) = -SCIPsetInfinity(set);
18154 }
18155 (*scalar) = 0.0;
18156 }
18157 else
18158 (*constant) += *scalar * (*var)->data.multaggr.constant;
18159 }
18160 (*scalar) *= (*var)->data.multaggr.scalars[0];
18161 *var = (*var)->data.multaggr.vars[0];
18162 break;
18163 }
18164 return SCIP_OKAY;
18165
18166 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18167 assert((*var)->data.aggregate.var != NULL);
18168 assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
18169 && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
18170 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18171 (*constant) += *scalar * (*var)->data.aggregate.constant;
18172 (*scalar) *= (*var)->data.aggregate.scalar;
18173 *var = (*var)->data.aggregate.var;
18174 break;
18175
18176 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18177 assert((*var)->negatedvar != NULL);
18178 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18179 assert((*var)->negatedvar->negatedvar == *var);
18180 assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
18181 && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
18182 if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
18183 (*constant) += *scalar * (*var)->data.negate.constant;
18184 (*scalar) *= -1.0;
18185 *var = (*var)->negatedvar;
18186 break;
18187
18188 default:
18189 SCIPerrorMessage("unknown variable status\n");
18190 SCIPABORT();
18191 return SCIP_INVALIDDATA; /*lint !e527*/
18192 }
18193 }
18194 *scalar = 0.0;
18195
18196 return SCIP_OKAY;
18197}
18198
18199/** transforms given variable, scalar and constant to the corresponding active, fixed, or
18200 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
18201 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
18202 * with only one active variable (this can happen due to fixings after the multi-aggregation),
18203 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
18204 */
18206 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18207 SCIP_RATIONAL* scalar, /**< pointer to scalar a in sum a*x + c */
18208 SCIP_RATIONAL* constant /**< pointer to constant c in sum a*x + c */
18209 )
18210{
18211 assert(var != NULL);
18212 assert(scalar != NULL);
18213 assert(constant != NULL);
18215
18216 while( *var != NULL )
18217 {
18218 switch( SCIPvarGetStatusExact(*var) )
18219 {
18221 if( (*var)->data.original.transvar == NULL )
18222 {
18223 SCIPerrorMessage("original variable has no transformed variable attached\n");
18224 return SCIP_INVALIDDATA;
18225 }
18226 *var = (*var)->data.original.transvar;
18227 break;
18228
18231 return SCIP_OKAY;
18232
18233 case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
18234 if( !SCIPrationalIsInfinity(constant) && !SCIPrationalIsNegInfinity(constant) )
18235 {
18236 if( SCIPrationalIsInfinity((*var)->exactdata->glbdom.lb) || SCIPrationalIsNegInfinity(((*var)->exactdata->glbdom.lb)) )
18237 {
18238 assert(!SCIPrationalIsZero(scalar));
18239 if( SCIPrationalIsPositive(scalar) == SCIPrationalIsPositive((*var)->exactdata->glbdom.lb) )
18240 SCIPrationalSetInfinity(constant);
18241 else
18243 }
18244 else
18245 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->glbdom.lb);
18246 }
18247 SCIPrationalSetReal(scalar, 0.0);
18248 return SCIP_OKAY;
18249
18251 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
18252 if ( (*var)->data.multaggr.nvars == 1 )
18253 {
18254 assert((*var)->data.multaggr.vars != NULL);
18255 assert((*var)->data.multaggr.scalars != NULL);
18256 assert((*var)->data.multaggr.vars[0] != NULL);
18257 if( !SCIPrationalIsAbsInfinity(constant) )
18258 {
18259 /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
18260 * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
18261 * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
18262 */
18263 if( SCIPrationalIsAbsInfinity((*var)->exactdata->multaggr.constant) )
18264 {
18265 if( SCIPrationalGetSign(scalar) == SCIPrationalGetSign((*var)->exactdata->multaggr.constant) && !SCIPrationalIsZero(scalar) )
18266 {
18268 SCIPrationalSetInfinity(constant);
18269 }
18270 else
18271 {
18272 assert(!SCIPrationalIsInfinity(constant));
18274 }
18275 SCIPrationalSetReal(scalar, 0.0);
18276 }
18277 else
18278 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->multaggr.constant);
18279 }
18280 SCIPrationalMult(scalar, scalar, (*var)->exactdata->multaggr.scalars[0]);
18281 *var = (*var)->data.multaggr.vars[0];
18282 break;
18283 }
18284 return SCIP_OKAY;
18285
18286 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
18287 assert((*var)->data.aggregate.var != NULL);
18288 assert(!SCIPrationalIsAbsInfinity((*var)->exactdata->aggregate.constant));
18289 if( !SCIPrationalIsAbsInfinity(constant) )
18290 SCIPrationalAddProd(constant, scalar, (*var)->exactdata->aggregate.constant);
18291 SCIPrationalMult(scalar, scalar, (*var)->exactdata->aggregate.scalar);
18292 *var = (*var)->data.aggregate.var;
18293 break;
18294 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
18295 assert((*var)->negatedvar != NULL);
18296 assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
18297 assert((*var)->negatedvar->negatedvar == *var);
18298 if( !SCIPrationalIsInfinity(constant) && !SCIPrationalIsNegInfinity(constant) )
18299 SCIPrationalAddProdReal(constant, scalar, (*var)->data.negate.constant);
18300
18301 SCIPrationalNegate(scalar, scalar);
18302 *var = (*var)->negatedvar;
18303 break;
18304
18305 default:
18306 SCIPerrorMessage("unknown variable status\n");
18307 SCIPABORT();
18308 return SCIP_INVALIDDATA; /*lint !e527*/
18309 }
18310 }
18311 SCIPrationalSetReal(scalar, 0.0);
18312
18313 return SCIP_OKAY;
18314}
18315
18316
18317/** retransforms given variable, scalar and constant to the corresponding original variable, scalar
18318 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
18319 */
18321 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18322 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
18323 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
18324 )
18325{
18326 SCIP_VAR* parentvar;
18327
18328 assert(var != NULL);
18329 assert(*var != NULL);
18330 assert(scalar != NULL);
18331 assert(constant != NULL);
18332
18333 while( !SCIPvarIsOriginal(*var) )
18334 {
18335 /* if the variable has no parent variables, it was generated during solving and has no corresponding original
18336 * var
18337 */
18338 if( (*var)->nparentvars == 0 )
18339 {
18340 /* negated variables do not need to have a parent variables, and negated variables can exist in original
18341 * space
18342 */
18344 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
18345 {
18346 *scalar *= -1.0;
18347 *constant -= (*var)->data.negate.constant * (*scalar);
18348 *var = (*var)->negatedvar;
18349
18350 continue;
18351 }
18352 /* if the variables does not have any parent the variables was created during solving and has no original
18353 * counterpart
18354 */
18355 else
18356 {
18357 *var = NULL;
18358
18359 return SCIP_OKAY;
18360 }
18361 }
18362
18363 /* follow the link to the first parent variable */
18364 parentvar = (*var)->parentvars[0];
18365 assert(parentvar != NULL);
18366
18367 switch( SCIPvarGetStatus(parentvar) )
18368 {
18370 break;
18371
18376 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
18377 return SCIP_INVALIDDATA;
18378
18379 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
18380 assert(parentvar->data.aggregate.var == *var);
18381 assert(parentvar->data.aggregate.scalar != 0.0);
18382 *scalar /= parentvar->data.aggregate.scalar;
18383 *constant -= parentvar->data.aggregate.constant * (*scalar);
18384 break;
18385
18386 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
18387 assert(parentvar->negatedvar != NULL);
18389 assert(parentvar->negatedvar->negatedvar == parentvar);
18390 *scalar *= -1.0;
18391 *constant -= parentvar->data.negate.constant * (*scalar);
18392 break;
18393
18394 default:
18395 SCIPerrorMessage("unknown variable status\n");
18396 return SCIP_INVALIDDATA;
18397 }
18398
18399 assert( parentvar != NULL );
18400 *var = parentvar;
18401 }
18402
18403 return SCIP_OKAY;
18404}
18405
18406/** retransforms given variable, scalar anqd constant to the corresponding original variable, scalar
18407 * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
18408 */
18410 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
18411 SCIP_RATIONAL* scalar, /**< pointer to scalar a in sum a*x + c */
18412 SCIP_RATIONAL* constant /**< pointer to constant c in sum a*x + c */
18413 )
18414{
18415 SCIP_VAR* parentvar;
18416
18417 assert(var != NULL);
18418 assert(*var != NULL);
18419 assert(scalar != NULL);
18420 assert(constant != NULL);
18421
18422 while( !SCIPvarIsOriginal(*var) )
18423 {
18424 /* if the variable has no parent variables, it was generated during solving and has no corresponding original
18425 * var
18426 */
18427 if( (*var)->nparentvars == 0 )
18428 {
18429 /* negated variables do not need to have a parent variables, and negated variables can exist in original
18430 * space
18431 */
18433 ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
18434 {
18435 SCIPrationalNegate(scalar, scalar);
18436 SCIPrationalDiffProdReal(constant, scalar, (*var)->data.negate.constant);
18437 *var = (*var)->negatedvar;
18438
18439 continue;
18440 }
18441 /* if the variables does not have any parent the variables was created during solving and has no original
18442 * counterpart
18443 */
18444 else
18445 {
18446 *var = NULL;
18447
18448 return SCIP_OKAY;
18449 }
18450 }
18451
18452 /* follow the link to the first parent variable */
18453 parentvar = (*var)->parentvars[0];
18454 assert(parentvar != NULL);
18455
18456 switch( SCIPvarGetStatusExact(parentvar) )
18457 {
18459 break;
18460
18465 SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
18466 return SCIP_INVALIDDATA;
18467
18468 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
18469 assert(parentvar->data.aggregate.var == *var);
18470 assert(parentvar->data.aggregate.scalar != 0.0);
18471 SCIPrationalDiv(scalar, scalar, parentvar->exactdata->aggregate.scalar);
18472 SCIPrationalDiffProd(constant, scalar, parentvar->exactdata->aggregate.constant);
18473 break;
18474
18475 case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
18476 assert(parentvar->negatedvar != NULL);
18478 assert(parentvar->negatedvar->negatedvar == parentvar);
18479 SCIPrationalNegate(scalar, scalar);
18480 SCIPrationalDiffProdReal(constant, scalar, parentvar->data.negate.constant);
18481 break;
18482
18483 default:
18484 SCIPerrorMessage("unknown variable status\n");
18485 return SCIP_INVALIDDATA;
18486 }
18487
18488 assert( parentvar != NULL );
18489 *var = parentvar;
18490 }
18491
18492 return SCIP_OKAY;
18493}
18494
18495
18496/** returns whether the given variable is the direct counterpart of an original problem variable */
18498 SCIP_VAR* var /**< problem variable */
18499 )
18500{
18501 SCIP_VAR* parentvar;
18502 assert(var != NULL);
18503
18504 if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
18505 return FALSE;
18506
18507 assert(var->parentvars != NULL);
18508 parentvar = var->parentvars[0];
18509 assert(parentvar != NULL);
18510
18511 /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
18512 while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
18513 parentvar = parentvar->parentvars[0];
18514 assert( parentvar != NULL );
18515
18516 return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
18517}
18518
18519/** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
18520 * the variable's own data due to diving, that operate only on the LP without updating the variables
18521 */
18523 SCIP_VAR* var /**< problem variable */
18524 )
18525{
18526 assert(var != NULL);
18527
18528 /* get bounds of attached variables */
18529 switch( SCIPvarGetStatus(var) )
18530 {
18532 assert(var->data.original.transvar != NULL);
18533 return SCIPvarGetObjLP(var->data.original.transvar);
18534
18536 assert(var->data.col != NULL);
18537 return SCIPcolGetObj(var->data.col);
18538
18541 return var->obj;
18542
18543 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18544 assert(var->data.aggregate.var != NULL);
18545 return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
18546
18548 SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
18549 SCIPABORT();
18550 return 0.0; /*lint !e527*/
18551
18552 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18553 assert(var->negatedvar != NULL);
18555 assert(var->negatedvar->negatedvar == var);
18556 return -SCIPvarGetObjLP(var->negatedvar);
18557
18558 default:
18559 SCIPerrorMessage("unknown variable status\n");
18560 SCIPABORT();
18561 return 0.0; /*lint !e527*/
18562 }
18563}
18564
18565/** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
18566 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
18567 */
18569 SCIP_VAR* var, /**< problem variable */
18570 SCIP_SET* set /**< global SCIP settings */
18571 )
18572{
18573 assert(var != NULL);
18574 assert(set != NULL);
18575 assert(var->scip == set->scip);
18576
18577 /* get bounds of attached variables */
18578 switch( SCIPvarGetStatus(var) )
18579 {
18581 assert(var->data.original.transvar != NULL);
18582 return SCIPvarGetLbLP(var->data.original.transvar, set);
18583
18585 assert(var->data.col != NULL);
18586 return SCIPcolGetLb(var->data.col);
18587
18590 return var->locdom.lb;
18591
18592 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18593 assert(var->data.aggregate.var != NULL);
18594 if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
18595 || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
18596 {
18597 return -SCIPsetInfinity(set);
18598 }
18599 else if( var->data.aggregate.scalar > 0.0 )
18600 {
18601 /* a > 0 -> get lower bound of y */
18602 return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18603 }
18604 else if( var->data.aggregate.scalar < 0.0 )
18605 {
18606 /* a < 0 -> get upper bound of y */
18607 return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18608 }
18609 else
18610 {
18611 SCIPerrorMessage("scalar is zero in aggregation\n");
18612 SCIPABORT();
18613 return SCIP_INVALID; /*lint !e527*/
18614 }
18615
18617 /**@todo get the sides of the corresponding linear constraint */
18618 SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
18619 SCIPABORT();
18620 return SCIP_INVALID; /*lint !e527*/
18621
18622 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18623 assert(var->negatedvar != NULL);
18625 assert(var->negatedvar->negatedvar == var);
18626 return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
18627
18628 default:
18629 SCIPerrorMessage("unknown variable status\n");
18630 SCIPABORT();
18631 return SCIP_INVALID; /*lint !e527*/
18632 }
18633}
18634
18635/** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
18636 * data due to diving or conflict analysis, that operate only on the LP without updating the variables
18637 */
18639 SCIP_VAR* var, /**< problem variable */
18640 SCIP_SET* set /**< global SCIP settings */
18641 )
18642{
18643 assert(var != NULL);
18644 assert(set != NULL);
18645 assert(var->scip == set->scip);
18646
18647 /* get bounds of attached variables */
18648 switch( SCIPvarGetStatus(var) )
18649 {
18651 assert(var->data.original.transvar != NULL);
18652 return SCIPvarGetUbLP(var->data.original.transvar, set);
18653
18655 assert(var->data.col != NULL);
18656 return SCIPcolGetUb(var->data.col);
18657
18660 return var->locdom.ub;
18661
18662 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
18663 assert(var->data.aggregate.var != NULL);
18664 if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
18665 || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
18666 {
18667 return SCIPsetInfinity(set);
18668 }
18669 if( var->data.aggregate.scalar > 0.0 )
18670 {
18671 /* a > 0 -> get upper bound of y */
18672 return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18673 }
18674 else if( var->data.aggregate.scalar < 0.0 )
18675 {
18676 /* a < 0 -> get lower bound of y */
18677 return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
18678 }
18679 else
18680 {
18681 SCIPerrorMessage("scalar is zero in aggregation\n");
18682 SCIPABORT();
18683 return SCIP_INVALID; /*lint !e527*/
18684 }
18685
18687 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
18688 SCIPABORT();
18689 return SCIP_INVALID; /*lint !e527*/
18690
18691 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18692 assert(var->negatedvar != NULL);
18694 assert(var->negatedvar->negatedvar == var);
18695 return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
18696
18697 default:
18698 SCIPerrorMessage("unknown variable status\n");
18699 SCIPABORT();
18700 return SCIP_INVALID; /*lint !e527*/
18701 }
18702}
18703
18704/** gets primal LP solution value of variable */
18706 SCIP_VAR* var /**< problem variable */
18707 )
18708{
18709 assert(var != NULL);
18710
18711 switch( SCIPvarGetStatus(var) )
18712 {
18714 if( var->data.original.transvar == NULL )
18715 return SCIP_INVALID;
18716 return SCIPvarGetLPSol(var->data.original.transvar);
18717
18720
18722 assert(var->data.col != NULL);
18723 return SCIPcolGetPrimsol(var->data.col);
18724
18726 assert(var->locdom.lb == var->locdom.ub || (var->exactdata != NULL && SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub))); /*lint !e777*/
18727 return var->locdom.lb;
18728
18730 {
18731 SCIP_Real lpsolval;
18732
18733 assert(!var->donotaggr);
18734 assert(var->data.aggregate.var != NULL);
18735 lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
18736
18737 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
18738 * corresponding infinity value instead of performing an arithmetical transformation (compare method
18739 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
18740 * (or is called by) a public interface method; instead, we only assert that values are finite
18741 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
18742 * positives and negatives if the parameter <numerics/infinity> is modified by the user
18743 */
18744// assert(lpsolval > -SCIP_DEFAULT_INFINITY);
18745// assert(lpsolval < +SCIP_DEFAULT_INFINITY);
18746
18747 if( lpsolval >= SCIP_DEFAULT_INFINITY )
18748 return (var->data.aggregate.scalar > 0) ? SCIP_DEFAULT_INFINITY : -SCIP_DEFAULT_INFINITY;
18749 else if( lpsolval <= -SCIP_DEFAULT_INFINITY )
18750 return (var->data.aggregate.scalar > 0) ? -SCIP_DEFAULT_INFINITY : SCIP_DEFAULT_INFINITY;
18751
18752 return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
18753 }
18755 {
18757 int i;
18758
18759 assert(!var->donotmultaggr);
18760 assert(var->data.multaggr.vars != NULL);
18761 assert(var->data.multaggr.scalars != NULL);
18762 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18763 * assert(var->data.multaggr.nvars >= 2);
18764 */
18765 primsol = var->data.multaggr.constant;
18766 for( i = 0; i < var->data.multaggr.nvars; ++i )
18767 primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
18768 return primsol;
18769 }
18770 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18771 assert(var->negatedvar != NULL);
18773 assert(var->negatedvar->negatedvar == var);
18774 return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
18775
18776 default:
18777 SCIPerrorMessage("unknown variable status\n");
18778 SCIPABORT();
18779 return SCIP_INVALID; /*lint !e527*/
18780 }
18781}
18782
18783/** gets exact primal LP solution value of variable or value of safe dual solution */
18785 SCIP_VAR* var, /**< problem variable */
18786 SCIP_RATIONAL* res /**< store the resulting value */
18787 )
18788{
18789 assert(var != NULL);
18790
18791 switch( SCIPvarGetStatusExact(var) )
18792 {
18794 if( var->data.original.transvar == NULL )
18796 SCIPvarGetLPSolExact(var->data.original.transvar, res);
18797 break;
18798
18801 break;
18802
18804 assert(var->data.col != NULL);
18805 SCIPrationalSetRational(res, SCIPcolExactGetPrimsol(var->exactdata->colexact));
18806 break;
18807
18809 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub)); /*lint !e777*/
18810 SCIPrationalSetRational(res, var->exactdata->locdom.lb);
18811 break;
18812
18814 assert(var->data.aggregate.var != NULL);
18815 SCIPvarGetLPSolExact(var->data.aggregate.var, res);
18816 SCIPrationalMult(res, res, var->exactdata->aggregate.scalar);
18817 SCIPrationalAdd(res, res, var->exactdata->aggregate.constant);
18818 break;
18819
18821 {
18822 SCIP_RATIONAL* tmp;
18823 int i;
18824
18825 assert(!var->donotmultaggr);
18826 assert(var->data.multaggr.vars != NULL);
18827 assert(var->data.multaggr.scalars != NULL);
18828
18829 (void) SCIPrationalCreate(&tmp);
18830 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18831 * assert(var->data.multaggr.nvars >= 2);
18832 */
18833 SCIPrationalSetRational(res, var->exactdata->multaggr.constant);
18834 for( i = 0; i < var->data.multaggr.nvars; ++i )
18835 {
18836 SCIPvarGetLPSolExact(var->data.multaggr.vars[i], tmp);
18837 SCIPrationalAddProd(res, var->exactdata->multaggr.scalars[i], tmp);
18838 }
18839 SCIPrationalFree(&tmp);
18840 break;
18841 }
18842
18843 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18844 assert(var->negatedvar != NULL);
18846 assert(var->negatedvar->negatedvar == var);
18847 SCIPvarGetLPSolExact(var->negatedvar, res);
18848 SCIPrationalDiffReal(res, res, var->data.negate.constant);
18849 SCIPrationalNegate(res, res);
18850 break;
18851
18852 default:
18853 SCIPerrorMessage("unknown variable status\n");
18854 SCIPABORT();
18855 }
18856}
18857
18858/** gets primal NLP solution value of variable */
18860 SCIP_VAR* var /**< problem variable */
18861 )
18862{
18863 SCIP_Real solval;
18864 int i;
18865
18866 assert(var != NULL);
18867
18868 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
18869 switch( SCIPvarGetStatus(var) )
18870 {
18872 return SCIPvarGetNLPSol(var->data.original.transvar);
18873
18876 return var->nlpsol;
18877
18879 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
18880 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
18881 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
18882 return SCIPvarGetLbGlobal(var);
18883
18884 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
18885 solval = SCIPvarGetNLPSol(var->data.aggregate.var);
18886 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
18887
18889 solval = var->data.multaggr.constant;
18890 for( i = 0; i < var->data.multaggr.nvars; ++i )
18891 solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
18892 return solval;
18893
18895 solval = SCIPvarGetNLPSol(var->negatedvar);
18896 return var->data.negate.constant - solval;
18897
18898 default:
18899 SCIPerrorMessage("unknown variable status\n");
18900 SCIPABORT();
18901 return SCIP_INVALID; /*lint !e527*/
18902 }
18903}
18904
18905/** gets pseudo solution value of variable at current node */
18906static
18908 SCIP_VAR* var /**< problem variable */
18909 )
18910{
18911 SCIP_Real pseudosol;
18912 int i;
18913
18914 assert(var != NULL);
18915
18916 switch( SCIPvarGetStatus(var) )
18917 {
18919 if( var->data.original.transvar == NULL )
18920 return SCIP_INVALID;
18921 return SCIPvarGetPseudoSol(var->data.original.transvar);
18922
18926
18928 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
18929 return var->locdom.lb;
18930
18932 {
18933 SCIP_Real pseudosolval;
18934 assert(!var->donotaggr);
18935 assert(var->data.aggregate.var != NULL);
18936 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
18937 * corresponding infinity value instead of performing an arithmetical transformation (compare method
18938 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
18939 * (or is called by) a public interface method; instead, we only assert that values are finite
18940 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
18941 * positives and negatives if the parameter <numerics/infinity> is modified by the user
18942 */
18943 pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
18944 assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
18945 assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
18946 return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
18947 }
18949 assert(!var->donotmultaggr);
18950 assert(var->data.multaggr.vars != NULL);
18951 assert(var->data.multaggr.scalars != NULL);
18952 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
18953 * assert(var->data.multaggr.nvars >= 2);
18954 */
18955 pseudosol = var->data.multaggr.constant;
18956 for( i = 0; i < var->data.multaggr.nvars; ++i )
18957 pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
18958 return pseudosol;
18959
18960 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
18961 assert(var->negatedvar != NULL);
18963 assert(var->negatedvar->negatedvar == var);
18964 return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
18965
18966 default:
18967 SCIPerrorMessage("unknown variable status\n");
18968 SCIPABORT();
18969 return SCIP_INVALID; /*lint !e527*/
18970 }
18971}
18972
18973/** gets exact pseudo solution value of variable at current node */
18974static
18976 SCIP_VAR* var /**< problem variable */
18977 )
18978{
18979 assert(var != NULL);
18980
18981 switch( SCIPvarGetStatusExact(var) )
18982 {
18984 if( var->data.original.transvar == NULL )
18985 return NULL;
18986 return SCIPvarGetPseudoSolExact(var->data.original.transvar);
18987
18991
18993 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
18994 return var->exactdata->locdom.lb;
18995
18999 default:
19000 SCIPerrorMessage("unknown variable status\n");
19001 SCIPABORT();
19002 return NULL; /*lint !e527*/
19003 }
19004}
19005
19006/** gets current LP or pseudo solution value of variable */
19008 SCIP_VAR* var, /**< problem variable */
19009 SCIP_Bool getlpval /**< should the LP solution value be returned? */
19010 )
19011{
19012 if( getlpval )
19013 return SCIPvarGetLPSol(var);
19014 else
19015 return SCIPvarGetPseudoSol(var);
19016}
19017
19018/** gets current exact LP or pseudo solution value of variable */
19020 SCIP_VAR* var, /**< problem variable */
19021 SCIP_RATIONAL* res, /**< the resulting value */
19022 SCIP_Bool getlpval /**< should the LP solution value be returned? */
19023 )
19024{
19025 assert(var != NULL);
19026
19027 if( getlpval )
19029 else
19031}
19032
19033/** remembers the current solution as root solution in the problem variables */
19035 SCIP_VAR* var, /**< problem variable */
19036 SCIP_Bool roothaslp /**< is the root solution from LP? */
19037 )
19038{
19039 assert(var != NULL);
19040
19041 var->rootsol = SCIPvarGetSol(var, roothaslp);
19042}
19043
19044/** updates the current solution as best root solution of the given variable if it is better */
19046 SCIP_VAR* var, /**< problem variable */
19047 SCIP_SET* set, /**< global SCIP settings */
19048 SCIP_Real rootsol, /**< root solution value */
19049 SCIP_Real rootredcost, /**< root reduced cost */
19050 SCIP_Real rootlpobjval /**< objective value of the root LP */
19051 )
19052{
19053 assert(var != NULL);
19054 assert(set != NULL);
19055 assert(var->scip == set->scip);
19056
19057 /* if reduced cost are zero nothing to update */
19058 if( SCIPsetIsDualfeasZero(set, rootredcost) )
19059 return;
19060
19061 /* check if we have already a best combination stored */
19062 if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
19063 {
19064 SCIP_Real currcutoffbound;
19065 SCIP_Real cutoffbound;
19067
19068 /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
19069 * root reduced cost, and root LP objective value combination
19070 */
19071 if( var->bestrootredcost > 0.0 )
19073 else
19075
19076 currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
19077
19078 /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
19079 * cost, and root LP objective value combination
19080 */
19081 if( rootredcost > 0.0 )
19083 else
19085
19086 cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
19087
19088 /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
19089 if( cutoffbound > currcutoffbound )
19090 {
19091 SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
19092 SCIPvarGetName(var), currcutoffbound, cutoffbound);
19093
19094 var->bestrootsol = rootsol;
19095 var->bestrootredcost = rootredcost;
19096 var->bestrootlpobjval = rootlpobjval;
19097 }
19098 }
19099 else
19100 {
19101 SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
19102 SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
19103 SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
19104 SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
19105
19106 var->bestrootsol = rootsol;
19107 var->bestrootredcost = rootredcost;
19108 var->bestrootlpobjval = rootlpobjval;
19109 }
19110}
19111
19112/** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
19113 * completely solved, zero is returned
19114 */
19116 SCIP_VAR* var /**< problem variable */
19117 )
19118{
19120 int i;
19121
19122 assert(var != NULL);
19123
19124 switch( SCIPvarGetStatus(var) )
19125 {
19127 if( var->data.original.transvar == NULL )
19128 return 0.0;
19129 return SCIPvarGetRootSol(var->data.original.transvar);
19130
19133 return var->rootsol;
19134
19136 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19137 return var->locdom.lb;
19138
19140 assert(!var->donotaggr);
19141 assert(var->data.aggregate.var != NULL);
19142 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
19143 * corresponding infinity value instead of performing an arithmetical transformation (compare method
19144 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
19145 * (or is called by) a public interface method; instead, we only assert that values are finite
19146 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
19147 * positives and negatives if the parameter <numerics/infinity> is modified by the user
19148 */
19149 assert(SCIPvarGetRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
19150 assert(SCIPvarGetRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
19151 return var->data.aggregate.scalar * SCIPvarGetRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
19152
19154 assert(!var->donotmultaggr);
19155 assert(var->data.multaggr.vars != NULL);
19156 assert(var->data.multaggr.scalars != NULL);
19157 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19158 * assert(var->data.multaggr.nvars >= 2);
19159 */
19160 rootsol = var->data.multaggr.constant;
19161 for( i = 0; i < var->data.multaggr.nvars; ++i )
19162 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
19163 return rootsol;
19164
19165 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19166 assert(var->negatedvar != NULL);
19168 assert(var->negatedvar->negatedvar == var);
19169 return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
19170
19171 default:
19172 SCIPerrorMessage("unknown variable status\n");
19173 SCIPABORT();
19174 return SCIP_INVALID; /*lint !e527*/
19175 }
19176}
19177
19178/** returns for given variable the reduced cost */
19179static
19181 SCIP_VAR* var, /**< problem variable */
19182 SCIP_SET* set, /**< global SCIP settings */
19183 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
19184 SCIP_STAT* stat, /**< problem statistics */
19185 SCIP_LP* lp /**< current LP data */
19186 )
19187{
19189 {
19190 SCIP_COL* col;
19192 SCIP_BASESTAT basestat;
19193 SCIP_Bool lpissolbasic;
19194
19195 col = SCIPvarGetCol(var);
19196 assert(col != NULL);
19197
19198 basestat = SCIPcolGetBasisStatus(col);
19199 lpissolbasic = SCIPlpIsSolBasic(lp);
19201
19202 if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
19204 {
19205 SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
19206
19207 assert(set->exact_enable || (((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
19208 (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
19210 assert(set->exact_enable || (((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
19211 (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
19213
19214 if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
19215 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
19216 (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
19217 (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
19218 return redcost;
19219 else
19220 return 0.0;
19221 }
19222
19223 return 0.0;
19224 }
19225
19226 return 0.0;
19227}
19228
19229#define MAX_CLIQUELENGTH 50
19230/** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
19231 * the binary variable is fixed to the given value
19232 */
19234 SCIP_VAR* var, /**< problem variable */
19235 SCIP_SET* set, /**< global SCIP settings */
19236 SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
19237 SCIP_STAT* stat, /**< problem statistics */
19238 SCIP_PROB* prob, /**< transformed problem, or NULL */
19239 SCIP_LP* lp /**< current LP data */
19240 )
19241{
19242 SCIP_Real implredcost;
19243 int ncliques;
19244 int nvars;
19245
19248
19249 /* get reduced cost of given variable */
19250 implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
19251
19252#ifdef SCIP_MORE_DEBUG
19253 SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
19254#endif
19255
19256 /* the following algorithm is expensive */
19257 ncliques = SCIPvarGetNCliques(var, varfixing);
19258
19259 if( ncliques > 0 )
19260 {
19261 SCIP_CLIQUE** cliques;
19262 SCIP_CLIQUE* clique;
19263 SCIP_VAR** clqvars;
19264 SCIP_VAR** probvars;
19265 SCIP_VAR* clqvar;
19266 SCIP_Bool* clqvalues;
19267 int* entries;
19268 int* ids;
19269 SCIP_Real redcost;
19270 SCIP_Bool cleanedup;
19271 int nclqvars;
19272 int nentries;
19273 int nids;
19274 int id;
19275 int c;
19276 int v;
19277
19278 assert(prob != NULL);
19280
19281 nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
19282
19283 SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
19284 nids = 0;
19285 SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
19286
19287 cliques = SCIPvarGetCliques(var, varfixing);
19288 assert(cliques != NULL);
19289
19290 for( c = ncliques - 1; c >= 0; --c )
19291 {
19292 clique = cliques[c];
19293 assert(clique != NULL);
19294 nclqvars = SCIPcliqueGetNVars(clique);
19295 assert(nclqvars > 0);
19296
19297 if( nclqvars > MAX_CLIQUELENGTH )
19298 continue;
19299
19300 clqvars = SCIPcliqueGetVars(clique);
19301 clqvalues = SCIPcliqueGetValues(clique);
19302 assert(clqvars != NULL);
19303 assert(clqvalues != NULL);
19304
19305 cleanedup = SCIPcliqueIsCleanedUp(clique);
19306
19307 for( v = nclqvars - 1; v >= 0; --v )
19308 {
19309 clqvar = clqvars[v];
19310 assert(clqvar != NULL);
19311
19312 /* ignore binary variable which are fixed */
19313 if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
19314 (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
19315 {
19316 int probindex = SCIPvarGetProbindex(clqvar) + 1;
19317 assert(0 < probindex && probindex < nentries);
19318
19319#ifdef SCIP_DISABLED_CODE
19320 /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
19321 * can appear since there is no guarantee that all these infeasible bounds were found
19322 */
19323 assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
19324#endif
19325 if( entries[probindex] == 0 )
19326 {
19327 ids[nids] = probindex;
19328 ++nids;
19329
19330 /* mark variable as visited */
19331 entries[probindex] = (clqvalues[v] ? probindex : -probindex);
19332 }
19333 }
19334 }
19335 }
19336
19337 probvars = SCIPprobGetVars(prob);
19338 assert(probvars != NULL);
19339
19340 /* add all implied reduced cost */
19341 for( v = nids - 1; v >= 0; --v )
19342 {
19343 id = ids[v];
19344 assert(0 < id && id < nentries);
19345 assert(entries[id] != 0);
19346 assert(probvars[id - 1] != NULL);
19347 assert(SCIPvarIsActive(probvars[id - 1]));
19348 assert(SCIPvarIsBinary(probvars[id - 1]));
19349 assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
19350
19351 if( (entries[id] > 0) != varfixing )
19352 redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
19353 else
19354 redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
19355
19356 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
19357 implredcost += redcost;
19358
19359 /* reset entries clear buffer array */
19360 entries[id] = 0;
19361 }
19362
19365 }
19366
19367#ifdef SCIP_MORE_DEBUG
19368 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
19369 implredcost);
19370#endif
19371
19372 /* collect non-binary implication information */
19373 nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
19374
19375 if( nvars > 0 )
19376 {
19377 SCIP_VAR** vars;
19378 SCIP_VAR* implvar;
19379 SCIP_COL* col;
19380 SCIP_Real* bounds;
19381 SCIP_BOUNDTYPE* boundtypes;
19382 SCIP_Real redcost;
19383 SCIP_Real lb;
19384 SCIP_Real ub;
19385 SCIP_Bool lpissolbasic;
19386 int v;
19387
19388 vars = SCIPimplicsGetVars(var->implics, varfixing);
19389 boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
19390 bounds = SCIPimplicsGetBounds(var->implics, varfixing);
19391 lpissolbasic = SCIPlpIsSolBasic(lp);
19392
19393 for( v = nvars - 1; v >= 0; --v )
19394 {
19395 implvar = vars[v];
19396 assert(implvar != NULL);
19397
19398 lb = SCIPvarGetLbLocal(implvar);
19399 ub = SCIPvarGetUbLocal(implvar);
19400
19401 /* ignore binary variable which are fixed or not of column status */
19402 if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
19403 continue;
19404
19405 col = SCIPvarGetCol(implvar);
19406 assert(col != NULL);
19407 redcost = 0.0;
19408
19409 /* solved lp with basis information or not? */
19410 if( lpissolbasic )
19411 {
19412 SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
19413
19414 /* check if the implication is not not yet applied */
19415 if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
19416 {
19417 redcost = SCIPcolGetRedcost(col, stat, lp);
19419
19420 if( !varfixing )
19421 redcost *= (lb - bounds[v]);
19422 else
19423 redcost *= (bounds[v] - lb);
19424 }
19425 else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
19426 {
19427 redcost = SCIPcolGetRedcost(col, stat, lp);
19429
19430 if( varfixing )
19431 redcost *= (bounds[v] - ub);
19432 else
19433 redcost *= (ub - bounds[v]);
19434 }
19435 }
19436 else
19437 {
19439
19440 /* check if the implication is not not yet applied */
19441 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
19442 {
19443 redcost = SCIPcolGetRedcost(col, stat, lp);
19445
19446 if( varfixing )
19447 redcost *= (lb - bounds[v]);
19448 else
19449 redcost *= (bounds[v] - lb);
19450 }
19451 else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
19452 {
19453 redcost = SCIPcolGetRedcost(col, stat, lp);
19455
19456 if( varfixing )
19457 redcost *= (bounds[v] - ub);
19458 else
19459 redcost *= (ub - bounds[v]);
19460 }
19461 }
19462
19463 /* improve implied reduced cost */
19464 if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
19465 implredcost += redcost;
19466 }
19467 }
19468
19469#ifdef SCIP_MORE_DEBUG
19470 SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
19471 SCIPvarGetName(var), ncliques, nvars, implredcost);
19472#endif
19473
19474 return implredcost;
19475}
19476
19477/** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
19478 * the root relaxation is not yet completely solved, zero is returned
19479 */
19481 SCIP_VAR* var /**< problem variable */
19482 )
19483{
19485 int i;
19486
19487 assert(var != NULL);
19488
19489 switch( SCIPvarGetStatus(var) )
19490 {
19492 if( var->data.original.transvar == NULL )
19493 return 0.0;
19494 return SCIPvarGetBestRootSol(var->data.original.transvar);
19495
19498 return var->bestrootsol;
19499
19501 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19502 return var->locdom.lb;
19503
19505 assert(!var->donotaggr);
19506 assert(var->data.aggregate.var != NULL);
19507 /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
19508 * corresponding infinity value instead of performing an arithmetical transformation (compare method
19509 * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
19510 * (or is called by) a public interface method; instead, we only assert that values are finite
19511 * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
19512 * positives and negatives if the parameter <numerics/infinity> is modified by the user
19513 */
19514 assert(SCIPvarGetBestRootSol(var->data.aggregate.var) > -SCIP_DEFAULT_INFINITY);
19515 assert(SCIPvarGetBestRootSol(var->data.aggregate.var) < +SCIP_DEFAULT_INFINITY);
19516 return var->data.aggregate.scalar * SCIPvarGetBestRootSol(var->data.aggregate.var) + var->data.aggregate.constant;
19517
19519 assert(!var->donotmultaggr);
19520 assert(var->data.multaggr.vars != NULL);
19521 assert(var->data.multaggr.scalars != NULL);
19522 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19523 * assert(var->data.multaggr.nvars >= 2);
19524 */
19525 rootsol = var->data.multaggr.constant;
19526 for( i = 0; i < var->data.multaggr.nvars; ++i )
19527 rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
19528 return rootsol;
19529
19530 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19531 assert(var->negatedvar != NULL);
19533 assert(var->negatedvar->negatedvar == var);
19534 return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
19535
19536 default:
19537 SCIPerrorMessage("unknown variable status\n");
19538 SCIPABORT();
19539 return 0.0; /*lint !e527*/
19540 }
19541}
19542
19543/** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
19544 * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
19545 * returned
19546 */
19548 SCIP_VAR* var /**< problem variable */
19549 )
19550{
19551 assert(var != NULL);
19552
19553 switch( SCIPvarGetStatus(var) )
19554 {
19556 if( var->data.original.transvar == NULL )
19557 return SCIP_INVALID;
19558 return SCIPvarGetBestRootRedcost(var->data.original.transvar);
19559
19562 return var->bestrootredcost;
19563
19568 return 0.0;
19569
19570 default:
19571 SCIPerrorMessage("unknown variable status\n");
19572 SCIPABORT();
19573 return 0.0; /*lint !e527*/
19574 }
19575}
19576
19577/** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
19578 * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
19579 * SCIP_INVALID is returned
19580 */
19582 SCIP_VAR* var /**< problem variable */
19583 )
19584{
19585 assert(var != NULL);
19586
19587 switch( SCIPvarGetStatus(var) )
19588 {
19590 if( var->data.original.transvar == NULL )
19591 return SCIP_INVALID;
19592 return SCIPvarGetBestRootLPObjval(var->data.original.transvar);
19593
19596 return var->bestrootlpobjval;
19597
19602 return SCIP_INVALID;
19603
19604 default:
19605 SCIPerrorMessage("unknown variable status\n");
19606 SCIPABORT();
19607 return SCIP_INVALID; /*lint !e527*/
19608 }
19609}
19610
19611/** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
19613 SCIP_VAR* var, /**< problem variable */
19614 SCIP_Real rootsol, /**< root solution value */
19615 SCIP_Real rootredcost, /**< root reduced cost */
19616 SCIP_Real rootlpobjval /**< objective value of the root LP */
19617 )
19618{
19619 assert(var != NULL);
19620
19621 var->bestrootsol = rootsol;
19622 var->bestrootredcost = rootredcost;
19623 var->bestrootlpobjval = rootlpobjval;
19624}
19625
19626/** stores the solution value as relaxation solution in the problem variable */
19628 SCIP_VAR* var, /**< problem variable */
19629 SCIP_SET* set, /**< global SCIP settings */
19630 SCIP_RELAXATION* relaxation, /**< global relaxation data */
19631 SCIP_Real solval, /**< solution value in the current relaxation solution */
19632 SCIP_Bool updateobj /**< should the objective value be updated? */
19633 )
19634{
19635 assert(var != NULL);
19636 assert(relaxation != NULL);
19637 assert(set != NULL);
19638 assert(var->scip == set->scip);
19639
19640 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
19641 switch( SCIPvarGetStatus(var) )
19642 {
19644 SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
19645 break;
19646
19649 if( updateobj )
19650 SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
19651 var->relaxsol = solval;
19652 break;
19653
19655 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
19656 {
19657 SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
19658 SCIPvarGetName(var), var->glbdom.lb, solval);
19659 return SCIP_INVALIDDATA;
19660 }
19661 break;
19662
19663 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19664 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
19665 SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
19666 (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
19667 break;
19669 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
19670 return SCIP_INVALIDDATA;
19671
19673 SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
19674 break;
19675
19676 default:
19677 SCIPerrorMessage("unknown variable status\n");
19678 return SCIP_INVALIDDATA;
19679 }
19680
19681 return SCIP_OKAY;
19682}
19683
19684/** returns the solution value of the problem variable in the relaxation solution
19685 *
19686 * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
19687 */
19689 SCIP_VAR* var, /**< problem variable */
19690 SCIP_SET* set /**< global SCIP settings */
19691 )
19692{
19693 SCIP_Real solvalsum;
19694 SCIP_Real solval;
19695 int i;
19696
19697 assert(var != NULL);
19698 assert(set != NULL);
19699 assert(var->scip == set->scip);
19700
19701 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
19702 switch( SCIPvarGetStatus(var) )
19703 {
19705 return SCIPvarGetRelaxSol(var->data.original.transvar, set);
19706
19709 return var->relaxsol;
19710
19712 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
19713 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
19714 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
19715 return SCIPvarGetLbGlobal(var);
19716
19717 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19718 solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
19719 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
19720 {
19721 if( var->data.aggregate.scalar * solval > 0.0 )
19722 return SCIPsetInfinity(set);
19723 if( var->data.aggregate.scalar * solval < 0.0 )
19724 return -SCIPsetInfinity(set);
19725 }
19726 return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
19727
19729 solvalsum = var->data.multaggr.constant;
19730 for( i = 0; i < var->data.multaggr.nvars; ++i )
19731 {
19732 solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
19733 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
19734 {
19735 if( var->data.multaggr.scalars[i] * solval > 0.0 )
19736 return SCIPsetInfinity(set);
19737 if( var->data.multaggr.scalars[i] * solval < 0.0 )
19738 return -SCIPsetInfinity(set);
19739 }
19740 solvalsum += var->data.multaggr.scalars[i] * solval;
19741 }
19742 return solvalsum;
19743
19745 solval = SCIPvarGetRelaxSol(var->negatedvar, set);
19746 if( SCIPsetIsInfinity(set, solval) )
19747 return -SCIPsetInfinity(set);
19748 if( SCIPsetIsInfinity(set, -solval) )
19749 return SCIPsetInfinity(set);
19750 return var->data.negate.constant - solval;
19751
19752 default:
19753 SCIPerrorMessage("unknown variable status\n");
19754 SCIPABORT();
19755 return SCIP_INVALID; /*lint !e527*/
19756 }
19757}
19758
19759/** returns the solution value of the transformed problem variable in the relaxation solution */
19761 SCIP_VAR* var /**< problem variable */
19762 )
19763{
19764 assert(var != NULL);
19766
19767 return var->relaxsol;
19768}
19769
19770/** stores the solution value as NLP solution in the problem variable */
19772 SCIP_VAR* var, /**< problem variable */
19773 SCIP_SET* set, /**< global SCIP settings */
19774 SCIP_Real solval /**< solution value in the current NLP solution */
19775 )
19776{
19777 assert(var != NULL);
19778 assert(set != NULL);
19779 assert(var->scip == set->scip);
19780
19781 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
19782 switch( SCIPvarGetStatus(var) )
19783 {
19785 SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
19786 break;
19787
19790 var->nlpsol = solval;
19791 break;
19792
19794 if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
19795 {
19796 SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
19797 SCIPvarGetName(var), var->glbdom.lb, solval);
19798 SCIPABORT();
19799 return SCIP_INVALIDCALL; /*lint !e527*/
19800 }
19801 break;
19802
19803 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
19804 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
19805 SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
19806 break;
19807
19809 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
19810 SCIPABORT();
19811 return SCIP_INVALIDCALL; /*lint !e527*/
19812
19814 SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
19815 break;
19816
19817 default:
19818 SCIPerrorMessage("unknown variable status\n");
19819 SCIPABORT();
19820 return SCIP_ERROR; /*lint !e527*/
19821 }
19822
19823 return SCIP_OKAY;
19824}
19825
19826/** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
19828 SCIP_VAR* var /**< problem variable */
19829 )
19830{
19831 SCIP_Real avgsol;
19832 int i;
19833
19834 assert(var != NULL);
19835
19836 switch( SCIPvarGetStatus(var) )
19837 {
19839 if( var->data.original.transvar == NULL )
19840 return 0.0;
19841 return SCIPvarGetAvgSol(var->data.original.transvar);
19842
19845 avgsol = var->primsolavg;
19846 avgsol = MAX(avgsol, var->glbdom.lb);
19847 avgsol = MIN(avgsol, var->glbdom.ub);
19848 return avgsol;
19849
19851 assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
19852 return var->locdom.lb;
19853
19855 assert(!var->donotaggr);
19856 assert(var->data.aggregate.var != NULL);
19857 return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
19858 + var->data.aggregate.constant;
19859
19861 assert(!var->donotmultaggr);
19862 assert(var->data.multaggr.vars != NULL);
19863 assert(var->data.multaggr.scalars != NULL);
19864 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
19865 * assert(var->data.multaggr.nvars >= 2);
19866 */
19867 avgsol = var->data.multaggr.constant;
19868 for( i = 0; i < var->data.multaggr.nvars; ++i )
19869 avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
19870 return avgsol;
19871
19872 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
19873 assert(var->negatedvar != NULL);
19875 assert(var->negatedvar->negatedvar == var);
19876 return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
19877
19878 default:
19879 SCIPerrorMessage("unknown variable status\n");
19880 SCIPABORT();
19881 return 0.0; /*lint !e527*/
19882 }
19883}
19884
19885/** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
19886 * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
19887 */
19889 SCIP_VAR* var, /**< active problem variable */
19890 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
19891 SCIP_SET* set, /**< global SCIP settings */
19892 SCIP_STAT* stat, /**< problem statistics */
19893 SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
19894 int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
19895 )
19896{
19897 int nvlbs;
19898
19899 assert(var != NULL);
19900 assert(stat != NULL);
19901 assert(set != NULL);
19902 assert(var->scip == set->scip);
19903 assert(closestvlb != NULL);
19904 assert(closestvlbidx != NULL);
19905
19906 *closestvlbidx = -1;
19907 *closestvlb = SCIP_REAL_MIN;
19908
19909 nvlbs = SCIPvarGetNVlbs(var);
19910 if( nvlbs > 0 )
19911 {
19912 SCIP_VAR** vlbvars;
19913 SCIP_Real* vlbcoefs;
19914 SCIP_Real* vlbconsts;
19915 int i;
19916
19917 vlbvars = SCIPvarGetVlbVars(var);
19918 vlbcoefs = SCIPvarGetVlbCoefs(var);
19919 vlbconsts = SCIPvarGetVlbConstants(var);
19920
19921 /* check for cached values */
19922 if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
19923 {
19924 i = var->closestvlbidx;
19925 assert(0 <= i && i < nvlbs);
19926 assert(SCIPvarIsActive(vlbvars[i]));
19927 *closestvlbidx = i;
19928 *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
19929 }
19930 else
19931 {
19932 /* search best VUB */
19933 for( i = 0; i < nvlbs; i++ )
19934 {
19935 if( SCIPvarIsActive(vlbvars[i]) )
19936 {
19937 SCIP_Real vlbsol;
19938
19939 vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
19940 if( vlbsol > *closestvlb )
19941 {
19942 *closestvlb = vlbsol;
19943 *closestvlbidx = i;
19944 }
19945 }
19946 }
19947
19948 if( sol == NULL )
19949 {
19950 /* update cached value */
19951 if( var->closestvblpcount != stat->lpcount )
19952 var->closestvubidx = -1;
19953 var->closestvlbidx = *closestvlbidx;
19954 var->closestvblpcount = stat->lpcount;
19955 }
19956 }
19957 }
19958}
19959
19960/** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
19961 * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
19962 */
19964 SCIP_VAR* var, /**< active problem variable */
19965 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
19966 SCIP_SET* set, /**< global SCIP settings */
19967 SCIP_STAT* stat, /**< problem statistics */
19968 SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
19969 int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
19970 )
19971{
19972 int nvubs;
19973
19974 assert(var != NULL);
19975 assert(set != NULL);
19976 assert(var->scip == set->scip);
19977 assert(closestvub != NULL);
19978 assert(closestvubidx != NULL);
19979
19980 *closestvubidx = -1;
19981 *closestvub = SCIP_REAL_MAX;
19982
19983 nvubs = SCIPvarGetNVubs(var);
19984 if( nvubs > 0 )
19985 {
19986 SCIP_VAR** vubvars;
19987 SCIP_Real* vubcoefs;
19988 SCIP_Real* vubconsts;
19989 int i;
19990
19991 vubvars = SCIPvarGetVubVars(var);
19992 vubcoefs = SCIPvarGetVubCoefs(var);
19993 vubconsts = SCIPvarGetVubConstants(var);
19994
19995 /* check for cached values */
19996 if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
19997 {
19998 i = var->closestvubidx;
19999 assert(0 <= i && i < nvubs);
20000 assert(SCIPvarIsActive(vubvars[i]));
20001 *closestvubidx = i;
20002 *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
20003 }
20004 else
20005 {
20006 /* search best VUB */
20007 for( i = 0; i < nvubs; i++ )
20008 {
20009 if( SCIPvarIsActive(vubvars[i]) )
20010 {
20011 SCIP_Real vubsol;
20012
20013 vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
20014 if( vubsol < *closestvub )
20015 {
20016 *closestvub = vubsol;
20017 *closestvubidx = i;
20018 }
20019 }
20020 }
20021
20022 if( sol == NULL )
20023 {
20024 /* update cached value */
20025 if( var->closestvblpcount != stat->lpcount )
20026 var->closestvlbidx = -1;
20027 var->closestvubidx = *closestvubidx;
20028 var->closestvblpcount = stat->lpcount;
20029 }
20030 }
20031 }
20032}
20033
20034/** resolves variable to columns and adds them with the coefficient to the row */
20036 SCIP_VAR* var, /**< problem variable */
20037 BMS_BLKMEM* blkmem, /**< block memory */
20038 SCIP_SET* set, /**< global SCIP settings */
20039 SCIP_STAT* stat, /**< problem statistics */
20040 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
20041 SCIP_PROB* prob, /**< problem data */
20042 SCIP_LP* lp, /**< current LP data */
20043 SCIP_ROW* row, /**< LP row */
20044 SCIP_Real val /**< value of coefficient */
20045 )
20046{
20047 int i;
20048
20049 assert(var != NULL);
20050 assert(set != NULL);
20051 assert(var->scip == set->scip);
20052 assert(row != NULL);
20054
20055 SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
20056
20057 if ( SCIPsetIsZero(set, val) )
20058 return SCIP_OKAY;
20059
20060 switch( SCIPvarGetStatus(var) )
20061 {
20063 if( var->data.original.transvar == NULL )
20064 {
20065 SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
20066 return SCIP_INVALIDDATA;
20067 }
20068 SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
20069 return SCIP_OKAY;
20070
20072 /* add globally fixed variables as constant */
20073 if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
20074 {
20075 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
20076 return SCIP_OKAY;
20077 }
20078 /* convert loose variable into column */
20079 SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
20081 /*lint -fallthrough*/
20082
20084 assert(var->data.col != NULL);
20085 assert(var->data.col->var == var);
20086 SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
20087 return SCIP_OKAY;
20088
20090 assert(var->glbdom.lb == var->glbdom.ub || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub))); /*lint !e777*/
20091 assert(var->locdom.lb == var->locdom.ub || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub))); /*lint !e777*/
20092 assert(var->locdom.lb == var->glbdom.lb || (set->exact_enable && SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->locdom.lb))); /*lint !e777*/
20093 assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
20094 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
20095 return SCIP_OKAY;
20096
20098 assert(!var->donotaggr);
20099 assert(var->data.aggregate.var != NULL);
20100 SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
20101 row, var->data.aggregate.scalar * val) );
20102 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
20103 return SCIP_OKAY;
20104
20106 assert(!var->donotmultaggr);
20107 assert(var->data.multaggr.vars != NULL);
20108 assert(var->data.multaggr.scalars != NULL);
20109 /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
20110 * assert(var->data.multaggr.nvars >= 2);
20111 */
20112 for( i = 0; i < var->data.multaggr.nvars; ++i )
20113 {
20114 SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
20115 row, var->data.multaggr.scalars[i] * val) );
20116 }
20117 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
20118 return SCIP_OKAY;
20119
20120 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
20121 assert(var->negatedvar != NULL);
20123 assert(var->negatedvar->negatedvar == var);
20124 SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
20125 SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
20126 return SCIP_OKAY;
20127
20128 default:
20129 SCIPerrorMessage("unknown variable status\n");
20130 return SCIP_INVALIDDATA;
20131 }
20132}
20133
20134/** resolves variable to exact columns and adds them with the coefficient to the exact Row */
20136 SCIP_VAR* var, /**< problem variable */
20137 BMS_BLKMEM* blkmem, /**< block memory */
20138 SCIP_SET* set, /**< global SCIP settings */
20139 SCIP_STAT* stat, /**< problem statistics */
20140 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
20141 SCIP_PROB* prob, /**< problem data */
20142 SCIP_LPEXACT* lpexact, /**< current LP data */
20143 SCIP_ROWEXACT* rowexact, /**< LP row */
20144 SCIP_RATIONAL* val /**< value of coefficient */
20145 )
20146{
20147 SCIP_RATIONAL* tmp;
20148 int i;
20149
20150 assert(var != NULL);
20151 assert(set != NULL);
20152 assert(var->scip == set->scip);
20153 assert(rowexact != NULL);
20155
20156 SCIPrationalDebugMessage("adding coefficient %q<%s> to exact row <%s>\n", val, var->name, rowexact->fprow->name);
20157
20158 if ( SCIPrationalIsZero(val) )
20159 return SCIP_OKAY;
20160
20161 switch( SCIPvarGetStatusExact(var) )
20162 {
20164 if( var->data.original.transvar == NULL )
20165 {
20166 SCIPerrorMessage("cannot add untransformed original variable <%s> to excact LP row <%s>\n", var->name, rowexact->fprow->name);
20167 return SCIP_INVALIDDATA;
20168 }
20169 SCIP_CALL( SCIPvarAddToRowExact(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lpexact, rowexact, val) );
20170 break;
20171
20173 /* add globally fixed variables as constant */
20174 if( SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub) )
20175 {
20176 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20177 SCIPrationalMult(tmp, val, var->exactdata->glbdom.lb);
20178 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20179 SCIPrationalFreeBuffer(set->buffer, &tmp);
20180 break;
20181 }
20182 /* convert loose variable into column */
20183 SCIP_CALL( SCIPvarColumnExact(var, blkmem, set, stat, lpexact) );
20185 /*lint -fallthrough*/
20186
20188 assert(var->data.col != NULL);
20189 assert(var->data.col->var == var);
20190 SCIP_CALL( SCIProwExactIncCoef(rowexact, blkmem, set, eventqueue, lpexact, var->exactdata->colexact, val) );
20191 break;
20192
20194 assert(SCIPrationalIsEQ(var->exactdata->glbdom.lb, var->exactdata->glbdom.ub)); /*lint !e777*/
20195 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->locdom.ub)); /*lint !e777*/
20196 assert(SCIPrationalIsEQ(var->exactdata->locdom.lb, var->exactdata->glbdom.lb)); /*lint !e777*/
20197 assert(!SCIPrationalIsAbsInfinity(var->exactdata->locdom.lb));
20198
20199 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20200
20201 SCIPrationalMult(tmp, val, var->exactdata->locdom.lb);
20202 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20203
20204 SCIPrationalFreeBuffer(set->buffer, &tmp);
20205
20206 break;
20207
20209 assert(var->data.aggregate.var != NULL);
20210
20211 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20212 SCIPrationalMult(tmp, var->exactdata->aggregate.scalar, val);
20213 SCIP_CALL( SCIPvarAddToRowExact(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lpexact,
20214 rowexact, tmp) );
20215 SCIPrationalMult(tmp, var->exactdata->aggregate.constant, val);
20216 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20217 SCIPrationalFreeBuffer(set->buffer, &tmp);
20218 return SCIP_OKAY;
20219
20221 assert(!var->donotmultaggr);
20222 assert(var->data.multaggr.vars != NULL);
20223 assert(var->data.multaggr.scalars != NULL);
20224
20225 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20226
20227 for( i = 0; i < var->data.multaggr.nvars; ++i )
20228 {
20229 SCIPrationalMult(tmp, var->exactdata->multaggr.scalars[i], val);
20230 SCIP_CALL( SCIPvarAddToRowExact(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lpexact,
20231 rowexact, tmp) );
20232 }
20233 SCIPrationalMult(tmp, var->exactdata->multaggr.constant, val);
20234 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20235
20236 SCIPrationalFreeBuffer(set->buffer, &tmp);
20237 return SCIP_OKAY;
20238
20239 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
20240 assert(var->negatedvar != NULL);
20242 assert(var->negatedvar->negatedvar == var);
20243
20244 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
20245
20246 SCIPrationalNegate(tmp, val);
20247 SCIP_CALL( SCIPvarAddToRowExact(var->negatedvar, blkmem, set, stat, eventqueue, prob, lpexact, rowexact, tmp) );
20248
20249 SCIPrationalMultReal(tmp, val, var->data.negate.constant);
20250 SCIP_CALL( SCIProwExactAddConstant(rowexact, set, stat, lpexact, tmp) );
20251
20252 SCIPrationalFreeBuffer(set->buffer, &tmp);
20253
20254 break;
20255
20256 default:
20257 SCIPerrorMessage("unknown variable status\n");
20258 return SCIP_INVALIDDATA;
20259 }
20260
20261 return SCIP_OKAY;
20262}
20263
20264/* optionally, define this compiler flag to write complete variable histories to a file */
20265#ifdef SCIP_HISTORYTOFILE
20266SCIP_Longint counter = 0l;
20267const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
20268#include "scip/scip.h"
20269#endif
20270
20271/** updates the pseudo costs of the given variable and the global pseudo costs after a change of
20272 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the LP's objective value
20273 */
20275 SCIP_VAR* var, /**< problem variable */
20276 SCIP_SET* set, /**< global SCIP settings */
20277 SCIP_STAT* stat, /**< problem statistics */
20278 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
20279 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
20280 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
20281 )
20282{
20283 SCIP_Real oldrootpseudocosts;
20284 assert(var != NULL);
20285 assert(set != NULL);
20286 assert(var->scip == set->scip);
20287 assert(stat != NULL);
20288
20289 /* check if history statistics should be collected for a variable */
20290 if( !stat->collectvarhistory )
20291 return SCIP_OKAY;
20292
20293 switch( SCIPvarGetStatus(var) )
20294 {
20296 if( var->data.original.transvar == NULL )
20297 {
20298 SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
20299 return SCIP_INVALIDDATA;
20300 }
20301 SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
20302 return SCIP_OKAY;
20303
20306 /* store old pseudo-costs for root LP best-estimate update */
20307 oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
20308
20309 /* update history */
20310 SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
20311 SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
20312 SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
20313 SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
20314
20315 /* update root LP best-estimate */
20316 SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
20317
20318 /* append history to file */
20319#ifdef SCIP_HISTORYTOFILE
20320 {
20321 FILE* f;
20322 char filename[256];
20323 SCIP_NODE* currentnode;
20324 SCIP_NODE* parentnode;
20325 currentnode = SCIPgetFocusNode(set->scip);
20326 parentnode = SCIPnodeGetParent(currentnode);
20327
20328 sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
20329 f = fopen(filename, "a");
20330 if( NULL != f )
20331 {
20332 fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
20333 ++counter,
20335 SCIPnodeGetNumber(currentnode),
20336 parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
20338 SCIPgetDepth(set->scip),
20339 objdelta,
20340 solvaldelta);
20341 fclose(f);
20342 }
20343 }
20344#endif
20345 return SCIP_OKAY;
20346
20348 SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
20349 return SCIP_INVALIDDATA;
20350
20352 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
20353 SCIP_CALL( SCIPvarUpdatePseudocost(var->data.aggregate.var, set, stat,
20354 solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
20355 return SCIP_OKAY;
20356
20358 SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
20359 return SCIP_INVALIDDATA;
20360
20362 SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
20363 return SCIP_OKAY;
20364
20365 default:
20366 SCIPerrorMessage("unknown variable status\n");
20367 return SCIP_INVALIDDATA;
20368 }
20369}
20370
20371/** updates the ancestral pseudo costs of the given variable and the global ancestral pseudo costs after a change of
20372 * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the LP's objective value
20373 */
20375 SCIP_VAR* var, /**< problem variable */
20376 SCIP_SET* set, /**< global SCIP settings */
20377 SCIP_STAT* stat, /**< problem statistics */
20378 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
20379 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
20380 SCIP_Real weight /**< weight in (0,1] of this update in discounted pseudo cost sum */
20381 )
20382{
20383 assert(var != NULL);
20384 assert(set != NULL);
20385 assert(var->scip == set->scip);
20386 assert(stat != NULL);
20387
20388 /* check if history statistics should be collected for a variable */
20389 if( !stat->collectvarhistory )
20390 return SCIP_OKAY;
20391
20392 switch( SCIPvarGetStatus(var) )
20393 {
20395 if( var->data.original.transvar == NULL )
20396 {
20397 SCIPerrorMessage("cannot update ancestral pseudo costs of original untransformed variable\n");
20398 return SCIP_INVALIDDATA;
20399 }
20400 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
20401 return SCIP_OKAY;
20402
20405 /* update history */
20406 SCIPhistoryUpdateAncPseudocost(var->history, set, solvaldelta, objdelta, weight);
20407 SCIPhistoryUpdateAncPseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
20408 SCIPhistoryUpdateAncPseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
20409 SCIPhistoryUpdateAncPseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
20410 return SCIP_OKAY;
20411
20413 SCIPerrorMessage("cannot update ancestral pseudo cost values of a fixed variable\n");
20414 return SCIP_INVALIDDATA;
20415
20417 assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
20418 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->data.aggregate.var, set, stat,
20419 solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
20420 return SCIP_OKAY;
20421
20423 SCIPerrorMessage("cannot update ancestral pseudo cost values of a multi-aggregated variable\n");
20424 return SCIP_INVALIDDATA;
20425
20427 SCIP_CALL( SCIPvarUpdateAncPseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
20428 return SCIP_OKAY;
20429
20430 default:
20431 SCIPerrorMessage("unknown variable status\n");
20432 return SCIP_INVALIDDATA;
20433 }
20434}
20435
20436/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
20438 SCIP_VAR* var, /**< problem variable */
20439 SCIP_STAT* stat, /**< problem statistics */
20440 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20441 )
20442{
20443 SCIP_BRANCHDIR dir;
20444
20445 assert(var != NULL);
20446 assert(stat != NULL);
20447
20448 switch( SCIPvarGetStatus(var) )
20449 {
20451 if( var->data.original.transvar == NULL )
20452 return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
20453 else
20454 return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
20455
20458 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20459
20460 return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
20461 ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
20462 : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
20463
20465 return 0.0;
20466
20468 return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20469
20471 return 0.0;
20472
20474 return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
20475
20476 default:
20477 SCIPerrorMessage("unknown variable status\n");
20478 SCIPABORT();
20479 return 0.0; /*lint !e527*/
20480 }
20481}
20482
20483/** gets the variable's ancestral pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
20485 SCIP_VAR* var, /**< problem variable */
20486 SCIP_STAT* stat, /**< problem statistics */
20487 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20488 )
20489{
20490 SCIP_BRANCHDIR dir;
20491
20492 assert(var != NULL);
20493 assert(stat != NULL);
20494
20495 switch( SCIPvarGetStatus(var) )
20496 {
20498 if( var->data.original.transvar == NULL )
20499 return SCIPhistoryGetAncPseudocost(stat->glbhistory, solvaldelta);
20500 else
20501 return SCIPvarGetAncPseudocost(var->data.original.transvar, stat, solvaldelta);
20502
20505 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20506
20507 return SCIPhistoryGetAncPseudocostCount(var->history, dir) > 0.0
20508 ? SCIPhistoryGetAncPseudocost(var->history, solvaldelta)
20509 : SCIPhistoryGetAncPseudocost(stat->glbhistory, solvaldelta);
20510
20512 return 0.0;
20513
20515 return SCIPvarGetAncPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20516
20518 return 0.0;
20519
20521 return SCIPvarGetAncPseudocost(var->negatedvar, stat, -solvaldelta);
20522
20523 default:
20524 SCIPerrorMessage("unknown variable status\n");
20525 SCIPABORT();
20526 return 0.0; /*lint !e527*/
20527 }
20528}
20529
20530/** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
20531 * only using the pseudo cost information of the current run
20532 */
20534 SCIP_VAR* var, /**< problem variable */
20535 SCIP_STAT* stat, /**< problem statistics */
20536 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
20537 )
20538{
20539 SCIP_BRANCHDIR dir;
20540
20541 assert(var != NULL);
20542 assert(stat != NULL);
20543
20544 switch( SCIPvarGetStatus(var) )
20545 {
20547 if( var->data.original.transvar == NULL )
20548 return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
20549 else
20550 return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
20551
20554 dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
20555
20556 return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
20557 ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
20558 : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
20559
20561 return 0.0;
20562
20564 return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
20565
20567 return 0.0;
20568
20570 return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
20571
20572 default:
20573 SCIPerrorMessage("unknown variable status\n");
20574 SCIPABORT();
20575 return 0.0; /*lint !e527*/
20576 }
20577}
20578
20579/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
20581 SCIP_VAR* var, /**< problem variable */
20582 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20583 )
20584{
20585 assert(var != NULL);
20587
20588 switch( SCIPvarGetStatus(var) )
20589 {
20591 if( var->data.original.transvar == NULL )
20592 return 0.0;
20593 else
20594 return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
20595
20598 return SCIPhistoryGetPseudocostCount(var->history, dir);
20599
20601 return 0.0;
20602
20604 if( var->data.aggregate.scalar > 0.0 )
20605 return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
20606 else
20607 return SCIPvarGetPseudocostCount(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20608
20610 return 0.0;
20611
20613 return SCIPvarGetPseudocostCount(var->negatedvar, SCIPbranchdirOpposite(dir));
20614
20615 default:
20616 SCIPerrorMessage("unknown variable status\n");
20617 SCIPABORT();
20618 return 0.0; /*lint !e527*/
20619 }
20620}
20621
20622/** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
20623 * only using the pseudo cost information of the current run
20624 */
20626 SCIP_VAR* var, /**< problem variable */
20627 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20628 )
20629{
20630 assert(var != NULL);
20632
20633 switch( SCIPvarGetStatus(var) )
20634 {
20636 if( var->data.original.transvar == NULL )
20637 return 0.0;
20638 else
20639 return SCIPvarGetPseudocostCountCurrentRun(var->data.original.transvar, dir);
20640
20643 return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
20644
20646 return 0.0;
20647
20649 if( var->data.aggregate.scalar > 0.0 )
20650 return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, dir);
20651 else
20652 return SCIPvarGetPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20653
20655 return 0.0;
20656
20659
20660 default:
20661 SCIPerrorMessage("unknown variable status\n");
20662 SCIPABORT();
20663 return 0.0; /*lint !e527*/
20664 }
20665}
20666
20667/** gets the variable's (possible fractional) number of ancestor pseudo cost updates for the given direction,
20668 * only using the pseudo cost information of the current run
20669 */
20671 SCIP_VAR* var, /**< problem variable */
20672 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
20673 )
20674{
20675 assert(var != NULL);
20677
20678 switch( SCIPvarGetStatus(var) )
20679 {
20681 if( var->data.original.transvar == NULL )
20682 return 0.0;
20683 else
20684 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.original.transvar, dir);
20685
20688 return SCIPhistoryGetAncPseudocostCount(var->historycrun, dir);
20689
20691 return 0.0;
20692
20694 if( var->data.aggregate.scalar > 0.0 )
20695 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.aggregate.var, dir);
20696 else
20697 return SCIPvarGetAncPseudocostCountCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
20698
20700 return 0.0;
20701
20704
20705 default:
20706 SCIPerrorMessage("unknown variable status\n");
20707 SCIPABORT();
20708 return 0.0; /*lint !e527*/
20709 }
20710}
20711
20712/** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
20714 SCIP_VAR* var, /**< problem variable */
20715 SCIP_STAT* stat, /**< problem statistics */
20716 SCIP_SET* set, /**< global SCIP settings */
20717 SCIP_Real solval /**< solution value, e.g., LP solution value */
20718 )
20719{
20720 SCIP_Real upscore;
20721 SCIP_Real downscore;
20722 SCIP_Real solvaldeltaup;
20723 SCIP_Real solvaldeltadown;
20724
20725 /* LP root estimate only works for variables with fractional LP root solution */
20726 if( SCIPsetIsFeasIntegral(set, solval) )
20727 return 0.0;
20728
20729 /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
20731 return 0.0;
20732
20733 /* compute delta's to ceil and floor of root LP solution value */
20734 solvaldeltaup = SCIPsetCeil(set, solval) - solval;
20735 solvaldeltadown = SCIPsetFloor(set, solval) - solval;
20736
20737 upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
20738 downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
20739
20740 return MIN(upscore, downscore);
20741}
20742
20743/** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
20745 SCIP_VAR* var, /**< problem variable */
20746 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
20747 SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
20748 )
20749{
20750 assert(var != NULL);
20752
20753 switch( SCIPvarGetStatus(var) )
20754 {
20756 if( var->data.original.transvar == NULL )
20757 return 0.0;
20758 else
20759 return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
20760
20763 if( onlycurrentrun )
20764 return SCIPhistoryGetPseudocostVariance(var->historycrun, dir);
20765 else
20766 return SCIPhistoryGetPseudocostVariance(var->history, dir);
20767
20769 return 0.0;
20770
20772 if( var->data.aggregate.scalar > 0.0 )
20773 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
20774 else
20775 return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
20776
20778 return 0.0;
20779
20781 return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
20782
20783 default:
20784 SCIPerrorMessage("unknown variable status\n");
20785 SCIPABORT();
20786 return 0.0; /*lint !e527*/
20787 }
20788}
20789
20790/** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
20791 *
20792 * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
20793 * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
20794 * of 2 * clevel - 1.
20795 *
20796 * @return value of confidence bound for this variable
20797 */
20799 SCIP_VAR* var, /**< variable in question */
20800 SCIP_SET* set, /**< global SCIP settings */
20801 SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
20802 SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
20803 SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
20804 )
20805{
20806 SCIP_Real confidencebound;
20807
20808 confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
20809 if( SCIPsetIsFeasPositive(set, confidencebound) )
20810 {
20811 SCIP_Real count;
20812
20813 if( onlycurrentrun )
20815 else
20816 count = SCIPvarGetPseudocostCount(var, dir);
20817 /* assertion is valid because variance is positive */
20818 assert(count >= 1.9);
20819
20820 confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
20821 confidencebound = sqrt(confidencebound);
20822
20823 /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
20824 * the number of pseudo cost evaluations of this variable in the respective direction. */
20825 confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
20826 }
20827 else
20828 confidencebound = 0.0;
20829
20830 return confidencebound;
20831}
20832
20833/** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
20834 * Error is calculated at a specific confidence level
20835 */
20837 SCIP_VAR* var, /**< variable in question */
20838 SCIP_SET* set, /**< global SCIP settings */
20839 SCIP_STAT* stat, /**< problem statistics */
20840 SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
20841 SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
20842 )
20843{
20844 SCIP_Real downsize;
20845 SCIP_Real upsize;
20846 SCIP_Real size;
20847 SCIP_Real relerrorup;
20848 SCIP_Real relerrordown;
20849 SCIP_Real relerror;
20850
20851 /* check, if the pseudo cost score of the variable is reliable */
20854 size = MIN(downsize, upsize);
20855
20856 /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
20857 if( size <= 1.9 )
20858 return FALSE;
20859
20860 /* use the relative error between the current mean pseudo cost value of the candidate and its upper
20861 * confidence interval bound at confidence level of 95% for individual variable reliability.
20862 * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
20863 */
20864 if( downsize >= 1.9 )
20865 {
20866 SCIP_Real normval;
20867
20869 normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
20870 normval = MAX(1.0, normval);
20871
20872 relerrordown /= normval;
20873 }
20874 else
20875 relerrordown = 0.0;
20876
20877 if( upsize >= 1.9 )
20878 {
20879 SCIP_Real normval;
20880
20882 normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
20883 normval = MAX(1.0, normval);
20884 relerrorup /= normval;
20885 }
20886 else
20887 relerrorup = 0.0;
20888
20889 /* consider the relative error threshold violated, if it is violated in at least one branching direction */
20890 relerror = MAX(relerrorup, relerrordown);
20891
20892 return (relerror <= threshold);
20893}
20894
20895/** check if variable pseudo-costs have a significant difference in location. The significance depends on
20896 * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
20897 * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
20898 * unknown location means of the underlying pseudo-cost distributions of x and y.
20899 *
20900 * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
20901 * better than x (despite the current information), meaning that y can be expected to yield branching
20902 * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
20903 * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
20904 * than y.
20905 *
20906 * @note The order of x and y matters for the one-sided hypothesis
20907 *
20908 * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
20909 * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
20910 *
20911 * @return TRUE if the hypothesis can be safely rejected at the given confidence level
20912 */
20914 SCIP_SET* set, /**< global SCIP settings */
20915 SCIP_STAT* stat, /**< problem statistics */
20916 SCIP_VAR* varx, /**< variable x */
20917 SCIP_Real fracx, /**< the fractionality of variable x */
20918 SCIP_VAR* vary, /**< variable y */
20919 SCIP_Real fracy, /**< the fractionality of variable y */
20920 SCIP_BRANCHDIR dir, /**< branching direction */
20921 SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
20922 SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
20923 )
20924{
20925 SCIP_Real meanx;
20926 SCIP_Real meany;
20927 SCIP_Real variancex;
20928 SCIP_Real variancey;
20929 SCIP_Real countx;
20930 SCIP_Real county;
20931 SCIP_Real tresult;
20932 SCIP_Real realdirection;
20933
20934 if( varx == vary )
20935 return FALSE;
20936
20937 countx = SCIPvarGetPseudocostCount(varx, dir);
20938 county = SCIPvarGetPseudocostCount(vary, dir);
20939
20940 /* if not at least 2 measurements were taken, return FALSE */
20941 if( countx <= 1.9 || county <= 1.9 )
20942 return FALSE;
20943
20944 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
20945
20946 meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
20947 meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
20948
20949 variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
20950 variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
20951
20952 /* if there is no variance, the means are taken from a constant distribution */
20953 if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
20954 return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
20955
20956 tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
20957
20958 /* for the two-sided hypothesis, just take the absolute of t */
20959 if( !onesided )
20960 tresult = REALABS(tresult);
20961
20962 return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
20963}
20964
20965/** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
20966 * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
20967 * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
20968 * of at least \p threshold.
20969 *
20970 * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
20971 * the estimated probability to exceed \p threshold is less than 25 %.
20972 *
20973 * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
20974 * of confidence.
20975 *
20976 * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
20977 * at the given confidence level \p clevel.
20978 */
20980 SCIP_SET* set, /**< global SCIP settings */
20981 SCIP_STAT* stat, /**< problem statistics */
20982 SCIP_VAR* var, /**< variable x */
20983 SCIP_Real frac, /**< the fractionality of variable x */
20984 SCIP_Real threshold, /**< the threshold to test against */
20985 SCIP_BRANCHDIR dir, /**< branching direction */
20986 SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
20987 )
20988{
20989 SCIP_Real mean;
20990 SCIP_Real variance;
20991 SCIP_Real count;
20992 SCIP_Real realdirection;
20993 SCIP_Real probability;
20994 SCIP_Real problimit;
20995
20996 count = SCIPvarGetPseudocostCount(var, dir);
20997
20998 /* if not at least 2 measurements were taken, return FALSE */
20999 if( count <= 1.9 )
21000 return FALSE;
21001
21002 realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
21003
21004 mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
21005 variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
21006
21007 /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
21008 if( SCIPsetIsFeasGE(set, mean, threshold) )
21009 return FALSE;
21010
21011 /* if there is no variance, the means are taken from a constant distribution */
21012 if( SCIPsetIsFeasEQ(set, variance, 0.0) )
21013 return SCIPsetIsFeasLT(set, mean, threshold);
21014
21015 /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
21016 probability = SCIPnormalCDF(mean, variance, threshold);
21017
21018 /* determine a probability limit corresponding to the given confidence level */
21019 switch( clevel )
21020 {
21022 problimit = 0.75;
21023 break;
21025 problimit = 0.875;
21026 break;
21028 problimit = 0.9;
21029 break;
21031 problimit = 0.95;
21032 break;
21034 problimit = 0.975;
21035 break;
21036 default:
21037 problimit = -1;
21038 SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
21039 SCIPABORT();
21040 break;
21041 }
21042
21043 return (probability >= problimit);
21044}
21045
21046/** find the corresponding history entry if already existing, otherwise create new entry */
21047static
21049 SCIP_VAR* var, /**< problem variable */
21050 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21051 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21052 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21053 SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
21054 )
21055{
21056 assert(var != NULL);
21057 assert(blkmem != NULL);
21058 assert(set != NULL);
21059 assert(history != NULL);
21060
21061 (*history) = NULL;
21062
21063 if( var->valuehistory == NULL )
21064 {
21065 SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
21066 }
21067
21068 SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
21069
21070 return SCIP_OKAY;
21071}
21072
21073/** check if value based history should be used */
21074static
21076 SCIP_VAR* var, /**< problem variable */
21077 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21078 SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21079 )
21080{
21081 /* check if the domain value is unknown (not specific) */
21082 if( value == SCIP_UNKNOWN ) /*lint !e777*/
21083 return FALSE;
21084
21085 assert(set != NULL);
21086
21087 /* check if value based history should be collected */
21088 if( !set->history_valuebased )
21089 return FALSE;
21090
21091 /* value based history is not collected for binary variable since the standard history already contains all information */
21093 return FALSE;
21094
21095 /* value based history is not collected for continuous variables */
21097 return FALSE;
21098
21099 return TRUE;
21100}
21101
21102/** increases VSIDS of the variable by the given weight */
21104 SCIP_VAR* var, /**< problem variable */
21105 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21106 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21107 SCIP_STAT* stat, /**< problem statistics */
21108 SCIP_BRANCHDIR dir, /**< branching direction */
21109 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21110 SCIP_Real weight /**< weight of this update in VSIDS */
21111 )
21112{
21113 assert(var != NULL);
21115
21116 /* check if history statistics should be collected for a variable */
21117 if( !stat->collectvarhistory )
21118 return SCIP_OKAY;
21119
21120 if( SCIPsetIsZero(set, weight) )
21121 return SCIP_OKAY;
21122
21123 switch( SCIPvarGetStatus(var) )
21124 {
21126 if( var->data.original.transvar == NULL )
21127 {
21128 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
21129 return SCIP_INVALIDDATA;
21130 }
21131 SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21132 return SCIP_OKAY;
21133
21136 {
21137 SCIPhistoryIncVSIDS(var->history, dir, weight);
21138 SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
21139
21140 if( useValuehistory(var, value, set) )
21141 {
21142 SCIP_HISTORY* history;
21143
21144 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21145 assert(history != NULL);
21146
21147 SCIPhistoryIncVSIDS(history, dir, weight);
21148 SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
21149 value, weight, SCIPhistoryGetVSIDS(history, dir));
21150 }
21151
21152 return SCIP_OKAY;
21153 }
21155 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
21156 return SCIP_INVALIDDATA;
21157
21159 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21160
21161 if( var->data.aggregate.scalar > 0.0 )
21162 {
21163 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21164 }
21165 else
21166 {
21167 assert(var->data.aggregate.scalar < 0.0);
21168 SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21169 }
21170 return SCIP_OKAY;
21171
21173 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
21174 return SCIP_INVALIDDATA;
21175
21177 value = 1.0 - value;
21178
21179 SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21180 return SCIP_OKAY;
21181
21182 default:
21183 SCIPerrorMessage("unknown variable status\n");
21184 return SCIP_INVALIDDATA;
21185 }
21186}
21187
21188/** scales the VSIDS of the variable by the given scalar */
21190 SCIP_VAR* var, /**< problem variable */
21191 SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
21192 )
21193{
21194 assert(var != NULL);
21195
21196 switch( SCIPvarGetStatus(var) )
21197 {
21199 if( var->data.original.transvar == NULL )
21200 {
21201 SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
21202 return SCIP_INVALIDDATA;
21203 }
21204 SCIP_CALL( SCIPvarScaleVSIDS(var->data.original.transvar, scalar) );
21205 return SCIP_OKAY;
21206
21209 {
21210 SCIPhistoryScaleVSIDS(var->history, scalar);
21211 SCIPhistoryScaleVSIDS(var->historycrun, scalar);
21212 SCIPvaluehistoryScaleVSIDS(var->valuehistory, scalar);
21213
21214 return SCIP_OKAY;
21215 }
21217 SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
21218 return SCIP_INVALIDDATA;
21219
21221 SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
21222 return SCIP_OKAY;
21223
21225 SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
21226 return SCIP_INVALIDDATA;
21227
21229 SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
21230 return SCIP_OKAY;
21231
21232 default:
21233 SCIPerrorMessage("unknown variable status\n");
21234 return SCIP_INVALIDDATA;
21235 }
21236}
21237
21238/** increases the number of active conflicts by one and the overall length of the variable by the given length */
21240 SCIP_VAR* var, /**< problem variable */
21241 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21242 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21243 SCIP_STAT* stat, /**< problem statistics */
21244 SCIP_BRANCHDIR dir, /**< branching direction */
21245 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21246 SCIP_Real length /**< length of the conflict */
21247 )
21248{
21249 assert(var != NULL);
21251
21252 /* check if history statistics should be collected for a variable */
21253 if( !stat->collectvarhistory )
21254 return SCIP_OKAY;
21255
21256 switch( SCIPvarGetStatus(var) )
21257 {
21259 if( var->data.original.transvar == NULL )
21260 {
21261 SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
21262 return SCIP_INVALIDDATA;
21263 }
21264 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
21265 return SCIP_OKAY;
21266
21269 {
21270 SCIPhistoryIncNActiveConflicts(var->history, dir, length);
21271 SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
21272
21273 if( useValuehistory(var, value, set) )
21274 {
21275 SCIP_HISTORY* history;
21276
21277 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21278 assert(history != NULL);
21279
21280 SCIPhistoryIncNActiveConflicts(history, dir, length);
21281 }
21282
21283 return SCIP_OKAY;
21284 }
21286 SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
21287 return SCIP_INVALIDDATA;
21288
21290 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21291
21292 if( var->data.aggregate.scalar > 0.0 )
21293 {
21294 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
21295 }
21296 else
21297 {
21298 assert(var->data.aggregate.scalar < 0.0);
21299 SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
21300 }
21301 return SCIP_OKAY;
21302
21304 SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
21305 return SCIP_INVALIDDATA;
21306
21308 value = 1.0 - value;
21309
21310 SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
21311 return SCIP_OKAY;
21312
21313 default:
21314 SCIPerrorMessage("unknown variable status\n");
21315 return SCIP_INVALIDDATA;
21316 }
21317}
21318
21319/** gets the number of active conflicts containing this variable in given direction */
21321 SCIP_VAR* var, /**< problem variable */
21322 SCIP_STAT* stat, /**< problem statistics */
21323 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21324 )
21325{
21326 assert(var != NULL);
21327 assert(stat != NULL);
21329
21330 switch( SCIPvarGetStatus(var) )
21331 {
21333 if( var->data.original.transvar == NULL )
21334 return 0;
21335 else
21336 return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
21337
21340 return SCIPhistoryGetNActiveConflicts(var->history, dir);
21341
21343 return 0;
21344
21346 if( var->data.aggregate.scalar > 0.0 )
21347 return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
21348 else
21349 return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21350
21352 return 0;
21353
21355 return SCIPvarGetNActiveConflicts(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21356
21357 default:
21358 SCIPerrorMessage("unknown variable status\n");
21359 SCIPABORT();
21360 return 0; /*lint !e527*/
21361 }
21362}
21363
21364/** gets the number of active conflicts containing this variable in given direction
21365 * in the current run
21366 */
21368 SCIP_VAR* var, /**< problem variable */
21369 SCIP_STAT* stat, /**< problem statistics */
21370 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21371 )
21372{
21373 assert(var != NULL);
21374 assert(stat != NULL);
21376
21377 switch( SCIPvarGetStatus(var) )
21378 {
21380 if( var->data.original.transvar == NULL )
21381 return 0;
21382 else
21383 return SCIPvarGetNActiveConflictsCurrentRun(var->data.original.transvar, stat, dir);
21384
21387 return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
21388
21390 return 0;
21391
21393 if( var->data.aggregate.scalar > 0.0 )
21394 return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
21395 else
21396 return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21397
21399 return 0;
21400
21402 return SCIPvarGetNActiveConflictsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21403
21404 default:
21405 SCIPerrorMessage("unknown variable status\n");
21406 SCIPABORT();
21407 return 0; /*lint !e527*/
21408 }
21409}
21410
21411/** gets the average conflict length in given direction due to branching on the variable */
21413 SCIP_VAR* var, /**< problem variable */
21414 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21415 )
21416{
21417 assert(var != NULL);
21419
21420 switch( SCIPvarGetStatus(var) )
21421 {
21423 if( var->data.original.transvar == NULL )
21424 return 0.0;
21425 else
21426 return SCIPvarGetAvgConflictlength(var->data.original.transvar, dir);
21427
21430 return SCIPhistoryGetAvgConflictlength(var->history, dir);
21432 return 0.0;
21433
21435 if( var->data.aggregate.scalar > 0.0 )
21436 return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
21437 else
21438 return SCIPvarGetAvgConflictlength(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21439
21441 return 0.0;
21442
21444 return SCIPvarGetAvgConflictlength(var->negatedvar, SCIPbranchdirOpposite(dir));
21445
21446 default:
21447 SCIPerrorMessage("unknown variable status\n");
21448 SCIPABORT();
21449 return 0.0; /*lint !e527*/
21450 }
21451}
21452
21453/** gets the average conflict length in given direction due to branching on the variable
21454 * in the current run
21455 */
21457 SCIP_VAR* var, /**< problem variable */
21458 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21459 )
21460{
21461 assert(var != NULL);
21463
21464 switch( SCIPvarGetStatus(var) )
21465 {
21467 if( var->data.original.transvar == NULL )
21468 return 0.0;
21469 else
21470 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.original.transvar, dir);
21471
21474 return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
21475
21477 return 0.0;
21478
21480 if( var->data.aggregate.scalar > 0.0 )
21481 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, dir);
21482 else
21483 return SCIPvarGetAvgConflictlengthCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21484
21486 return 0.0;
21487
21490
21491 default:
21492 SCIPerrorMessage("unknown variable status\n");
21493 SCIPABORT();
21494 return 0.0; /*lint !e527*/
21495 }
21496}
21497
21498/** increases the number of branchings counter of the variable */
21500 SCIP_VAR* var, /**< problem variable */
21501 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21502 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21503 SCIP_STAT* stat, /**< problem statistics */
21504 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21505 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21506 int depth /**< depth at which the bound change took place */
21507 )
21508{
21509 assert(var != NULL);
21510 assert(stat != NULL);
21512
21513 /* check if history statistics should be collected for a variable */
21514 if( !stat->collectvarhistory )
21515 return SCIP_OKAY;
21516
21517 switch( SCIPvarGetStatus(var) )
21518 {
21520 if( var->data.original.transvar == NULL )
21521 {
21522 SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
21523 return SCIP_INVALIDDATA;
21524 }
21525 SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
21526 return SCIP_OKAY;
21527
21530 {
21531 SCIPhistoryIncNBranchings(var->history, dir, depth);
21532 SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
21535
21536 if( useValuehistory(var, value, set) )
21537 {
21538 SCIP_HISTORY* history;
21539
21540 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21541 assert(history != NULL);
21542
21543 SCIPhistoryIncNBranchings(history, dir, depth);
21544 }
21545
21546 return SCIP_OKAY;
21547 }
21549 SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
21550 return SCIP_INVALIDDATA;
21551
21553 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21554
21555 if( var->data.aggregate.scalar > 0.0 )
21556 {
21557 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
21558 }
21559 else
21560 {
21561 assert(var->data.aggregate.scalar < 0.0);
21562 SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
21563 }
21564 return SCIP_OKAY;
21565
21567 SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
21568 return SCIP_INVALIDDATA;
21569
21571 value = 1.0 - value;
21572
21573 SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
21574 return SCIP_OKAY;
21575
21576 default:
21577 SCIPerrorMessage("unknown variable status\n");
21578 return SCIP_INVALIDDATA;
21579 }
21580}
21581
21582/** increases the inference sum of the variable by the given weight */
21584 SCIP_VAR* var, /**< problem variable */
21585 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21586 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21587 SCIP_STAT* stat, /**< problem statistics */
21588 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21589 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21590 SCIP_Real weight /**< weight of this update in inference score */
21591 )
21592{
21593 assert(var != NULL);
21594 assert(stat != NULL);
21596
21597 /* check if history statistics should be collected for a variable */
21598 if( !stat->collectvarhistory )
21599 return SCIP_OKAY;
21600
21601 switch( SCIPvarGetStatus(var) )
21602 {
21604 if( var->data.original.transvar == NULL )
21605 {
21606 SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
21607 return SCIP_INVALIDDATA;
21608 }
21609 SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21610 return SCIP_OKAY;
21611
21614 {
21615 SCIPhistoryIncInferenceSum(var->history, dir, weight);
21616 SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
21617 SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
21618 SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
21619
21620 if( useValuehistory(var, value, set) )
21621 {
21622 SCIP_HISTORY* history;
21623
21624 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21625 assert(history != NULL);
21626
21627 SCIPhistoryIncInferenceSum(history, dir, weight);
21628 }
21629
21630 return SCIP_OKAY;
21631 }
21633 SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
21634 return SCIP_INVALIDDATA;
21635
21637 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21638
21639 if( var->data.aggregate.scalar > 0.0 )
21640 {
21641 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21642 }
21643 else
21644 {
21645 assert(var->data.aggregate.scalar < 0.0);
21646 SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21647 }
21648 return SCIP_OKAY;
21649
21651 SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
21652 return SCIP_INVALIDDATA;
21653
21655 value = 1.0 - value;
21656
21657 SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21658 return SCIP_OKAY;
21659
21660 default:
21661 SCIPerrorMessage("unknown variable status\n");
21662 return SCIP_INVALIDDATA;
21663 }
21664}
21665
21666/** increases the cutoff sum of the variable by the given weight */
21668 SCIP_VAR* var, /**< problem variable */
21669 BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
21670 SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
21671 SCIP_STAT* stat, /**< problem statistics */
21672 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
21673 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
21674 SCIP_Real weight /**< weight of this update in cutoff score */
21675 )
21676{
21677 assert(var != NULL);
21678 assert(stat != NULL);
21680
21681 /* check if history statistics should be collected for a variable */
21682 if( !stat->collectvarhistory )
21683 return SCIP_OKAY;
21684
21685 switch( SCIPvarGetStatus(var) )
21686 {
21688 if( var->data.original.transvar == NULL )
21689 {
21690 SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
21691 return SCIP_INVALIDDATA;
21692 }
21693 SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
21694 return SCIP_OKAY;
21695
21698 {
21699 SCIPhistoryIncCutoffSum(var->history, dir, weight);
21700 SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
21701 SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
21702 SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
21703
21704 if( useValuehistory(var, value, set) )
21705 {
21706 SCIP_HISTORY* history;
21707
21708 SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
21709 assert(history != NULL);
21710
21711 SCIPhistoryIncCutoffSum(history, dir, weight);
21712 }
21713
21714 return SCIP_OKAY;
21715 }
21717 SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
21718 return SCIP_INVALIDDATA;
21719
21721 value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
21722
21723 if( var->data.aggregate.scalar > 0.0 )
21724 {
21725 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
21726 }
21727 else
21728 {
21729 assert(var->data.aggregate.scalar < 0.0);
21730 SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21731 }
21732 return SCIP_OKAY;
21733
21735 SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
21736 return SCIP_INVALIDDATA;
21737
21739 value = 1.0 - value;
21740
21741 SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
21742 return SCIP_OKAY;
21743
21744 default:
21745 SCIPerrorMessage("unknown variable status\n");
21746 return SCIP_INVALIDDATA;
21747 }
21748}
21749
21750/** returns the number of times, a bound of the variable was changed in given direction due to branching */
21752 SCIP_VAR* var, /**< problem variable */
21753 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21754 )
21755{
21756 assert(var != NULL);
21758
21759 switch( SCIPvarGetStatus(var) )
21760 {
21762 if( var->data.original.transvar == NULL )
21763 return 0;
21764 else
21765 return SCIPvarGetNBranchings(var->data.original.transvar, dir);
21766
21769 return SCIPhistoryGetNBranchings(var->history, dir);
21770
21772 return 0;
21773
21775 if( var->data.aggregate.scalar > 0.0 )
21776 return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
21777 else
21778 return SCIPvarGetNBranchings(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21779
21781 return 0;
21782
21784 return SCIPvarGetNBranchings(var->negatedvar, SCIPbranchdirOpposite(dir));
21785
21786 default:
21787 SCIPerrorMessage("unknown variable status\n");
21788 SCIPABORT();
21789 return 0; /*lint !e527*/
21790 }
21791}
21792
21793/** returns the number of times, a bound of the variable was changed in given direction due to branching
21794 * in the current run
21795 */
21797 SCIP_VAR* var, /**< problem variable */
21798 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21799 )
21800{
21801 assert(var != NULL);
21803
21804 switch( SCIPvarGetStatus(var) )
21805 {
21807 if( var->data.original.transvar == NULL )
21808 return 0;
21809 else
21810 return SCIPvarGetNBranchingsCurrentRun(var->data.original.transvar, dir);
21811
21814 return SCIPhistoryGetNBranchings(var->historycrun, dir);
21815
21817 return 0;
21818
21820 if( var->data.aggregate.scalar > 0.0 )
21821 return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, dir);
21822 else
21823 return SCIPvarGetNBranchingsCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21824
21826 return 0;
21827
21830
21831 default:
21832 SCIPerrorMessage("unknown variable status\n");
21833 SCIPABORT();
21834 return 0; /*lint !e527*/
21835 }
21836}
21837
21838/** returns the average depth of bound changes in given direction due to branching on the variable */
21840 SCIP_VAR* var, /**< problem variable */
21841 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21842 )
21843{
21844 assert(var != NULL);
21846
21847 switch( SCIPvarGetStatus(var) )
21848 {
21850 if( var->data.original.transvar == NULL )
21851 return 0.0;
21852 else
21853 return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
21854
21857 return SCIPhistoryGetAvgBranchdepth(var->history, dir);
21858
21860 return 0.0;
21861
21863 if( var->data.aggregate.scalar > 0.0 )
21864 return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
21865 else
21866 return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
21867
21869 return 0.0;
21870
21872 return SCIPvarGetAvgBranchdepth(var->negatedvar, SCIPbranchdirOpposite(dir));
21873
21874 default:
21875 SCIPerrorMessage("unknown variable status\n");
21876 SCIPABORT();
21877 return 0.0; /*lint !e527*/
21878 }
21879}
21880
21881/** returns the average depth of bound changes in given direction due to branching on the variable
21882 * in the current run
21883 */
21885 SCIP_VAR* var, /**< problem variable */
21886 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21887 )
21888{
21889 assert(var != NULL);
21891
21892 switch( SCIPvarGetStatus(var) )
21893 {
21895 if( var->data.original.transvar == NULL )
21896 return 0.0;
21897 else
21898 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.original.transvar, dir);
21899
21902 return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
21903
21905 return 0.0;
21906
21908 if( var->data.aggregate.scalar > 0.0 )
21909 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var, dir);
21910 else
21911 return SCIPvarGetAvgBranchdepthCurrentRun(var->data.aggregate.var,
21913
21915 return 0.0;
21916
21918 return SCIPvarGetAvgBranchdepthCurrentRun(var->negatedvar,
21920
21921 default:
21922 SCIPerrorMessage("unknown variable status\n");
21923 SCIPABORT();
21924 return 0.0; /*lint !e527*/
21925 }
21926}
21927
21928/** returns the variable's VSIDS score */
21930 SCIP_VAR* var, /**< problem variable */
21931 SCIP_STAT* stat, /**< problem statistics */
21932 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21933 )
21934{
21935 assert(var != NULL);
21936 assert(stat != NULL);
21938
21940 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
21941
21942 switch( SCIPvarGetStatus(var) )
21943 {
21945 if( var->data.original.transvar == NULL )
21946 return 0.0;
21947 else
21948 return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
21949
21952 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
21953 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
21954
21956 return 0.0;
21957
21959 if( var->data.aggregate.scalar > 0.0 )
21960 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
21961 else
21962 /* coverity[overrun-local] */
21963 return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
21964
21966 return 0.0;
21967
21969 /* coverity[overrun-local] */
21970 return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
21971
21972 default:
21973 SCIPerrorMessage("unknown variable status\n");
21974 SCIPABORT();
21975 return 0.0; /*lint !e527*/
21976 }
21977}
21978
21979/** returns the variable's VSIDS score only using conflicts of the current run */
21981 SCIP_VAR* var, /**< problem variable */
21982 SCIP_STAT* stat, /**< problem statistics */
21983 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
21984 )
21985{
21986 assert(var != NULL);
21987 assert(stat != NULL);
21989
21991 {
21992 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
21993 return SCIP_INVALID;
21994 }
21995
21996 switch( SCIPvarGetStatus(var) )
21997 {
21999 if( var->data.original.transvar == NULL )
22000 return 0.0;
22001 else
22002 return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
22003
22006 return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
22007
22009 return 0.0;
22010
22012 if( var->data.aggregate.scalar > 0.0 )
22013 return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
22014 else
22015 return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22016
22018 return 0.0;
22019
22021 return SCIPvarGetVSIDSCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22022
22023 default:
22024 SCIPerrorMessage("unknown variable status\n");
22025 SCIPABORT();
22026 return 0.0; /*lint !e527*/
22027 }
22028}
22029
22030/** returns the number of inferences branching on this variable in given direction triggered */
22032 SCIP_VAR* var, /**< problem variable */
22033 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22034 )
22035{
22036 assert(var != NULL);
22038
22039 switch( SCIPvarGetStatus(var) )
22040 {
22042 if( var->data.original.transvar == NULL )
22043 return 0.0;
22044 else
22045 return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
22046
22049 return SCIPhistoryGetInferenceSum(var->history, dir);
22050
22052 return 0.0;
22053
22055 if( var->data.aggregate.scalar > 0.0 )
22056 return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
22057 else
22058 return SCIPvarGetInferenceSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22059
22061 return 0.0;
22062
22064 return SCIPvarGetInferenceSum(var->negatedvar, SCIPbranchdirOpposite(dir));
22065
22066 default:
22067 SCIPerrorMessage("unknown variable status\n");
22068 SCIPABORT();
22069 return 0.0; /*lint !e527*/
22070 }
22071}
22072
22073/** returns the number of inferences branching on this variable in given direction triggered
22074 * in the current run
22075 */
22077 SCIP_VAR* var, /**< problem variable */
22078 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22079 )
22080{
22081 assert(var != NULL);
22083
22084 switch( SCIPvarGetStatus(var) )
22085 {
22087 if( var->data.original.transvar == NULL )
22088 return 0.0;
22089 else
22090 return SCIPvarGetInferenceSumCurrentRun(var->data.original.transvar, dir);
22091
22094 return SCIPhistoryGetInferenceSum(var->historycrun, dir);
22095
22097 return 0.0;
22098
22100 if( var->data.aggregate.scalar > 0.0 )
22101 return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, dir);
22102 else
22103 return SCIPvarGetInferenceSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22104
22106 return 0.0;
22107
22110
22111 default:
22112 SCIPerrorMessage("unknown variable status\n");
22113 SCIPABORT();
22114 return 0.0; /*lint !e527*/
22115 }
22116}
22117
22118/** returns the average number of inferences found after branching on the variable in given direction */
22120 SCIP_VAR* var, /**< problem variable */
22121 SCIP_STAT* stat, /**< problem statistics */
22122 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22123 )
22124{
22125 assert(var != NULL);
22126 assert(stat != NULL);
22128
22129 switch( SCIPvarGetStatus(var) )
22130 {
22132 if( var->data.original.transvar == NULL )
22133 return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
22134 else
22135 return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
22136
22139 if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
22140 return SCIPhistoryGetAvgInferences(var->history, dir);
22141 else
22142 {
22143 int nimpls;
22144 int ncliques;
22145
22147 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
22148 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
22149 }
22150
22152 return 0.0;
22153
22155 if( var->data.aggregate.scalar > 0.0 )
22156 return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
22157 else
22158 return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22159
22161 return 0.0;
22162
22164 return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22165
22166 default:
22167 SCIPerrorMessage("unknown variable status\n");
22168 SCIPABORT();
22169 return 0.0; /*lint !e527*/
22170 }
22171}
22172
22173/** returns the average number of inferences found after branching on the variable in given direction
22174 * in the current run
22175 */
22177 SCIP_VAR* var, /**< problem variable */
22178 SCIP_STAT* stat, /**< problem statistics */
22179 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22180 )
22181{
22182 assert(var != NULL);
22183 assert(stat != NULL);
22185
22186 switch( SCIPvarGetStatus(var) )
22187 {
22189 if( var->data.original.transvar == NULL )
22191 else
22192 return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
22193
22196 if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
22197 return SCIPhistoryGetAvgInferences(var->historycrun, dir);
22198 else
22199 {
22200 int nimpls;
22201 int ncliques;
22202
22204 ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
22205 return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
22206 }
22207
22209 return 0.0;
22210
22212 if( var->data.aggregate.scalar > 0.0 )
22213 return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
22214 else
22215 return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22216
22218 return 0.0;
22219
22221 return SCIPvarGetAvgInferencesCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22222
22223 default:
22224 SCIPerrorMessage("unknown variable status\n");
22225 SCIPABORT();
22226 return 0.0; /*lint !e527*/
22227 }
22228}
22229
22230/** returns the number of cutoffs branching on this variable in given direction produced */
22232 SCIP_VAR* var, /**< problem variable */
22233 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22234 )
22235{
22236 assert(var != NULL);
22238
22239 switch( SCIPvarGetStatus(var) )
22240 {
22242 if( var->data.original.transvar == NULL )
22243 return 0;
22244 else
22245 return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
22246
22249 return SCIPhistoryGetCutoffSum(var->history, dir);
22250
22252 return 0;
22253
22255 if( var->data.aggregate.scalar > 0.0 )
22256 return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
22257 else
22258 return SCIPvarGetCutoffSum(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22259
22261 return 0;
22262
22264 return SCIPvarGetCutoffSum(var->negatedvar, SCIPbranchdirOpposite(dir));
22265
22266 default:
22267 SCIPerrorMessage("unknown variable status\n");
22268 SCIPABORT();
22269 return 0; /*lint !e527*/
22270 }
22271}
22272
22273/** returns the number of cutoffs branching on this variable in given direction produced in the current run */
22275 SCIP_VAR* var, /**< problem variable */
22276 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22277 )
22278{
22279 assert(var != NULL);
22281
22282 switch( SCIPvarGetStatus(var) )
22283 {
22285 if( var->data.original.transvar == NULL )
22286 return 0;
22287 else
22288 return SCIPvarGetCutoffSumCurrentRun(var->data.original.transvar, dir);
22289
22292 return SCIPhistoryGetCutoffSum(var->historycrun, dir);
22293
22295 return 0;
22296
22298 if( var->data.aggregate.scalar > 0.0 )
22299 return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
22300 else
22301 return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, SCIPbranchdirOpposite(dir));
22302
22304 return 0;
22305
22308
22309 default:
22310 SCIPerrorMessage("unknown variable status\n");
22311 SCIPABORT();
22312 return 0; /*lint !e527*/
22313 }
22314}
22315
22316/** returns the average number of cutoffs found after branching on the variable in given direction */
22318 SCIP_VAR* var, /**< problem variable */
22319 SCIP_STAT* stat, /**< problem statistics */
22320 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22321 )
22322{
22323 assert(var != NULL);
22324 assert(stat != NULL);
22326
22327 switch( SCIPvarGetStatus(var) )
22328 {
22330 if( var->data.original.transvar == NULL )
22331 return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
22332 else
22333 return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
22334
22337 return SCIPhistoryGetNBranchings(var->history, dir) > 0
22338 ? SCIPhistoryGetAvgCutoffs(var->history, dir)
22340
22342 return 0.0;
22343
22345 if( var->data.aggregate.scalar > 0.0 )
22346 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
22347 else
22348 return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22349
22351 return 0.0;
22352
22354 return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22355
22356 default:
22357 SCIPerrorMessage("unknown variable status\n");
22358 SCIPABORT();
22359 return 0.0; /*lint !e527*/
22360 }
22361}
22362
22363/** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
22365 SCIP_VAR* var, /**< problem variable */
22366 SCIP_STAT* stat, /**< problem statistics */
22367 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
22368 )
22369{
22370 assert(var != NULL);
22371 assert(stat != NULL);
22373
22374 switch( SCIPvarGetStatus(var) )
22375 {
22377 if( var->data.original.transvar == NULL )
22378 return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
22379 else
22380 return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
22381
22384 return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
22385 ? SCIPhistoryGetAvgCutoffs(var->historycrun, dir)
22387
22389 return 0.0;
22390
22392 if( var->data.aggregate.scalar > 0.0 )
22393 return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
22394 else
22395 return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
22396
22398 return 0.0;
22399
22401 return SCIPvarGetAvgCutoffsCurrentRun(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
22402
22403 default:
22404 SCIPerrorMessage("unknown variable status\n");
22405 SCIPABORT();
22406 return 0.0; /*lint !e527*/
22407 }
22408}
22409
22410/** returns the variable's average GMI efficacy score value generated from simplex tableau rows of this variable */
22412 SCIP_VAR* var, /**< problem variable */
22413 SCIP_STAT* stat /**< problem statistics */
22414 )
22415{
22416 assert(var != NULL);
22417 assert(stat != NULL);
22418
22419 switch( SCIPvarGetStatus(var) )
22420 {
22422 if( var->data.original.transvar == NULL )
22423 return 0.0;
22424 else
22425 return SCIPvarGetAvgGMIScore(var->data.original.transvar, stat);
22426
22429 return SCIPhistoryGetAvgGMIeff(var->history);
22430
22432 return 0.0;
22433
22435 return SCIPvarGetAvgGMIScore(var->data.aggregate.var, stat);
22436
22438 return 0.0;
22439
22441 return SCIPvarGetAvgGMIScore(var->negatedvar, stat);
22442
22443 default:
22444 SCIPerrorMessage("unknown variable status\n");
22445 SCIPABORT();
22446 return 0.0; /*lint !e527*/
22447 }
22448}
22449
22450/** increase the variable's GMI efficacy scores generated from simplex tableau rows of this variable */
22452 SCIP_VAR* var, /**< problem variable */
22453 SCIP_STAT* stat, /**< problem statistics */
22454 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
22455 )
22456{
22457 assert(var != NULL);
22458 assert(stat != NULL);
22459 assert(gmieff >= 0);
22460
22461 switch( SCIPvarGetStatus(var) )
22462 {
22464 if( var->data.original.transvar != NULL )
22465 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.original.transvar, stat, gmieff) );
22466 return SCIP_OKAY;
22467
22470 SCIPhistoryIncGMIeffSum(var->history, gmieff);
22471 return SCIP_OKAY;
22472
22474 return SCIP_INVALIDDATA;
22475
22477 SCIP_CALL( SCIPvarIncGMIeffSum(var->data.aggregate.var, stat, gmieff) );
22478 return SCIP_OKAY;
22479
22481 SCIP_CALL( SCIPvarIncGMIeffSum(var->negatedvar, stat, gmieff) );
22482 return SCIP_OKAY;
22483
22485 return SCIP_INVALIDDATA;
22486
22487 default:
22488 SCIPerrorMessage("unknown variable status\n");
22489 SCIPABORT();
22490 return SCIP_INVALIDDATA; /*lint !e527*/
22491 }
22492}
22493
22494/** returns the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
22496 SCIP_VAR* var, /**< problem variable */
22497 SCIP_STAT* stat /**< problem statistics */
22498 )
22499{
22500 assert(var != NULL);
22501 assert(stat != NULL);
22502
22503 switch( SCIPvarGetStatus(var) )
22504 {
22506 if( var->data.original.transvar != NULL )
22507 return SCIPvarGetLastGMIScore(var->data.original.transvar, stat);
22508 return 0.0;
22509
22512 return SCIPhistoryGetLastGMIeff(var->history);
22513
22515 return 0.0;
22516
22518 return SCIPvarGetLastGMIScore(var->data.aggregate.var, stat);
22519
22521 return 0.0;
22522
22524 return SCIPvarGetLastGMIScore(var->negatedvar, stat);
22525
22526 default:
22527 SCIPerrorMessage("unknown variable status\n");
22528 SCIPABORT();
22529 return 0.0; /*lint !e527*/
22530 }
22531}
22532
22533
22534/** sets the variable's last GMI efficacy score value generated from a simplex tableau row of this variable */
22536 SCIP_VAR* var, /**< problem variable */
22537 SCIP_STAT* stat, /**< problem statistics */
22538 SCIP_Real gmieff /**< efficacy of last GMI cut produced when variable was frac and basic */
22539 )
22540{
22541 assert(var != NULL);
22542 assert(stat != NULL);
22543 assert(gmieff >= 0);
22544
22545 switch( SCIPvarGetStatus(var) )
22546 {
22548 if( var->data.original.transvar != NULL )
22549 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.original.transvar, stat, gmieff) );
22550 return SCIP_OKAY;
22551
22554 SCIPhistorySetLastGMIeff(var->history, gmieff);
22555 return SCIP_OKAY;
22556
22558 return SCIP_INVALIDDATA;
22559
22561 SCIP_CALL( SCIPvarSetLastGMIScore(var->data.aggregate.var, stat, gmieff) );
22562 return SCIP_OKAY;
22563
22565 SCIP_CALL( SCIPvarSetLastGMIScore(var->negatedvar, stat, gmieff) );
22566 return SCIP_OKAY;
22567
22569 return SCIP_INVALIDDATA;
22570
22571 default:
22572 SCIPerrorMessage("unknown variable status\n");
22573 SCIPABORT();
22574 return SCIP_INVALIDDATA; /*lint !e527*/
22575 }
22576}
22577
22578
22579
22580/*
22581 * information methods for bound changes
22582 */
22583
22584/** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
22586 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
22587 BMS_BLKMEM* blkmem, /**< block memory */
22588 SCIP_VAR* var, /**< active variable that changed the bounds */
22589 SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
22590 SCIP_Real oldbound, /**< old value for bound */
22591 SCIP_Real newbound /**< new value for bound */
22592 )
22593{
22594 assert(bdchginfo != NULL);
22595
22596 SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
22597 (*bdchginfo)->oldbound = oldbound;
22598 (*bdchginfo)->newbound = newbound;
22599 (*bdchginfo)->var = var;
22600 (*bdchginfo)->inferencedata.var = var;
22601 (*bdchginfo)->inferencedata.reason.prop = NULL;
22602 (*bdchginfo)->inferencedata.info = 0;
22603 (*bdchginfo)->bdchgidx.depth = INT_MAX;
22604 (*bdchginfo)->bdchgidx.pos = -1;
22605 (*bdchginfo)->pos = 0;
22606 (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
22607 (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
22608 (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
22609 (*bdchginfo)->redundant = FALSE;
22610
22611 return SCIP_OKAY;
22612}
22613
22614/** frees a bound change information object */
22616 SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
22617 BMS_BLKMEM* blkmem /**< block memory */
22618 )
22619{
22620 assert(bdchginfo != NULL);
22621
22622 BMSfreeBlockMemory(blkmem, bdchginfo);
22623}
22624
22625/** returns the bound change information for the last lower bound change on given active problem variable before or
22626 * after the bound change with the given index was applied;
22627 * returns NULL, if no change to the lower bound was applied up to this point of time
22628 */
22630 SCIP_VAR* var, /**< active problem variable */
22631 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22632 SCIP_Bool after /**< should the bound change with given index be included? */
22633 )
22634{
22635 int i;
22636
22637 assert(var != NULL);
22639
22640 /* search the correct bound change information for the given bound change index */
22641 if( after )
22642 {
22643 for( i = var->nlbchginfos-1; i >= 0; --i )
22644 {
22645 assert(var->lbchginfos[i].var == var);
22646 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22647 assert(var->lbchginfos[i].pos == i);
22648
22649 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22650 if( var->lbchginfos[i].redundant )
22651 return NULL;
22652 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
22653
22654 /* if we reached the bound change index, return the current bound change info */
22655 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
22656 return &var->lbchginfos[i];
22657 }
22658 }
22659 else
22660 {
22661 for( i = var->nlbchginfos-1; i >= 0; --i )
22662 {
22663 assert(var->lbchginfos[i].var == var);
22664 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22665 assert(var->lbchginfos[i].pos == i);
22666
22667 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22668 if( var->lbchginfos[i].redundant )
22669 return NULL;
22670 assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
22671
22672 /* if we reached the bound change index, return the current bound change info */
22673 if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
22674 return &var->lbchginfos[i];
22675 }
22676 }
22677
22678 return NULL;
22679}
22680
22681/** returns the bound change information for the last upper bound change on given active problem variable before or
22682 * after the bound change with the given index was applied;
22683 * returns NULL, if no change to the upper bound was applied up to this point of time
22684 */
22686 SCIP_VAR* var, /**< active problem variable */
22687 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22688 SCIP_Bool after /**< should the bound change with given index be included? */
22689 )
22690{
22691 int i;
22692
22693 assert(var != NULL);
22695
22696 /* search the correct bound change information for the given bound change index */
22697 if( after )
22698 {
22699 for( i = var->nubchginfos-1; i >= 0; --i )
22700 {
22701 assert(var->ubchginfos[i].var == var);
22702 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22703 assert(var->ubchginfos[i].pos == i);
22704
22705 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22706 if( var->ubchginfos[i].redundant )
22707 return NULL;
22708 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
22709
22710 /* if we reached the bound change index, return the current bound change info */
22711 if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
22712 return &var->ubchginfos[i];
22713 }
22714 }
22715 else
22716 {
22717 for( i = var->nubchginfos-1; i >= 0; --i )
22718 {
22719 assert(var->ubchginfos[i].var == var);
22720 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22721 assert(var->ubchginfos[i].pos == i);
22722
22723 /* if we reached the (due to global bounds) redundant bound changes, return NULL */
22724 if( var->ubchginfos[i].redundant )
22725 return NULL;
22726 assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
22727
22728 /* if we reached the bound change index, return the current bound change info */
22729 if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
22730 return &var->ubchginfos[i];
22731 }
22732 }
22733
22734 return NULL;
22735}
22736
22737/** returns the bound change information for the last lower or upper bound change on given active problem variable
22738 * before or after the bound change with the given index was applied;
22739 * returns NULL, if no change to the lower/upper bound was applied up to this point of time
22740 */
22742 SCIP_VAR* var, /**< active problem variable */
22743 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
22744 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
22745 SCIP_Bool after /**< should the bound change with given index be included? */
22746 )
22747{
22748 if( boundtype == SCIP_BOUNDTYPE_LOWER )
22749 return SCIPvarGetLbchgInfo(var, bdchgidx, after);
22750 else
22751 {
22752 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
22753 return SCIPvarGetUbchgInfo(var, bdchgidx, after);
22754 }
22755}
22756
22757/** bound change index representing the initial time before any bound changes took place */
22759
22760/** bound change index representing the presolving stage */
22762
22763/** returns the last bound change index, at which the bounds of the given variable were tightened */
22765 SCIP_VAR* var /**< problem variable */
22766 )
22767{
22768 SCIP_BDCHGIDX* lbchgidx;
22769 SCIP_BDCHGIDX* ubchgidx;
22770
22771 assert(var != NULL);
22772
22774
22775 /* check, if variable is original without transformed variable */
22776 if( var == NULL )
22777 return &initbdchgidx;
22778
22779 /* check, if variable was fixed in presolving */
22780 if( !SCIPvarIsActive(var) )
22781 return &presolvebdchgidx;
22782
22784
22785 /* get depths of last bound change information for the lower and upper bound */
22786 lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
22787 ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
22788 ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
22789 ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
22790
22791 if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
22792 return ubchgidx;
22793 else
22794 return lbchgidx;
22795}
22796
22797/** returns the last depth level, at which the bounds of the given variable were tightened;
22798 * returns -2, if the variable's bounds are still the global bounds
22799 * returns -1, if the variable was fixed in presolving
22800 */
22802 SCIP_VAR* var /**< problem variable */
22803 )
22804{
22805 SCIP_BDCHGIDX* bdchgidx;
22806
22807 bdchgidx = SCIPvarGetLastBdchgIndex(var);
22808 assert(bdchgidx != NULL);
22809
22810 return bdchgidx->depth;
22811}
22812
22813/** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
22814 * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
22815 */
22817 SCIP_VAR* var, /**< problem variable */
22818 SCIP_SET* set, /**< global SCIP settings */
22819 SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
22820 SCIP_Real bound /**< conflicting bound */
22821 )
22822{
22823 int i;
22824
22825 assert(var != NULL);
22826 assert(set != NULL);
22827 assert(var->scip == set->scip);
22828
22829 if( boundtype == SCIP_BOUNDTYPE_LOWER )
22830 {
22831 /* check if the bound is in conflict with the current local bounds */
22832 if( SCIPsetIsLE(set, bound, var->locdom.ub) )
22833 return -1;
22834
22835 /* check if the bound is in conflict with the global bound */
22836 if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
22837 return 0;
22838
22839 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
22840 assert(var->nubchginfos > 0);
22841 assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
22842
22843 /* search for the first conflicting bound change */
22844 for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
22845 {
22846 assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
22847 assert((SCIP_BOUNDTYPE)var->ubchginfos[i].boundtype == SCIP_BOUNDTYPE_UPPER);
22848 }
22849 assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
22850 assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
22851
22852 /* return the depth at which the first conflicting bound change took place */
22853 return var->ubchginfos[i].bdchgidx.depth;
22854 }
22855 else
22856 {
22857 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
22858
22859 /* check if the bound is in conflict with the current local bounds */
22860 if( SCIPsetIsGE(set, bound, var->locdom.lb) )
22861 return -1;
22862
22863 /* check if the bound is in conflict with the global bound */
22864 if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
22865 return 0;
22866
22867 /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
22868 assert(var->nlbchginfos > 0);
22869 assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
22870
22871 /* search for the first conflicting bound change */
22872 for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
22873 {
22874 assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
22875 assert((SCIP_BOUNDTYPE)var->lbchginfos[i].boundtype == SCIP_BOUNDTYPE_LOWER);
22876 }
22877 assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
22878 assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
22879
22880 /* return the depth at which the first conflicting bound change took place */
22881 return var->lbchginfos[i].bdchgidx.depth;
22882 }
22883}
22884
22885/** returns whether the first binary variable was fixed earlier than the second one;
22886 * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
22887 * second one is not fixed
22888 */
22890 SCIP_VAR* var1, /**< first binary variable */
22891 SCIP_VAR* var2 /**< second binary variable */
22892 )
22893{
22894 SCIP_BDCHGIDX* bdchgidx1;
22895 SCIP_BDCHGIDX* bdchgidx2;
22896
22897 assert(var1 != NULL);
22898 assert(var2 != NULL);
22899 assert(SCIPvarIsBinary(var1));
22900 assert(SCIPvarIsBinary(var2));
22901
22902 var1 = SCIPvarGetProbvar(var1);
22903 var2 = SCIPvarGetProbvar(var2);
22904 assert(var1 != NULL);
22905 assert(var2 != NULL);
22906
22907 /* check, if variables are globally fixed */
22908 if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
22909 return FALSE;
22910 if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
22911 return TRUE;
22912
22915 assert(SCIPvarIsBinary(var1));
22916 assert(SCIPvarIsBinary(var2));
22917 assert(var1->nlbchginfos + var1->nubchginfos <= 1);
22918 assert(var2->nlbchginfos + var2->nubchginfos <= 1);
22919 assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
22920 assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
22921 assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
22922 assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
22923
22924 if( var1->nlbchginfos == 1 )
22925 bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
22926 else if( var1->nubchginfos == 1 )
22927 bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
22928 else
22929 bdchgidx1 = NULL;
22930
22931 if( var2->nlbchginfos == 1 )
22932 bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
22933 else if( var2->nubchginfos == 1 )
22934 bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
22935 else
22936 bdchgidx2 = NULL;
22937
22938 return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
22939}
22940
22941/** for a given array of variables, this function counts the numbers of variables for each variable and implied type combination */
22943 SCIP_VAR** vars, /**< array of variables to count the types for */
22944 int nvars, /**< number of variables in the array */
22945 int* nbinvars, /**< pointer to store number of binary variables or NULL if not needed */
22946 int* nintvars, /**< pointer to store number of integer variables or NULL if not needed */
22947 int* nbinimplvars, /**< pointer to store number of binary implied integral vars or NULL if not needed */
22948 int* nintimplvars, /**< pointer to store number of integer implied integral vars or NULL if not needed */
22949 int* ncontimplvars, /**< pointer to store number of continuous implied integral vars or NULL if not needed */
22950 int* ncontvars /**< pointer to store number of continuous variables or NULL if not needed */
22951 )
22952{
22953 assert(vars != NULL || nvars == 0);
22954 int binvars = 0;
22955 int binimplvars = 0;
22956 int intvars = 0;
22957 int intimplvars = 0;
22958 int contvars = 0;
22959 int contimplvars = 0;
22960 int v;
22961
22962 for( v = 0; v < nvars; ++v )
22963 {
22965 switch( SCIPvarGetType(vars[v]) )
22966 {
22968 if( implied )
22969 ++binimplvars;
22970 else
22971 ++binvars;
22972 break;
22974 if( implied )
22975 ++intimplvars;
22976 else
22977 ++intvars;
22978 break;
22980 if( implied )
22981 ++contimplvars;
22982 else
22983 ++contvars;
22984 break;
22985 default:
22986 SCIPerrorMessage("unknown variable type\n");
22987 SCIPABORT();
22988 } /*lint !e788*/
22989 }
22990 if( nbinvars != NULL )
22991 *nbinvars = binvars;
22992 if( nintvars != NULL )
22993 *nintvars = intvars;
22994 if( nbinimplvars != NULL )
22995 *nbinimplvars = binimplvars;
22996 if( nintimplvars != NULL )
22997 *nintimplvars = intimplvars;
22998 if( ncontimplvars != NULL )
22999 *ncontimplvars = contimplvars;
23000 if( ncontvars != NULL )
23001 *ncontvars = contvars;
23002}
23003
23004/*
23005 * Hash functions
23006 */
23007
23008/** gets the key (i.e. the name) of the given variable */
23009SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
23010{ /*lint --e{715}*/
23011 SCIP_VAR* var = (SCIP_VAR*)elem;
23012
23013 assert(var != NULL);
23014 return var->name;
23015}
23016
23017
23018
23019
23020/*
23021 * simple functions implemented as defines
23022 */
23023
23024/* In debug mode, the following methods are implemented as function calls to ensure
23025 * type validity.
23026 * In optimized mode, the methods are implemented as defines to improve performance.
23027 * However, we want to have them in the library anyways, so we have to undef the defines.
23028 */
23029
23030#undef SCIPboundchgGetNewbound
23031#undef SCIPboundchgGetLPSolVal
23032#undef SCIPboundchgGetVar
23033#undef SCIPboundchgGetBoundchgtype
23034#undef SCIPboundchgGetBoundtype
23035#undef SCIPboundchgIsRedundant
23036#undef SCIPdomchgGetNBoundchgs
23037#undef SCIPdomchgGetBoundchg
23038#undef SCIPholelistGetLeft
23039#undef SCIPholelistGetRight
23040#undef SCIPholelistGetNext
23041#undef SCIPvarGetName
23042#undef SCIPvarGetNUses
23043#undef SCIPvarGetData
23044#undef SCIPvarSetData
23045#undef SCIPvarSetDelorigData
23046#undef SCIPvarSetTransData
23047#undef SCIPvarSetDeltransData
23048#undef SCIPvarGetStatus
23049#undef SCIPvarIsOriginal
23050#undef SCIPvarIsTransformed
23051#undef SCIPvarIsNegated
23052#undef SCIPvarGetType
23053#undef SCIPvarIsBinary
23054#undef SCIPvarIsIntegral
23055#undef SCIPvarIsImpliedIntegral
23056#undef SCIPvarIsNonimpliedIntegral
23057#undef SCIPvarIsInitial
23058#undef SCIPvarIsRemovable
23059#undef SCIPvarIsDeleted
23060#undef SCIPvarIsDeletable
23061#undef SCIPvarMarkDeletable
23062#undef SCIPvarMarkNotDeletable
23063#undef SCIPvarIsActive
23064#undef SCIPvarGetIndex
23065#undef SCIPvarGetProbindex
23066#undef SCIPvarGetTransVar
23067#undef SCIPvarGetCol
23068#undef SCIPvarIsInLP
23069#undef SCIPvarGetMinAggrCoef
23070#undef SCIPvarGetMaxAggrCoef
23071#undef SCIPvarGetAggrVar
23072#undef SCIPvarGetAggrScalar
23073#undef SCIPvarGetAggrConstant
23074#undef SCIPvarGetMultaggrNVars
23075#undef SCIPvarGetMultaggrVars
23076#undef SCIPvarGetMultaggrScalars
23077#undef SCIPvarGetMultaggrConstant
23078#undef SCIPvarGetNegatedVar
23079#undef SCIPvarGetNegationVar
23080#undef SCIPvarGetNegationConstant
23081#undef SCIPvarGetObj
23082#undef SCIPvarGetLbOriginal
23083#undef SCIPvarGetUbOriginal
23084#undef SCIPvarGetHolelistOriginal
23085#undef SCIPvarGetLbGlobal
23086#undef SCIPvarGetUbGlobal
23087#undef SCIPvarGetHolelistGlobal
23088#undef SCIPvarGetBestBoundGlobal
23089#undef SCIPvarGetWorstBoundGlobal
23090#undef SCIPvarGetLbLocal
23091#undef SCIPvarGetUbLocal
23092#undef SCIPvarGetHolelistLocal
23093#undef SCIPvarGetBestBoundLocal
23094#undef SCIPvarGetWorstBoundLocal
23095#undef SCIPvarGetBestBoundType
23096#undef SCIPvarGetWorstBoundType
23097#undef SCIPvarGetLbLazy
23098#undef SCIPvarGetUbLazy
23099#undef SCIPvarGetBranchFactor
23100#undef SCIPvarGetBranchPriority
23101#undef SCIPvarGetBranchDirection
23102#undef SCIPvarGetNVlbs
23103#undef SCIPvarGetVlbVars
23104#undef SCIPvarGetVlbCoefs
23105#undef SCIPvarGetVlbConstants
23106#undef SCIPvarGetNVubs
23107#undef SCIPvarGetVubVars
23108#undef SCIPvarGetVubCoefs
23109#undef SCIPvarGetVubConstants
23110#undef SCIPvarGetNImpls
23111#undef SCIPvarGetImplVars
23112#undef SCIPvarGetImplTypes
23113#undef SCIPvarGetImplBounds
23114#undef SCIPvarGetImplIds
23115#undef SCIPvarGetNCliques
23116#undef SCIPvarGetCliques
23117#undef SCIPvarGetLPSol
23118#undef SCIPvarGetNLPSol
23119#undef SCIPvarGetBdchgInfoLb
23120#undef SCIPvarGetNBdchgInfosLb
23121#undef SCIPvarGetBdchgInfoUb
23122#undef SCIPvarGetNBdchgInfosUb
23123#undef SCIPvarGetValuehistory
23124#undef SCIPvarGetPseudoSol
23125#undef SCIPvarCatchEvent
23126#undef SCIPvarDropEvent
23127#undef SCIPvarGetVSIDS
23128#undef SCIPvarGetCliqueComponentIdx
23129#undef SCIPvarIsRelaxationOnly
23130#undef SCIPvarMarkRelaxationOnly
23131#undef SCIPbdchgidxGetPos
23132#undef SCIPbdchgidxGetDepth
23133#undef SCIPbdchgidxIsEarlierNonNull
23134#undef SCIPbdchgidxIsEarlier
23135#undef SCIPbdchginfoGetOldbound
23136#undef SCIPbdchginfoGetNewbound
23137#undef SCIPbdchginfoGetVar
23138#undef SCIPbdchginfoGetChgtype
23139#undef SCIPbdchginfoGetBoundtype
23140#undef SCIPbdchginfoGetDepth
23141#undef SCIPbdchginfoGetPos
23142#undef SCIPbdchginfoGetIdx
23143#undef SCIPbdchginfoGetInferVar
23144#undef SCIPbdchginfoGetInferCons
23145#undef SCIPbdchginfoGetInferProp
23146#undef SCIPbdchginfoGetInferInfo
23147#undef SCIPbdchginfoGetInferBoundtype
23148#undef SCIPbdchginfoIsRedundant
23149#undef SCIPbdchginfoHasInferenceReason
23150#undef SCIPbdchginfoIsTighter
23151
23152
23153/** returns the new value of the bound in the bound change data */
23155 SCIP_BOUNDCHG* boundchg /**< bound change data */
23156 )
23157{
23158 assert(boundchg != NULL);
23159
23160 return boundchg->newbound;
23161}
23162
23163/** returns the lp solution value in the branching data of the bound change data */
23165 SCIP_BOUNDCHG* boundchg /**< bound change data */
23166 )
23167{
23168 assert(boundchg != NULL);
23169
23170 return boundchg->data.branchingdata.lpsolval;
23171}
23172
23173/** returns the variable of the bound change in the bound change data */
23175 SCIP_BOUNDCHG* boundchg /**< bound change data */
23176 )
23177{
23178 assert(boundchg != NULL);
23179
23180 return boundchg->var;
23181}
23182
23183/** returns the bound change type of the bound change in the bound change data */
23185 SCIP_BOUNDCHG* boundchg /**< bound change data */
23186 )
23187{
23188 assert(boundchg != NULL);
23189
23190 return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
23191}
23192
23193/** returns the bound type of the bound change in the bound change data */
23195 SCIP_BOUNDCHG* boundchg /**< bound change data */
23196 )
23197{
23198 assert(boundchg != NULL);
23199
23200 return (SCIP_BOUNDTYPE)(boundchg->boundtype);
23201}
23202
23203/** returns whether the bound change is redundant due to a more global bound that is at least as strong */
23205 SCIP_BOUNDCHG* boundchg /**< bound change data */
23206 )
23207{
23208 assert(boundchg != NULL);
23209
23210 return boundchg->redundant;
23211}
23212
23213/** returns the number of bound changes in the domain change data */
23215 SCIP_DOMCHG* domchg /**< domain change data */
23216 )
23217{
23218 return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
23219}
23220
23221/** returns a particular bound change in the domain change data */
23223 SCIP_DOMCHG* domchg, /**< domain change data */
23224 int pos /**< position of the bound change in the domain change data */
23225 )
23226{
23227 assert(domchg != NULL);
23228 assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
23229
23230 return &domchg->domchgbound.boundchgs[pos];
23231}
23232
23233/** returns left bound of open interval in hole */
23235 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23236 )
23237{
23238 assert(holelist != NULL);
23239
23240 return holelist->hole.left;
23241}
23242
23243/** returns right bound of open interval in hole */
23245 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23246 )
23247{
23248 assert(holelist != NULL);
23249
23250 return holelist->hole.right;
23251}
23252
23253/** returns next hole in list */
23255 SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
23256 )
23257{
23258 assert(holelist != NULL);
23259
23260 return holelist->next;
23261}
23262
23263/** returns the name of the variable
23264 *
23265 * @note to change the name of a variable, use SCIPchgVarName() from scip.h
23266 */
23267const char* SCIPvarGetName(
23268 SCIP_VAR* var /**< problem variable */
23269 )
23270{
23271 assert(var != NULL);
23272
23273 return var->name;
23274}
23275
23276/** gets number of times, the variable is currently captured */
23278 SCIP_VAR* var /**< problem variable */
23279 )
23280{
23281 assert(var != NULL);
23282
23283 return var->nuses;
23284}
23285
23286/** returns the user data of the variable */
23288 SCIP_VAR* var /**< problem variable */
23289 )
23290{
23291 assert(var != NULL);
23292
23293 return var->vardata;
23294}
23295
23296/** sets the user data for the variable */
23298 SCIP_VAR* var, /**< problem variable */
23299 SCIP_VARDATA* vardata /**< user variable data */
23300 )
23301{
23302 assert(var != NULL);
23303
23304 var->vardata = vardata;
23305}
23306
23307/** sets method to free user data for the original variable */
23309 SCIP_VAR* var, /**< problem variable */
23310 SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
23311 )
23312{
23313 assert(var != NULL);
23315
23316 var->vardelorig = vardelorig;
23317}
23318
23319/** sets method to transform user data of the variable */
23321 SCIP_VAR* var, /**< problem variable */
23322 SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
23323 )
23324{
23325 assert(var != NULL);
23327
23328 var->vartrans = vartrans;
23329}
23330
23331/** sets method to free transformed user data for the variable */
23333 SCIP_VAR* var, /**< problem variable */
23334 SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
23335 )
23336{
23337 assert(var != NULL);
23338
23339 var->vardeltrans = vardeltrans;
23340}
23341
23342/** sets method to copy this variable into sub-SCIPs */
23344 SCIP_VAR* var, /**< problem variable */
23345 SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
23346 )
23347{
23348 assert(var != NULL);
23349
23350 var->varcopy = varcopy;
23351}
23352
23353/** sets the initial flag of a variable; only possible for original or loose variables */
23355 SCIP_VAR* var, /**< problem variable */
23356 SCIP_Bool initial /**< initial flag */
23357 )
23358{
23359 assert(var != NULL);
23360
23362 return SCIP_INVALIDCALL;
23363
23364 var->initial = initial;
23365
23366 return SCIP_OKAY;
23367}
23368
23369/** sets the removable flag of a variable; only possible for original or loose variables */
23371 SCIP_VAR* var, /**< problem variable */
23372 SCIP_Bool removable /**< removable flag */
23373 )
23374{
23375 assert(var != NULL);
23376
23378 return SCIP_INVALIDCALL;
23379
23380 var->removable = removable;
23381
23382 return SCIP_OKAY;
23383}
23384
23385/** gets status of variable */
23387 SCIP_VAR* var /**< problem variable */
23388 )
23389{
23390 assert(var != NULL);
23391
23392 return (SCIP_VARSTATUS)(var->varstatus);
23393}
23394
23395/** returns the status of the exact variable data */
23397 SCIP_VAR* var /**< scip variable */
23398 )
23399{
23400 assert(var != NULL);
23401 assert(var->exactdata != NULL);
23402
23403 return var->exactdata->varstatusexact;
23404}
23405
23406/** returns whether the variable has exact variable data */
23408 SCIP_VAR* var /**< scip variable */
23409 )
23410{
23411 assert(var != NULL);
23412
23413 return (var->exactdata != NULL);
23414}
23415
23416/** returns whether the variable belongs to the original problem */
23418 SCIP_VAR* var /**< problem variable */
23419 )
23420{
23421 assert(var != NULL);
23423
23426 && SCIPvarGetStatus(var->negatedvar) == SCIP_VARSTATUS_ORIGINAL));
23427}
23428
23429/** returns whether the variable belongs to the transformed problem */
23431 SCIP_VAR* var /**< problem variable */
23432 )
23433{
23434 assert(var != NULL);
23436
23439 || SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_ORIGINAL));
23440}
23441
23442/** returns whether the variable was created by negation of a different variable */
23444 SCIP_VAR* var /**< problem variable */
23445 )
23446{
23447 assert(var != NULL);
23448
23450}
23451
23452/** gets type of variable */
23454 SCIP_VAR* var /**< problem variable */
23455 )
23456{
23457 assert(var != NULL);
23458
23459 return (SCIP_VARTYPE)(var->vartype);
23460}
23461
23462/** gets the implied integral type of the variable */
23464 SCIP_VAR* var /**< problem variable */
23465 )
23466{
23467 assert(var != NULL);
23468
23469 return (SCIP_IMPLINTTYPE)(var->varimpltype);
23470}
23471
23472/** returns TRUE if the variable is of binary type; this is the case if:
23473 * (1) variable type is binary
23474 * (2) variable type is integer or implicit integer and
23475 * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
23476 * (ii) the lazy upper bound or the global upper bound is less than or equal to one
23477 */
23479 SCIP_VAR* var /**< problem variable */
23480 )
23481{
23482 assert(var != NULL);
23483
23486 && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
23487}
23488
23489/** returns whether variable is of integral type (binary, integer, or implied integral of any type) */
23491 SCIP_VAR* var /**< problem variable */
23492 )
23493{
23495}
23496
23497/** returns whether variable is implied integral (weakly or strongly) */
23499 SCIP_VAR* var /**< problem variable */
23500 )
23501{
23503}
23504
23505/** returns TRUE if the variable is integral, but not implied integral. */
23507 SCIP_VAR* var /**< problem variable */
23508 )
23509{
23511}
23512
23513/** returns whether variable's column should be present in the initial root LP */
23515 SCIP_VAR* var /**< problem variable */
23516 )
23517{
23518 assert(var != NULL);
23519
23520 return var->initial;
23521}
23522
23523/** returns whether variable's column is removable from the LP (due to aging or cleanup) */
23525 SCIP_VAR* var /**< problem variable */
23526 )
23527{
23528 assert(var != NULL);
23529
23530 return var->removable;
23531}
23532
23533/** returns whether the variable was deleted from the problem */
23535 SCIP_VAR* var /**< problem variable */
23536 )
23537{
23538 assert(var != NULL);
23539
23540 return var->deleted;
23541}
23542
23543/** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
23544 * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
23545 */
23547 SCIP_VAR* var /**< problem variable */
23548 )
23549{
23550 assert(var != NULL);
23551 assert(var->probindex == -1);
23552
23553 var->deletable = TRUE;
23554}
23555
23556/** marks the variable to be not deletable from the problem */
23558 SCIP_VAR* var
23559 )
23560{
23561 assert(var != NULL);
23562
23563 var->deletable = FALSE;
23564}
23565
23566/** marks variable to be deleted from global structures (cliques etc.) when cleaning up
23567 *
23568 * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
23569 */
23571 SCIP_VAR* var /**< problem variable */
23572 )
23573{
23574 assert(var != NULL);
23575
23576 var->delglobalstructs = TRUE;
23577}
23578
23579/** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
23581 SCIP_VAR* var /**< problem variable */
23582 )
23583{
23584 assert(var != NULL);
23585
23586 return var->delglobalstructs;
23587}
23588
23589/** returns whether a variable has been introduced to define a relaxation
23590 *
23591 * These variables are only valid for the current SCIP solve round,
23592 * they are not contained in any (checked) constraints, but may be used
23593 * in cutting planes, for example.
23594 * Relaxation-only variables are not copied by SCIPcopyVars and cuts
23595 * that contain these variables are not added as linear constraints when
23596 * restarting or transferring information from a copied SCIP to a SCIP.
23597 * Also conflicts with relaxation-only variables are not generated at
23598 * the moment.
23599 */
23601 SCIP_VAR* var /**< problem variable */
23602 )
23603{
23604 assert(var != NULL);
23605
23606 return var->relaxationonly;
23607}
23608
23609/** marks that this variable has only been introduced to define a relaxation
23610 *
23611 * The variable must not have a coefficient in the objective and must be deletable.
23612 * If it is not marked deletable, it will be marked as deletable, which is only possible
23613 * before the variable is added to a problem.
23614 *
23615 * @see SCIPvarIsRelaxationOnly
23616 * @see SCIPvarMarkDeletable
23617 */
23619 SCIP_VAR* var /**< problem variable */
23620 )
23621{
23622 assert(var != NULL);
23623 assert(SCIPvarGetObj(var) == 0.0);
23624
23625 if( !SCIPvarIsDeletable(var) )
23627
23628 var->relaxationonly = TRUE;
23629}
23630
23631/** returns whether variable is allowed to be deleted completely from the problem */
23633 SCIP_VAR* var
23634 )
23635{
23636 assert(var != NULL);
23637
23638 return var->deletable;
23639}
23640
23641/** returns whether variable is an active (neither fixed nor aggregated) variable */
23643 SCIP_VAR* var /**< problem variable */
23644 )
23645{
23646 assert(var != NULL);
23647
23648 return (var->probindex >= 0);
23649}
23650
23651/** gets unique index of variable */
23653 SCIP_VAR* var /**< problem variable */
23654 )
23655{
23656 assert(var != NULL);
23657
23658 return var->index;
23659}
23660
23661/** gets position of variable in problem, or -1 if variable is not active */
23663 SCIP_VAR* var /**< problem variable */
23664 )
23665{
23666 assert(var != NULL);
23667
23668 return var->probindex;
23669}
23670
23671/** gets transformed variable of ORIGINAL variable */
23673 SCIP_VAR* var /**< problem variable */
23674 )
23675{
23676 assert(var != NULL);
23678
23679 return var->data.original.transvar;
23680}
23681
23682/** gets column of COLUMN variable */
23684 SCIP_VAR* var /**< problem variable */
23685 )
23686{
23687 assert(var != NULL);
23689
23690 return var->data.col;
23691}
23692
23693/** gets exact column of COLUMN variable */
23695 SCIP_VAR* var /**< problem variable */
23696 )
23697{
23698 assert(var != NULL);
23699 assert(var->exactdata != NULL);
23701
23702 return var->exactdata->colexact;
23703}
23704
23705/** returns whether the variable is a COLUMN variable that is member of the current LP */
23707 SCIP_VAR* var /**< problem variable */
23708 )
23709{
23710 assert(var != NULL);
23711
23712 return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
23713}
23714
23715/** gets minimal absolute coefficient of a loose variable in (multi)aggregations of other variables */
23717 SCIP_VAR* var /**< problem variable */
23718 )
23719{
23721
23722 return var->data.loose.minaggrcoef;
23723}
23724
23725/** gets lower bound on absolute coefficient of a loose variable in (multi)aggregations of other variables */
23727 SCIP_VAR* var /**< problem variable */
23728 )
23729{
23731
23732 return var->data.loose.maxaggrcoef;
23733}
23734
23735/** gets upper bound on absolute coefficient of a loose variable in (multi)aggregations of other variables */
23737 SCIP_VAR* var /**< problem variable */
23738 )
23739{
23740 assert(var != NULL);
23742 assert(!var->donotaggr);
23743
23744 return var->data.aggregate.var;
23745}
23746
23747/** gets aggregation scalar a of an aggregated variable x = a*y + c */
23749 SCIP_VAR* var /**< problem variable */
23750 )
23751{
23752 assert(var != NULL);
23754 assert(!var->donotaggr);
23755
23756 return var->data.aggregate.scalar;
23757}
23758
23759/** gets aggregation scalar a of an aggregated variable x = a*y + c */
23761 SCIP_VAR* var /**< problem variable */
23762 )
23763{
23764 assert(var != NULL);
23766
23767 return var->exactdata->aggregate.scalar;
23768}
23769
23770/** gets aggregation constant c of an aggregated variable x = a*y + c */
23772 SCIP_VAR* var /**< problem variable */
23773 )
23774{
23775 assert(var != NULL);
23777 assert(!var->donotaggr);
23778
23779 return var->data.aggregate.constant;
23780}
23781
23782/** gets aggregation constant c of an aggregated variable x = a*y + c */
23784 SCIP_VAR* var /**< problem variable */
23785 )
23786{
23787 assert(var != NULL);
23789
23790 return var->exactdata->aggregate.constant;
23791}
23792
23793/** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23795 SCIP_VAR* var /**< problem variable */
23796 )
23797{
23798 assert(var != NULL);
23800 assert(!var->donotmultaggr);
23801
23802 return var->data.multaggr.nvars;
23803}
23804
23805/** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23807 SCIP_VAR* var /**< problem variable */
23808 )
23809{
23810 assert(var != NULL);
23812 assert(!var->donotmultaggr);
23813
23814 return var->data.multaggr.vars;
23815}
23816
23817/** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23819 SCIP_VAR* var /**< problem variable */
23820 )
23821{
23822 assert(var != NULL);
23824 assert(!var->donotmultaggr);
23825
23826 return var->data.multaggr.scalars;
23827}
23828
23829/** gets vector of exact aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23831 SCIP_VAR* var /**< problem variable */
23832 )
23833{
23834 assert(var != NULL);
23836 assert(!var->donotmultaggr);
23837 assert(var->exactdata != NULL);
23838
23839 return var->exactdata->multaggr.scalars;
23840}
23841
23842/** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23844 SCIP_VAR* var /**< problem variable */
23845 )
23846{
23847 assert(var != NULL);
23849 assert(!var->donotmultaggr);
23850
23851 return var->data.multaggr.constant;
23852}
23853
23854/** gets exact aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
23856 SCIP_VAR* var /**< problem variable */
23857 )
23858{
23859 assert(var != NULL);
23861 assert(!var->donotmultaggr);
23862 assert(var->exactdata != NULL);
23863
23864 return var->exactdata->multaggr.constant;
23865}
23866
23867/** gets the negation of the given variable; may return NULL, if no negation is existing yet */
23869 SCIP_VAR* var /**< negated problem variable */
23870 )
23871{
23872 assert(var != NULL);
23873
23874 return var->negatedvar;
23875}
23876
23877/** gets the negation variable x of a negated variable x' = offset - x */
23879 SCIP_VAR* var /**< negated problem variable */
23880 )
23881{
23882 assert(var != NULL);
23884
23885 return var->negatedvar;
23886}
23887
23888/** gets the negation offset of a negated variable x' = offset - x */
23890 SCIP_VAR* var /**< negated problem variable */
23891 )
23892{
23893 assert(var != NULL);
23895
23896 return var->data.negate.constant;
23897}
23898
23899/** gets objective function value of variable */
23901 SCIP_VAR* var /**< problem variable */
23902 )
23903{
23904 assert(var != NULL);
23905
23906 return var->obj;
23907}
23908
23909/** gets exact objective function value of variable */
23911 SCIP_VAR* var /**< problem variable */
23912 )
23913{
23914 assert(var != NULL);
23915 assert(var->exactdata != NULL);
23916
23917 return var->exactdata->obj;
23918}
23919
23920/** gets exact objective function value of variable */
23922 SCIP_VAR* var /**< problem variable */
23923 )
23924{
23925 assert(var != NULL);
23926 assert(var->exactdata != NULL);
23927
23928 return var->exactdata->objinterval;
23929}
23930
23931/** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
23933 SCIP_VAR* var /**< problem variable */
23934 )
23935{
23936 assert(var != NULL);
23937
23938 return var->unchangedobj;
23939}
23940
23941/** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
23942 * e.g. obj(x) = 1 this method returns for ~x the value -1
23943 */
23945 SCIP_VAR* var, /**< problem variable */
23946 SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
23947 )
23948{
23949 SCIP_VAR* probvar = var;
23950 SCIP_Real mult = 1.0;
23951
23952 assert(probvar != NULL);
23953 assert(aggrobj != NULL);
23954
23955 while( probvar != NULL )
23956 {
23957 switch( SCIPvarGetStatus(probvar) )
23958 {
23962 (*aggrobj) = mult * SCIPvarGetObj(probvar);
23963 return SCIP_OKAY;
23964
23966 assert(SCIPvarGetObj(probvar) == 0.0);
23967 (*aggrobj) = 0.0;
23968 return SCIP_OKAY;
23969
23971 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
23972 if ( probvar->data.multaggr.nvars == 1 )
23973 {
23974 assert( probvar->data.multaggr.vars != NULL );
23975 assert( probvar->data.multaggr.scalars != NULL );
23976 assert( probvar->data.multaggr.vars[0] != NULL );
23977 mult *= probvar->data.multaggr.scalars[0];
23978 probvar = probvar->data.multaggr.vars[0];
23979 break;
23980 }
23981 else
23982 {
23983 SCIP_Real tmpobj;
23984 int v;
23985
23986 (*aggrobj) = 0.0;
23987
23988 for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
23989 {
23990 SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
23991 (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
23992 }
23993 return SCIP_OKAY;
23994 }
23995
23996 case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
23997 assert(probvar->data.aggregate.var != NULL);
23998 mult *= probvar->data.aggregate.scalar;
23999 probvar = probvar->data.aggregate.var;
24000 break;
24001
24002 case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
24003 assert(probvar->negatedvar != NULL);
24005 assert(probvar->negatedvar->negatedvar == probvar);
24006 mult *= -1.0;
24007 probvar = probvar->negatedvar;
24008 break;
24009
24010 default:
24011 SCIPABORT();
24012 return SCIP_INVALIDDATA; /*lint !e527*/
24013 }
24014 }
24015
24016 return SCIP_INVALIDDATA;
24017}
24018
24019/** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
24021 SCIP_VAR* var /**< original problem variable */
24022 )
24023{
24024 assert(var != NULL);
24026
24028 return var->data.original.origdom.lb;
24029 else
24030 {
24032 assert(var->negatedvar != NULL);
24034
24035 return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
24036 }
24037}
24038
24039/** gets exact original lower bound of original problem variable (i.e. the bound set in problem creation) */
24041 SCIP_VAR* var /**< original problem variable */
24042 )
24043{
24044 assert(var != NULL);
24046 assert(var->exactdata != NULL);
24047
24049 return var->exactdata->origdom.lb;
24050 else
24051 {
24053 assert(var->negatedvar != NULL);
24055
24056 SCIPerrorMessage("negated var not implemented yet for rational data \n");
24057 SCIPABORT();
24058 return NULL;
24059 }
24060}
24061
24062/** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
24064 SCIP_VAR* var /**< original problem variable */
24065 )
24066{
24067 assert(var != NULL);
24069
24071 return var->data.original.origdom.ub;
24072 else
24073 {
24075 assert(var->negatedvar != NULL);
24077
24078 return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
24079 }
24080}
24081
24082/** gets exact original upper bound of original problem variable (i.e. the bound set in problem creation) */
24084 SCIP_VAR* var /**< original problem variable */
24085 )
24086{
24087 assert(var != NULL);
24089 assert(var->exactdata != NULL);
24090
24092 return var->exactdata->origdom.ub;
24093 else
24094 {
24096 assert(var->negatedvar != NULL);
24098
24099 SCIPerrorMessage("negated var not implemented yet for rational data \n");
24100 SCIPABORT();
24101 return NULL;
24102 }
24103}
24104
24105/** gets the original hole list of an original variable */
24107 SCIP_VAR* var /**< problem variable */
24108 )
24109{
24110 assert(var != NULL);
24112
24114 return var->data.original.origdom.holelist;
24115
24116 return NULL;
24117}
24118
24119/** gets global lower bound of variable */
24121 SCIP_VAR* var /**< problem variable */
24122 )
24123{
24124 assert(var != NULL);
24125
24126 return var->glbdom.lb;
24127}
24128
24129/** gets exact global lower bound of variable */
24131 SCIP_VAR* var /**< problem variable */
24132 )
24133{
24134 assert(var != NULL);
24135 assert(var->exactdata != NULL);
24136 assert(var->exactdata->glbdom.lb != NULL);
24137
24138 return var->exactdata->glbdom.lb;
24139}
24140
24141/** gets global upper bound of variable */
24143 SCIP_VAR* var /**< problem variable */
24144 )
24145{
24146 assert(var != NULL);
24147
24148 return var->glbdom.ub;
24149}
24150
24151/** gets exact global upper bound of variable */
24153 SCIP_VAR* var /**< problem variable */
24154 )
24155{
24156 assert(var != NULL);
24157 assert(var->exactdata != NULL);
24158 assert(var->exactdata->glbdom.ub != NULL);
24159
24160 return var->exactdata->glbdom.ub;
24161}
24162
24163/** gets the global hole list of an active variable */
24165 SCIP_VAR* var /**< problem variable */
24166 )
24167{
24168 assert(var != NULL);
24169
24170 return var->glbdom.holelist;
24171}
24172
24173/** gets best global bound of variable with respect to the objective function */
24175 SCIP_VAR* var /**< problem variable */
24176 )
24177{
24178 assert(var != NULL);
24179
24180 if( var->obj >= 0.0 )
24181 return var->glbdom.lb;
24182 else
24183 return var->glbdom.ub;
24184}
24185
24186/** gets best exact global bound of variable with respect to the objective function */
24188 SCIP_VAR* var /**< problem variable */
24189 )
24190{
24191 assert(var != NULL);
24192 assert(var->exactdata != NULL);
24193 assert(var->exactdata->glbdom.lb != NULL);
24194 assert(var->exactdata->glbdom.ub != NULL);
24195 assert(var->exactdata->obj != NULL);
24196
24197 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24198 return var->exactdata->glbdom.lb;
24199 else
24200 return var->exactdata->glbdom.ub;
24201}
24202
24203/** gets worst global bound of variable with respect to the objective function */
24205 SCIP_VAR* var /**< problem variable */
24206 )
24207{
24208 assert(var != NULL);
24209
24210 if( var->obj >= 0.0 )
24211 return var->glbdom.ub;
24212 else
24213 return var->glbdom.lb;
24214}
24215
24216/** gets worst exact global bound of variable with respect to the objective function */
24218 SCIP_VAR* var /**< problem variable */
24219 )
24220{
24221 assert(var != NULL);
24222 assert(var->exactdata != NULL);
24223 assert(var->exactdata->glbdom.lb != NULL);
24224 assert(var->exactdata->glbdom.ub != NULL);
24225 assert(var->exactdata->obj != NULL);
24226
24227 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24228 return var->exactdata->glbdom.ub;
24229 else
24230 return var->exactdata->glbdom.lb;
24231}
24232
24233/** gets current lower bound of variable */
24235 SCIP_VAR* var /**< problem variable */
24236 )
24237{
24238 assert(var != NULL);
24239
24240 return var->locdom.lb;
24241}
24242
24243/** gets current exact lower bound of variable */
24245 SCIP_VAR* var /**< problem variable */
24246 )
24247{
24248 assert(var != NULL);
24249 assert(var->exactdata != NULL);
24250 assert(var->exactdata->locdom.lb != NULL);
24251
24252 return var->exactdata->locdom.lb;
24253}
24254
24256 SCIP_VAR* var, /**< problem variable */
24257 SCIP_RATIONAL* output /**< output rational */
24258 )
24259{
24260 assert(var != NULL);
24261 assert(var->exactdata != NULL);
24262 assert(var->exactdata->locdom.lb != NULL);
24263 SCIPrationalSetFraction(output, (SCIP_Longint) (floor(var->locdom.lb)), 1LL);
24264 SCIPrationalMax(output, output, var->exactdata->locdom.lb);
24265}
24266
24267/** gets current upper bound of variable */
24269 SCIP_VAR* var /**< problem variable */
24270 )
24271{
24272 assert(var != NULL);
24273
24274 return var->locdom.ub;
24275}
24276
24277/** gets current exact upper bound of variable */
24279 SCIP_VAR* var /**< problem variable */
24280 )
24281{
24282 assert(var != NULL);
24283 assert(var->exactdata != NULL);
24284 assert(var->exactdata->locdom.ub != NULL);
24285
24286 return var->exactdata->locdom.ub;
24287}
24288
24290 SCIP_VAR* var, /**< problem variable */
24291 SCIP_RATIONAL* output /**< output rational */
24292 )
24293{
24294 assert(var != NULL);
24295 assert(var->exactdata != NULL);
24296 assert(var->exactdata->locdom.ub != NULL);
24297 SCIPrationalSetFraction(output, (SCIP_Longint) (ceil(var->locdom.ub)), 1LL);
24298 SCIPrationalMin(output, output, var->exactdata->locdom.ub);
24299}
24300
24301/** gets the current hole list of an active variable */
24303 SCIP_VAR* var /**< problem variable */
24304 )
24305{
24306 assert(var != NULL);
24307
24308 return var->locdom.holelist;
24309}
24310
24311/** gets best local bound of variable with respect to the objective function */
24313 SCIP_VAR* var /**< problem variable */
24314 )
24315{
24316 assert(var != NULL);
24317
24318 if( var->obj >= 0.0 )
24319 return var->locdom.lb;
24320 else
24321 return var->locdom.ub;
24322}
24323
24324/** gets best exact local bound of variable with respect to the objective function */
24326 SCIP_VAR* var /**< problem variable */
24327 )
24328{
24329 assert(var != NULL);
24330 assert(var->exactdata != NULL);
24331 assert(var->exactdata->locdom.lb != NULL);
24332 assert(var->exactdata->locdom.ub != NULL);
24333 assert(var->exactdata->obj != NULL);
24334
24335 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24336 return var->exactdata->locdom.lb;
24337 else
24338 return var->exactdata->locdom.ub;
24339}
24340
24341/** gets worst local bound of variable with respect to the objective function */
24343 SCIP_VAR* var /**< problem variable */
24344 )
24345{
24346 assert(var != NULL);
24347
24348 if( var->obj >= 0.0 )
24349 return var->locdom.ub;
24350 else
24351 return var->locdom.lb;
24352}
24353
24354/** gets worst exact local bound of variable with respect to the objective function */
24356 SCIP_VAR* var /**< problem variable */
24357 )
24358{
24359 assert(var != NULL);
24360 assert(var->exactdata != NULL);
24361 assert(var->exactdata->locdom.lb != NULL);
24362 assert(var->exactdata->locdom.ub != NULL);
24363 assert(var->exactdata->obj != NULL);
24364
24365 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24366 return var->exactdata->locdom.ub;
24367 else
24368 return var->exactdata->locdom.lb;
24369}
24370
24371/** gets type (lower or upper) of best bound of variable with respect to the objective function */
24373 SCIP_VAR* var /**< problem variable */
24374 )
24375{
24376 assert(var != NULL);
24377
24378 if( var->obj >= 0.0 )
24379 return SCIP_BOUNDTYPE_LOWER;
24380 else
24381 return SCIP_BOUNDTYPE_UPPER;
24382}
24383
24384/** gets type (lower or upper) of best bound of variable with respect to the objective function */
24386 SCIP_VAR* var /**< problem variable */
24387 )
24388{
24389 assert(var != NULL);
24390 assert(var->exactdata != NULL);
24391 assert(var->exactdata->obj != NULL);
24392
24393 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24394 return SCIP_BOUNDTYPE_LOWER;
24395 else
24396 return SCIP_BOUNDTYPE_UPPER;
24397}
24398
24399/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
24401 SCIP_VAR* var /**< problem variable */
24402 )
24403{
24404 assert(var != NULL);
24405
24406 if( var->obj >= 0.0 )
24407 return SCIP_BOUNDTYPE_UPPER;
24408 else
24409 return SCIP_BOUNDTYPE_LOWER;
24410}
24411
24412/** gets type (lower or upper) of worst bound of variable with respect to the objective function */
24414 SCIP_VAR* var /**< problem variable */
24415 )
24416{
24417 assert(var != NULL);
24418 assert(var->exactdata != NULL);
24419 assert(var->exactdata->obj != NULL);
24420
24421 if( !SCIPrationalIsNegative(var->exactdata->obj) )
24422 return SCIP_BOUNDTYPE_UPPER;
24423 else
24424 return SCIP_BOUNDTYPE_LOWER;
24425}
24426
24427/** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
24429 SCIP_VAR* var /**< problem variable */
24430 )
24431{
24432 assert(var != NULL);
24433
24434 return var->lazylb;
24435}
24436
24437/** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
24439 SCIP_VAR* var /**< problem variable */
24440 )
24441{
24442 assert(var != NULL);
24443
24444 return var->lazyub;
24445}
24446
24447/** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
24448 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
24449 */
24451 SCIP_VAR* var /**< problem variable */
24452 )
24453{
24454 assert(var != NULL);
24455
24456 return var->branchfactor;
24457}
24458
24459/** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
24460 * with lower priority
24461 */
24463 SCIP_VAR* var /**< problem variable */
24464 )
24465{
24466 assert(var != NULL);
24467
24468 return var->branchpriority;
24469}
24470
24471/** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
24473 SCIP_VAR* var /**< problem variable */
24474 )
24475{
24476 assert(var != NULL);
24477
24478 return (SCIP_BRANCHDIR)var->branchdirection;
24479}
24480
24481/** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
24483 SCIP_VAR* var /**< problem variable */
24484 )
24485{
24486 assert(var != NULL);
24487
24488 return SCIPvboundsGetNVbds(var->vlbs);
24489}
24490
24491/** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
24492 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
24493 */
24495 SCIP_VAR* var /**< problem variable */
24496 )
24497{
24498 assert(var != NULL);
24499
24500 return SCIPvboundsGetVars(var->vlbs);
24501}
24502
24503/** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
24505 SCIP_VAR* var /**< problem variable */
24506 )
24507{
24508 assert(var != NULL);
24509
24510 return SCIPvboundsGetCoefs(var->vlbs);
24511}
24512
24513/** gets array with bounding constants d_i in 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 SCIPvboundsGetConstants(var->vlbs);
24521}
24522
24523/** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
24525 SCIP_VAR* var /**< problem variable */
24526 )
24527{
24528 assert(var != NULL);
24529
24530 return SCIPvboundsGetNVbds(var->vubs);
24531}
24532
24533/** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
24534 * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
24535 */
24537 SCIP_VAR* var /**< problem variable */
24538 )
24539{
24540 assert(var != NULL);
24541
24542 return SCIPvboundsGetVars(var->vubs);
24543}
24544
24545/** gets array with bounding coefficients b_i in variable upper 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 SCIPvboundsGetCoefs(var->vubs);
24553}
24554
24555/** gets array with bounding constants d_i in 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 SCIPvboundsGetConstants(var->vubs);
24563}
24564
24565/** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
24566 * there are no implications for nonbinary variable x
24567 */
24569 SCIP_VAR* var, /**< active problem variable */
24570 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24571 )
24572{
24573 assert(var != NULL);
24575
24576 return SCIPimplicsGetNImpls(var->implics, varfixing);
24577}
24578
24579/** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
24580 * problem variable x, there are no implications for nonbinary variable x;
24581 * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
24582 * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
24583 * (see SCIPvarGetIndex())
24584 */
24586 SCIP_VAR* var, /**< active problem variable */
24587 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24588 )
24589{
24590 assert(var != NULL);
24592
24593 return SCIPimplicsGetVars(var->implics, varfixing);
24594}
24595
24596/** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
24597 * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
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 SCIPimplicsGetTypes(var->implics, varfixing);
24609}
24610
24611/** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
24612 * variable x, there are no implications for nonbinary variable x
24613 */
24615 SCIP_VAR* var, /**< active problem variable */
24616 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24617 )
24618{
24619 assert(var != NULL);
24621
24622 return SCIPimplicsGetBounds(var->implics, varfixing);
24623}
24624
24625/** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
24626 * there are no implications for nonbinary variable x.
24627 * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
24628 * its id is negative, otherwise it is nonnegative.
24629 */
24631 SCIP_VAR* var, /**< active problem variable */
24632 SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
24633 )
24634{
24635 assert(var != NULL);
24637
24638 return SCIPimplicsGetIds(var->implics, varfixing);
24639}
24640
24641/** gets number of cliques, the active variable is contained in */
24643 SCIP_VAR* var, /**< active problem variable */
24644 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
24645 )
24646{
24647 assert(var != NULL);
24648
24649 return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
24650}
24651
24652/** gets array of cliques, the active variable is contained in */
24654 SCIP_VAR* var, /**< active problem variable */
24655 SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
24656 )
24657{
24658 assert(var != NULL);
24659
24660 return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
24661}
24662
24663/** gets primal LP solution value of variable */
24665 SCIP_VAR* var /**< problem variable */
24666 )
24667{
24668 assert(var != NULL);
24669
24671 return SCIPcolGetPrimsol(var->data.col);
24672 else
24673 return SCIPvarGetLPSol_rec(var);
24674}
24675
24676/** gets exact primal LP solution value of variable */
24678 SCIP_VAR* var, /**< problem variable */
24679 SCIP_RATIONAL* res /**< resulting value */
24680 )
24681{
24682 assert(var != NULL);
24683
24685 SCIPrationalSetRational(res, SCIPcolExactGetPrimsol(var->exactdata->colexact));
24686 else
24688}
24689
24690/** gets primal NLP solution value of variable */
24692 SCIP_VAR* var /**< problem variable */
24693 )
24694{
24695 assert(var != NULL);
24696
24698 return var->nlpsol;
24699 else
24700 return SCIPvarGetNLPSol_rec(var);
24701}
24702
24703/** return lower bound change info at requested position */
24705 SCIP_VAR* var, /**< problem variable */
24706 int pos /**< requested position */
24707 )
24708{
24709 assert(pos >= 0);
24710 assert(pos < var->nlbchginfos);
24711
24712 return &var->lbchginfos[pos];
24713}
24714
24715/** gets the number of lower bound change info array */
24717 SCIP_VAR* var /**< problem variable */
24718 )
24719{
24720 return var->nlbchginfos;
24721}
24722
24723/** return upper bound change info at requested position */
24725 SCIP_VAR* var, /**< problem variable */
24726 int pos /**< requested position */
24727 )
24728{
24729 assert(pos >= 0);
24730 assert(pos < var->nubchginfos);
24731
24732 return &var->ubchginfos[pos];
24733}
24734
24735/** gets the number upper bound change info array */
24737 SCIP_VAR* var /**< problem variable */
24738 )
24739{
24740 assert(var != NULL);
24741
24742 return var->nubchginfos;
24743}
24744
24745/** returns the value based history for the variable */
24747 SCIP_VAR* var /**< problem variable */
24748 )
24749{
24750 assert(var != NULL);
24751
24752 return var->valuehistory;
24753}
24754
24755/** gets pseudo solution value of variable */
24757 SCIP_VAR* var /**< problem variable */
24758 )
24759{
24760 assert(var != NULL);
24761
24764 else
24766}
24767
24768/** gets exact pseudo solution value of variable */
24770 SCIP_VAR* var /**< problem variable */
24771 )
24772{
24773 assert(var != NULL);
24774
24777 else
24779}
24780
24781/** returns the variable's VSIDS score */
24783 SCIP_VAR* var, /**< problem variable */
24784 SCIP_STAT* stat, /**< problem statistics */
24785 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
24786 )
24787{
24788 assert(var != NULL);
24789
24791 return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
24792 else
24793 return SCIPvarGetVSIDS_rec(var, stat, dir);
24794}
24795
24796/** includes event handler with given data in variable's event filter */
24798 SCIP_VAR* var, /**< problem variable */
24799 BMS_BLKMEM* blkmem, /**< block memory */
24800 SCIP_SET* set, /**< global SCIP settings */
24801 SCIP_EVENTTYPE eventtype, /**< event type to catch */
24802 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
24803 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
24804 int* filterpos /**< pointer to store position of event filter entry, or NULL */
24805 )
24806{
24807 assert(var != NULL);
24808 assert(set != NULL);
24809 assert(var->scip == set->scip);
24810 assert(var->eventfilter != NULL);
24811 assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
24812 assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
24814
24815 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
24816 eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
24817
24818 SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
24819
24820 return SCIP_OKAY;
24821}
24822
24823/** deletes event handler with given data from variable's event filter */
24825 SCIP_VAR* var, /**< problem variable */
24826 BMS_BLKMEM* blkmem, /**< block memory */
24827 SCIP_SET* set, /**< global SCIP settings */
24828 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
24829 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
24830 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
24831 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
24832 )
24833{
24834 assert(var != NULL);
24835 assert(set != NULL);
24836 assert(var->scip == set->scip);
24837 assert(var->eventfilter != NULL);
24839
24840 SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
24841 (void*)eventdata);
24842
24843 SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
24844
24845 return SCIP_OKAY;
24846}
24847
24848/** returns the position of the bound change index */
24850 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
24851 )
24852{
24853 assert(bdchgidx != NULL);
24854
24855 return bdchgidx->pos;
24856}
24857
24858/** returns the depth of the bound change index */
24860 SCIP_BDCHGIDX* bdchgidx /**< bound change index */
24861 )
24862{
24863 assert(bdchgidx != NULL);
24864
24865 return bdchgidx->depth;
24866}
24867
24868/** returns whether first bound change index belongs to an earlier applied bound change than second one */
24870 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
24871 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
24872 )
24873{
24874 assert(bdchgidx1 != NULL);
24875 assert(bdchgidx1->depth >= -2);
24876 assert(bdchgidx1->pos >= 0);
24877 assert(bdchgidx2 != NULL);
24878 assert(bdchgidx2->depth >= -2);
24879 assert(bdchgidx2->pos >= 0);
24880
24881 return (bdchgidx1->depth < bdchgidx2->depth)
24882 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
24883}
24884
24885/** returns whether first bound change index belongs to an earlier applied bound change than second one;
24886 * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
24887 * last bound change was applied to the current node
24888 */
24890 SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
24891 SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
24892 )
24893{
24894 assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
24895 assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
24896 assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
24897 assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
24898
24899 if( bdchgidx1 == NULL )
24900 return FALSE;
24901 else if( bdchgidx2 == NULL )
24902 return TRUE;
24903 else
24904 return (bdchgidx1->depth < bdchgidx2->depth)
24905 || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
24906}
24907
24908/** returns old bound that was overwritten for given bound change information */
24910 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24911 )
24912{
24913 assert(bdchginfo != NULL);
24914
24915 return bdchginfo->oldbound;
24916}
24917
24918/** returns new bound installed for given bound change information */
24920 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24921 )
24922{
24923 assert(bdchginfo != NULL);
24924
24925 return bdchginfo->newbound;
24926}
24927
24928/** returns variable that belongs to the given bound change information */
24930 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24931 )
24932{
24933 assert(bdchginfo != NULL);
24934
24935 return bdchginfo->var;
24936}
24937
24938/** returns whether the bound change information belongs to a branching decision or a deduction */
24940 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24941 )
24942{
24943 assert(bdchginfo != NULL);
24944
24945 return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
24946}
24947
24948/** returns whether the bound change information belongs to a lower or upper bound change */
24950 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24951 )
24952{
24953 assert(bdchginfo != NULL);
24954
24955 return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
24956}
24957
24958/** returns depth level of given bound change information */
24960 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24961 )
24962{
24963 assert(bdchginfo != NULL);
24964
24965 return bdchginfo->bdchgidx.depth;
24966}
24967
24968/** returns bound change position in its depth level of given bound change information */
24970 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24971 )
24972{
24973 assert(bdchginfo != NULL);
24974
24975 return bdchginfo->bdchgidx.pos;
24976}
24977
24978/** returns bound change index of given bound change information */
24980 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24981 )
24982{
24983 assert(bdchginfo != NULL);
24984
24985 return &bdchginfo->bdchgidx;
24986}
24987
24988/** returns inference variable of given bound change information */
24990 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
24991 )
24992{
24993 assert(bdchginfo != NULL);
24996
24997 return bdchginfo->inferencedata.var;
24998}
24999
25000/** returns inference constraint of given bound change information */
25002 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25003 )
25004{
25005 assert(bdchginfo != NULL);
25007 assert(bdchginfo->inferencedata.reason.cons != NULL);
25008
25009 return bdchginfo->inferencedata.reason.cons;
25010}
25011
25012/** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
25014 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25015 )
25016{
25017 assert(bdchginfo != NULL);
25019
25020 return bdchginfo->inferencedata.reason.prop;
25021}
25022
25023/** returns inference user information of given bound change information */
25025 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25026 )
25027{
25028 assert(bdchginfo != NULL);
25031
25032 return bdchginfo->inferencedata.info;
25033}
25034
25035/** returns inference bound of inference variable of given bound change information */
25037 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25038 )
25039{
25040 assert(bdchginfo != NULL);
25043
25044 return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
25045}
25046
25047/** returns the relaxed bound change type */
25049 SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
25050 )
25051{
25052 return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
25053}
25054
25055
25056/** returns whether the bound change information belongs to a redundant bound change */
25058 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25059 )
25060{
25061 assert(bdchginfo != NULL);
25062 assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
25063
25064 return bdchginfo->redundant;
25065}
25066
25067/** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
25069 SCIP_BDCHGINFO* bdchginfo /**< bound change information */
25070 )
25071{
25072 assert(bdchginfo != NULL);
25073
25076 && bdchginfo->inferencedata.reason.prop != NULL);
25077}
25078
25079/** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
25080 * has a tighter new bound as the second bound change
25081 */
25083 SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
25084 SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
25085 )
25086{
25087 assert(bdchginfo1 != NULL);
25088 assert(bdchginfo2 != NULL);
25089 assert(bdchginfo1->var == bdchginfo2->var);
25090 assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
25091
25092 return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
25093 ? bdchginfo1->newbound > bdchginfo2->newbound
25094 : bdchginfo1->newbound < bdchginfo2->newbound);
25095}
25096
25097/** returns position of variable in certificate */
25099 SCIP_VAR* var /**< variable to get index for */
25100 )
25101{
25102 assert(var != NULL);
25103 assert(var->exactdata != NULL);
25104
25105 return var->exactdata->certificateindex;
25106}
25107
25108/** sets index of variable in certificate */
25110 SCIP_VAR* var, /**< variable to set index for */
25111 int certidx /**< the index */
25112 )
25113{
25114 assert(var != NULL);
25115 assert(var->exactdata != NULL);
25116 assert(certidx >= 0);
25117
25118 var->exactdata->certificateindex = certidx;
25119}
25120
25121/** sets index of variable in certificate */
25123 SCIP_VAR* var, /**< variable to set index for */
25124 SCIP_Longint certidx /**< the index */
25125 )
25126{
25127 assert(var != NULL);
25128 assert(var->exactdata != NULL);
25129 assert(certidx >= 0);
25130
25131 var->exactdata->glbdom.ubcertificateidx = certidx;
25132 var->exactdata->locdom.ubcertificateidx = certidx;
25133}
25134
25135/** sets index of variable in certificate */
25137 SCIP_VAR* var, /**< variable to set index for */
25138 SCIP_Longint certidx /**< the index */
25139 )
25140{
25141 assert(var != NULL);
25142 assert(var->exactdata != NULL);
25143 assert(certidx >= 0);
25144
25145 var->exactdata->locdom.ubcertificateidx = certidx;
25146}
25147
25148/** sets index of variable in certificate */
25150 SCIP_VAR* var, /**< variable to set index for */
25151 SCIP_Longint certidx /**< the index */
25152 )
25153{
25154 assert(var != NULL);
25155 assert(var->exactdata != NULL);
25156 assert(certidx >= 0);
25157
25158 var->exactdata->locdom.lbcertificateidx = certidx;
25159}
25160
25161/** sets index of variable in certificate */
25163 SCIP_VAR* var, /**< variable to set index for */
25164 SCIP_Longint certidx /**< the index */
25165 )
25166{
25167 assert(var != NULL);
25168 assert(var->exactdata != NULL);
25169 assert(certidx >= 0);
25170
25171 var->exactdata->glbdom.lbcertificateidx = certidx;
25172 var->exactdata->locdom.lbcertificateidx = certidx;
25173}
25174
25175/** returns index of variable bound in vipr certificate */
25177 SCIP_VAR* var /**< variable to get index for */
25178 )
25179{
25180 assert(var->exactdata != NULL);
25181 assert(var->exactdata->locdom.lbcertificateidx != -1);
25182 assert(var->exactdata->locdom.lbcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->locdom.lbcertificateidx >= 0);
25183
25184 return var->exactdata->locdom.lbcertificateidx;
25185}
25186
25187/** returns index of variable bound in vipr certificate */
25189 SCIP_VAR* var /**< variable to get index for */
25190 )
25191{
25192 assert(var->exactdata != NULL);
25193 assert(var->exactdata->locdom.ubcertificateidx != -1);
25194 assert(var->exactdata->locdom.ubcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->locdom.ubcertificateidx >= 0);
25195
25196 return var->exactdata->locdom.ubcertificateidx;
25197}
25198
25199/** returns index of variable bound in vipr certificate */
25201 SCIP_VAR* var /**< variable to get index for */
25202 )
25203{
25204 assert(var->exactdata != NULL);
25205 assert(var->exactdata->glbdom.lbcertificateidx != -1);
25206 assert(var->exactdata->glbdom.lbcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->glbdom.lbcertificateidx >= 0);
25207
25208 return var->exactdata->glbdom.lbcertificateidx;
25209}
25210
25211/** returns index of variable bound in vipr certificate */
25213 SCIP_VAR* var /**< variable to get index for */
25214 )
25215{
25216 assert(var->exactdata != NULL);
25217 assert(var->exactdata->glbdom.ubcertificateidx != -1);
25218 assert(var->exactdata->glbdom.ubcertificateidx <= SCIPcertificateGetCurrentIndex(SCIPgetCertificate(var->scip)) && var->exactdata->glbdom.ubcertificateidx >= 0);
25219
25220 return var->exactdata->glbdom.ubcertificateidx;
25221}
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:6427
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition cons.c:6439
internal methods for constraints and constraint handlers
#define MAX_CLIQUELENGTH
#define MAXABSVBCOEF
#define MAXDNOM
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition debug.h:298
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition debug.h:305
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition debug.h:299
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition debug.h:304
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition debug.h:306
#define SCIP_DEFAULT_INFINITY
Definition def.h:170
#define NULL
Definition def.h:255
#define SCIP_MAXSTRLEN
Definition def.h:276
#define SCIP_Longint
Definition def.h:148
#define EPSISINT(x, eps)
Definition def.h:202
#define SCIP_REAL_MAX
Definition def.h:165
#define SCIP_INVALID
Definition def.h:185
#define SCIP_INTERVAL_INFINITY
Definition def.h:187
#define SCIP_Bool
Definition def.h:98
#define EPSLE(x, y, eps)
Definition def.h:192
#define MIN(x, y)
Definition def.h:231
#define SCIP_ALLOC(x)
Definition def.h:373
#define SCIP_Real
Definition def.h:163
#define SCIP_UNKNOWN
Definition def.h:186
#define ABS(x)
Definition def.h:223
#define SQR(x)
Definition def.h:206
#define EPSEQ(x, y, eps)
Definition def.h:190
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define MAX(x, y)
Definition def.h:227
#define SCIP_CALL_ABORT(x)
Definition def.h:341
#define SCIPABORT()
Definition def.h:334
#define SCIP_REAL_MIN
Definition def.h:166
#define REALABS(x)
Definition def.h:189
#define EPSZ(x, eps)
Definition def.h:195
#define SCIP_CALL(x)
Definition def.h:362
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:752
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:634
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:780
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:656
SCIP_RETCODE SCIPeventAddExactObjChg(SCIP_EVENT *event, BMS_BLKMEM *blkmem, SCIP_RATIONAL *oldobj, SCIP_RATIONAL *newobj)
Definition event.c:827
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition event.c:677
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition event.c:2561
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition event.c:2167
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition event.c:2933
SCIP_RETCODE SCIPeventAddExactBdChg(SCIP_EVENT *event, BMS_BLKMEM *blkmem, SCIP_RATIONAL *oldbound, SCIP_RATIONAL *newbound)
Definition event.c:808
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition event.c:845
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition event.c:2300
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition event.c:2142
SCIP_RETCODE SCIPeventProcess(SCIP_EVENT *event, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter)
Definition event.c:1804
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition event.c:933
SCIP_RETCODE SCIPeventChgType(SCIP_EVENT *event, SCIP_EVENTTYPE eventtype)
Definition event.c:1204
SCIP_RETCODE SCIPeventCreateImplTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_IMPLINTTYPE oldtype, SCIP_IMPLINTTYPE newtype)
Definition event.c:975
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition event.c:2207
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:727
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition event.c:702
SCIP_RETCODE SCIPeventCreateTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_VARTYPE oldtype, SCIP_VARTYPE newtype)
Definition event.c:952
internal methods for managing events
const char * SCIPgetProbName(SCIP *scip)
Definition scip_prob.c:1242
int SCIPgetNTotalVars(SCIP *scip)
Definition scip_prob.c:3064
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3143
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9197
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition misc.c:9449
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition misc.c:9470
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_Bool SCIPshouldCertificateTrackBounds(SCIP *scip)
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition lp.c:17336
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition lp.c:17346
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition lp.c:17379
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition lp.c:17356
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition lp.c:17509
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition lp.c:17414
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8389
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:8522
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition tree.c:8821
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:23514
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition var.c:18705
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17236
SCIP_Longint SCIPvarGetUbCertificateIndexLocal(SCIP_VAR *var)
Definition var.c:25188
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18320
void SCIPvarSetLbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25162
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition var.c:24302
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition var.c:24482
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition var.c:17801
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition var.c:23534
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition var.c:23889
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition var.c:23683
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25057
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21884
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition var.c:4484
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition var.c:23843
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition var.c:24372
void SCIPvarSetTransData(SCIP_VAR *var,)
Definition var.c:23320
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition var.c:17530
SCIP_BOUNDTYPE SCIPvarGetWorstBoundTypeExact(SCIP_VAR *var)
Definition var.c:24413
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition var.c:19007
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23868
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition var.c:24504
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23478
SCIP_Longint SCIPvarGetUbCertificateIndexGlobal(SCIP_VAR *var)
Definition var.c:25212
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23194
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition var.c:23244
void SCIPvarSetDelorigData(SCIP_VAR *var,)
Definition var.c:23308
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21839
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition var.c:24174
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:24889
SCIP_RATIONAL * SCIPvarGetBestBoundGlobalExact(SCIP_VAR *var)
Definition var.c:24187
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:22889
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24979
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition var.c:23174
void SCIPvarSetCertificateIndex(SCIP_VAR *var, int certidx)
Definition var.c:25109
SCIP_RATIONAL * SCIPvarGetAggrScalarExact(SCIP_VAR *var)
Definition var.c:23760
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition var.c:16441
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition var.c:23222
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24568
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23386
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4386
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition var.c:23184
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22031
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition var.c:23771
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23498
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition var.c:23944
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24268
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition var.c:4449
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition var.c:19480
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition var.c:23254
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition var.c:24020
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22629
SCIP_RATIONAL * SCIPvarGetAggrConstantExact(SCIP_VAR *var)
Definition var.c:23783
SCIP_RATIONAL * SCIPvarGetPseudoSolExact(SCIP_VAR *var)
Definition var.c:24769
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23430
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition var.c:23546
void SCIPvarGetImplicVarBounds(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Real *lb, SCIP_Real *ub)
Definition var.c:16476
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25013
int SCIPvarGetCertificateIndex(SCIP_VAR *var)
Definition var.c:25098
SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
Definition var.c:23506
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition var.c:23154
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition var.c:4473
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23900
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition var.c:23748
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17550
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition var.c:23618
SCIP_RETCODE SCIPvarGetOrigvarSumExact(SCIP_VAR **var, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant)
Definition var.c:18409
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23453
SCIP_BOUNDTYPE SCIPvarGetBestBoundTypeExact(SCIP_VAR *var)
Definition var.c:24385
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24142
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition var.c:23354
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24585
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition var.c:19612
SCIP_VARSTATUS SCIPvarGetStatusExact(SCIP_VAR *var)
Definition var.c:23396
SCIP_RATIONAL * SCIPvarGetWorstBoundLocalExact(SCIP_VAR *var)
Definition var.c:24355
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24959
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25024
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23652
SCIP_INTERVAL SCIPvarGetObjInterval(SCIP_VAR *var)
Definition var.c:23921
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25001
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition var.c:18859
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition var.c:22764
SCIP_COLEXACT * SCIPvarGetColExact(SCIP_VAR *var)
Definition var.c:23694
void SCIPvarGetLPSolExact_rec(SCIP_VAR *var, SCIP_RATIONAL *res)
Definition var.c:18784
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24969
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition var.c:24342
int SCIPvarGetNUses(SCIP_VAR *var)
Definition var.c:23277
SCIP_RATIONAL * SCIPvarGetLbOriginalExact(SCIP_VAR *var)
Definition var.c:24040
SCIP_RATIONAL * SCIPvarGetUbOriginalExact(SCIP_VAR *var)
Definition var.c:24083
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition var.c:23214
SCIP_Longint SCIPvarGetLbCertificateIndexGlobal(SCIP_VAR *var)
Definition var.c:25200
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23267
SCIP_Bool SCIPvarIsExact(SCIP_VAR *var)
Definition var.c:23407
SCIP_RETCODE SCIPvarGetProbvarBoundExact(SCIP_VAR **var, SCIP_RATIONAL *bound, SCIP_BOUNDTYPE *boundtype)
Definition var.c:17894
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition var.c:24063
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition var.c:24204
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24929
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition var.c:16461
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:23570
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition var.c:24514
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition var.c:19115
SCIP_RATIONAL * SCIPvarGetMultaggrConstantExact(SCIP_VAR *var)
Definition var.c:23855
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24630
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition var.c:24312
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition var.c:24524
SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
Definition var.c:24278
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition var.c:24450
void SCIPvarSetUbCertificateIndexGlobal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25122
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition var.c:19827
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition var.c:23632
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24909
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23490
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition var.c:18497
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition var.c:24438
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition var.c:24756
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition var.c:24472
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25036
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition var.c:23297
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24614
void SCIPvarSetDeltransData(SCIP_VAR *var,)
Definition var.c:23332
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition var.c:24664
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22741
void SCIPvarGetSolExact(SCIP_VAR *var, SCIP_RATIONAL *res, SCIP_Bool getlpval)
Definition var.c:19019
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition var.c:23287
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition var.c:23806
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition var.c:25082
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition var.c:23794
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition var.c:23370
SCIP_Longint SCIPvarGetLbCertificateIndexLocal(SCIP_VAR *var)
Definition var.c:25176
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition var.c:24106
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition var.c:23524
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24642
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24939
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24234
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23443
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24989
SCIP_RATIONAL * SCIPvarGetBestBoundLocalExact(SCIP_VAR *var)
Definition var.c:24325
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25068
SCIP_RATIONAL * SCIPvarGetLbGlobalExact(SCIP_VAR *var)
Definition var.c:24130
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition var.c:23204
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21751
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition var.c:23600
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:23878
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition var.c:17990
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition var.c:24494
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition var.c:22685
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition var.c:23234
SCIP_RATIONAL ** SCIPvarGetMultaggrScalarsExact(SCIP_VAR *var)
Definition var.c:23830
SCIP_Real SCIPvarGetMaxAggrCoef(SCIP_VAR *var)
Definition var.c:23726
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition var.c:24462
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:23417
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24653
SCIP_Real SCIPvarGetMinAggrCoef(SCIP_VAR *var)
Definition var.c:23716
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24120
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition var.c:23557
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition var.c:19547
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition var.c:24704
SCIP_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
Definition var.c:24244
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition var.c:23463
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17274
void SCIPvarsCountTypes(SCIP_VAR **vars, int nvars, int *nbinvars, int *nintvars, int *nbinimplvars, int *nintimplvars, int *ncontimplvars, int *ncontvars)
Definition var.c:22942
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22274
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition var.c:19581
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition var.c:17642
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21796
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition var.c:24556
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition var.c:4462
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition var.c:23672
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition var.c:24691
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition var.c:24536
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition var.c:24736
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24949
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition var.c:24746
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition var.c:24400
void SCIPvarSetCopyData(SCIP_VAR *var,)
Definition var.c:23343
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22076
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition var.c:16807
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition var.c:24869
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition var.c:24546
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition var.c:24164
void SCIPvarGetLPSolExact(SCIP_VAR *var, SCIP_RATIONAL *res)
Definition var.c:24677
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24919
SCIP_RATIONAL * SCIPvarGetWorstBoundGlobalExact(SCIP_VAR *var)
Definition var.c:24217
SCIP_Real SCIPboundchgGetLPSolVal(SCIP_BOUNDCHG *boundchg)
Definition var.c:23164
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4328
SCIP_RATIONAL * SCIPvarGetObjExact(SCIP_VAR *var)
Definition var.c:23910
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition var.c:24724
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition var.c:24716
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24600
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition var.c:22801
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition var.c:17610
SCIP_RATIONAL * SCIPvarGetUbGlobalExact(SCIP_VAR *var)
Definition var.c:24152
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition var.c:23818
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:22231
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition var.c:24428
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition var.c:23706
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition var.c:23736
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition misc.c:200
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition misc.c:127
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition misc.c:110
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPsortPtrPtr(void **ptrarray1, void **ptrarray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition misc.c:10955
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition misc.c:10985
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:323
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition history.c:364
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition history.c:342
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition history.c:409
return SCIP_OKAY
int c
int depth
SCIP_Bool cutoff
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real primsol
SCIP_Real frac
SCIP_Real newobj
SCIP_Real oldobj
static SCIP_VAR ** vars
SCIP_Real * rootsol
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition history.c:78
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition history.c:529
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:790
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:690
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:764
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:703
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:816
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition history.c:51
SCIP_Real SCIPhistoryGetAncPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:596
void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition history.c:907
void SCIPhistoryUpdateAncPseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition history.c:255
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:732
SCIP_Real SCIPhistoryGetAncPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition history.c:543
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:803
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:581
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition history.c:557
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition history.c:674
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition history.c:649
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:748
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition history.c:716
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition history.c:191
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:661
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:829
SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
Definition history.c:897
SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
Definition history.c:874
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition history.c:777
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition history.c:66
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition history.c:117
void SCIPhistoryIncGMIeffSum(SCIP_HISTORY *history, SCIP_Real gmieff)
Definition history.c:884
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition history.c:520
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition history.c:635
internal methods for branching and inference history
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3335
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition implics.c:1285
SCIP_RETCODE SCIPcliquetableAdd(SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition implics.c:2377
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition implics.c:1683
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition implics.c:73
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition implics.c:3310
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition implics.c:333
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition implics.c:3384
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3459
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition implics.c:1605
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3353
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition implics.c:3468
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition implics.c:3302
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition implics.c:3374
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition implics.c:3396
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition implics.c:288
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3365
SCIP_RETCODE SCIPimplicsAdd(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *conflict, SCIP_Bool *added)
Definition implics.c:633
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition implics.c:206
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition implics.c:1441
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3326
SCIP_RETCODE SCIPcliqueAddVar(SCIP_CLIQUE *clique, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Bool value, SCIP_Bool *doubleentry, SCIP_Bool *oppositeentry)
Definition implics.c:1151
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition implics.c:3344
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition implics.c:3450
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition implics.c:1527
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition implics.c:3430
void SCIPimplicsGetVarImplicPoss(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, int *lowerimplicpos, int *upperimplicpos)
Definition implics.c:916
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition implics.c:836
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition implics.c:3318
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition implics.c:3294
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition implics.c:933
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition implics.c:451
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition implics.c:1482
methods for implications, variable bounds, and cliques
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition lp.c:18241
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition lp.c:3997
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition lp.c:3572
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition lp.c:3952
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition lp.c:14686
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition lp.c:5856
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition lp.c:3893
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition lp.c:5744
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition lp.c:18251
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition lp.c:4147
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition lp.c:3473
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14665
static const SCIP_Real scalars[]
Definition lp.c:5959
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition lp.c:14541
internal methods for LP management
SCIP_RETCODE SCIPlpExactUpdateVarColumn(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_VAR *var)
Definition lpexact.c:6663
SCIP_RETCODE SCIProwExactIncCoef(SCIP_ROWEXACT *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LPEXACT *lpexact, SCIP_COLEXACT *col, SCIP_RATIONAL *incval)
Definition lpexact.c:5321
void SCIPlpExactDecNLoosevars(SCIP_LPEXACT *lpexact)
Definition lpexact.c:6770
SCIP_RATIONAL * SCIPcolExactGetPrimsol(SCIP_COLEXACT *col)
Definition lpexact.c:6039
SCIP_Bool SCIPlpExactDiving(SCIP_LPEXACT *lpexact)
Definition lpexact.c:8423
SCIP_RETCODE SCIPcolExactFree(SCIP_COLEXACT **col, BMS_BLKMEM *blkmem)
Definition lpexact.c:2754
SCIP_RETCODE SCIPcolExactChgUb(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newub)
Definition lpexact.c:3093
SCIP_RETCODE SCIProwExactAddConstant(SCIP_ROWEXACT *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *addval)
Definition lpexact.c:5416
SCIP_RETCODE SCIPcolExactCreate(SCIP_COLEXACT **col, SCIP_COL *fpcol, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROWEXACT **rows, SCIP_RATIONAL **vals, SCIP_Bool removable)
Definition lpexact.c:2410
SCIP_RETCODE SCIPcolExactChgLb(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newlb)
Definition lpexact.c:3048
internal methods for exact LP management
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition memory.h:456
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition memory.h:462
#define BMSfreeBlockMemory(mem, ptr)
Definition memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition memory.h:451
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition memory.h:468
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition memory.h:469
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition memory.h:454
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition memory.h:458
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition memory.h:453
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:437
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition message.c:618
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition message.c:427
real eps
SCIP_RETCODE SCIPprimalUpdateObjoffsetExact(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition primal.c:646
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition primal.c:590
internal methods for collecting primal CIP solutions and primal informations
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition prob.c:1874
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition prob.c:2904
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition prob.c:1412
const char * SCIPprobGetName(SCIP_PROB *prob)
Definition prob.c:2859
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition prob.c:1669
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:2868
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition prob.c:2913
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition prob.c:2803
void SCIPprobAddObjoffsetExact(SCIP_PROB *prob, SCIP_RATIONAL *addval)
Definition prob.c:1685
internal methods for storing and manipulating the main problem
public methods for managing constraints
public methods for branching and inference history structure
public methods for implications, variable bounds, and cliques
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPdebugMessage
Definition pub_message.h:96
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for propagators
public methods for problem variables
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition relax.c:864
internal methods for relaxators
SCIP callable library.
public methods for certified solving
public methods for exact solving
public methods for global and local (sub)problems
public methods for the probing mode
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:7292
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:6716
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:7076
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6617
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:7136
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:7087
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition set.c:6422
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition set.c:6728
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:7017
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6993
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6945
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:6648
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6577
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition set.c:7124
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:7314
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition set.c:6402
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6537
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:7065
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition set.c:3197
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6969
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition set.c:6380
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6557
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition set.c:6515
SCIP_Bool SCIPsetIsSumZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6864
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition set.c:7303
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:6597
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:6670
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition set.c:6637
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition set.c:7041
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition set.c:6392
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition set.c:6740
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition set.c:6080
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition set.c:7098
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition set.c:6659
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition set.h:1782
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition set.h:1789
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition set.h:1775
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition set.h:1786
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition set.h:1777
#define SCIPsetDebugMsg
Definition set.h:1811
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition set.h:1779
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition sol.c:1912
internal methods for storing primal CIP solutions
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition stat.c:870
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:9568
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:18522
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20437
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition var.c:17338
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:8055
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:7863
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_RATIONAL *lbexact, SCIP_RATIONAL *ubexact, SCIP_RATIONAL *objexact, SCIP_VARTYPE *vartype, SCIP_IMPLINTTYPE *impltype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_RATIONAL *lazylbexact, SCIP_RATIONAL *lazyubexact, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition var.c:2972
SCIP_RETCODE SCIPvarIncNBranchings(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, int depth)
Definition var.c:21499
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:10294
static SCIP_RETCODE varFreeExactData(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition var.c:3604
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:459
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_RATIONAL *newboundexact, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition var.c:1734
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition var.c:11771
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:16512
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:10409
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:12230
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20580
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:14534
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition var.c:22615
static SCIP_RETCODE domAddHole(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition var.c:230
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition var.c:4581
SCIP_RETCODE SCIPvarChgObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newobj)
Definition var.c:9419
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:16963
void SCIPvarGetUbLocalExactMinimal(SCIP_VAR *var, SCIP_RATIONAL *output)
Definition var.c:24289
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition var.c:20744
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:19233
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:14724
SCIP_RETCODE SCIPvarSetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real gmieff)
Definition var.c:22535
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, SCIP_RATIONAL *lbexact, SCIP_RATIONAL *ubexact, char **endptr)
Definition var.c:2926
void SCIPvarInitSolve(SCIP_VAR *var)
Definition var.c:3846
SCIP_RETCODE SCIPvarChgUbGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound)
Definition var.c:11618
SCIP_Real SCIPvarGetAncPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20670
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:21583
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:15033
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:11321
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:6174
SCIP_RETCODE SCIPvarChgBdGlobalExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lpexact, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *newbound, SCIP_BOUNDTYPE boundtype)
Definition var.c:11848
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition var.c:3859
SCIP_RETCODE SCIPvarTryAggregateVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7688
SCIP_RETCODE SCIPvarIncVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition var.c:21103
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:12043
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:13112
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:14297
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22317
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:18205
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:14693
SCIP_RETCODE SCIPvarGetMultaggrUbLocalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *result)
Definition var.c:13786
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition var.c:8794
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition var.c:20274
void SCIPvarSetLbCertificateIndexLocal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25149
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition var.c:4494
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:13997
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:12430
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16725
int SCIPbdchgidxGetDepth(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:24859
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:9349
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3656
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition var.c:14178
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22176
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:14575
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3787
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition var.c:19963
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:21239
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:9122
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:9910
static SCIP_RATIONAL * SCIPvarGetPseudoSolExact_rec(SCIP_VAR *var)
Definition var.c:18975
void SCIPvarAdjustLbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *lb)
Definition var.c:9927
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:24824
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:11178
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition var.c:19771
SCIP_RETCODE SCIPvarCopy(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP *sourcescip, SCIP_VAR *sourcevar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global)
Definition var.c:2751
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:20798
static SCIP_BDCHGIDX presolvebdchgidx
Definition var.c:22761
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:11876
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition var.c:20836
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, SCIP_RATIONAL *valueexact)
Definition var.c:2872
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:10028
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:20035
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:15107
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18568
static SCIP_RETCODE tryAggregateIntVarsExact(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_RATIONAL *scalarx, SCIP_RATIONAL *scalary, SCIP_RATIONAL *rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7421
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition var.c:10012
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:11952
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition var.c:9847
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:1348
SCIP_RETCODE SCIPvarColumnExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPEXACT *lp)
Definition var.c:4646
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition var.c:19760
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition var.c:3953
SCIP_Real SCIPvarGetAvgGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition var.c:22411
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:24782
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:9704
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition var.c:4725
SCIP_RETCODE SCIPvarIncCutoffSum(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition var.c:21667
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13574
static SCIP_RETCODE varNegateExactData(SCIP_VAR *negvar, SCIP_VAR *origvar, BMS_BLKMEM *blkmem)
Definition var.c:8933
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:20913
void SCIPvarCapture(SCIP_VAR *var)
Definition var.c:3762
static SCIP_RETCODE varEventGubChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition var.c:10371
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:17150
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20533
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:19034
void SCIPvarGetLbLocalExactMaximal(SCIP_VAR *var, SCIP_RATIONAL *output)
Definition var.c:24255
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:10893
SCIP_Bool SCIPvarDoNotAggr(SCIP_VAR *var)
Definition var.c:8843
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:9242
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:5989
void SCIPvarAdjustUbExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *ub)
Definition var.c:9978
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21320
SCIP_RETCODE SCIPvarChgLbExactDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newbound)
Definition var.c:13365
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:19045
static SCIP_Real adjustedLbExactFloat(SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1908
SCIP_RETCODE SCIPvarFixExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_RATIONAL *fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:4987
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21929
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:9301
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:13249
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:21189
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition var.c:21048
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21412
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:10700
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:20625
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:11475
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:8415
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:10220
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:11035
static SCIP_RETCODE varUpdateAggregationBoundsExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:6366
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:6599
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition var.c:3479
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_Bool isintegral, SCIP_Real ub)
Definition var.c:1937
SCIP_RETCODE SCIPvarCreateTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition var.c:2531
SCIP_RETCODE SCIPvarParseTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition var.c:3357
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:18638
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:4612
SCIP_Real SCIPvarGetAncPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition var.c:20484
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition var.c:10161
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:13422
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:22119
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:9589
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition var.c:22816
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition var.c:4179
static void adjustedUbExact(SCIP_SET *set, SCIP_Bool isintegral, SCIP_RATIONAL *ub)
Definition var.c:1970
SCIP_RETCODE SCIPvarChgUbExactDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LPEXACT *lpexact, SCIP_RATIONAL *newbound)
Definition var.c:13512
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13936
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:11914
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition var.c:19888
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition var.c:11794
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:14595
static SCIP_RETCODE tryAggregateIntVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:7183
SCIP_RETCODE SCIPvarChgLbOriginalExact(SCIP_VAR *var, SCIP_SET *set, SCIP_RATIONAL *newbound)
Definition var.c:10087
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:20979
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:9159
#define MAXIMPLSCLOSURE
Definition var.c:83
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition var.c:2294
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition var.c:6116
SCIP_RETCODE SCIPvarAddVlb(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15316
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:10448
static void varUpdateMinMaxAggrCoef(SCIP_VAR *var, SCIP_VAR *aggvar, SCIP_Real aggscalar)
Definition var.c:6147
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition var.c:3919
void SCIPdomchgAddCurrentCertificateIndex(SCIP_DOMCHG *domchg, SCIP_CERTIFICATE *certificate)
Definition var.c:1714
static SCIP_RETCODE varAddUbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition var.c:560
SCIP_RETCODE SCIPvarUpdateAncPseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition var.c:20374
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:24797
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:14425
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition var.c:23580
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:16764
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:9385
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:19688
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition var.c:16747
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition var.c:24849
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:11819
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition var.c:21075
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition var.c:16687
SCIP_RETCODE SCIPvarMarkDoNotAggr(SCIP_VAR *var)
Definition var.c:9170
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:16828
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:12715
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition var.c:4680
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition var.c:3531
static SCIP_BDCHGIDX initbdchgidx
Definition var.c:22758
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:16601
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:12572
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition var.c:17019
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:12845
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1327
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition var.c:9206
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition var.c:158
static SCIP_Real adjustedUbExactFloat(SCIP_Bool isintegral, SCIP_Real lb)
Definition var.c:1957
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LOCKTYPE locktype, int addnlocksdown, int addnlocksup)
Definition var.c:4200
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition var.c:8979
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13722
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition var.c:22585
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition var.c:20713
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition var.c:18075
SCIP_Bool SCIPvarIsAggrCoefAcceptable(SCIP_SET *set, SCIP_VAR *var, SCIP_Real scalar)
Definition var.c:8909
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:22451
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:10521
SCIP_Real SCIPvarGetLastGMIScore(SCIP_VAR *var, SCIP_STAT *stat)
Definition var.c:22495
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:9961
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:25048
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition var.c:19180
SCIP_RETCODE SCIPvarGetActiveRepresentatives(SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition var.c:5180
static SCIP_RETCODE varAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *infeasible, int *nbdchgs, SCIP_Bool *added)
Definition var.c:14824
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition var.c:13275
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition var.c:4820
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition var.c:18907
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21456
SCIP_RETCODE SCIPvarCopyExactData(BMS_BLKMEM *blkmem, SCIP_VAR *targetvar, SCIP_VAR *sourcevar, SCIP_Bool negateobj)
Definition var.c:2686
SCIP_RETCODE SCIPvarChgUbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition var.c:12983
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition var.c:1399
SCIP_RETCODE SCIPvarParseOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition var.c:3234
SCIP_RETCODE SCIPvarAddVub(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition var.c:15783
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21980
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition var.c:10480
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition var.c:9102
SCIP_RETCODE SCIPvarAggregateExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_VAR *aggvar, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition var.c:6909
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition var.c:208
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition var.c:3828
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition var.c:6132
static SCIP_RETCODE varProcessAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition var.c:14049
void SCIPvarSetUbCertificateIndexLocal(SCIP_VAR *var, SCIP_Longint certidx)
Definition var.c:25136
void SCIPvarAdjustUbExactFloat(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition var.c:9995
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:9087
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition var.c:3503
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition var.c:13870
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition var.c:19627
void SCIPvarAdjustLbExactFloat(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition var.c:9944
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition var.c:16892
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:11990
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:16241
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:21367
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:9494
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:10332
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition var.c:17083
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition var.c:22364
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition var.c:8876
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:13638
static void printBoundsExact(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_RATIONAL *lb, SCIP_RATIONAL *ub, const char *name)
Definition var.c:3889
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition var.c:9071
SCIP_RETCODE SCIPvarGetActiveRepresentativesExact(SCIP_SET *set, SCIP_VAR **vars, SCIP_RATIONAL **scalars, int *nvars, int varssize, SCIP_RATIONAL *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition var.c:5511
SCIP_RETCODE SCIPvarAddToRowExact(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LPEXACT *lpexact, SCIP_ROWEXACT *rowexact, SCIP_RATIONAL *val)
Definition var.c:20135
internal methods for problem variables