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