Scippy

SCIP

Solving Constraint Integer Programs

prop_genvbounds.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file prop_genvbounds.c
26 * @ingroup DEFPLUGINS_PROP
27 * @brief generalized variable bounds propagator
28 * @author Stefan Weltge
29 * @author Ambros Gleixner
30 * @author Benjamin Mueller
31 */
32
33/**@todo should we only discard events catched from nodes that are not the current node's ancestors? */
34/**@todo improve computation of minactivity */
35/**@todo for multaggr vars on left-hand side, create a linear constraint, probably in exitpre */
36
37/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
38
40#include "scip/cons_linear.h"
41#include "scip/debug.h"
43#include "scip/pub_event.h"
44#include "scip/pub_message.h"
45#include "scip/pub_misc.h"
46#include "scip/pub_prop.h"
47#include "scip/pub_tree.h"
48#include "scip/pub_var.h"
49#include "scip/scip_conflict.h"
50#include "scip/scip_cons.h"
52#include "scip/scip_event.h"
53#include "scip/scip_general.h"
54#include "scip/scip_mem.h"
55#include "scip/scip_message.h"
56#include "scip/scip_numerics.h"
57#include "scip/scip_param.h"
58#include "scip/scip_prob.h"
59#include "scip/scip_probing.h"
60#include "scip/scip_prop.h"
61#include "scip/scip_sol.h"
62#include "scip/scip_solve.h"
64#include "scip/scip_tree.h"
65#include "scip/scip_var.h"
66#include <string.h>
67
68#define PROP_NAME "genvbounds"
69#define PROP_DESC "generalized variable bounds propagator"
70#define PROP_TIMING SCIP_PROPTIMING_ALWAYS
71#define PROP_PRIORITY 3000000 /**< propagator priority */
72#define PROP_FREQ 1 /**< propagator frequency */
73#define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators
74 * found reductions? */
75#define PROP_PRESOL_PRIORITY -2000000 /**< priority of the presolving method (>= 0: before, < 0: after
76 * constraint handlers); combined with presolvers */
77#define PROP_PRESOLTIMING SCIP_PRESOLTIMING_FAST /* timing of the presolving method (fast, medium, or exhaustive) */
78#define PROP_PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates
79 * in (-1: no limit) */
80#define DEFAULT_GLOBAL_PROPAGATION TRUE /**< apply global propagation? */
81#define DEFAULT_PROPAGATE_IN_ROOT_NODE TRUE /**< apply genvbounds in root node if no new incumbent was found? */
82#define DEFAULT_SORT TRUE /**< sort genvbounds and wait for bound change events? (otherwise all
83 * genvbounds are applied in each node) */
84#define DEFAULT_PROPASCONSS FALSE /**< should genvbounds be transformed to (linear) constraints? */
85
86#define EVENTHDLR_NAME "genvbounds"
87#define EVENTHDLR_DESC "event handler for generalized variable bounds propagator"
88
89
90/*
91 * Data structures
92 */
93
94/** GenVBound data */
96{
97 SCIP_VAR** vars; /**< pointers to variables x_j occurring in this generalized variable
98 * bound */
99 SCIP_VAR* var; /**< pointer to variable x_i */
100 SCIP_Real* coefs; /**< coefficients a_j of the variables listed in vars */
101 SCIP_Real constant; /**< constant term in generalized variable bound */
102 SCIP_Real cutoffcoef; /**< cutoff bound's coefficient */
103 int coefssize; /**< size of coefs array */
104 int index; /**< index of this genvbound in genvboundstore array */
105 int ncoefs; /**< number of nonzero coefficients a_j */
106 SCIP_BOUNDTYPE boundtype; /**< type of bound provided by the genvbound, SCIP_BOUNDTYPE_LOWER/UPPER
107 * if +/- x_i on left-hand side */
108 SCIP_Bool relaxonly; /**< contains a relaxation-only variable */
109};
110typedef struct GenVBound GENVBOUND;
111
112/** starting indices data structure */
113struct SCIP_EventData
114{
115 SCIP_PROP* prop; /**< pointer to genvbounds propagator */
116 SCIP_VAR* var; /**< variable */
117 int* startindices; /**< array to store the first indices of genvbounds in components that are
118 * impacted by a change of this bound */
119 int* startcomponents; /**< array to store the components corresponding to startindices array */
120 int nstarts; /**< number of indices stored in startindices array */
121 int startindicessize; /**< size of the startindices and startcomponents arrays */
122};
123
124/** propagator data */
125struct SCIP_PropData
126{
127 GENVBOUND** genvboundstore; /**< array to store genvbounds; fast access is provided by hashmaps
128 * lbgenvbounds and ubgenvbounds */
129 SCIP_EVENTDATA** lbevents; /**< array of lower bound event data */
130 SCIP_EVENTDATA** ubevents; /**< array of upper bound event data */
131 SCIP_EVENTHDLR* eventhdlr; /**< genvbounds propagator event handler */
132 SCIP_HASHMAP* lbgenvbounds; /**< hashmap to provide fast access to lower bound genvbounds in
133 * genvboundstore array */
134 SCIP_HASHMAP* ubgenvbounds; /**< hashmap to provide fast access to upper bound genvbounds in
135 * genvboundstore array */
136 SCIP_HASHMAP* lbeventsmap; /**< hashmap to provide fast access to lbevents array */
137 SCIP_HASHMAP* ubeventsmap; /**< hashmap to provide fast access to ubevents array */
138 SCIP_HASHMAP* startmap; /**< hashmap to provide fast access to startindices array */
139 SCIP_PROP* prop; /**< pointer to genvbounds propagator */
140 SCIP_Longint lastnodenumber; /**< last node number where events for starting indices were caught */
141 SCIP_VAR* cutoffboundvar; /**< artificial variable representing primal cutoff bound */
142 int* componentsstart; /**< stores the components starting indices in genvboundstore array; the
143 * entry componentsstart[ncomponents] is equal to ngenvbounds, which
144 * makes it easier to iterate over all components */
145 int componentsstartsize;/**< size of componentsstart array */
146 int* startindices; /**< storing indices of components where local propagation should start */
147 int* startcomponents; /**< components corresponding to indices stored in startindices array */
148 int startindicessize; /**< size of startindices and startcomponents arrays */
149 int* gstartindices; /**< storing indices of components where global propagation, i.e.,
150 * propagation of an improved primal bound, should start */
151 int* gstartcomponents; /**< components corresponding to indices stored in gstartindices array */
152 int gstartindicessize; /**< size of gstartindices and gstartcomponents arrays */
153 SCIP_Real lastcutoff; /**< cutoff bound's value last time genvbounds propagator was called */
154 int genvboundstoresize; /**< size of genvboundstore array */
155 int ngenvbounds; /**< number of genvbounds stored in genvboundstore array */
156 int ncomponents; /**< number of components in genvboundstore array */
157 int nindices; /**< number of indices stored in startindices array */
158 int ngindices; /**< number of indices stored in gstartindices array */
159 int nlbevents; /**< number of data entries in lbevents array */
160 int nubevents; /**< number of data entries in ubevents array */
161 SCIP_Bool issorted; /**< stores wether array genvboundstore is topologically sorted */
162 SCIP_Bool global; /**< apply global propagation? */
163 SCIP_Bool propinrootnode; /**< apply genvbounds in root node if no new incumbent was found? */
164 SCIP_Bool sort; /**< sort genvbounds and wait for bound change events? (otherwise all
165 * genvbounds are applied in each node) */
166 SCIP_Bool propasconss; /**< should genvbounds be transformed to (linear) constraints? */
167 SCIP_PROPTIMING inittiming; /**< initial propagator timing */
168};
169
170
171/*
172 * Local methods
173 */
174
175/** returns correct cutoff bound value */
176static
178 SCIP* scip /**< SCIP data structure */
179 )
180{
181 assert(scip != NULL);
182
183 SCIPdebugMsg(scip, "cutoff = %.9g (%.9g + %.9g * %.9g)\n",
186
187 /* the cutoff bound is valid w.r.t. the current objective function in the transformed problem; during presolving,
188 * however, the objective function can change (e.g., when a variable is fixed, its contribution in the objective is
189 * subtracted from the cutoff bound and added to the objective offset); we solve this by transforming the
190 * contribution of the cutoff bound in the generalized variable bound to the original problem as described in
191 * function SCIPgenVBoundAdd()
192 */
194}
195
196/** returns corresponding genvbound in genvboundstore if there is one, NULL otherwise */
197static
199 SCIP* scip, /**< SCIP data structure */
200 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
201 SCIP_VAR* var, /**< bounds variable */
202 SCIP_BOUNDTYPE boundtype /**< bounds type */
203 )
204{
205 SCIP_HASHMAP* hashmap;
206
207 assert(scip != NULL);
208 assert(propdata != NULL);
209 assert(var != NULL);
210
211 hashmap = boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
212
213 return (GENVBOUND*) SCIPhashmapGetImage(hashmap, var);
214}
215
216#ifdef SCIP_DEBUG
217/** prints a genvbound as debug message */
218static
219void printGenVBound(
220 SCIP* scip, /**< SCIP data structure */
221 GENVBOUND* genvbound /**< genvbound to be printed */
222 )
223{
224 SCIP_Bool first;
225 int i;
226
227 assert(genvbound != NULL);
228
229 if( genvbound->boundtype == SCIP_BOUNDTYPE_UPPER )
230 {
231 SCIPdebugMsgPrint(scip, "- ");
232 }
233
234 SCIPdebugMsgPrint(scip, "<%s> >= ", SCIPvarGetName(genvbound->var));
235
236 first = TRUE;
237 for( i = 0; i < genvbound->ncoefs; i++ )
238 {
239 if( !first )
240 {
241 SCIPdebugMsgPrint(scip, " + ");
242 }
243
244 SCIPdebugMsgPrint(scip, "%g * <%s>", genvbound->coefs[i], SCIPvarGetName(genvbound->vars[i]));
245
246 first = FALSE;
247 }
248
249 if( !SCIPisZero(scip, genvbound->cutoffcoef) )
250 {
251 SCIPdebugMsgPrint(scip, " + %g * cutoff_bound", genvbound->cutoffcoef);
252 }
253
254 if( !SCIPisZero(scip, genvbound->constant) )
255 {
256 SCIPdebugMsgPrint(scip, " + %g", genvbound->constant);
257 }
258
259 SCIPdebugMsgPrint(scip, "\n");
260}
261#endif
262
263/** calculates the minactivity of a linear combination of variables stored in an array */
264static
266 SCIP* scip, /**< SCIP data structure */
267 SCIP_VAR** vars, /**< array of variables */
268 SCIP_Real* coefs, /**< array of coefficients */
269 int nvars, /**< number of variables */
270 SCIP_Bool global /**< use global variable bounds? */
271 )
272{
273 SCIP_Real minval;
274 int i;
275
276 assert(scip != NULL);
277 assert(vars != NULL);
278 assert(coefs != NULL);
279 assert(nvars >= 0);
280
281 minval = 0.0;
282
283 for( i = 0; i < nvars; i++ )
284 {
286
287 /* get global or local bound */
288 if( global )
289 bound = coefs[i] > 0.0 ? SCIPvarGetLbGlobal(vars[i]) : SCIPvarGetUbGlobal(vars[i]);
290 else
291 bound = coefs[i] > 0.0 ? SCIPvarGetLbLocal(vars[i]) : SCIPvarGetUbLocal(vars[i]);
292
293 /* with infinite bounds we cannot compute a valid minactivity and return minus infinity */
295 return -SCIPinfinity(scip);
296
297 /* add contribution to minactivity */
298 minval += coefs[i] * bound;
299 }
300
301 return minval;
302}
303
304/** calculates the minactivity of a linear combination of variables stored in the current conflict set */
305static
307 SCIP* scip, /**< SCIP data structure */
308 SCIP_VAR** vars, /**< array of variables */
309 SCIP_Real* coefs, /**< array of coefficients */
310 int nvars, /**< number of variables */
311 SCIP_BDCHGIDX* bdchgidx /**< bound change at which minactivity should be computed; if NULL use local bounds */
312 )
313{
314 SCIP_Real minval;
315 int i;
316
317 assert(scip != NULL);
318 assert(vars != NULL);
319 assert(coefs != NULL);
320 assert(nvars >= 0);
321
322 minval = 0.0;
323
324 for( i = 0; i < nvars; i++ )
325 {
327
328 if( coefs[i] > 0.0 )
329 {
330 /* get bound at current bound change */
331 bound = SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE);
332
333 /* if bdchgidx is NULL, assert that we use local bounds */
334 assert(bdchgidx != NULL || SCIPisEQ(scip, bound, SCIPvarGetLbLocal(vars[i])));
335
336 /* if bdchgidx is not NULL, use the possibly tighter bound already in the current conflict set */
337 if( bdchgidx != NULL && SCIPgetConflictVarLb(scip, vars[i]) > bound )
338 bound = SCIPgetConflictVarLb(scip, vars[i]);
339 }
340 else
341 {
342 /* get bound at current bound change */
343 bound = SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE);
344
345 /* if bdchgidx is NULL, assert that we use local bounds */
346 assert(bdchgidx != NULL || SCIPisEQ(scip, bound, SCIPvarGetUbLocal(vars[i])));
347
348 /* if bdchgidx is not NULL, use the possibly tighter bound already in the current conflict set */
349 if( bdchgidx != NULL && SCIPgetConflictVarUb(scip, vars[i]) < bound )
350 bound = SCIPgetConflictVarUb(scip, vars[i]);
351 }
352
353 /* with infinite bounds we cannot compute a valid minactivity and return minus infinity */
355 return -SCIPinfinity(scip);
356
357 /* add contribution to minactivity */
358 minval += coefs[i] * bound;
359 }
360
361 return minval;
362}
363
364/** returns a valid bound given by a generalized variable bound */
365static
367 SCIP* scip, /**< SCIP data structure */
368 GENVBOUND* genvbound, /**< generalized variable bound */
369 SCIP_Bool global /**< use global variable bounds? */
370 )
371{
372 SCIP_Real boundval;
373
374 assert(scip != NULL);
375 assert(genvbound != NULL);
376
377 boundval = getGenVBoundsMinActivity(scip, genvbound->vars, genvbound->coefs, genvbound->ncoefs, global);
378
379 if( SCIPisInfinity(scip, -boundval) )
380 return (genvbound->boundtype == SCIP_BOUNDTYPE_LOWER) ? -SCIPinfinity(scip) : SCIPinfinity(scip);
381
382 if( genvbound->cutoffcoef != 0.0 )
383 boundval += genvbound->cutoffcoef * getCutoffboundGenVBound(scip);
384
385 boundval += genvbound->constant;
386
387 if( genvbound->boundtype == SCIP_BOUNDTYPE_UPPER )
388 boundval *= -1.0;
389
390 return boundval;
391}
392
393#ifdef WITH_DEBUG_SOLUTION
394/** checks whether a generalized variable bound violates the debug solution */
395static
396SCIP_RETCODE checkDebugSolutionGenVBound(
397 SCIP* scip, /**< SCIP data structure */
398 GENVBOUND* genvbound /**< generalized variable bound */
399 )
400{
401 SCIP_SOL* debugsol;
402 SCIP_Real activity;
403 SCIP_Real solval;
404 int i;
405
406 assert(scip != NULL);
407 assert(genvbound != NULL);
408
409 if( !SCIPdebugIsMainscip(scip) )
410 return SCIP_OKAY;
411
412 /* the genvbound must be valid for all cutoff bounds greater equal the objective value of the debug solution */
413 SCIP_CALL( SCIPdebugGetSol(scip, &debugsol) );
414
415 /* check whether a debug solution is available */
416 if( debugsol == NULL )
417 return SCIP_OKAY;
418
419 activity = 0.0;
420 for( i = 0; i < genvbound->ncoefs; i++ )
421 {
422 SCIP_CALL( SCIPdebugGetSolVal(scip, genvbound->vars[i], &solval) );
423 if( solval != SCIP_UNKNOWN || solval != SCIP_INVALID )
424 activity += genvbound->coefs[i] * solval;
425 else
426 printf("***** debug: ignoring variable with %s value in debug solution\n",
427 solval == SCIP_UNKNOWN ? "unknown" : "invalid");
428 }
429
430 activity += genvbound->cutoffcoef *
432 activity += genvbound->constant;
433
434 SCIP_CALL( SCIPdebugGetSolVal(scip, genvbound->var, &solval) );
435 if( solval != SCIP_UNKNOWN || solval != SCIP_INVALID )
436 {
437 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
438 {
439 SCIP_CALL( SCIPdebugCheckLbGlobal(scip, genvbound->var, activity) );
440 }
441 else if( genvbound->boundtype == SCIP_BOUNDTYPE_UPPER )
442 {
443 SCIP_CALL( SCIPdebugCheckUbGlobal(scip, genvbound->var, -activity) );
444 }
445 }
446
447 return SCIP_OKAY;
448}
449#endif
450
451/** allocate local and global startindices, startcomponents and startmap */
452static
454 SCIP* scip, /**< SCIP data structure */
455 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
456 )
457{
458 assert(scip != NULL);
459 assert(propdata != NULL);
460
461 assert(propdata->startcomponents == NULL);
462 assert(propdata->startindices == NULL);
463 assert(propdata->startmap == NULL);
464 assert(propdata->nindices == -1);
465
466 assert(propdata->gstartindices == NULL);
467 assert(propdata->gstartcomponents == NULL);
468 assert(propdata->ngindices == -1);
469
470 assert(propdata->ngenvbounds >= 1);
471 assert(propdata->ncomponents >= 1);
472
473 SCIPdebugMsg(scip, "create starting data\n");
474
475 /* allocate memory for arrays */
476 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->startindices), propdata->ncomponents) );
477 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->startcomponents), propdata->ncomponents) );
478 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->gstartindices), propdata->ncomponents) );
479 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->gstartcomponents), propdata->ncomponents) );
480 propdata->startindicessize = propdata->ncomponents;
481 propdata->gstartindicessize = propdata->ncomponents;
482
483 /* create hashmap */
484 SCIP_CALL( SCIPhashmapCreate(&(propdata->startmap), SCIPblkmem(scip), propdata->ncomponents) );
485
486 propdata->nindices = 0;
487 propdata->ngindices = 0;
488
489 return SCIP_OKAY;
490}
491
492/** free local and global startindices, startcomponents and startmap */
493static
495 SCIP* scip, /**< SCIP data structure */
496 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
497 )
498{
499 assert(scip != NULL);
500 assert(propdata != NULL);
501
502 SCIPdebugMsg(scip, "free starting data\n");
503
504 if( propdata->startcomponents != NULL )
505 {
506 assert(propdata->startindices != NULL);
507 assert(propdata->startmap != NULL);
508 assert(propdata->nindices >= 0);
509
510 SCIPfreeBlockMemoryArray(scip, &(propdata->startindices), propdata->startindicessize);
511 SCIPfreeBlockMemoryArray(scip, &(propdata->startcomponents), propdata->startindicessize);
512 propdata->startindicessize = 0;
513 SCIPhashmapFree(&(propdata->startmap));
514 propdata->nindices = -1;
515
516 assert(propdata->gstartindices != NULL);
517 assert(propdata->gstartcomponents != NULL);
518 assert(propdata->ngindices >= 0);
519
520 SCIPfreeBlockMemoryArray(scip, &(propdata->gstartindices), propdata->gstartindicessize);
521 SCIPfreeBlockMemoryArray(scip, &(propdata->gstartcomponents), propdata->gstartindicessize);
522 propdata->gstartindicessize = 0;
523 propdata->ngindices = -1;
524 }
525
526 assert(propdata->startcomponents == NULL);
527 assert(propdata->startindices == NULL);
528 assert(propdata->startmap == NULL);
529 assert(propdata->nindices == -1);
530
531 assert(propdata->gstartindices == NULL);
532 assert(propdata->gstartcomponents == NULL);
533 assert(propdata->ngindices == -1);
534
535 return SCIP_OKAY;
536}
537
538static
540 SCIP* scip, /**< SCIP data structure */
541 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
542 )
543{
544 int i;
545
546 assert(scip != NULL);
547 assert(propdata != NULL);
548
549 assert(propdata->gstartindices != NULL);
550 assert(propdata->gstartcomponents != NULL);
551 assert(propdata->ngindices == 0);
552
553 SCIPdebugMsg(scip, "fill global starting data\n");
554
555 for( i = 0; i < propdata->ncomponents; i++ )
556 {
557 int j;
558
559 for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ ) /*lint !e679*/
560 {
561 assert(j < propdata->ngenvbounds);
562
563 if( !SCIPisZero(scip, propdata->genvboundstore[j]->cutoffcoef) )
564 {
565 assert(SCIPisNegative(scip, propdata->genvboundstore[j]->cutoffcoef));
566
567 propdata->gstartcomponents[propdata->ngindices] = i;
568 propdata->gstartindices[propdata->ngindices] = j;
569
570 /* go to next component */
571 propdata->ngindices++;
572 break;
573 }
574 }
575 }
576
577 /* resize arrays */
578 if( propdata->gstartindicessize != propdata->ngindices )
579 {
580 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->gstartindices), propdata->gstartindicessize, \
581 propdata->ngindices) );
582 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->gstartcomponents), propdata->gstartindicessize, \
583 propdata->ngindices) );
584 propdata->gstartindicessize = propdata->ngindices;
585 }
586
587 return SCIP_OKAY;
588}
589
590
591/** resets local starting data */
592static
594 SCIP* scip, /**< SCIP data structure */
595 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
596 )
597{
598 assert(scip != NULL);
599 assert(propdata != NULL);
600 assert(propdata->startcomponents != NULL);
601 assert(propdata->startindices != NULL);
602 assert(propdata->startmap != NULL);
603 assert(propdata->nindices >= 0);
604
605 SCIP_CALL( SCIPhashmapRemoveAll(propdata->startmap) );
606 propdata->nindices = 0;
607
608 return SCIP_OKAY;
609}
610
611/** frees sorted components data */
612static
614 SCIP* scip, /**< SCIP data structure */
615 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
616 )
617{
618 assert(scip != NULL);
619 assert(propdata != NULL);
620
621 SCIPdebugMsg(scip, "free components data\n");
622
623 if( propdata->componentsstart != NULL )
624 {
625 assert(propdata->ncomponents > 0);
626
627 SCIPfreeBlockMemoryArray(scip, &(propdata->componentsstart), propdata->componentsstartsize);
628 propdata->componentsstartsize = 0;
629 propdata->ncomponents = -1;
630 }
631
632 assert(propdata->componentsstart == NULL);
633 assert(propdata->ncomponents == -1);
634
635 return SCIP_OKAY;
636}
637
638/** frees memory allocated for a generalized variable bound */
639static
641 SCIP* scip,
642 GENVBOUND* genvbound
643 )
644{
645 int i;
646
647 assert(scip != NULL);
648 assert(genvbound != NULL);
649 assert(genvbound->coefs != NULL);
650 assert(genvbound->vars != NULL);
651 assert(genvbound->var != NULL);
652
653 /* release variables */
654 for( i = 0; i < genvbound->ncoefs; ++i )
655 {
656 assert(genvbound->vars[i] != NULL);
657 SCIP_CALL( SCIPreleaseVar(scip, &(genvbound->vars[i])) );
658 }
659 SCIP_CALL( SCIPreleaseVar(scip, &genvbound->var) );
660
661 /* free memory */
662 SCIPfreeBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize);
663 SCIPfreeBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize);
664 SCIPfreeBlockMemory(scip, &genvbound);
665
666 return SCIP_OKAY;
667}
668
669/** helper function to release all genvbounds */
670static
672 SCIP* scip,
673 SCIP_PROP* prop,
674 SCIP_PROPDATA* propdata
675 )
676{
677 int i;
678
679 assert(scip != NULL);
680 assert(prop != NULL);
681 assert(propdata != NULL);
682
683 if( propdata->genvboundstore != NULL )
684 {
685 /* disable genvbounds propagator */
686 if( propdata->ngenvbounds >= 1 )
688
689 /* free genvbounds */
690 for( i = propdata->ngenvbounds - 1; i >= 0; i-- )
691 {
692 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
693 }
694
695 /* free genvboundstore hashmaps */
696 SCIPhashmapFree(&(propdata->lbgenvbounds));
697 SCIPhashmapFree(&(propdata->ubgenvbounds));
698
699 /* free genvboundstore array */
700 SCIPfreeBlockMemoryArray(scip, &(propdata->genvboundstore), propdata->genvboundstoresize);
701
702 /* set the number of genvbounds to zero */
703 propdata->ngenvbounds = 0;
704
705 /* free componentsstart array */
706 SCIP_CALL( freeComponentsData(scip, propdata) );
707
708 /* free starting indices data */
709 SCIP_CALL( freeStartingData(scip, propdata) );
710
711 /* release the cutoffboundvar and undo the locks */
712 if( propdata->cutoffboundvar != NULL )
713 {
714 SCIP_CALL( SCIPaddVarLocksType(scip, propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL, -1, -1) );
715 SCIP_CALL( SCIPreleaseVar(scip, &(propdata->cutoffboundvar)) );
716 propdata->cutoffboundvar = NULL;
717 SCIPdebugMsg(scip, "release cutoffboundvar!\n");
718 }
719 }
720
721 return SCIP_OKAY;
722}
723
724/** helper function to release relax-only genvbounds */
725static
727 SCIP* scip,
728 SCIP_PROP* prop,
729 SCIP_PROPDATA* propdata
730 )
731{
732 SCIP_Bool freedgenvbound;
733 int i;
734
735 assert(scip != NULL);
736 assert(propdata != NULL);
737
738 if( propdata->genvboundstore == NULL )
739 return SCIP_OKAY;
740
741 /* free genvbounds */
742 freedgenvbound = FALSE;
743 for( i = 0 ; i < propdata->ngenvbounds; )
744 {
745 if( propdata->genvboundstore[i]->relaxonly )
746 {
747 SCIP_CALL( SCIPhashmapRemove(propdata->genvboundstore[i]->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds,
748 propdata->genvboundstore[i]->var) );
749
750 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
751 if( i != propdata->ngenvbounds-1 )
752 {
753 propdata->genvboundstore[i] = propdata->genvboundstore[propdata->ngenvbounds-1];
754 propdata->genvboundstore[i]->index = i;
755 }
756 --propdata->ngenvbounds;
757
758 propdata->issorted = FALSE;
759 freedgenvbound = TRUE;
760 }
761 else
762 ++i;
763 }
764
765 if( freedgenvbound )
766 {
767 /* free componentsstart array */
768 SCIP_CALL( freeComponentsData(scip, propdata) );
769
770 /* free starting indices data */
771 SCIP_CALL( freeStartingData(scip, propdata) );
772 }
773
774 /* disable genvbounds propagator */
775 if( propdata->ngenvbounds == 0 )
777
778 return SCIP_OKAY;
779}
780
781/** resolves propagation of lower bound on +/- left-hand side variable of a generalized variable bound */
782static
784 SCIP* scip, /**< SCIP data structure */
785 GENVBOUND* genvbound, /**< genvbound data structure */
786 SCIP_BDCHGIDX* bdchgidx, /**< the index of the bound change, representing the point of time where the change took place */
787 SCIP_Real* boundval, /**< pointer to lower bound value on +/- left-hand side variable */
788 SCIP_Bool* success /**< was the explanation succesful? */
789 )
790{
791 SCIP_VAR* lhsvar;
792 SCIP_VAR** vars;
793 SCIP_Real minactivity;
794 SCIP_Real tmpboundval;
795 SCIP_Real slack;
796 int nvars;
797 int i;
798
799 assert(scip != NULL);
800 assert(genvbound != NULL);
801 assert(boundval != NULL);
802 assert(success != NULL);
803
804 *success = FALSE;
805
806 /* get left-hand side variable */
807 lhsvar = genvbound->var;
808 assert(lhsvar != NULL);
809
810 /* get right-hand side variables */
811 vars = genvbound->vars;
812 nvars = genvbound->ncoefs;
813 assert(vars != NULL);
814
815 /* if only the primal bound participates in the propagation, it is globally valid and should not be analyzed */
816 assert(nvars > 0);
817
818 /* when resolving a propagation, bdchgidx is not NULL and boundval should be the bound change performed for the
819 * left-hand side variable
820 */
821 assert(bdchgidx == NULL || genvbound->boundtype != SCIP_BOUNDTYPE_LOWER || SCIPisEQ(scip,
822 SCIPvarIsIntegral(genvbound->var) ? SCIPfeasCeil(scip, *boundval) : *boundval, SCIPgetVarLbAtIndex(scip, lhsvar, bdchgidx, TRUE)));
823 assert(bdchgidx == NULL || genvbound->boundtype != SCIP_BOUNDTYPE_UPPER || SCIPisEQ(scip,
824 SCIPvarIsIntegral(genvbound->var) ? SCIPfeasCeil(scip, *boundval) : *boundval, -SCIPgetVarUbAtIndex(scip, lhsvar, bdchgidx, TRUE)));
825
826 /* when creating an initial conflict, bdchgidx is NULL and +/-boundval must exceed the upper/lower bound of the
827 * left-hand side variable
828 */
829 assert(bdchgidx != NULL || genvbound->boundtype != SCIP_BOUNDTYPE_LOWER
830 || SCIPisGT(scip, *boundval, SCIPvarGetUbLocal(lhsvar)));
831 assert(bdchgidx != NULL || genvbound->boundtype != SCIP_BOUNDTYPE_UPPER
832 || SCIPisGT(scip, *boundval, -SCIPvarGetLbLocal(lhsvar)));
833
834 SCIPdebugMsg(scip, "resolving genvbound propagation: lhs=%s<%s> >= boundval=%.15g\n",
835 genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? "+" : "-", SCIPvarGetName(lhsvar), *boundval);
836
837 /* subtract constant terms from bound value */
838 tmpboundval = *boundval;
839 tmpboundval -= genvbound->cutoffcoef * getCutoffboundGenVBound(scip);
840 tmpboundval -= genvbound->constant;
841
842 SCIPdebugMsg(scip, "subtracting constant terms gives boundval=%.15g\n", tmpboundval);
843
844 /* compute minimal activity; if bdchgidx is NULL, we create the initial conflict and use local bounds */
845 minactivity = getGenVBoundsMinActivityConflict(scip, genvbound->vars, genvbound->coefs, genvbound->ncoefs, bdchgidx);
846
847 SCIPdebugMsg(scip, "minactivity of right-hand side is minactivity=%.15g\n", minactivity);
848
849 /* a genvbound might have been replaced since the propagation took place, hence we have to check that the current
850 * genvbound can explain the propagation at the given bound change index; note that by now, with smaller cutoff
851 * bound, we might even perform a stronger propagation
852 */
853 if( SCIPisLT(scip, minactivity, tmpboundval) )
854 {
855 SCIPdebugMsg(scip, "minactivity is too small to explain propagation; was genvbound replaced?\n");
856 return SCIP_OKAY;
857 }
858
859 /* if bdchgidx is NULL, i.e., we create the initial conflict, we should be able to explain the bound change */
860 assert(SCIPisGE(scip, minactivity, tmpboundval));
861
862 slack = MAX(minactivity - tmpboundval, 0.0);
863
864 SCIPdebugMsg(scip, "slack=%.15g\n", slack);
865
866 /* add variables on the right-hand side as reasons for propagation */
867 for( i = 0; i < nvars; i++ )
868 {
869 assert(vars[i] != NULL);
870 assert(SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE)));
871 assert(SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE)));
872
873 /* coefficient is positive */
874 if( genvbound->coefs[i] > 0.0 )
875 {
876 SCIP_Real lbatindex;
877 SCIP_Real conflictlb;
878
879 /* get bound at current bound change */
880 lbatindex = SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, TRUE);
881
882 /* get bound already enforced by conflict set */
883 conflictlb = SCIPgetConflictVarLb(scip, genvbound->vars[i]);
884 assert(SCIPisGE(scip, conflictlb, SCIPvarGetLbGlobal(genvbound->vars[i])));
885
886 SCIPdebugMsg(scip, "lower bound of variable <%s> (genvbound->vars[%d]) in conflict set / at index is %.15g / %.15g\n",
887 SCIPvarGetName(genvbound->vars[i]), i, conflictlb, lbatindex);
888
889 /* if bound is already enforced by conflict set we do not need to add the bound change; since we used the
890 * tighest bound already when computing the initial minactivity, the slack is already correct
891 */
892 if( SCIPisLE(scip, lbatindex, conflictlb) )
893 {
894 SCIPdebugMsg(scip, "skipping lower bound of variable <%s> (genvbound->vars[%d]) already enforced in conflict set\n",
895 SCIPvarGetName(genvbound->vars[i]), i);
896 }
897 else
898 {
899 SCIP_Real relaxedlb;
900
901 /* compute relaxed bound that would suffice to explain the bound change */
902 relaxedlb = lbatindex - (slack / genvbound->coefs[i]);
903 assert(relaxedlb <= lbatindex);
904
905 /* add variable to conflict set */
906 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, genvbound->vars[i], bdchgidx, relaxedlb ) );
907
908 /* get new bound of variable in conflict set; after possible bound widening in SCIPaddConflictLbRelaxed(),
909 * it should be between conflictlb and lbatindex
910 */
911 relaxedlb = SCIPgetConflictVarLb(scip, genvbound->vars[i]);
912 assert(SCIPisGE(scip, relaxedlb, conflictlb));
913 assert(SCIPisLE(scip, relaxedlb, lbatindex));
914
915 /* update slack and ensure that its nonegative */
916 slack -= genvbound->coefs[i] * (lbatindex - relaxedlb);
917 slack = MAX(slack, 0.0);
918
919 SCIPdebugMsg(scip, "added lower bound of variable <%s> (genvbound->vars[%d]); new slack=%.15g\n",
920 SCIPvarGetName(genvbound->vars[i]), i, slack);
921 }
922 }
923 /* coefficient is negative */
924 else
925 {
926 SCIP_Real ubatindex;
927 SCIP_Real conflictub;
928
929 /* get bound at current bound change */
930 ubatindex = SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, TRUE);
931
932 /* get bound already enforced by conflict set */
933 conflictub = SCIPgetConflictVarUb(scip, genvbound->vars[i]);
934 assert(SCIPisLE(scip, conflictub, SCIPvarGetUbGlobal(genvbound->vars[i])));
935
936 SCIPdebugMsg(scip, "upper bound of variable <%s> (genvbound->vars[%d]) in conflict set / at index is %.15g / %.15g\n",
937 SCIPvarGetName(genvbound->vars[i]), i, conflictub, ubatindex);
938
939 /* if bound is already enforced by conflict set we do not need to add the bound change; since we used the
940 * tighest bound already when computing the initial minactivity, the slack is already correct
941 */
942 if( SCIPisGE(scip, ubatindex, conflictub) )
943 {
944 SCIPdebugMsg(scip, "skipping upper bound of variable <%s> (genvbound->vars[%d]) already enforced in conflict set\n",
945 SCIPvarGetName(genvbound->vars[i]), i);
946 }
947 else
948 {
949 SCIP_Real relaxedub;
950
951 /* compute relaxed bound that would suffice to explain the bound change */
952 relaxedub = ubatindex - (slack / genvbound->coefs[i]);
953 assert(relaxedub >= ubatindex);
954
955 /* add variable to conflict set */
956 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, genvbound->vars[i], bdchgidx, relaxedub ) );
957
958 /* get new bound of variable in conflict set; after possible bound widening in SCIPaddConflictUbRelaxed(),
959 * it should be between conflictub and ubatindex
960 */
961 relaxedub = SCIPgetConflictVarUb(scip, genvbound->vars[i]);
962 assert(SCIPisLE(scip, relaxedub, conflictub));
963 assert(SCIPisGE(scip, relaxedub, ubatindex));
964
965 /* update slack and ensure that its nonegative */
966 slack -= genvbound->coefs[i] * (ubatindex - relaxedub);
967 slack = MAX(slack, 0.0);
968
969 SCIPdebugMsg(scip, "added upper bound of variable <%s> (genvbound->vars[%d]); new slack=%.15g\n",
970 SCIPvarGetName(genvbound->vars[i]), i, slack);
971 }
972 }
973 }
974
975 /* if slack is positive, return increased boundval */
976 if( SCIPisPositive(scip, slack) )
977 tmpboundval += slack;
978
979 /* add constant terms again */
980 tmpboundval += genvbound->cutoffcoef * getCutoffboundGenVBound(scip);
981 tmpboundval += genvbound->constant;
982
983 /* boundval should not have been decreased; if this happened nevertheless, maybe due to numerical errors, we quit
984 * without success
985 */
986 if( SCIPisLT(scip, tmpboundval, *boundval) )
987 {
988 SCIPdebugMsg(scip, "boundval was reduced from %.15g to %.15g; propagation not resolved\n", *boundval, tmpboundval);
989 return SCIP_OKAY;
990 }
991
992 /* return widened boundval */
993 *boundval = tmpboundval;
994 *success = TRUE;
995
996 return SCIP_OKAY;
997}
998
999/** create initial conflict */
1000static
1002 SCIP* scip, /**< SCIP data structure */
1003 GENVBOUND* genvbound /**< genvbound data structure */
1004 )
1005{
1006 SCIP_Bool success;
1007
1008 assert(scip != NULL);
1009 assert(genvbound != NULL);
1010
1011 /* check if conflict analysis is applicable */
1013 return SCIP_OKAY;
1014
1015 /* initialize conflict analysis */
1017
1018 /* left-hand side variable >= ... */
1019 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
1020 {
1021 SCIP_Real infeasthreshold;
1023
1024 /* get minimal right-hand side bound that leads to infeasibility; first try with a factor of 2 for robustness */
1025 bound = REALABS(SCIPvarGetUbLocal(genvbound->var));
1026 infeasthreshold = MAX(bound, 1.0) * 2 * SCIPfeastol(scip);
1027 bound = SCIPvarGetUbLocal(genvbound->var) + infeasthreshold;
1028
1029 /* add right-hand side variables that force the lower bound of the left-hand side variable above its upper bound
1030 * to conflict set
1031 */
1032 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
1033 assert(!success || SCIPisFeasGT(scip, bound, SCIPvarGetUbLocal(genvbound->var)));
1034
1035 /* if infeasibility cannot be proven with the tighter bound, try with actual bound */
1036 if( !success )
1037 {
1038 bound = REALABS(SCIPvarGetUbLocal(genvbound->var));
1039 infeasthreshold = MAX(bound, 1.0) * SCIPfeastol(scip);
1040 bound = SCIPvarGetUbLocal(genvbound->var) + infeasthreshold;
1041
1042 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
1043 success = success && SCIPisFeasGT(scip, bound, SCIPvarGetUbLocal(genvbound->var));
1044 }
1045
1046 /* compute upper bound on left-hand side variable that leads to infeasibility */
1047 bound -= infeasthreshold;
1048 success = success && SCIPisGE(scip, bound, SCIPvarGetUbLocal(genvbound->var));
1049
1050 /* initial reason could not be constructed, maybe due to numerics; do not apply conflict analysis */
1051 if( !success )
1052 {
1053 SCIPdebugMsg(scip, "strange: could not create initial reason to start conflict analysis\n");
1054 return SCIP_OKAY;
1055 }
1056
1057 /* if bound is already enforced by conflict set we do not have to add it */
1058 if( SCIPisGE(scip, bound, SCIPgetConflictVarUb(scip, genvbound->var)) )
1059 {
1060 SCIPdebugMsg(scip, "skipping upper bound of left-hand side variable <%s> already enforced in conflict set\n",
1061 SCIPvarGetName(genvbound->var));
1062 }
1063 else
1064 {
1065 SCIPdebugMsg(scip, "adding upper bound of left-hand side variable <%s>\n", SCIPvarGetName(genvbound->var));
1066
1068 }
1069 }
1070 /* left-hand side variable <= ..., i.e., - left-hand side variable >= ... */
1071 else
1072 {
1073 SCIP_Real infeasthreshold;
1075
1076 /* get minimal right-hand side bound that leads to infeasibility; try with a factor of 2 first for robustness */
1077 bound = REALABS(SCIPvarGetLbLocal(genvbound->var));
1078 infeasthreshold = MAX(bound, 1.0) * 2 * SCIPfeastol(scip);
1079 bound = -SCIPvarGetLbLocal(genvbound->var) + infeasthreshold;
1080
1081 /* add right-hand side variables that force the upper bound of the left-hand side variable below its lower bound
1082 * to conflict set
1083 */
1084 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
1085 assert(!success || SCIPisFeasLT(scip, -bound, SCIPvarGetLbLocal(genvbound->var)));
1086
1087 /* if infeasibility cannot be proven with the tighter bound, try with actual bound */
1088 if( !success )
1089 {
1090 bound = REALABS(SCIPvarGetLbLocal(genvbound->var));
1091 infeasthreshold = MAX(bound, 1.0) * SCIPfeastol(scip);
1092 bound = -SCIPvarGetLbLocal(genvbound->var) + infeasthreshold;
1093
1094 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, NULL, &bound, &success) );
1095 success = success && SCIPisFeasLT(scip, -bound, SCIPvarGetLbLocal(genvbound->var));
1096 }
1097
1098 /* compute lower bound on left-hand side variable that leads to infeasibility */
1099 bound = -bound + infeasthreshold;
1100 success = success && SCIPisLE(scip, bound, SCIPvarGetLbLocal(genvbound->var));
1101
1102 /* initial reason could not be constructed, maybe due to numerics; do not apply conflict analysis */
1103 if( !success )
1104 {
1105 SCIPdebugMsg(scip, "strange: could not create initial reason to start conflict analysis\n");
1106 return SCIP_OKAY;
1107 }
1108
1109 /* if bound is already enforced by conflict set we do not have to add it */
1110 if( SCIPisLE(scip, bound, SCIPgetConflictVarLb(scip, genvbound->var)) )
1111 {
1112 SCIPdebugMsg(scip, "skipping lower bound of left-hand side variable <%s> already enforced in conflict set\n",
1113 SCIPvarGetName(genvbound->var));
1114 }
1115 else
1116 {
1117 SCIPdebugMsg(scip, "adding lower bound of left-hand side variable <%s>\n", SCIPvarGetName(genvbound->var));
1118
1120 }
1121 }
1122
1123 /* analyze the conflict */
1125
1126 return SCIP_OKAY;
1127}
1128
1129/** apply propagation for one generalized variable bound; also if the left-hand side variable is locally fixed, we
1130 * compute the right-hand side minactivity to possibly detect infeasibility
1131 */
1132static
1134 SCIP* scip, /**< SCIP data structure */
1135 SCIP_PROP* prop, /**< genvbounds propagator */
1136 GENVBOUND* genvbound, /**< genvbound data structure */
1137 SCIP_Bool global, /**< apply global bound changes? (global: true, local: false)*/
1138 SCIP_RESULT* result, /**< result pointer */
1139 int* nchgbds /**< counter to increment if bound was tightened */
1140 )
1141{
1142 SCIP_Real boundval;
1143 SCIP_Bool infeas;
1144 SCIP_Bool tightened;
1145
1146 assert(scip != NULL);
1147 assert(genvbound != NULL);
1148 assert(genvbound->var != NULL);
1149 assert(SCIPvarGetStatus(genvbound->var) != SCIP_VARSTATUS_MULTAGGR);
1150 assert(result != NULL);
1151 assert(*result != SCIP_DIDNOTRUN);
1152
1153 /* get bound value provided by genvbound */
1154 boundval = getGenVBoundsBound(scip, genvbound, global);
1155
1156 if( SCIPisInfinity(scip, REALABS(boundval)) )
1157 return SCIP_OKAY;
1158
1159#ifdef SCIP_DEBUG
1160 {
1161 SCIP_Real lb;
1162 SCIP_Real ub;
1163 SCIP_Real new_lb;
1164 SCIP_Real new_ub;
1165
1166 lb = global ? SCIPvarGetLbGlobal(genvbound->var) : SCIPvarGetLbLocal(genvbound->var);
1167 ub = global ? SCIPvarGetUbGlobal(genvbound->var) : SCIPvarGetUbLocal(genvbound->var);
1168 new_lb = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? boundval : lb;
1169 new_ub = genvbound->boundtype == SCIP_BOUNDTYPE_UPPER ? boundval : ub;
1170
1171 SCIPdebugMsg(scip, " %s genvbound propagation for <%s>\n", global ?
1172 "global" : "local", SCIPvarGetName(genvbound->var));
1173 SCIPdebugMsg(scip, " genvbound: ");
1174 printGenVBound(scip, genvbound);
1175 SCIPdebugMsg(scip, " [%.15g,%.15g] -> [%.15g,%.15g]\n", lb, ub, new_lb, new_ub);
1176 }
1177#endif
1178
1179 /* tighten bound globally */
1180 if( global || genvbound->ncoefs <= 0 )
1181 {
1182 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
1183 {
1184 SCIP_CALL( SCIPtightenVarLbGlobal(scip, genvbound->var, boundval, FALSE, &infeas, &tightened) );
1185 }
1186 else
1187 {
1188 SCIP_CALL( SCIPtightenVarUbGlobal(scip, genvbound->var, boundval, FALSE, &infeas, &tightened) );
1189 }
1190 }
1191 /* tighten bound locally and start conflict analysis in case of infeasibility; as inferinfo we pass the index of the
1192 * genvbound that was used for propagation
1193 */
1194 else
1195 {
1196 if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
1197 {
1198 SCIP_CALL( SCIPinferVarLbProp(scip, genvbound->var, boundval, prop, genvbound->index, FALSE, &infeas, &tightened) );
1199
1200 /* initialize conflict analysis if infeasible */
1201 if( infeas )
1202 {
1203 SCIPdebugMsg(scip, " -> lower bound tightening on variable <%s> led to infeasibility\n",
1204 SCIPvarGetName(genvbound->var));
1205
1207 }
1208 }
1209 else
1210 {
1211 SCIP_CALL( SCIPinferVarUbProp(scip, genvbound->var, boundval, prop, genvbound->index, FALSE, &infeas, &tightened) );
1212
1213 /* initialize conflict analysis if infeasible */
1214 if( infeas )
1215 {
1216 SCIPdebugMsg(scip, " -> upper bound tightening on variable <%s> led to infeasibility\n",
1217 SCIPvarGetName(genvbound->var));
1218
1220 }
1221 }
1222 }
1223
1224 /* handle result */
1225 if( infeas )
1226 {
1227 *result = SCIP_CUTOFF;
1228 SCIPdebugMsg(scip, " cutoff!\n");
1229 }
1230 else if( tightened )
1231 {
1233 if( nchgbds != NULL )
1234 ++(*nchgbds);
1235 SCIPdebugMsg(scip, " tightened!\n");
1236 }
1237
1238 return SCIP_OKAY;
1239}
1240
1241#ifdef SCIP_DEBUG
1242/** prints event data as debug message */
1243static
1244void printEventData(
1245 SCIP_EVENTDATA* eventdata,
1246 SCIP_BOUNDTYPE boundtype
1247 )
1248{
1249 int i;
1250
1251 SCIPdebugMessage("event data: %s bound of <%s> tightened ==> start propagating at ",
1252 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(eventdata->var));
1253
1254 /* if there is eventdata it should contain at least one starting index */
1255 assert(eventdata->nstarts > 0);
1256
1257 for( i = 0; i < eventdata->nstarts; i++ )
1258 {
1259 SCIPdebugPrintf("(component %d, index %d) ", eventdata->startcomponents[i], eventdata->startindices[i]);
1260 }
1261 SCIPdebugPrintf("\n");
1262}
1263#endif
1264
1265/** frees event data */
1266static
1268 SCIP* scip, /**< SCIP data structure */
1269 SCIP_EVENTDATA** eventdata /**< event data to be freed */
1270 )
1271{
1272 assert(scip != NULL);
1273 assert(eventdata != NULL);
1274 assert(*eventdata != NULL);
1275
1276 SCIPfreeBlockMemoryArray(scip, &((*eventdata)->startcomponents), (*eventdata)->startindicessize);
1277 SCIPfreeBlockMemoryArray(scip, &((*eventdata)->startindices), (*eventdata)->startindicessize);
1278
1279 (*eventdata)->startindicessize = 0;
1280 (*eventdata)->nstarts = -1;
1281 (*eventdata)->var = NULL;
1282 (*eventdata)->prop = NULL;
1283
1284 SCIPfreeBlockMemory(scip, eventdata);
1285
1286 return SCIP_OKAY;
1287}
1288
1289/** frees all eventdata stored */
1290static
1292 SCIP* scip, /**< SCIP data structure */
1293 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1294 )
1295{
1296 int i;
1297
1298 assert(scip != NULL);
1299 assert(propdata != NULL);
1300
1301 if( propdata->lbevents != NULL )
1302 {
1303 assert(propdata->ubevents != NULL);
1304 assert(propdata->lbeventsmap != NULL);
1305 assert(propdata->ubeventsmap != NULL);
1306
1307 SCIPhashmapFree(&(propdata->lbeventsmap));
1308 SCIPhashmapFree(&(propdata->ubeventsmap));
1309
1310 for( i = propdata->nlbevents - 1; i >= 0; i-- )
1311 {
1312 SCIP_CALL( freeEventData(scip, &(propdata->lbevents[i])) );
1313 }
1314
1315 for( i = propdata->nubevents - 1; i >= 0; i-- )
1316 {
1317 SCIP_CALL( freeEventData(scip, &(propdata->ubevents[i])) );
1318 }
1319
1320 SCIPfreeBlockMemoryArray(scip, &(propdata->ubevents), propdata->nubevents);
1321 SCIPfreeBlockMemoryArray(scip, &(propdata->lbevents), propdata->nlbevents);
1322 propdata->nlbevents = -1;
1323 propdata->nubevents = -1;
1324 }
1325
1326 assert(propdata->lbevents == NULL);
1327 assert(propdata->ubevents == NULL);
1328 assert(propdata->lbeventsmap == NULL);
1329 assert(propdata->ubeventsmap == NULL);
1330 assert(propdata->nlbevents == -1);
1331 assert(propdata->nubevents == -1);
1332
1333 return SCIP_OKAY;
1334}
1335
1336/** drops all events caught by genvbounds propagator and frees their data */
1337static
1339 SCIP* scip, /**< SCIP data structure */
1340 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1341 )
1342{
1343 int i;
1344
1345 SCIPdebugMsg(scip, "drop and free events\n");
1346
1347 assert(scip != NULL);
1348 assert(propdata != NULL);
1349 assert(propdata->eventhdlr != NULL);
1350
1351 if( propdata->lbevents != NULL )
1352 {
1353 assert(propdata->ubevents != NULL);
1354 assert(propdata->nlbevents >= 0);
1355 assert(propdata->nubevents >= 0);
1356
1357 for( i = propdata->nlbevents - 1; i >= 0; i-- )
1358 {
1359 /* drop event */
1360 SCIP_CALL( SCIPdropVarEvent(scip, propdata->lbevents[i]->var, SCIP_EVENTTYPE_LBTIGHTENED, propdata->eventhdlr,
1361 propdata->lbevents[i], -1) );
1362 }
1363
1364 for( i = propdata->nubevents - 1; i >= 0; i-- )
1365 {
1366 /* drop event */
1367 SCIP_CALL( SCIPdropVarEvent(scip, propdata->ubevents[i]->var, SCIP_EVENTTYPE_UBTIGHTENED, propdata->eventhdlr,
1368 propdata->ubevents[i], -1) );
1369 }
1370
1371 /* free event data */
1372 SCIP_CALL( freeAllEventData(scip, propdata) );
1373 }
1374
1375 assert(propdata->lbevents == NULL);
1376 assert(propdata->ubevents == NULL);
1377 assert(propdata->nlbevents == -1);
1378 assert(propdata->nubevents == -1);
1379
1380 return SCIP_OKAY;
1381}
1382
1383/** returns the corresponding event data entry in the corresponding array, if there is one; if not: allocates a new
1384 * event data entry, stores it in the array and returns its adress
1385 */
1386static
1388 SCIP* scip, /**< SCIP data structure */
1389 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1390 SCIP_VAR* var, /**< variable */
1391 SCIP_BOUNDTYPE boundtype, /**< type of bound */
1392 SCIP_EVENTDATA** eventdata /**< event data to return */
1393 )
1394{
1395 SCIP_HASHMAP* hashmap;
1396
1397 assert(scip != NULL);
1398 assert(propdata != NULL);
1399 assert(var != NULL);
1400
1401 hashmap = boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbeventsmap : propdata->ubeventsmap;
1402
1403 if( SCIPhashmapExists(hashmap, var) )
1404 *eventdata = (SCIP_EVENTDATA*) SCIPhashmapGetImage(hashmap, var);
1405 else
1406 {
1407 /* set up new eventdata entry */
1408 SCIP_CALL( SCIPallocBlockMemory(scip, eventdata) );
1409 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*eventdata)->startcomponents), propdata->ncomponents) );
1410 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*eventdata)->startindices), propdata->ncomponents) );
1411 (*eventdata)->startindicessize = propdata->ncomponents;
1412 (*eventdata)->nstarts = 0;
1413 (*eventdata)->var = var;
1414 (*eventdata)->prop = propdata->prop;
1415
1416 /* store event data in eventarray */
1417 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1418 {
1419 propdata->lbevents[propdata->nlbevents] = *eventdata;
1420 propdata->nlbevents++;
1421 }
1422 else
1423 {
1424 propdata->ubevents[propdata->nubevents] = *eventdata;
1425 propdata->nubevents++;
1426 }
1427
1428 /* store hashmap entry */
1429 SCIP_CALL( SCIPhashmapInsert(hashmap, var, (*eventdata)) );
1430 }
1431
1432 return SCIP_OKAY;
1433}
1434
1435/** adds an event to the event array lbevents (if boundtype == SCIP_BOUNDTYPE_LOWER) or ubevents (if boundtype ==
1436 * SCIP_BOUNDTYPE_UPPER)
1437 */
1438static
1440 SCIP* scip, /**< SCIP data structure */
1441 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1442 SCIP_VAR* var, /**< variable thats event to be added */
1443 int startindex, /**< starting index */
1444 int startcomponent, /**< starting components index */
1445 SCIP_BOUNDTYPE boundtype /**< type of bound */
1446 )
1447{
1448 SCIP_EVENTDATA* eventdata;
1449
1450 assert(scip != NULL);
1451 assert(propdata != NULL);
1452 assert(var != NULL);
1453 assert(startindex >= 0);
1454 assert(startcomponent >= 0);
1455
1456 /* get eventdata entry */
1457 SCIP_CALL( getEventData(scip, propdata, var, boundtype, &eventdata) );
1458 assert(eventdata != NULL);
1459
1460 if( eventdata->nstarts > 0 && eventdata->startcomponents[eventdata->nstarts - 1] == startcomponent )
1461 {
1462 /* if there is already a starting index for startcomponent stored at the last entry of eventdata->startindices,
1463 * it should be smaller; this relies on the implementation of setUpEvents(), calling addEventData() in
1464 * topological order
1465 */
1466 assert(eventdata->startindices[eventdata->nstarts - 1] < startindex);
1467 }
1468 else
1469 {
1470 /* append starting information */
1471 eventdata->startcomponents[eventdata->nstarts] = startcomponent;
1472 eventdata->startindices[eventdata->nstarts] = startindex;
1473
1474 /* increase counter */
1475 eventdata->nstarts++;
1476 }
1477
1478 return SCIP_OKAY;
1479}
1480
1481static
1483 SCIP* scip, /**< SCIP data structure */
1484 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1485 )
1486{
1487 int nprobvars;
1488 int i;
1489
1490 assert(scip != NULL);
1491 assert(propdata != NULL);
1492 assert(propdata->eventhdlr != NULL);
1493 assert(propdata->lbevents == NULL);
1494 assert(propdata->ubevents == NULL);
1495 assert(propdata->issorted);
1496 assert(propdata->nlbevents == -1);
1497 assert(propdata->nubevents == -1);
1498
1499 SCIPdebugMsg(scip, "set up events\n");
1500
1501 /* allocate lbevents, ubevents, and their hashmaps */
1502 nprobvars = SCIPgetNVars(scip) + SCIPgetNFixedVars(scip);
1503 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->lbevents), nprobvars) );
1504 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->ubevents), nprobvars) );
1505 SCIP_CALL( SCIPhashmapCreate(&(propdata->lbeventsmap), SCIPblkmem(scip), nprobvars) );
1506 SCIP_CALL( SCIPhashmapCreate(&(propdata->ubeventsmap), SCIPblkmem(scip), nprobvars) );
1507 propdata->nlbevents = 0;
1508 propdata->nubevents = 0;
1509
1510 /* loop over all components of genvboundstore */
1511 for( i = 0; i < propdata->ncomponents; i++ )
1512 {
1513 int j;
1514
1515 /* loop over all genvbounds in this component */
1516 for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ ) /*lint !e679*/
1517 {
1518 GENVBOUND* genvbound;
1519 int k;
1520
1521 assert(j < propdata->ngenvbounds);
1522
1523 genvbound = propdata->genvboundstore[j];
1524 assert(genvbound != NULL);
1525
1526 /* loop over all coefficients in this genvbound */
1527 for( k = 0; k < genvbound->ncoefs; k++ )
1528 {
1529 if( SCIPisPositive(scip, genvbound->coefs[k]) )
1530 {
1531 SCIP_CALL( addEventData(scip, propdata, genvbound->vars[k], j, i, SCIP_BOUNDTYPE_LOWER) );
1532 }
1533 else
1534 {
1535 SCIP_CALL( addEventData(scip, propdata, genvbound->vars[k], j, i, SCIP_BOUNDTYPE_UPPER) );
1536 }
1537 }
1538 }
1539 }
1540
1541 /* resize lbevents and ubevents array */
1542 assert(propdata->nlbevents <= nprobvars);
1543 assert(propdata->nubevents <= nprobvars);
1544 if( propdata->nlbevents < nprobvars )
1545 {
1546 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->lbevents), nprobvars, propdata->nlbevents) );
1547 }
1548 if( propdata->nubevents < nprobvars )
1549 {
1550 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->ubevents), nprobvars, propdata->nubevents) );
1551 }
1552
1553 /* resize and register lower bound events */
1554 for( i = 0; i < propdata->nlbevents; i++ )
1555 {
1556 SCIP_EVENTDATA* eventdata = propdata->lbevents[i];
1557
1558 assert(eventdata != NULL);
1559 assert(eventdata->nstarts > 0);
1560 assert(eventdata->startcomponents != NULL);
1561 assert(eventdata->startindices != NULL);
1562
1563 /* resize arrays stored in eventdata */
1564 if( eventdata->startindicessize != eventdata->nstarts )
1565 {
1566 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startcomponents), eventdata->startindicessize, \
1567 eventdata->nstarts) );
1568 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startindices), eventdata->startindicessize, \
1569 eventdata->nstarts) );
1570 eventdata->startindicessize = eventdata->nstarts;
1571 }
1572
1573 /* register event */
1574 SCIP_CALL( SCIPcatchVarEvent(scip, eventdata->var, SCIP_EVENTTYPE_LBTIGHTENED, propdata->eventhdlr, eventdata, \
1575 NULL) );
1576 }
1577
1578 /* resize and register upper bound events */
1579 for( i = 0; i < propdata->nubevents; i++ )
1580 {
1581 SCIP_EVENTDATA* eventdata = propdata->ubevents[i];
1582
1583 assert(eventdata != NULL);
1584 assert(eventdata->nstarts > 0);
1585 assert(eventdata->startcomponents != NULL);
1586 assert(eventdata->startindices != NULL);
1587
1588 /* resize arrays stored in eventdata */
1589 if( eventdata->startindicessize != eventdata->nstarts )
1590 {
1591 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startcomponents), eventdata->startindicessize, \
1592 eventdata->nstarts) );
1593 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(eventdata->startindices), eventdata->startindicessize, \
1594 eventdata->nstarts) );
1595 eventdata->startindicessize = eventdata->nstarts;
1596 }
1597 /* register event */
1598 SCIP_CALL( SCIPcatchVarEvent(scip, eventdata->var, SCIP_EVENTTYPE_UBTIGHTENED, propdata->eventhdlr, eventdata,
1599 NULL) );
1600 }
1601
1602 return SCIP_OKAY;
1603}
1604
1605/** performs a topological sort on genvboundstore array
1606 *
1607 * The genvbounds graph is defined as follows: Given two genvbounds
1608 *
1609 * (genvbound1) c1 * x_i1 >= RHS1
1610 *
1611 * and
1612 *
1613 * (genvbound2) c2 * x_i2 >= RHS2,
1614 *
1615 * there is an arc from genvbound1 to genvbound2 iff c1 = +1 and x_i1 appears with positive coefficient in RHS2 or
1616 * c1 = -1 and x_i1 appears with negative coefficient in RHS2; in this case, a bound change of x_i1 deduced from
1617 * genvbound1 improves genvbound2's minactivity in RHS2.
1618 *
1619 * The method computes the strongly connected components and sorts them topologically. The order of the nodes in an
1620 * strongly connected component is arbitrary.
1621 */
1622static
1624 SCIP* scip, /**< SCIP data structure */
1625 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1626 )
1627{
1628 GENVBOUND** genvboundssorted; /* array to store the sorted genvbounds */
1629 SCIP_DIGRAPH* graph;
1630 int* strongcomponents;
1631 int* strongcompstartidx;
1632 int sortedindex;
1633 int i;
1634
1635 assert(scip != NULL);
1636 assert(propdata != NULL);
1637 assert(propdata->componentsstart == NULL);
1638
1639 SCIPdebugMsg(scip, "(re-)sort genvbounds topologically\n");
1640
1641 /* create digraph */
1642 SCIP_CALL( SCIPcreateDigraph(scip, &graph, propdata->ngenvbounds) );
1643
1644 /* add outgoing arcs for each genvbound */
1645 for( i = 0; i < propdata->ngenvbounds; i++ )
1646 {
1647 GENVBOUND* genvbound;
1648 int j;
1649
1650 assert(i < propdata->ngenvbounds);
1651
1652 genvbound = propdata->genvboundstore[i];
1653
1654 for( j = 0; j < genvbound->ncoefs; j++ )
1655 {
1656 if( SCIPisPositive(scip, genvbound->coefs[j]) &&
1657 SCIPhashmapExists(propdata->lbgenvbounds, genvbound->vars[j]) )
1658 {
1659 int from = ((GENVBOUND*) SCIPhashmapGetImage(propdata->lbgenvbounds, genvbound->vars[j]))->index;
1660 SCIP_CALL( SCIPdigraphAddArc(graph, from, i, NULL) );
1661 }
1662 else if( SCIPisNegative(scip, genvbound->coefs[j]) &&
1663 SCIPhashmapExists(propdata->ubgenvbounds, genvbound->vars[j]) )
1664 {
1665 int from = ((GENVBOUND*) SCIPhashmapGetImage(propdata->ubgenvbounds, genvbound->vars[j]))->index;
1666 SCIP_CALL( SCIPdigraphAddArc(graph, from, i, NULL) );
1667 }
1668 }
1669 }
1670
1671 /* perform the topological sort */
1672 SCIP_CALL( SCIPdigraphComputeUndirectedComponents(graph, 1, NULL, &(propdata->ncomponents)) );
1674 assert(SCIPdigraphGetNComponents(graph) == propdata->ncomponents);
1675
1676 /* allocate memory for genvboundssorted and componentsstart array */
1677 SCIP_CALL( SCIPallocBufferArray(scip, &genvboundssorted, propdata->ngenvbounds) );
1678 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->componentsstart), propdata->ncomponents + 1) );
1679 propdata->componentsstartsize = propdata->ncomponents + 1;
1680
1681 /* allocate memory for strong component arrays */
1682 SCIP_CALL( SCIPallocBufferArray(scip, &strongcomponents, SCIPdigraphGetNNodes(graph)) ); /*lint !e666*/
1683 SCIP_CALL( SCIPallocBufferArray(scip, &strongcompstartidx, SCIPdigraphGetNNodes(graph) + 1) ); /*lint !e666*/
1684
1685 /* compute sorted genvbounds array, fill componentsstart array */
1686 sortedindex = 0;
1687 propdata->componentsstart[propdata->ncomponents] = propdata->ngenvbounds;
1688 for( i = 0; i < propdata->ncomponents; i++ )
1689 {
1690 int j;
1691 int *nodes;
1692 int nnodes;
1693 int nstrongcomponents;
1694
1695 SCIPdigraphGetComponent(graph, i, &nodes, &nnodes);
1696 propdata->componentsstart[i] = sortedindex;
1697
1698 /* compute the strong components of the i-th undirected component */
1699 if( nnodes > 2 )
1700 {
1701 SCIP_CALL( SCIPdigraphComputeDirectedComponents(graph, i, strongcomponents, strongcompstartidx,
1702 &nstrongcomponents) );
1703
1704 for( j = 0; j < nnodes; ++j )
1705 {
1706 int node;
1707
1708 /* take the nodes at the end of the strong components array first to respect the topological
1709 * order of the different strong components
1710 */
1711 node = strongcomponents[nnodes - j - 1];
1712
1713 assert(node < propdata->ngenvbounds);
1714 genvboundssorted[sortedindex] = propdata->genvboundstore[node];
1715 sortedindex++;
1716 }
1717 }
1718 else
1719 {
1720 for( j = 0; j < nnodes; j++ )
1721 {
1722 assert(nodes[j] < propdata->ngenvbounds);
1723 genvboundssorted[sortedindex] = propdata->genvboundstore[nodes[j]];
1724 sortedindex++;
1725 }
1726 }
1727 }
1728 assert(sortedindex == propdata->ngenvbounds);
1729
1730 /* copy sorted genvbounds into genvboundstore */
1731 for( i = 0; i < propdata->ngenvbounds; i++ )
1732 {
1733 assert(genvboundssorted[i] != NULL);
1734
1735 propdata->genvboundstore[i] = genvboundssorted[i];
1736 propdata->genvboundstore[i]->index = i;
1737 }
1738
1739 /* free strong component arrays */
1740 SCIPfreeBufferArray(scip, &strongcompstartidx);
1741 SCIPfreeBufferArray(scip, &strongcomponents);
1742
1743 SCIPfreeBufferArray(scip, &(genvboundssorted));
1744
1745 /* free digraph */
1746 SCIPdigraphFree(&graph);
1747
1748 /* remember genvboundstore as sorted */
1749 propdata->issorted = TRUE;
1750
1751#ifdef SCIP_DEBUG
1752 SCIPdebugMsg(scip, "genvbounds got: %d\n", propdata->ngenvbounds);
1753 for( i = 0; i < propdata->ncomponents; i++ )
1754 {
1755 int j;
1756
1757 SCIPdebugMsg(scip, "{\n");
1758
1759 for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ )
1760 {
1761 SCIPdebugMsg(scip, " [%d] ", j);
1762 printGenVBound(scip, propdata->genvboundstore[j]);
1763 }
1764
1765 SCIPdebugMsg(scip, "}\n");
1766 }
1767#endif
1768
1769 return SCIP_OKAY;
1770}
1771
1772/** apply propagation of generalized variable bounds */
1773static
1775 SCIP* scip, /**< SCIP data structure */
1776 SCIP_PROP* prop, /**< genvbounds propagator */
1777 SCIP_Bool global, /**< use global variable bounds for propagation? */
1778 SCIP_RESULT* result, /**< result pointer */
1779 int* nchgbds /**< counter to increase by the number of changed bounds */
1780 )
1781{
1782 SCIP_PROPDATA* propdata;
1783 int* startingcomponents;
1784 int* startingindices;
1785 int nindices;
1786 int i;
1787
1788 SCIPdebugMsg(scip, "applying %s genvbound propagation in depth %d\n", global ?
1789 "global" : "local", SCIPgetDepth(scip));
1790
1791 assert(scip != NULL);
1792 assert(prop != NULL);
1793 assert(result != NULL);
1794
1795 propdata = SCIPpropGetData(prop);
1796 assert(propdata != NULL);
1797 assert(propdata->genvboundstore != NULL);
1798
1799 if( *result == SCIP_DIDNOTRUN )
1800 *result = SCIP_DIDNOTFIND;
1801
1802 /* if the genvbounds are not sorted, i.e. if root node processing has not been finished, yet, we just propagate in
1803 * the order in which they have been added to genvboundstore
1804 */
1805 if( !propdata->issorted )
1806 {
1807 int j;
1808
1809 assert(!propdata->sort || SCIPinProbing(scip) || SCIPgetDepth(scip) == 0);
1810
1811 for( j = 0; j < propdata->ngenvbounds && *result != SCIP_CUTOFF; j++ )
1812 {
1813 if( ! SCIPvarIsActive(propdata->genvboundstore[j]->var) )
1814 {
1815 /**@todo resolve multiaggregation in exitpre */
1816 }
1817 else
1818 {
1819 SCIPdebugMsg(scip, "applying genvbound with index %d (unsorted mode)\n", j);
1820 SCIP_CALL( applyGenVBound(scip, prop, propdata->genvboundstore[j], global, result, nchgbds) );
1821 }
1822 }
1823
1824 return SCIP_OKAY;
1825 }
1826
1827 /* otherwise, we propagate only components affected by the latest bound changes */
1828 startingcomponents = global ? propdata->gstartcomponents : propdata->startcomponents;
1829 startingindices = global ? propdata->gstartindices : propdata->startindices;
1830 nindices = global ? propdata->ngindices : propdata->nindices;
1831
1832 for( i = 0; i < nindices && *result != SCIP_CUTOFF; i++ )
1833 {
1834 int j;
1835
1836 SCIPdebugMsg(scip, "starting in component %d at index %d\n", startingcomponents[i], startingindices[i]);
1837 for( j = startingindices[i]; j < propdata->componentsstart[startingcomponents[i] + 1] &&
1838 *result != SCIP_CUTOFF; j++ ) /*lint !e679*/
1839 {
1840 assert(j < propdata->ngenvbounds);
1841
1842 if( ! SCIPvarIsActive(propdata->genvboundstore[j]->var) )
1843 {
1844 /**@todo resolve multiaggregation in exitpre */
1845 }
1846 else
1847 {
1848 SCIPdebugMsg(scip, "applying genvbound with index %d, component %d\n", j, startingcomponents[i]);
1849 SCIP_CALL( applyGenVBound(scip, prop, propdata->genvboundstore[j], global, result, nchgbds) );
1850 }
1851 }
1852 }
1853
1854 /* we dont want to run again caused by this starting data */
1855 if( !global )
1856 {
1858 }
1859
1860 return SCIP_OKAY;
1861}
1862
1863/** initialize propagator data */
1864static
1866 SCIP* scip, /**< SCIP data structure */
1867 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1868 )
1869{
1870 int nprobvars;
1871
1872 assert(scip != NULL);
1873 assert(propdata != NULL);
1874 assert(propdata->eventhdlr != NULL);
1875 assert(propdata->ngenvbounds == -1);
1876
1877 SCIPdebugMsg(scip, "init propdata\n");
1878
1879 nprobvars = SCIPgetNVars(scip);
1880
1881 /* init genvboundstore */
1882 propdata->genvboundstoresize = 2 * nprobvars;
1883 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(propdata->genvboundstore), propdata->genvboundstoresize) );
1884 BMSclearMemoryArray(propdata->genvboundstore, propdata->genvboundstoresize);
1885 propdata->ngenvbounds = 0;
1886
1887 /* init genvboundstore hashmaps */
1888 SCIP_CALL( SCIPhashmapCreate(&(propdata->lbgenvbounds), SCIPblkmem(scip), nprobvars) );
1889 SCIP_CALL( SCIPhashmapCreate(&(propdata->ubgenvbounds), SCIPblkmem(scip), nprobvars) );
1890
1891 return SCIP_OKAY;
1892}
1893
1894/** adds a new genvbound to genvboundstore array and sets a hashmap entry */
1895static
1897 SCIP* scip, /**< SCIP data structure */
1898 SCIP_PROP* prop, /**< genvbounds propagator */
1899 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1900 GENVBOUND* genvbound /**< genvbound to be added */
1901 )
1902{
1903 SCIP_HASHMAP* hashmap;
1904
1905 assert(scip != NULL);
1906 assert(propdata != NULL);
1907 assert(genvbound != NULL);
1908 assert(getGenVBound(scip, propdata, genvbound->var, genvbound->boundtype) == NULL);
1909
1910 hashmap = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
1911
1912 /* e.g., during presolving after a restart, new variables might have been created; in this case, we need to extend
1913 * the genvboundstore; the new size may even exceed 2*SCIPgetNVars() if we have genvbounds with nonactive left-hand
1914 * side variables
1915 */
1916 assert(propdata->ngenvbounds <= propdata->genvboundstoresize);
1917 if( propdata->ngenvbounds == propdata->genvboundstoresize )
1918 {
1919 int oldsize = propdata->genvboundstoresize;
1920 propdata->genvboundstoresize = 2*propdata->genvboundstoresize + 1;
1921 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(propdata->genvboundstore), oldsize, propdata->genvboundstoresize) );
1922 }
1923
1924 /* enable genvbounds propagator */
1925 if( propdata->ngenvbounds == 0 )
1926 SCIPpropSetTimingmask(prop, propdata->inittiming);
1927
1928 /* new index is propdata->ngenvbounds */
1929 SCIP_CALL( SCIPhashmapInsert(hashmap, genvbound->var, genvbound) );
1930 propdata->genvboundstore[propdata->ngenvbounds] = genvbound;
1931 genvbound->index = propdata->ngenvbounds;
1932 propdata->ngenvbounds++;
1933
1934 assert(propdata->ngenvbounds <= propdata->genvboundstoresize);
1935
1936 return SCIP_OKAY;
1937}
1938
1939/** runs propagation routine */
1940static
1942 SCIP* scip, /**< SCIP data structure */
1943 SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1944 SCIP_RESULT* result, /**< result pointer */
1945 SCIP_Bool local, /**< should local propagation be applied? */
1946 int* nchgbds /**< counter to increase by the number of changed bounds */
1947 )
1948{
1949 assert(scip != NULL);
1950 assert(propdata != NULL);
1951 assert(propdata->prop != NULL);
1952 assert(result != NULL);
1953
1954 /* we only sort after the root node is finished; this avoids having to sort again after adding more genvbounds; if
1955 * the genvbounds are not sorted, we will simply propagate all of them in the order given
1956 */
1957 if( propdata->sort && !SCIPinProbing(scip) && SCIPgetDepth(scip) > 0 )
1958 {
1959 if( !propdata->issorted )
1960 {
1961 *result = SCIP_DIDNOTFIND;
1962
1963 SCIPdebugMsg(scip, "genvbounds are not sorted\n");
1964
1965 /* drop and free old events */
1966 SCIP_CALL( dropAndFreeEvents(scip, propdata) );
1967
1968 /* free old starting data */
1969 SCIP_CALL( freeStartingData(scip, propdata) );
1970
1971 /* free sorted components data */
1972 SCIP_CALL( freeComponentsData(scip, propdata) );
1973
1974 /* sort genvbounds */
1975 SCIP_CALL( sortGenVBounds(scip, propdata) );
1976
1977 /* create starting data */
1978 SCIP_CALL( createStartingData(scip, propdata) );
1979
1980 /* fill global starting data */
1982 }
1983
1984 /* set up new events to catch (if not done so far) */
1985 if( propdata->lbevents == NULL )
1986 {
1987 SCIP_CALL( setUpEvents(scip, propdata) );
1988 }
1989 }
1990
1991 /* apply global propagation if primal bound has improved */
1992 if( propdata->global && SCIPgetDepth(scip) > 0 && SCIPisFeasLT(scip, SCIPgetCutoffbound(scip), propdata->lastcutoff) )
1993 {
1994 if( propdata->ngindices > 0 )
1995 {
1996 SCIP_CALL( applyGenVBounds(scip, propdata->prop, TRUE, result, nchgbds) );
1997 assert(*result != SCIP_DIDNOTRUN);
1998 }
1999
2000 /* within the tree, the objective function should not change anymore, hence the cutoff bound should be a stable
2001 * point of reference
2002 */
2003 propdata->lastcutoff = SCIPgetCutoffbound(scip);
2004 }
2005
2006 /* apply local propagation if allowed */
2007 if( local && *result != SCIP_CUTOFF )
2008 {
2009 /* check if local propagation in root node is allowed */
2010 if( SCIPgetDepth(scip) > 0 || propdata->propinrootnode )
2011 {
2012 /* if genvbounds are already sorted, check if bound change events were caught; otherwise apply all genvbounds */
2013 if( !propdata->issorted
2014 || ( SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) == propdata->lastnodenumber && propdata->nindices > 0 ) )
2015 {
2016 SCIP_CALL( applyGenVBounds(scip, propdata->prop, FALSE, result, nchgbds) );
2017 assert(*result != SCIP_DIDNOTRUN);
2018 }
2019 }
2020 }
2021
2022 return SCIP_OKAY;
2023}
2024
2025/* adds all genvbounds in the genvboundstore as constraints to the problem; afterwards clears the genvboundstore */
2026static
2028 SCIP* scip, /**< SCIP data structure */
2029 SCIP_PROP* prop, /**< genvbounds propagator */
2030 SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
2031 )
2032{
2033 int i;
2034
2035 assert(scip != NULL);
2036 assert(propdata != NULL);
2037 assert(propdata->propasconss);
2038
2039 /* ensure that the cutoffboundvar is available */
2040 if( propdata->cutoffboundvar == NULL )
2041 {
2042 SCIP_Real ub;
2043 char name[16];
2044
2045 /* set the upper bound to the best primal value in the original problem */
2047
2048 SCIPdebugMsg(scip, "initialize cutoffboundvar with UB = %e\n", ub);
2049
2050 (void) SCIPsnprintf(name, 16, "cutoffboundvar");
2051 SCIP_CALL( SCIPcreateVarBasic(scip, &propdata->cutoffboundvar, name, -SCIPinfinity(scip), ub, 0.0, SCIP_VARTYPE_CONTINUOUS) );
2052 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, propdata->cutoffboundvar) );
2053
2054 SCIP_CALL( SCIPaddVar(scip, propdata->cutoffboundvar) );
2055
2056 /* lock the variable because it should not be subject to dual presolving reductions; because we create the
2057 * linear constraints as non-check constraints, the cutoffboundvar will not be locked by the linear constraint
2058 * handler
2059 */
2060 SCIP_CALL( SCIPaddVarLocksType(scip, propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL, 1, 1) );
2061 }
2062
2063 assert(propdata->cutoffboundvar != NULL);
2064
2065 /* now iterate over all genvbounds in the store and construct a linear constraint for each of them */
2066 for( i = 0; i < propdata->ngenvbounds; ++i )
2067 {
2068 GENVBOUND* genvbound;
2069 SCIP_CONS* cons;
2070 SCIP_VAR** vars;
2071 SCIP_Real* vals;
2072 char name[SCIP_MAXSTRLEN];
2073 int nvars;
2074 int j;
2075
2076 genvbound = propdata->genvboundstore[i];
2077 assert(genvbound != NULL);
2078
2079 nvars = genvbound->ncoefs + 2;
2080 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
2081 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
2082
2083 SCIPdebugMsgPrint(scip, "add cons: ");
2084
2085 /* copy the coefs/vars array */
2086 for( j = 0; j < genvbound->ncoefs; j++ )
2087 {
2088 vars[j] = genvbound->vars[j];
2089 vals[j] = genvbound->coefs[j];
2090 SCIPdebugMsgPrint(scip, "%e%s + ", vals[j], SCIPvarGetName(vars[j]));
2091 }
2092
2093 /* add the variable and the coefficient of the genvbound */
2094 vars[genvbound->ncoefs] = genvbound->var;
2095 vals[genvbound->ncoefs] = (genvbound->boundtype == SCIP_BOUNDTYPE_LOWER) ? -1.0 : 1.0;
2096
2097 SCIPdebugMsgPrint(scip, "%e%s + ", vals[genvbound->ncoefs], SCIPvarGetName(vars[genvbound->ncoefs]));
2098
2099 /* add cutoffcoef * cutoffboundvar */
2100 vars[genvbound->ncoefs + 1] = propdata->cutoffboundvar;
2101 vals[genvbound->ncoefs + 1] = genvbound->cutoffcoef;
2102
2103 SCIPdebugMsgPrint(scip, "%e%s <= %e\n", vals[genvbound->ncoefs + 1], SCIPvarGetName(vars[genvbound->ncoefs + 1]), -1.0*genvbound->constant);
2104
2105 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "genvbound_cons%d", genvbound->index);
2106
2107 /* create linear constraint with only propagate flag as TRUE */
2108 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nvars, vars, vals, -SCIPinfinity(scip), -genvbound->constant,
2110
2111 SCIP_CALL( SCIPaddCons(scip, cons) );
2112 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
2113
2114 /* free memory */
2115 SCIPfreeBufferArray(scip, &vars);
2116 SCIPfreeBufferArray(scip, &vals);
2117 }
2118
2119 /* now delete all genvbounds in the genvboundstore */
2120 if( propdata->genvboundstore != NULL )
2121 {
2122 /* disable genvbounds propagator */
2123 if( propdata->ngenvbounds >= 1 )
2125
2126 for( i = propdata->ngenvbounds - 1; i >= 0; i-- )
2127 {
2128 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
2129 }
2130
2131 /* free genvboundstore hashmaps */
2132 SCIPhashmapFree(&(propdata->lbgenvbounds));
2133 SCIPhashmapFree(&(propdata->ubgenvbounds));
2134
2135 /* drop and free all events */
2136 SCIP_CALL( dropAndFreeEvents(scip, propdata) );
2137
2138 /* free componentsstart array */
2139 SCIP_CALL( freeComponentsData(scip, propdata) );
2140
2141 /* free starting indices data */
2142 SCIP_CALL( freeStartingData(scip, propdata) );
2143
2144 SCIPfreeBlockMemoryArray(scip, &(propdata->genvboundstore), propdata->genvboundstoresize);
2145 propdata->genvboundstore = NULL;
2146 propdata->genvboundstoresize = 0;
2147 propdata->ngenvbounds = 0;
2148 }
2149
2150 return SCIP_OKAY;
2151}
2152
2153
2154
2155/*
2156 * Public methods
2157 */
2158
2159/** adds a generalized variable bound to the genvbounds propagator; if there is already a genvbound for the bound
2160 * "boundtype" of variable "var", it will be replaced
2161 */
2163 SCIP* scip, /**< SCIP data structure */
2164 SCIP_PROP* genvboundprop, /**< genvbound propagator */
2165 SCIP_VAR** vars, /**< array of RHSs variables */
2166 SCIP_VAR* var, /**< LHSs variable */
2167 SCIP_Real* coefs, /**< array of coefficients for the RHSs variables */
2168 int ncoefs, /**< size of coefs array */
2169 SCIP_Real coefcutoffbound, /**< nonpositive value of the cutoff bounds multiplier */
2170 SCIP_Real constant, /**< constant term */
2171 SCIP_BOUNDTYPE boundtype /**< type of bound provided by the genvbound */
2172 )
2173{
2174 /**@todo in debug mode: check if genvbound is nontrivial */
2175
2176 SCIP_PROPDATA* propdata;
2177 GENVBOUND* genvbound;
2178 SCIP_Bool newgenvbound;
2179 int i;
2180
2181 assert(scip != NULL);
2182 assert(genvboundprop != NULL);
2183 assert(strcmp(SCIPpropGetName(genvboundprop), PROP_NAME) == 0);
2184 assert(vars != NULL);
2185 assert(var != NULL);
2186 assert(coefs != NULL);
2187 assert(ncoefs >= 0);
2188 assert(coefcutoffbound <= 0.0);
2189 assert(!SCIPisInfinity(scip, -constant));
2190
2191 if( ncoefs < 0 || coefcutoffbound > 0.0 || SCIPisInfinity(scip, -constant) )
2192 {
2193 SCIPerrorMessage("cannot create generalized variable bound from invalid data\n");
2194 return SCIP_INVALIDDATA;
2195 }
2196
2197 propdata = SCIPpropGetData(genvboundprop);
2198 assert(propdata != NULL);
2199
2200 /* initialize propdata if not done yet */
2201 if( propdata->genvboundstore == NULL )
2202 {
2203 SCIP_CALL( initPropdata(scip, propdata) );
2204 }
2205
2206 genvbound = getGenVBound(scip, propdata, var, boundtype);
2207 newgenvbound = (genvbound == NULL);
2208
2209 /* release previous variables */
2210 if( !newgenvbound )
2211 {
2212 for( i = 0; i < genvbound->ncoefs; ++i )
2213 {
2214 assert(genvbound->vars[i] != NULL);
2215 SCIP_CALL( SCIPreleaseVar(scip, &(genvbound->vars[i])) );
2216 }
2217 }
2218
2219 /* check if there already is a genvbound corresponding to this bound, freeing its data and overwriting it */
2220 if( !newgenvbound && genvbound->ncoefs < ncoefs )
2221 {
2222 /* do not realloc since we do not want to keep and possibly copy the old entries */
2223 SCIPfreeBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize);
2224 SCIPfreeBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize);
2225
2226 /* allocate and copy arrays in genvbound */
2227 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
2228 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
2229 genvbound->coefssize = ncoefs;
2230 }
2231 else if( !newgenvbound && genvbound->ncoefs == ncoefs )
2232 {
2233 /* just update entries */
2234 for( i = 0; i < ncoefs; i++ )
2235 {
2236 genvbound->coefs[i] = coefs[i];
2237 genvbound->vars[i] = vars[i];
2238 }
2239 }
2240 else if( !newgenvbound && genvbound->ncoefs > ncoefs )
2241 {
2242 /* reallocate memory for arrays in genvbound to free unused memory */
2243 if( genvbound->coefssize < ncoefs )
2244 {
2245 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize, ncoefs) );
2246 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize, ncoefs) );
2247 genvbound->coefssize = ncoefs;
2248 }
2249
2250 /* update entries */
2251 for( i = 0; i < ncoefs; i++ )
2252 {
2253 genvbound->coefs[i] = coefs[i];
2254 genvbound->vars[i] = vars[i];
2255 }
2256 }
2257 else if( newgenvbound )
2258 {
2259 /* allocate memory for genvbound data */
2260 SCIP_CALL( SCIPallocBlockMemory(scip, &genvbound) );
2261
2262 /* allocate and copy arrays in genvbound */
2263 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
2264 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
2265 genvbound->coefssize = ncoefs;
2266 }
2267
2268 /* set up data for genvbound */
2269 genvbound->boundtype = boundtype;
2270 genvbound->var = var;
2271 genvbound->ncoefs = ncoefs;
2272 genvbound->constant = constant;
2273 genvbound->relaxonly = SCIPvarIsRelaxationOnly(genvbound->var);
2274
2275 /* capture variables and check for relax-only vars */
2276 for( i = 0; i < genvbound->ncoefs; ++i )
2277 {
2278 assert(genvbound->vars[i] != NULL);
2279 SCIP_CALL( SCIPcaptureVar(scip, genvbound->vars[i]) );
2280 if( SCIPvarIsRelaxationOnly(genvbound->vars[i]) )
2281 genvbound->relaxonly = TRUE;
2282 }
2283 if( newgenvbound )
2284 {
2285 assert(genvbound->var != NULL);
2286 SCIP_CALL( SCIPcaptureVar(scip, genvbound->var) );
2287 }
2288
2289 /* the cutoff bound is valid w.r.t. the current objective function in the transformed problem; during presolving,
2290 * however, the objective function can change (e.g., when a variable is fixed, its contribution in the objective
2291 * is subtracted from the cutoff bound and added to the objective offset); we solve this by transforming the
2292 * contribution of the cutoff bound in the generalized variable bound to the original problem as follows:
2293 *
2294 * +/- var >= ... + z * SCIPgetCutoffbound() + constant
2295 *
2296 * becomes
2297 *
2298 * +/- var >= ... + (z / SCIPgetTransObjscale()) * origcutoffbound + (constant - z * SCIPgetTransObjoffset())
2299 *
2300 * with SCIPgetCutoffbound() = origcutoffbound / SCIPgetTransObjscale() - SCIPgetTransObjoffset(); in the
2301 * propagation later, we will use (SCIPgetCutoffbound() + SCIPgetTransObjoffset()) * SCIPgetTransObjscale(), see
2302 * function getCutoffboundGenVBound()
2303 */
2304 if( SCIPisNegative(scip, coefcutoffbound) )
2305 {
2307 genvbound->cutoffcoef = coefcutoffbound / SCIPgetTransObjscale(scip);
2308 genvbound->constant -= (coefcutoffbound * SCIPgetTransObjoffset(scip));
2309 }
2310 else
2311 genvbound->cutoffcoef = 0.0;
2312
2313 /* if genvbound is not overwritten, create a new entry in genvboundstore */
2314 if( newgenvbound )
2315 {
2316 SCIP_CALL( addNewGenVBound(scip, genvboundprop, propdata, genvbound) );
2317 }
2318
2319 /* mark genvbounds array to be re-sorted */
2320 propdata->issorted = FALSE;
2321
2322 /* debug message */
2323 SCIPdebugMsg(scip, "added genvbound ");
2324 SCIPdebug( printGenVBound(scip, genvbound) );
2325#ifdef WITH_DEBUG_SOLUTION
2326 SCIP_CALL( checkDebugSolutionGenVBound(scip, genvbound) );
2327#endif
2328
2329 return SCIP_OKAY;
2330}
2331
2332
2333/*
2334 * Callback methods of propagator
2335 */
2336
2337/** copy method for propagator plugins (called when SCIP copies plugins)
2338 *
2339 * @note The UG framework assumes that all default plug-ins of SCIP implement a copy callback.
2340 */
2341static
2342SCIP_DECL_PROPCOPY(propCopyGenvbounds)
2343{ /*lint --e{715}*/
2344 assert(scip != NULL);
2345 assert(prop != NULL);
2346 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2347
2348 /* call inclusion method of constraint handler */
2350
2351 return SCIP_OKAY;
2352}
2353
2354/** initialization method of propagator (called after problem was transformed) */
2355static
2356SCIP_DECL_PROPINIT(propInitGenvbounds)
2357{ /*lint --e{715}*/
2358 SCIP_PROPDATA* propdata;
2359
2360 assert(scip != NULL);
2361 assert(prop != NULL);
2362 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2363
2364 /* get propagator data */
2365 propdata = SCIPpropGetData(prop);
2366 assert(propdata != NULL);
2367
2368 propdata->genvboundstore = NULL;
2369 propdata->genvboundstoresize = 0;
2370 propdata->lbevents = NULL;
2371 propdata->ubevents = NULL;
2372 propdata->lbgenvbounds = NULL;
2373 propdata->ubgenvbounds = NULL;
2374 propdata->lbeventsmap = NULL;
2375 propdata->ubeventsmap = NULL;
2376 propdata->startmap = NULL;
2377 propdata->componentsstart = NULL;
2378 propdata->startindices = NULL;
2379 propdata->startcomponents = NULL;
2380 propdata->gstartindices = NULL;
2381 propdata->gstartcomponents = NULL;
2382 propdata->lastcutoff = SCIPinfinity(scip);
2383 propdata->lastnodenumber = -1;
2384 propdata->cutoffboundvar = NULL;
2385 propdata->ngenvbounds = -1;
2386 propdata->ncomponents = -1;
2387 propdata->nindices = -1;
2388 propdata->ngindices = -1;
2389 propdata->nlbevents = -1;
2390 propdata->nubevents = -1;
2391 propdata->issorted = FALSE;
2392
2393 propdata->prop = prop;
2394
2395 /* store genvbounds timing */
2396 propdata->inittiming = SCIPpropGetTimingmask(prop);
2397
2398 /* disable genvbounds propagator, enabled when genvbounds are added */
2400
2401 return SCIP_OKAY;
2402}
2403
2404
2405/** presolving method of propagator */
2406static
2407SCIP_DECL_PROPPRESOL(propPresolGenvbounds)
2408{ /*lint --e{715}*/
2409 SCIP_PROPDATA* propdata;
2410
2411 assert(scip != NULL);
2412 assert(prop != NULL);
2413 assert(result != NULL);
2414 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2415
2416 *result = SCIP_DIDNOTRUN;
2417
2418 /* get propagator data */
2419 propdata = SCIPpropGetData(prop);
2420 assert(propdata != NULL);
2421
2422 /* do not run if no genvbounds were added yet */
2423 if( propdata->ngenvbounds < 1 )
2424 return SCIP_OKAY;
2425
2427 return SCIP_OKAY;
2428
2429 SCIPdebugMsg(scip, "proppresol in problem <%s>\n", SCIPgetProbName(scip));
2430
2431 /* propagate */
2432 SCIP_CALL( execGenVBounds(scip, propdata, result, TRUE, nchgbds) );
2433
2434 return SCIP_OKAY;
2435}
2436
2437
2438/** presolving initialization method of propagator (called when presolving is about to begin) */
2439static
2440SCIP_DECL_PROPINITPRE(propInitpreGenvbounds)
2441{ /*lint --e{715}*/
2442 SCIP_PROPDATA* propdata;
2443
2444 assert(scip != NULL);
2445 assert(prop != NULL);
2446 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2447
2448 /* get propagator data */
2449 propdata = SCIPpropGetData(prop);
2450 assert(propdata != NULL);
2451
2452 /* lock the variable because it should not be deleted after a restart */
2453 if( propdata->cutoffboundvar != NULL )
2454 {
2455 SCIPdebugMsg(scip, "propinitpre in problem <%s>: locking cutoffboundvar (current downlocks=%d, uplocks=%d)\n",
2457 SCIPvarGetNLocksUpType(propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL));
2458
2459 SCIP_CALL( SCIPaddVarLocksType(scip, propdata->cutoffboundvar, SCIP_LOCKTYPE_MODEL, 1, 1) );
2460 }
2461
2462 return SCIP_OKAY;
2463}
2464
2465
2466/** presolving deinitialization method of propagator (called after presolving has been finished) */
2467static
2468SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds)
2469{ /*lint --e{715}*/
2470 SCIP_VAR** vars;
2471 SCIP_PROPDATA* propdata;
2472 int i;
2473
2474 assert(scip != NULL);
2475 assert(prop != NULL);
2476 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2477
2478 SCIPdebugMsg(scip, "propexitpre in problem <%s>: removing fixed, aggregated, negated, and multi-aggregated variables from right-hand side\n",
2480
2481 /* get propagator data */
2482 propdata = SCIPpropGetData(prop);
2483 assert(propdata != NULL);
2484
2485 /* there should be no events on the right-hand side variables */
2486 assert(propdata->lbevents == NULL);
2487 assert(propdata->ubevents == NULL);
2488
2489 /* allocate memory to store new variables */
2491
2492 for( i = 0; i < propdata->ngenvbounds; )
2493 {
2494 GENVBOUND* genvbound;
2495 int requiredsize;
2496 int nvars;
2497 int j;
2498
2499 genvbound = propdata->genvboundstore[i];
2500 assert(genvbound != NULL);
2501
2502 /* store variables of the genvbound to release them properly */
2503 assert(genvbound->ncoefs <= SCIPgetNTotalVars(scip));
2504 BMScopyMemoryArray(vars, genvbound->vars, genvbound->ncoefs);
2505 nvars = genvbound->ncoefs;
2506
2507 /* replace non-active by active variables and update constant; note that this may result in coefficients where
2508 * SCIPisZero() is true; this should not create any problems
2509 */
2510 SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, genvbound->ncoefs, &genvbound->constant, &requiredsize) );
2511
2512 /* if space was not enough we need to resize the buffers */
2513 if( requiredsize > genvbound->ncoefs )
2514 {
2515 /* reallocate memory for arrays in genvbound to free unused memory */
2516 if( genvbound->coefssize < requiredsize )
2517 {
2518 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->coefs), genvbound->coefssize, requiredsize) );
2519 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(genvbound->vars), genvbound->coefssize, requiredsize) );
2520 genvbound->coefssize = requiredsize;
2521 }
2522
2523 SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, requiredsize, &genvbound->constant, &requiredsize) );
2524 assert(requiredsize <= genvbound->coefssize);
2525 }
2526 assert(requiredsize == genvbound->ncoefs);
2527
2528 /* capture new and release old variables */
2529 for( j = 0; j < genvbound->ncoefs; ++j )
2530 {
2531 assert(genvbound->vars[j] != NULL);
2532 SCIP_CALL( SCIPcaptureVar(scip, genvbound->vars[j]) );
2533 }
2534 for( j = 0; j < nvars; ++j )
2535 {
2536 assert(vars[j] != NULL);
2537 SCIP_CALL( SCIPreleaseVar(scip, &vars[j]) );
2538 }
2539
2540 /* if the resulting genvbound is trivial, remove it */
2541 /* we remove all genvbounds with an aggregated or multi-aggregated genvbound->var; tightening aggregated variables
2542 * might lead to some asserts in tree.c if the active variable has been already tightened (see !398);
2543 *
2544 * @todo replace aggregated variable by their active part
2545 */
2546 if( (genvbound->ncoefs == 0 && SCIPisZero(scip, genvbound->cutoffcoef))
2549 {
2550 SCIP_HASHMAP* hashmap;
2551
2552 hashmap = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
2553
2554 /* remove genvbound from hashmap */
2555 assert(SCIPhashmapExists(hashmap, genvbound->var));
2556 SCIP_CALL( SCIPhashmapRemove(hashmap, genvbound->var) );
2557
2558 /* free genvbound and fill gap */
2559 SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
2560 --(propdata->ngenvbounds);
2561
2562 /* move the last genvbound to the i-th position */
2563 if( i < propdata->ngenvbounds )
2564 {
2565 propdata->genvboundstore[i] = propdata->genvboundstore[propdata->ngenvbounds];
2566 propdata->genvboundstore[i]->index = i;
2567
2568 /* mark genvbounds array to be re-sorted */
2569 propdata->issorted = FALSE;
2570 }
2571 }
2572 else
2573 ++i;
2574 }
2575
2576 SCIPfreeBufferArray(scip, &vars);
2577
2578 /* disable genvbounds propagator */
2579 if( propdata->ngenvbounds == 0 )
2581
2582 return SCIP_OKAY;
2583}
2584
2585/** deinitialization method of propagator (called before transformed problem is freed) */
2586static
2587SCIP_DECL_PROPEXIT(propExitGenvbounds)
2588{
2589 SCIP_PROPDATA* propdata;
2590
2591 assert(scip != NULL);
2592 assert(prop != NULL);
2593 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2594
2595 /* get propagator data */
2596 propdata = SCIPpropGetData(prop);
2597 assert(propdata != NULL);
2598
2599 /* free remaining genvbounds */
2600 SCIP_CALL( freeGenVBounds(scip, prop, propdata) );
2601
2602 /* reset genvbounds timing */
2603 SCIPpropSetTimingmask(prop, propdata->inittiming);
2604
2605 return SCIP_OKAY;
2606}
2607
2608/** execution method of propagator */
2609static
2610SCIP_DECL_PROPEXEC(propExecGenvbounds)
2611{ /*lint --e{715}*/
2612 SCIP_PROPDATA* propdata;
2613
2614 assert(scip != NULL);
2615 assert(prop != NULL);
2616 assert(result != NULL);
2617 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2618
2619 *result = SCIP_DIDNOTRUN;
2620
2621 /* get propagator data */
2622 propdata = SCIPpropGetData(prop);
2623 assert(propdata != NULL);
2624 assert(propdata->ngenvbounds >= 1);
2625
2626 /* do not run if propagation w.r.t. current objective is not allowed */
2628 return SCIP_OKAY;
2629
2630 /* update upper bound of the cutoffboundvar */
2631 if( propdata->cutoffboundvar != NULL )
2632 {
2633 SCIP_Real newub;
2634 SCIP_Real oldub;
2635 SCIP_Bool infeasible;
2636 SCIP_Bool tightened;
2637
2638 assert(propdata->propasconss);
2639
2640 /* compute the primal bound in the original problem */
2642 oldub = SCIPvarGetUbLocal(propdata->cutoffboundvar);
2643
2644 if( SCIPisInfinity(scip, newub) == FALSE && SCIPisFeasLT(scip, newub, oldub) )
2645 {
2646 SCIP_CALL( SCIPtightenVarUbGlobal(scip, propdata->cutoffboundvar, newub, FALSE, &infeasible, &tightened) );
2647
2648 if( tightened )
2649 {
2650 SCIPdebugMsg(scip, "tightened UB of cutoffboundvar to %e (old: %e, infeas: %u, tightened: %u)\n",
2651 newub, oldub, infeasible, tightened);
2652 }
2653
2654 assert(infeasible == FALSE);
2655 }
2656 }
2657
2658 SCIPdebugMsg(scip, "propexec in problem <%s> at depth %d%s\n", SCIPgetProbName(scip), SCIPgetDepth(scip),
2659 SCIPinProbing(scip) ? " in probing" : "");
2660
2661 /* add the genvbounds in the genvboundstore as constraints to the problem; afterwards clear the genvboundstore */
2662 if( propdata->propasconss )
2663 {
2664 SCIP_CALL( createConstraints(scip, prop, propdata) );
2665 return SCIP_OKAY;
2666 }
2667
2668 /* propagate locally and globally */
2669 SCIP_CALL( execGenVBounds(scip, propdata, result, !SCIPinProbing(scip), NULL) );
2670
2671 /* when called in presolving stage the result is set to SCIP_SUCCESS instead of SCIP_REDUCEDDOM, this is corrected
2672 * here
2673 */
2674 if( *result == SCIP_SUCCESS )
2675 *result = SCIP_REDUCEDDOM;
2676
2677 SCIPdebugMsg(scip, "end of exec\n");
2678
2679 return SCIP_OKAY;
2680}
2681
2682/** propagation conflict resolving method of propagator */
2683static
2684SCIP_DECL_PROPRESPROP(propRespropGenvbounds)
2685{ /*lint --e{715}*/
2686 SCIP_PROPDATA* propdata;
2687 GENVBOUND* genvbound;
2688 SCIP_Real boundval;
2689 SCIP_Bool success;
2690
2691 SCIPdebugMsg(scip, "explain %s bound change of variable <%s>\n",
2692 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
2693
2694 /* get propagator data */
2695 propdata = SCIPpropGetData(prop);
2696 assert(propdata != NULL);
2697 assert(propdata->genvboundstore != NULL);
2698
2699 /* as inferinfo we passed the index of the genvbound that was used for propagation; the genvbound might have been
2700 * replaced, but also the new genvbound at this position has the same variable on the left-hand side
2701 */
2702 assert(inferinfo >= 0);
2703 assert(inferinfo < propdata->ngenvbounds);
2704
2705 *result = SCIP_DIDNOTFIND;
2706
2707 /* check also in optimized mode that inferinfo is correct */
2708 if( inferinfo >= propdata->ngenvbounds)
2709 {
2710 SCIPerrorMessage("generalized variable bounds propagator received inferinfo out of range; propagation not resolved, safe to continue\n");
2711 return SCIP_OKAY;
2712 }
2713
2714 /* get genvbound responsible for the bound change */
2715 genvbound = propdata->genvboundstore[inferinfo];
2716 assert(genvbound != NULL);
2717 assert(genvbound->var == infervar);
2718
2719 /* check also in optimized mode that inferinfo is correct */
2720 if( genvbound->var != infervar )
2721 {
2722 SCIPerrorMessage("generalized variable bounds propagator received incorrect inferinfo; propagation not resolved, but it's safe to continue\n");
2723 return SCIP_OKAY;
2724 }
2725
2726 /* get value of bound change on left-hand side */
2727 boundval = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER
2728 ? SCIPgetVarLbAtIndex(scip, genvbound->var, bdchgidx, TRUE)
2729 : -SCIPgetVarUbAtIndex(scip, genvbound->var, bdchgidx, TRUE);
2730
2731 /* if left-hand side variable is integral, it suffices to explain a bound change greater than boundval - 1 */
2732 if( SCIPvarIsIntegral(genvbound->var) )
2733 {
2734 SCIP_Real roundedboundval;
2735
2736 assert(SCIPisIntegral(scip, boundval));
2737
2738 roundedboundval = SCIPfeasCeil(scip, boundval - 1.0) + 2 * SCIPfeastol(scip);
2739 boundval = MIN(boundval, roundedboundval);
2740 }
2741
2742 /* resolve propagation */
2743 SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, bdchgidx, &boundval, &success) );
2744
2745 if( success )
2746 *result = SCIP_SUCCESS;
2747
2748 return SCIP_OKAY;
2749}
2750
2751/** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
2752static
2753SCIP_DECL_PROPEXITSOL(propExitsolGenvbounds)
2754{ /*lint --e{715}*/
2755 SCIP_PROPDATA* propdata;
2756
2757 assert(scip != NULL);
2758 assert(prop != NULL);
2759 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2760
2761 SCIPdebugMsg(scip, "propexitsol in problem <%s>\n", SCIPgetProbName(scip));
2762
2763 /* get propagator data */
2764 propdata = SCIPpropGetData(prop);
2765 assert(propdata != NULL);
2766
2767 if( !SCIPisInRestart(scip) )
2768 {
2769 /* free all genvbounds if we are not in a restart */
2770 SCIP_CALL( freeGenVBounds(scip, prop, propdata) );
2771 }
2772 else
2773 {
2774 /* free all genvbounds that use relax-only variables if we are in a restart */
2775 SCIP_CALL( freeGenVBoundsRelaxOnly(scip, prop, propdata) );
2776 }
2777
2778 /* drop and free all events */
2779 SCIP_CALL( dropAndFreeEvents(scip, propdata) );
2780
2781 return SCIP_OKAY;
2782}
2783
2784/** destructor of propagator to free user data (called when SCIP is exiting) */
2785static
2786SCIP_DECL_PROPFREE(propFreeGenvbounds)
2787{ /*lint --e{715}*/
2788 SCIP_PROPDATA* propdata;
2789
2790 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2791
2792 /* free propagator data */
2793 propdata = SCIPpropGetData(prop);
2794 assert(propdata != NULL);
2795
2796 SCIPfreeBlockMemory(scip, &propdata);
2797
2798 SCIPpropSetData(prop, NULL);
2799
2800 return SCIP_OKAY;
2801}
2802
2803
2804/*
2805 * Callback methods of event handler
2806 */
2807
2808static
2809SCIP_DECL_EVENTEXEC(eventExecGenvbounds)
2810{ /*lint --e{715}*/
2811 SCIP_PROPDATA* propdata;
2813 int i;
2814
2817 assert(eventdata != NULL);
2818 assert(eventdata->startcomponents != NULL);
2819 assert(eventdata->startindices != NULL);
2820 assert(eventdata->nstarts > 0);
2821 assert(eventdata->prop != NULL);
2822
2823 /* ignore final events */
2824 if( node == NULL )
2825 return SCIP_OKAY;
2826
2827 propdata = SCIPpropGetData(eventdata->prop);
2828 assert(propdata != NULL);
2829
2830 assert(propdata->startcomponents != NULL);
2831 assert(propdata->startmap != NULL);
2832 assert(propdata->startindices != NULL);
2833
2834 SCIPdebugMsg(scip, "catching eventdata:\n");
2835 SCIPdebug( printEventData(eventdata, SCIPeventGetType(event) == SCIP_EVENTTYPE_LBTIGHTENED ?
2837
2838 /**@todo find a way to identify when we are at a new probing node; in probing mode, the node number is always zero,
2839 * so we may miss resetting the starting data and may propagate more than necessary
2840 */
2841 /* check if we need to reset old local starting indices data */
2842 if( SCIPnodeGetNumber(node) != propdata->lastnodenumber )
2843 {
2845 propdata->lastnodenumber = SCIPnodeGetNumber(node);
2846 }
2847
2848 for( i = 0; i < eventdata->nstarts; i++ )
2849 {
2850 int component;
2851 int startidx;
2852
2853 component = eventdata->startcomponents[i];
2854 assert(component >= 0);
2855 startidx = eventdata->startindices[i];
2856
2857 /* there is already an entry for this component */
2858 if( SCIPhashmapExists(propdata->startmap, (void*)(size_t) (component + 1)) )
2859 {
2860 int componentidx;
2861
2862 /* get its index */
2863 componentidx = (SCIPhashmapGetImageInt(propdata->startmap, (void*)(size_t) (component + 1))) - 1; /*lint !e571 !e776*/
2864 assert(componentidx >= 0);
2865 assert(propdata->startcomponents[componentidx] == component);
2866
2867 if( propdata->startindices[componentidx] > startidx )
2868 propdata->startindices[componentidx] = startidx;
2869 }
2870 else
2871 {
2872 /* get a new entry */
2873 int componentidx;
2874 componentidx = propdata->nindices;
2875
2876 /* store index */
2877 propdata->startcomponents[componentidx] = component;
2878 propdata->startindices[componentidx] = startidx;
2879
2880 /* store component in hashmap */
2881 SCIP_CALL( SCIPhashmapInsertInt(propdata->startmap, (void*)(size_t) (component + 1), componentidx + 1) ); /*lint !e571 !e776*/
2882
2883 /* increase number of starting indices */
2884 propdata->nindices++;
2885 }
2886 }
2887
2888 return SCIP_OKAY;
2889}
2890
2891/*
2892 * propagator specific interface methods
2893 */
2894
2895/** creates the genvbounds propagator and includes it in SCIP */
2897 SCIP* scip /**< SCIP data structure */
2898 )
2899{
2900 SCIP_PROPDATA* propdata;
2901 SCIP_PROP* prop;
2902
2903 /* create genvbounds propagator data */
2904 SCIP_CALL( SCIPallocBlockMemory(scip, &propdata) );
2905 propdata->inittiming = PROP_TIMING;
2906
2907 /* include propagator */
2909 propExecGenvbounds, propdata) );
2910
2911 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyGenvbounds) );
2912 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeGenvbounds) );
2913 SCIP_CALL( SCIPsetPropInit(scip, prop, propInitGenvbounds) );
2914 SCIP_CALL( SCIPsetPropInitpre(scip, prop, propInitpreGenvbounds) );
2915 SCIP_CALL( SCIPsetPropExitpre(scip, prop, propExitpreGenvbounds) );
2916 SCIP_CALL( SCIPsetPropExit(scip, prop, propExitGenvbounds) );
2917 SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolGenvbounds) );
2918 SCIP_CALL( SCIPsetPropPresol(scip, prop, propPresolGenvbounds, PROP_PRESOL_PRIORITY,
2920 SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropGenvbounds) );
2921
2922 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/global",
2923 "apply global propagation?",
2924 &propdata->global, TRUE, DEFAULT_GLOBAL_PROPAGATION, NULL, NULL) );
2925
2926 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propinrootnode",
2927 "apply genvbounds in root node if no new incumbent was found?",
2928 &propdata->propinrootnode, TRUE, DEFAULT_PROPAGATE_IN_ROOT_NODE, NULL, NULL) );
2929
2930 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/sort",
2931 "sort genvbounds and wait for bound change events?",
2932 &propdata->sort, TRUE, DEFAULT_SORT, NULL, NULL) );
2933
2934 SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propasconss",
2935 "should genvbounds be transformed to (linear) constraints?",
2936 &propdata->propasconss, TRUE, DEFAULT_PROPASCONSS, NULL, NULL) );
2937
2938 /* include event handler */
2939 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &propdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecGenvbounds, NULL) );
2940
2941 return SCIP_OKAY;
2942}
static long bound
Constraint handler for linear constraints in their most general form, .
methods for debugging
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:298
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:312
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:299
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define SCIP_UNKNOWN
Definition: def.h:179
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
#define nnodes
Definition: gastrans.c:74
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
Definition: misc.c:8165
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7823
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:8374
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7739
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8295
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:8506
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:7645
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8361
SCIP_RETCODE SCIPcreateDigraph(SCIP *scip, SCIP_DIGRAPH **digraph, int nnodes)
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1907
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1242
SCIP_Real SCIPgetTransObjoffset(SCIP *scip)
Definition: scip_prob.c:1606
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3274
int SCIPgetNFixedVars(SCIP *scip)
Definition: scip_prob.c:2705
int SCIPgetNTotalVars(SCIP *scip)
Definition: scip_prob.c:3064
SCIP_Real SCIPgetTransObjscale(SCIP *scip)
Definition: scip_prob.c:1629
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3304
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3143
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3466
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3179
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3676
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3482
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPgenVBoundAdd(SCIP *scip, SCIP_PROP *genvboundprop, SCIP_VAR **vars, SCIP_VAR *var, SCIP_Real *coefs, int ncoefs, SCIP_Real coefcutoffbound, SCIP_Real constant, SCIP_BOUNDTYPE boundtype)
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
SCIP_RETCODE SCIPincludePropGenvbounds(SCIP *scip)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictRelaxedLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedlb)
SCIP_RETCODE SCIPanalyzeConflict(SCIP *scip, int validdepth, SCIP_Bool *success)
SCIP_RETCODE SCIPaddConflictRelaxedUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedub)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_Real SCIPgetConflictVarUb(SCIP *scip, SCIP_VAR *var)
SCIP_Real SCIPgetConflictVarLb(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:413
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:8483
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
Definition: prop.c:801
SCIP_RETCODE SCIPsetPropResprop(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPRESPROP((*propresprop)))
Definition: scip_prop.c:316
SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
Definition: prop.c:791
SCIP_RETCODE SCIPsetPropPresol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPPRESOL((*proppresol)), int presolpriority, int presolmaxrounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_prop.c:283
SCIP_RETCODE SCIPsetPropExitpre(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITPRE((*propexitpre)))
Definition: scip_prop.c:267
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:951
SCIP_RETCODE SCIPsetPropExit(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXIT((*propexit)))
Definition: scip_prop.c:203
void SCIPpropSetTimingmask(SCIP_PROP *prop, SCIP_PROPTIMING timingmask)
Definition: prop.c:1296
SCIP_RETCODE SCIPsetPropInit(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINIT((*propinit)))
Definition: scip_prop.c:187
SCIP_RETCODE SCIPsetPropInitpre(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITPRE((*propinitpre)))
Definition: scip_prop.c:251
SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
Definition: scip_prop.c:171
SCIP_RETCODE SCIPsetPropCopy(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPCOPY((*propcopy)))
Definition: scip_prop.c:155
SCIP_RETCODE SCIPsetPropExitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITSOL((*propexitsol)))
Definition: scip_prop.c:235
SCIP_RETCODE SCIPincludePropBasic(SCIP *scip, SCIP_PROP **propptr, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, SCIP_DECL_PROPEXEC((*propexec)), SCIP_PROPDATA *propdata)
Definition: scip_prop.c:118
SCIP_PROPTIMING SCIPpropGetTimingmask(SCIP_PROP *prop)
Definition: prop.c:1286
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:2005
SCIP_Bool SCIPisInRestart(SCIP *scip)
Definition: scip_solve.c:3709
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip_tree.c:91
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_RETCODE SCIPinferVarUbProp(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:7699
SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:8257
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:5118
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2872
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition: scip_var.c:2378
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:23600
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:11057
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2736
SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
Definition: scip_var.c:184
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
Definition: scip_var.c:10998
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1853
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:10984
SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:8026
SCIP_RETCODE SCIPinferVarLbProp(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_PROP *inferprop, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:7584
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
#define PROP_PRESOL_MAXROUNDS
#define PROP_PRESOLTIMING
#define PROP_DESC
static SCIP_RETCODE addEventData(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, int startindex, int startcomponent, SCIP_BOUNDTYPE boundtype)
static SCIP_RETCODE freeComponentsData(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_DECL_PROPRESPROP(propRespropGenvbounds)
#define DEFAULT_PROPAGATE_IN_ROOT_NODE
static SCIP_RETCODE analyzeGenVBoundConflict(SCIP *scip, GENVBOUND *genvbound)
static SCIP_DECL_PROPCOPY(propCopyGenvbounds)
static SCIP_RETCODE freeGenVBoundsRelaxOnly(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata)
static SCIP_RETCODE execGenVBounds(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_RESULT *result, SCIP_Bool local, int *nchgbds)
#define PROP_NAME
static SCIP_Real getGenVBoundsMinActivityConflict(SCIP *scip, SCIP_VAR **vars, SCIP_Real *coefs, int nvars, SCIP_BDCHGIDX *bdchgidx)
static SCIP_DECL_PROPINITPRE(propInitpreGenvbounds)
static SCIP_Real getGenVBoundsMinActivity(SCIP *scip, SCIP_VAR **vars, SCIP_Real *coefs, int nvars, SCIP_Bool global)
static SCIP_Real getGenVBoundsBound(SCIP *scip, GENVBOUND *genvbound, SCIP_Bool global)
static SCIP_RETCODE freeEventData(SCIP *scip, SCIP_EVENTDATA **eventdata)
static SCIP_RETCODE dropAndFreeEvents(SCIP *scip, SCIP_PROPDATA *propdata)
#define DEFAULT_PROPASCONSS
static SCIP_RETCODE setUpEvents(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_RETCODE sortGenVBounds(SCIP *scip, SCIP_PROPDATA *propdata)
#define DEFAULT_SORT
static SCIP_DECL_PROPEXEC(propExecGenvbounds)
static SCIP_DECL_PROPFREE(propFreeGenvbounds)
static SCIP_RETCODE fillGlobalStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_RETCODE resetLocalStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
#define PROP_DELAY
static GENVBOUND * getGenVBound(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype)
static SCIP_RETCODE freeGenVBound(SCIP *scip, GENVBOUND *genvbound)
static SCIP_Real getCutoffboundGenVBound(SCIP *scip)
static SCIP_RETCODE createConstraints(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata)
static SCIP_RETCODE applyGenVBounds(SCIP *scip, SCIP_PROP *prop, SCIP_Bool global, SCIP_RESULT *result, int *nchgbds)
#define DEFAULT_GLOBAL_PROPAGATION
static SCIP_RETCODE freeStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_DECL_PROPEXITSOL(propExitsolGenvbounds)
#define PROP_TIMING
static SCIP_RETCODE addNewGenVBound(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata, GENVBOUND *genvbound)
static SCIP_RETCODE getEventData(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_EVENTDATA **eventdata)
static SCIP_DECL_EVENTEXEC(eventExecGenvbounds)
static SCIP_DECL_PROPPRESOL(propPresolGenvbounds)
static SCIP_RETCODE createStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds)
static SCIP_DECL_PROPEXIT(propExitGenvbounds)
static SCIP_RETCODE applyGenVBound(SCIP *scip, SCIP_PROP *prop, GENVBOUND *genvbound, SCIP_Bool global, SCIP_RESULT *result, int *nchgbds)
static SCIP_RETCODE freeAllEventData(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_DECL_PROPINIT(propInitGenvbounds)
#define EVENTHDLR_DESC
static SCIP_RETCODE freeGenVBounds(SCIP *scip, SCIP_PROP *prop, SCIP_PROPDATA *propdata)
#define EVENTHDLR_NAME
static SCIP_RETCODE resolveGenVBoundPropagation(SCIP *scip, GENVBOUND *genvbound, SCIP_BDCHGIDX *bdchgidx, SCIP_Real *boundval, SCIP_Bool *success)
#define PROP_FREQ
#define PROP_PRIORITY
static SCIP_RETCODE initPropdata(SCIP *scip, SCIP_PROPDATA *propdata)
#define PROP_PRESOL_PRIORITY
generalized variable bounds propagator
public methods for managing events
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugMessage
Definition: pub_message.h:96
#define SCIPdebugPrintf
Definition: pub_message.h:99
public data structures and miscellaneous methods
public methods for propagators
public methods for branch and bound tree
public methods for problem variables
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for data structures
public methods for event handler plugins and event handlers
general public methods
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for propagator plugins
public methods for solutions
public solving methods
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
SCIP_BOUNDTYPE boundtype
SCIP_Real constant
SCIP_Real * coefs
SCIP_VAR * var
SCIP_VAR ** vars
SCIP_Real cutoffcoef
SCIP_Bool relaxonly
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:62
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:179
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
struct SCIP_PropData SCIP_PROPDATA
Definition: type_prop.h:52
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_SUCCESS
Definition: type_result.h:58
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PRESOLVING
Definition: type_set.h:49
#define SCIP_PROPTIMING_NONE
Definition: type_timing.h:65
unsigned int SCIP_PROPTIMING
Definition: type_timing.h:75
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:55
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141