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-2016 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  if( SCIPisInfinity(scip, REALABS(boundval)) )
983  return SCIP_OKAY;
984 
985 #ifdef SCIP_DEBUG
986  {
987  SCIP_Real lb;
988  SCIP_Real ub;
989  SCIP_Real new_lb;
990  SCIP_Real new_ub;
991 
992  lb = global ? SCIPvarGetLbGlobal(genvbound->var) : SCIPvarGetLbLocal(genvbound->var);
993  ub = global ? SCIPvarGetUbGlobal(genvbound->var) : SCIPvarGetUbLocal(genvbound->var);
994  new_lb = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? boundval : lb;
995  new_ub = genvbound->boundtype == SCIP_BOUNDTYPE_UPPER ? boundval : ub;
996 
997  SCIPdebugMessage(" %s genvbound propagation for <%s>\n", global ?
998  "global" : "local", SCIPvarGetName(genvbound->var));
999  SCIPdebugMessage(" genvbound: ");
1000  printGenVBound(scip, genvbound);
1001  SCIPdebugMessage(" [%.15g,%.15g] -> [%.15g,%.15g]\n", lb, ub, new_lb, new_ub);
1002  }
1003 #endif
1004 
1005  /* tighten bound globally */
1006  if( global || genvbound->ncoefs <= 0 )
1007  {
1008  if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
1009  {
1010  SCIP_CALL( SCIPtightenVarLbGlobal(scip, genvbound->var, boundval, FALSE, &infeas, &tightened) );
1011  }
1012  else
1013  {
1014  SCIP_CALL( SCIPtightenVarUbGlobal(scip, genvbound->var, boundval, FALSE, &infeas, &tightened) );
1015  }
1016  }
1017  /* tighten bound locally and start conflict analysis in case of infeasibility; as inferinfo we pass the index of the
1018  * genvbound that was used for propagation
1019  */
1020  else
1021  {
1022  if( genvbound->boundtype == SCIP_BOUNDTYPE_LOWER )
1023  {
1024  SCIP_CALL( SCIPinferVarLbProp(scip, genvbound->var, boundval, prop, genvbound->index, FALSE, &infeas, &tightened) );
1025 
1026  /* initialize conflict analysis if infeasible */
1027  if( infeas )
1028  {
1029  SCIPdebugMessage(" -> lower bound tightening on variable <%s> led to infeasibility\n",
1030  SCIPvarGetName(genvbound->var));
1031 
1032  SCIP_CALL( analyzeGenVBoundConflict(scip, genvbound) );
1033  }
1034  }
1035  else
1036  {
1037  SCIP_CALL( SCIPinferVarUbProp(scip, genvbound->var, boundval, prop, genvbound->index, FALSE, &infeas, &tightened) );
1038 
1039  /* initialize conflict analysis if infeasible */
1040  if( infeas )
1041  {
1042  SCIPdebugMessage(" -> upper bound tightening on variable <%s> led to infeasibility\n",
1043  SCIPvarGetName(genvbound->var));
1044 
1045  SCIP_CALL( analyzeGenVBoundConflict(scip, genvbound) );
1046  }
1047  }
1048  }
1049 
1050  /* handle result */
1051  if( infeas )
1052  {
1053  *result = SCIP_CUTOFF;
1054  SCIPdebugMessage(" cutoff!\n");
1055  }
1056  else if( tightened )
1057  {
1059  if( nchgbds != NULL )
1060  ++(*nchgbds);
1061  SCIPdebugMessage(" tightened!\n");
1062  }
1063 
1064  return SCIP_OKAY;
1065 }
1066 
1067 #ifdef SCIP_DEBUG
1068 /** prints event data as debug message */
1069 static
1070 void printEventData(
1071  SCIP_EVENTDATA* eventdata,
1073  )
1074 {
1075  int i;
1076  SCIPdebugMessage("event data: %s bound of <%s> tightened ==> start propagating at ",
1077  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(eventdata->var));
1078 
1079  /* if there is eventdata it should contain at least one starting index */
1080  assert(eventdata->nstarts > 0);
1081 
1082  for( i = 0; i < eventdata->nstarts; i++ )
1083  {
1084  SCIPdebugPrintf("(component %d, index %d) ", eventdata->startcomponents[i], eventdata->startindices[i]);
1085  }
1086 
1087  SCIPdebugPrintf("\n");
1088 }
1089 #endif
1090 
1091 /** frees event data */
1092 static
1094  SCIP* scip, /**< SCIP data structure */
1095  SCIP_EVENTDATA** eventdata /**< event data to be freed */
1096  )
1098  assert(scip != NULL);
1099  assert(eventdata != NULL);
1100  assert(*eventdata != NULL);
1101 
1102  SCIPfreeMemoryArray(scip, &((*eventdata)->startcomponents));
1103  SCIPfreeMemoryArray(scip, &((*eventdata)->startindices));
1104 
1105  (*eventdata)->nstarts = -1;
1106  (*eventdata)->var = NULL;
1107  (*eventdata)->prop = NULL;
1108 
1109  SCIPfreeMemory(scip, eventdata);
1110 
1111  return SCIP_OKAY;
1112 }
1113 
1114 /** frees all eventdata stored */
1115 static
1117  SCIP* scip, /**< SCIP data structure */
1118  SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1119  )
1121  int i;
1122 
1123  assert(scip != NULL);
1124  assert(propdata != NULL);
1125 
1126  if( propdata->lbevents != NULL )
1127  {
1128  assert(propdata->ubevents != NULL);
1129  assert(propdata->lbeventsmap != NULL);
1130  assert(propdata->ubeventsmap != NULL);
1131 
1132  SCIPhashmapFree(&(propdata->lbeventsmap));
1133  SCIPhashmapFree(&(propdata->ubeventsmap));
1134 
1135  for( i = propdata->nlbevents - 1; i >= 0; i-- )
1136  {
1137  SCIP_CALL( freeEventData(scip, &(propdata->lbevents[i])) );
1138  }
1139 
1140  for( i = propdata->nubevents - 1; i >= 0; i-- )
1141  {
1142  SCIP_CALL( freeEventData(scip, &(propdata->ubevents[i])) );
1143  }
1144 
1145  SCIPfreeMemoryArray(scip, &(propdata->ubevents));
1146  SCIPfreeMemoryArray(scip, &(propdata->lbevents));
1147  propdata->nlbevents = -1;
1148  propdata->nubevents = -1;
1149  }
1150 
1151  assert(propdata->lbevents == NULL);
1152  assert(propdata->ubevents == NULL);
1153  assert(propdata->lbeventsmap == NULL);
1154  assert(propdata->ubeventsmap == NULL);
1155  assert(propdata->nlbevents == -1);
1156  assert(propdata->nubevents == -1);
1157 
1158  return SCIP_OKAY;
1159 }
1160 
1161 /** drops all events caught by genvbounds propagator and frees their data */
1162 static
1164  SCIP* scip, /**< SCIP data structure */
1165  SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1166  )
1168  int i;
1169 
1170  SCIPdebugMessage("drop and free events\n");
1171 
1172  assert(scip != NULL);
1173  assert(propdata != NULL);
1174  assert(propdata->eventhdlr != NULL);
1175 
1176  if( propdata->lbevents != NULL )
1177  {
1178  assert(propdata->ubevents != NULL);
1179  assert(propdata->nlbevents >= 0);
1180  assert(propdata->nubevents >= 0);
1181 
1182  for( i = propdata->nlbevents - 1; i >= 0; i-- )
1183  {
1184  /* drop event */
1185  SCIP_CALL( SCIPdropVarEvent(scip, propdata->lbevents[i]->var, SCIP_EVENTTYPE_LBTIGHTENED, propdata->eventhdlr,
1186  propdata->lbevents[i], -1) );
1187  }
1188 
1189  for( i = propdata->nubevents - 1; i >= 0; i-- )
1190  {
1191  /* drop event */
1192  SCIP_CALL( SCIPdropVarEvent(scip, propdata->ubevents[i]->var, SCIP_EVENTTYPE_UBTIGHTENED, propdata->eventhdlr,
1193  propdata->ubevents[i], -1) );
1194  }
1195 
1196  /* free event data */
1197  SCIP_CALL( freeAllEventData(scip, propdata) );
1198  }
1199 
1200  assert(propdata->lbevents == NULL);
1201  assert(propdata->ubevents == NULL);
1202  assert(propdata->nlbevents == -1);
1203  assert(propdata->nubevents == -1);
1204 
1205  return SCIP_OKAY;
1206 }
1207 
1208 /** returns the corresponding event data entry in the corresponding array, if there is one; if not: allocates a new
1209  * event data entry, stores it in the array and returns its adress
1210  */
1211 static
1213  SCIP* scip, /**< SCIP data structure */
1214  SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1215  SCIP_VAR* var, /**< variable */
1216  SCIP_BOUNDTYPE boundtype, /**< type of bound */
1217  SCIP_EVENTDATA** eventdata /**< event data to return */
1218  )
1219 {
1220  SCIP_HASHMAP* hashmap;
1221 
1222  assert(scip != NULL);
1223  assert(propdata != NULL);
1224  assert(var != NULL);
1225 
1226  hashmap = boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbeventsmap : propdata->ubeventsmap;
1227 
1228  if( SCIPhashmapExists(hashmap, var) )
1229  *eventdata = (SCIP_EVENTDATA*) SCIPhashmapGetImage(hashmap, var);
1230  else
1231  {
1232  /* set up new eventdata entry */
1233  SCIP_CALL( SCIPallocMemory(scip, eventdata) );
1234  SCIP_CALL( SCIPallocMemoryArray(scip, &((*eventdata)->startcomponents), propdata->ncomponents) );
1235  SCIP_CALL( SCIPallocMemoryArray(scip, &((*eventdata)->startindices), propdata->ncomponents) );
1236  (*eventdata)->nstarts = 0;
1237  (*eventdata)->var = var;
1238  (*eventdata)->prop = propdata->prop;
1239 
1240  /* store event data in eventarray */
1241  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1242  {
1243  propdata->lbevents[propdata->nlbevents] = *eventdata;
1244  propdata->nlbevents++;
1245  }
1246  else
1247  {
1248  propdata->ubevents[propdata->nubevents] = *eventdata;
1249  propdata->nubevents++;
1250  }
1251 
1252  /* store hashmap entry */
1253  SCIP_CALL( SCIPhashmapInsert(hashmap, var, (*eventdata)) );
1254  }
1255 
1256  return SCIP_OKAY;
1257 }
1258 
1259 /** adds an event to the event array lbevents (if boundtype == SCIP_BOUNDTYPE_LOWER) or ubevents (if boundtype ==
1260  * SCIP_BOUNDTYPE_UPPER)
1261  */
1262 static
1264  SCIP* scip, /**< SCIP data structure */
1265  SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1266  SCIP_VAR* var, /**< variable thats event to be added */
1267  int startindex, /**< starting index */
1268  int startcomponent, /**< starting components index */
1269  SCIP_BOUNDTYPE boundtype /**< type of bound */
1270  )
1271 {
1272  SCIP_EVENTDATA* eventdata;
1273 
1274  assert(scip != NULL);
1275  assert(propdata != NULL);
1276  assert(var != NULL);
1277  assert(startindex >= 0);
1278  assert(startcomponent >= 0);
1279 
1280  /* get eventdata entry */
1281  SCIP_CALL( getEventData(scip, propdata, var, boundtype, &eventdata) );
1282  assert(eventdata != NULL);
1283 
1284  if( eventdata->nstarts > 0 && eventdata->startcomponents[eventdata->nstarts - 1] == startcomponent )
1285  {
1286  /* if there is already a starting index for startcomponent stored at the last entry of eventdata->startindices,
1287  * it should be smaller; this relies on the implementation of setUpEvents(), calling addEventData() in
1288  * topological order
1289  */
1290  assert(eventdata->startindices[eventdata->nstarts - 1] < startindex);
1291  }
1292  else
1293  {
1294  /* append starting information */
1295  eventdata->startcomponents[eventdata->nstarts] = startcomponent;
1296  eventdata->startindices[eventdata->nstarts] = startindex;
1297 
1298  /* increase counter */
1299  eventdata->nstarts++;
1300  }
1301 
1302  return SCIP_OKAY;
1303 }
1304 
1305 static
1307  SCIP* scip, /**< SCIP data structure */
1308  SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1309  )
1311  int nprobvars;
1312  int i;
1313 
1314  assert(scip != NULL);
1315  assert(propdata != NULL);
1316  assert(propdata->eventhdlr != NULL);
1317  assert(propdata->lbevents == NULL);
1318  assert(propdata->ubevents == NULL);
1319  assert(propdata->issorted);
1320  assert(propdata->nlbevents == -1);
1321  assert(propdata->nubevents == -1);
1322 
1323  SCIPdebugMessage("set up events\n");
1324 
1325  /* allocate lbevents, ubevents, and their hashmaps */
1326  nprobvars = SCIPgetNVars(scip) + SCIPgetNFixedVars(scip);
1327  SCIP_CALL( SCIPallocMemoryArray(scip, &(propdata->lbevents), nprobvars) );
1328  SCIP_CALL( SCIPallocMemoryArray(scip, &(propdata->ubevents), nprobvars) );
1329  SCIP_CALL( SCIPhashmapCreate(&(propdata->lbeventsmap), SCIPblkmem(scip), SCIPcalcHashtableSize(nprobvars)) );
1330  SCIP_CALL( SCIPhashmapCreate(&(propdata->ubeventsmap), SCIPblkmem(scip), SCIPcalcHashtableSize(nprobvars)) );
1331  propdata->nlbevents = 0;
1332  propdata->nubevents = 0;
1333 
1334  /* loop over all components of genvboundstore */
1335  for( i = 0; i < propdata->ncomponents; i++ )
1336  {
1337  int j;
1338 
1339  /* loop over all genvbounds in this component */
1340  for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ ) /*lint !e679*/
1341  {
1342  GENVBOUND* genvbound;
1343  int k;
1344 
1345  assert(j < propdata->ngenvbounds);
1346 
1347  genvbound = propdata->genvboundstore[j];
1348  assert(genvbound != NULL);
1349 
1350  /* loop over all coefficients in this genvbound */
1351  for( k = 0; k < genvbound->ncoefs; k++ )
1352  {
1353  if( SCIPisPositive(scip, genvbound->coefs[k]) )
1354  {
1355  SCIP_CALL( addEventData(scip, propdata, genvbound->vars[k], j, i, SCIP_BOUNDTYPE_LOWER) );
1356  }
1357  else
1358  {
1359  SCIP_CALL( addEventData(scip, propdata, genvbound->vars[k], j, i, SCIP_BOUNDTYPE_UPPER) );
1360  }
1361  }
1362  }
1363  }
1364 
1365  /* resize lbevents and ubevents array */
1366  assert(propdata->nlbevents <= nprobvars);
1367  assert(propdata->nubevents <= nprobvars);
1368  SCIP_CALL( SCIPreallocMemoryArray(scip, &(propdata->lbevents), propdata->nlbevents) );
1369  SCIP_CALL( SCIPreallocMemoryArray(scip, &(propdata->ubevents), propdata->nubevents) );
1370 
1371  /* resize and register lower bound events */
1372  for( i = 0; i < propdata->nlbevents; i++ )
1373  {
1374  SCIP_EVENTDATA* eventdata = propdata->lbevents[i];
1375 
1376  assert(eventdata != NULL);
1377  assert(eventdata->nstarts > 0);
1378  assert(eventdata->startcomponents != NULL);
1379  assert(eventdata->startindices != NULL);
1380 
1381  /* resize arrays stored in eventdata */
1382  SCIP_CALL( SCIPreallocMemoryArray(scip, &(eventdata->startcomponents), eventdata->nstarts) );
1383  SCIP_CALL( SCIPreallocMemoryArray(scip, &(eventdata->startindices), eventdata->nstarts) );
1384 
1385  /* register event */
1386  SCIP_CALL( SCIPcatchVarEvent(scip, eventdata->var, SCIP_EVENTTYPE_LBTIGHTENED, propdata->eventhdlr, eventdata,
1387  NULL) );
1388  }
1389 
1390  /* resize and register upper bound events */
1391  for( i = 0; i < propdata->nubevents; i++ )
1392  {
1393  SCIP_EVENTDATA* eventdata = propdata->ubevents[i];
1394 
1395  assert(eventdata != NULL);
1396  assert(eventdata->nstarts > 0);
1397  assert(eventdata->startcomponents != NULL);
1398  assert(eventdata->startindices != NULL);
1399 
1400  /* resize arrays stored in eventdata */
1401  SCIP_CALL( SCIPreallocMemoryArray(scip, &(eventdata->startcomponents), eventdata->nstarts) );
1402  SCIP_CALL( SCIPreallocMemoryArray(scip, &(eventdata->startindices), eventdata->nstarts) );
1403 
1404  /* register event */
1405  SCIP_CALL( SCIPcatchVarEvent(scip, eventdata->var, SCIP_EVENTTYPE_UBTIGHTENED, propdata->eventhdlr, eventdata,
1406  NULL) );
1407  }
1408 
1409  return SCIP_OKAY;
1410 }
1411 
1412 /** performs a topological sort on genvboundstore array
1413  *
1414  * The genvbounds graph is defined as follows: Given two genvbounds
1415  *
1416  * (genvbound1) c1 * x_i1 >= RHS1
1417  *
1418  * and
1419  *
1420  * (genvbound2) c2 * x_i2 >= RHS2,
1421  *
1422  * there is an arc from genvbound1 to genvbound2 iff c1 = +1 and x_i1 appears with positive coefficient in RHS2 or
1423  * c1 = -1 and x_i1 appears with negative coefficient in RHS2; in this case, a bound change of x_i1 deduced from
1424  * genvbound1 improves genvbound2's minactivity in RHS2.
1425  *
1426  * The method computes the strongly connected components and sorts them topologically. The order of the nodes in an
1427  * strongly connected component is arbitrary.
1428  */
1429 static
1431  SCIP* scip, /**< SCIP data structure */
1432  SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1433  )
1435  GENVBOUND** genvboundssorted; /* array to store the sorted genvbounds */
1436  SCIP_DIGRAPH* graph;
1437  int* strongcomponents;
1438  int* strongcompstartidx;
1439  int sortedindex;
1440  int i;
1441 
1442  assert(scip != NULL);
1443  assert(propdata != NULL);
1444  assert(propdata->componentsstart == NULL);
1445 
1446  SCIPdebugMessage("(re-)sort genvbounds topologically\n");
1447 
1448  /* create digraph */
1449  SCIP_CALL( SCIPdigraphCreate(&graph, propdata->ngenvbounds) );
1450 
1451  /* add outgoing arcs for each genvbound */
1452  for( i = 0; i < propdata->ngenvbounds; i++ )
1453  {
1454  GENVBOUND* genvbound;
1455  int j;
1456 
1457  assert(i < propdata->ngenvbounds);
1458 
1459  genvbound = propdata->genvboundstore[i];
1460 
1461  for( j = 0; j < genvbound->ncoefs; j++ )
1462  {
1463  if( SCIPisPositive(scip, genvbound->coefs[j]) &&
1464  SCIPhashmapExists(propdata->lbgenvbounds, genvbound->vars[j]) )
1465  {
1466  int from = ((GENVBOUND*) SCIPhashmapGetImage(propdata->lbgenvbounds, genvbound->vars[j]))->index;
1467  SCIP_CALL( SCIPdigraphAddArc(graph, from, i, NULL) );
1468  }
1469  else if( SCIPisNegative(scip, genvbound->coefs[j]) &&
1470  SCIPhashmapExists(propdata->ubgenvbounds, genvbound->vars[j]) )
1471  {
1472  int from = ((GENVBOUND*) SCIPhashmapGetImage(propdata->ubgenvbounds, genvbound->vars[j]))->index;
1473  SCIP_CALL( SCIPdigraphAddArc(graph, from, i, NULL) );
1474  }
1475  }
1476  }
1477 
1478  /* perform the topological sort */
1479  SCIP_CALL( SCIPdigraphComputeUndirectedComponents(graph, 1, NULL, &(propdata->ncomponents)) );
1481  assert(SCIPdigraphGetNComponents(graph) == propdata->ncomponents);
1482 
1483  /* allocate memory for genvboundssorted and componentsstart array */
1484  SCIP_CALL( SCIPallocMemoryArray(scip, &genvboundssorted, propdata->ngenvbounds) );
1485  SCIP_CALL( SCIPallocMemoryArray(scip, &(propdata->componentsstart), propdata->ncomponents + 1) );
1486 
1487  /* allocate memory for strong component arrays */
1488  SCIP_CALL( SCIPallocMemoryArray(scip, &strongcomponents, SCIPdigraphGetNNodes(graph)) ); /*lint !e666*/
1489  SCIP_CALL( SCIPallocMemoryArray(scip, &strongcompstartidx, SCIPdigraphGetNNodes(graph)) ); /*lint !e666*/
1490 
1491  /* compute sorted genvbounds array, fill componentsstart array */
1492  sortedindex = 0;
1493  propdata->componentsstart[propdata->ncomponents] = propdata->ngenvbounds;
1494  for( i = 0; i < propdata->ncomponents; i++ )
1495  {
1496  int j;
1497  int *nodes;
1498  int nnodes;
1499  int nstrongcomponents;
1500 
1501  SCIPdigraphGetComponent(graph, i, &nodes, &nnodes);
1502  propdata->componentsstart[i] = sortedindex;
1503 
1504  /* compute the strong components of the i-th undirected component */
1505  if( nnodes > 2 )
1506  {
1507  SCIP_CALL( SCIPdigraphComputeDirectedComponents(graph, i, strongcomponents, strongcompstartidx,
1508  &nstrongcomponents) );
1509 
1510  for( j = 0; j < nnodes; ++j )
1511  {
1512  int node;
1513 
1514  /* take the nodes at the end of the strong components array first to respect the topological
1515  * order of the different strong components
1516  */
1517  node = strongcomponents[nnodes - j - 1];
1518 
1519  assert(node < propdata->ngenvbounds);
1520  genvboundssorted[sortedindex] = propdata->genvboundstore[node];
1521  sortedindex++;
1522  }
1523  }
1524  else
1525  {
1526  for( j = 0; j < nnodes; j++ )
1527  {
1528  assert(nodes[j] < propdata->ngenvbounds);
1529  genvboundssorted[sortedindex] = propdata->genvboundstore[nodes[j]];
1530  sortedindex++;
1531  }
1532  }
1533  }
1534  assert(sortedindex == propdata->ngenvbounds);
1535 
1536  /* free strong component arrays */
1537  SCIPfreeMemoryArray(scip, &strongcompstartidx);
1538  SCIPfreeMemoryArray(scip, &strongcomponents);
1539 
1540  /* free digraph */
1541  SCIPdigraphFree(&graph);
1542 
1543  /* copy sorted genvbounds into genvboundstore */
1544  for( i = 0; i < propdata->ngenvbounds; i++ )
1545  {
1546  assert(genvboundssorted[i] != NULL);
1547 
1548  propdata->genvboundstore[i] = genvboundssorted[i];
1549  propdata->genvboundstore[i]->index = i;
1550  }
1551  SCIPfreeMemoryArray(scip, &(genvboundssorted));
1552 
1553  /* remember genvboundstore as sorted */
1554  propdata->issorted = TRUE;
1555 
1556 #ifdef SCIP_DEBUG
1557  SCIPdebugMessage("genvbounds got: %d\n", propdata->ngenvbounds);
1558  for( i = 0; i < propdata->ncomponents; i++ )
1559  {
1560  int j;
1561 
1562  SCIPdebugMessage("{\n");
1563 
1564  for( j = propdata->componentsstart[i]; j < propdata->componentsstart[i+1]; j++ )
1565  {
1566  SCIPdebugMessage(" [%d] ", j);
1567  printGenVBound(scip, propdata->genvboundstore[j]);
1568  }
1569 
1570  SCIPdebugMessage("}\n");
1571  }
1572 #endif
1573 
1574  return SCIP_OKAY;
1575 }
1576 
1577 /** apply propagation of generalized variable bounds */
1578 static
1580  SCIP* scip, /**< SCIP data structure */
1581  SCIP_PROP* prop, /**< genvbounds propagator */
1582  SCIP_Bool global, /**< use global variable bounds for propagation? */
1583  SCIP_RESULT* result, /**< result pointer */
1584  int* nchgbds /**< counter to increase by the number of changed bounds */
1585  )
1586 {
1587  SCIP_PROPDATA* propdata;
1588  int* startingcomponents;
1589  int* startingindices;
1590  int nindices;
1591  int i;
1592 
1593  SCIPdebugMessage("applying %s genvbound propagation in depth %d\n", global ?
1594  "global" : "local", SCIPgetDepth(scip));
1595 
1596  assert(scip != NULL);
1597  assert(prop != NULL);
1598  assert(result != NULL);
1599 
1600  propdata = SCIPpropGetData(prop);
1601  assert(propdata != NULL);
1602  assert(propdata->genvboundstore != NULL);
1603 
1604  if( *result == SCIP_DIDNOTRUN )
1605  *result = SCIP_DIDNOTFIND;
1606 
1607  /* if the genvbounds are not sorted, i.e. if root node processing has not been finished, yet, we just propagate in
1608  * the order in which they have been added to genvboundstore
1609  */
1610  if( !propdata->issorted )
1611  {
1612  int j;
1613 
1614  assert(!propdata->sort || SCIPinProbing(scip) || SCIPgetDepth(scip) == 0);
1615 
1616  for( j = 0; j < propdata->ngenvbounds && *result != SCIP_CUTOFF; j++ )
1617  {
1618  if( SCIPvarGetStatus(propdata->genvboundstore[j]->var) == SCIP_VARSTATUS_MULTAGGR )
1619  {
1620  /**@todo resolve multiaggregation in exitpre */
1621  }
1622  else
1623  {
1624  SCIPdebugMessage("applying genvbound with index %d (unsorted mode)\n", j);
1625  SCIP_CALL( applyGenVBound(scip, prop, propdata->genvboundstore[j], global, result, nchgbds) );
1626  }
1627  }
1628 
1629  return SCIP_OKAY;
1630  }
1631 
1632  /* otherwise, we propagate only components affected by the latest bound changes */
1633  startingcomponents = global ? propdata->gstartcomponents : propdata->startcomponents;
1634  startingindices = global ? propdata->gstartindices : propdata->startindices;
1635  nindices = global ? propdata->ngindices : propdata->nindices;
1636 
1637  for( i = 0; i < nindices && *result != SCIP_CUTOFF; i++ )
1638  {
1639  int j;
1640 
1641  SCIPdebugMessage("starting in component %d at index %d\n", startingcomponents[i], startingindices[i]);
1642  for( j = startingindices[i]; j < propdata->componentsstart[startingcomponents[i] + 1] &&
1643  *result != SCIP_CUTOFF; j++ ) /*lint !e679*/
1644  {
1645  assert(j < propdata->ngenvbounds);
1646 
1647  if( SCIPvarGetStatus(propdata->genvboundstore[j]->var) == SCIP_VARSTATUS_MULTAGGR )
1648  {
1649  /**@todo resolve multiaggregation in exitpre */
1650  }
1651  else
1652  {
1653  SCIPdebugMessage("applying genvbound with index %d, component %d\n", j, startingcomponents[i]);
1654  SCIP_CALL( applyGenVBound(scip, prop, propdata->genvboundstore[j], global, result, nchgbds) );
1655  }
1656  }
1657  }
1658 
1659  /* we dont want to run again caused by this starting data */
1660  if( !global )
1661  {
1662  SCIP_CALL( resetLocalStartingData(scip, propdata) );
1663  }
1664 
1665  return SCIP_OKAY;
1666 }
1667 
1668 /** initialize propagator data */
1669 static
1671  SCIP* scip, /**< SCIP data structure */
1672  SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1673  )
1675  int nprobvars;
1676 
1677  assert(scip != NULL);
1678  assert(propdata != NULL);
1679  assert(propdata->eventhdlr != NULL);
1680 
1681  SCIPdebugMessage("init propdata\n");
1682 
1683  nprobvars = SCIPgetNVars(scip);
1684 
1685  /* init genvboundstore */
1686  SCIP_CALL( SCIPallocMemoryArray(scip, &(propdata->genvboundstore), 2 * nprobvars) );
1687  BMSclearMemoryArray(propdata->genvboundstore, 2 * nprobvars);
1688  propdata->ngenvbounds = 0;
1689 
1690  /* init genvboundstore hashmaps */
1691  SCIP_CALL( SCIPhashmapCreate(&(propdata->lbgenvbounds), SCIPblkmem(scip), SCIPcalcHashtableSize(nprobvars)) );
1692  SCIP_CALL( SCIPhashmapCreate(&(propdata->ubgenvbounds), SCIPblkmem(scip), SCIPcalcHashtableSize(nprobvars)) );
1693 
1694  return SCIP_OKAY;
1695 }
1696 
1697 /** adds a new genvbound to genvboundstore array and sets a hashmap entry */
1698 static
1700  SCIP* scip, /**< SCIP data structure */
1701  SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1702  GENVBOUND* genvbound /**< genvbound to be added */
1703  )
1704 {
1705  SCIP_HASHMAP* hashmap;
1706 
1707  assert(scip != NULL);
1708  assert(propdata != NULL);
1709  assert(genvbound != NULL);
1710  assert(getGenVBound(scip, propdata, genvbound->var, genvbound->boundtype) == NULL);
1711 
1712  hashmap = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
1713 
1714  /* e.g., during presolving after a restart, new variables might have been created; in this case, we need to extend
1715  * the genvboundstore; the new size may even exceed 2*SCIPgetNVars() if we have genvbounds with nonactive left-hand
1716  * side variables
1717  */
1718  assert(propdata->ngenvbounds <= propdata->genvboundstoresize);
1719  if( propdata->ngenvbounds == propdata->genvboundstoresize )
1720  {
1721  propdata->genvboundstoresize = 2*propdata->genvboundstoresize + 1;
1722  SCIP_CALL( SCIPreallocMemoryArray(scip, &(propdata->genvboundstore), propdata->genvboundstoresize) );
1723  }
1724 
1725  /* new index is propdata->ngenvbounds */
1726  SCIP_CALL( SCIPhashmapInsert(hashmap, genvbound->var, genvbound) );
1727  propdata->genvboundstore[propdata->ngenvbounds] = genvbound;
1728  genvbound->index = propdata->ngenvbounds;
1729  propdata->ngenvbounds++;
1730 
1731  assert(propdata->ngenvbounds <= propdata->genvboundstoresize);
1732 
1733  return SCIP_OKAY;
1734 }
1735 
1736 /** runs propagation routine */
1737 static
1739  SCIP* scip, /**< SCIP data structure */
1740  SCIP_PROPDATA* propdata, /**< data of the genvbounds propagator */
1741  SCIP_RESULT* result, /**< result pointer */
1742  SCIP_Bool local, /**< should local propagation be applied? */
1743  int* nchgbds /**< counter to increase by the number of changed bounds */
1744  )
1745 {
1746  assert(scip != NULL);
1747  assert(propdata != NULL);
1748  assert(propdata->prop != NULL);
1749  assert(result != NULL);
1750 
1751  /* we only sort after the root node is finished; this avoids having to sort again after adding more genvbounds; if
1752  * the genvbounds are not sorted, we will simply propagate all of them in the order given
1753  */
1754  if( propdata->sort && !propdata->issorted && !SCIPinProbing(scip) && SCIPgetDepth(scip) > 0 )
1755  {
1756  *result = SCIP_DIDNOTFIND;
1757 
1758  SCIPdebugMessage("genvbounds are not sorted\n");
1759 
1760  /* drop and free old events */
1761  SCIP_CALL( dropAndFreeEvents(scip, propdata) );
1762 
1763  /* free old starting data */
1764  SCIP_CALL( freeStartingData(scip, propdata) );
1765 
1766  /* free sorted components data */
1767  SCIP_CALL( freeComponentsData(scip, propdata) );
1768 
1769  /* sort genvbounds */
1770  SCIP_CALL( sortGenVBounds(scip, propdata) );
1771 
1772  /* create starting data */
1773  SCIP_CALL( createStartingData(scip, propdata) );
1774 
1775  /* fill global starting data */
1776  SCIP_CALL( fillGlobalStartingData(scip, propdata) );
1777 
1778  /* set up new events to catch */
1779  SCIP_CALL( setUpEvents(scip, propdata) );
1780  }
1781 
1782  /* apply global propagation if primal bound has improved */
1783  if( propdata->global && SCIPgetDepth(scip) > 0 && SCIPisFeasLT(scip, SCIPgetCutoffbound(scip), propdata->lastcutoff) )
1784  {
1785  if( propdata->ngindices > 0 )
1786  {
1787  SCIP_CALL( applyGenVBounds(scip, propdata->prop, TRUE, result, nchgbds) );
1788  assert(*result != SCIP_DIDNOTRUN);
1789  }
1790 
1791  /* within the tree, the objective function should not change anymore, hence the cutoff bound should be a stable
1792  * point of reference
1793  */
1794  propdata->lastcutoff = SCIPgetCutoffbound(scip);
1795  }
1796 
1797  /* apply local propagation if allowed */
1798  if( local && *result != SCIP_CUTOFF )
1799  {
1800  /* check if local propagation in root node is allowed */
1801  if( SCIPgetDepth(scip) > 0 || propdata->propinrootnode )
1802  {
1803  /* if genvbounds are already sorted, check if bound change events were caught; otherwise apply all genvbounds */
1804  if( !propdata->issorted || ( SCIPgetCurrentNode(scip) == propdata->lastnodecaught && propdata->nindices > 0 ) )
1805  {
1806  SCIP_CALL( applyGenVBounds(scip, propdata->prop, FALSE, result, nchgbds) );
1807  assert(*result != SCIP_DIDNOTRUN);
1808  }
1809  }
1810  }
1811 
1812  return SCIP_OKAY;
1813 }
1814 
1815 /* adds all genvbounds in the genvboundstore as constraints to the problem; afterwards clears the genvboundstore */
1816 static
1818  SCIP* scip, /**< SCIP data structure */
1819  SCIP_PROPDATA* propdata /**< data of the genvbounds propagator */
1820  )
1822  int i;
1823 
1824  assert(scip != NULL);
1825  assert(propdata != NULL);
1826  assert(propdata->propasconss);
1827 
1828  /* ensure that the cutoffboundvar is available */
1829  if( propdata->cutoffboundvar == NULL )
1830  {
1831  SCIP_Real ub;
1832  char name[16];
1833 
1834  /* set the upper bound to the best primal value in the original problem */
1835  ub = getCutoffboundGenVBound(scip);
1836 
1837  SCIPdebugMessage("initialize cutoffboundvar with UB = %e\n", ub);
1838 
1839  (void) SCIPsnprintf(name, 16, "cutoffboundvar");
1840  SCIP_CALL( SCIPcreateVarBasic(scip, &propdata->cutoffboundvar, name, -SCIPinfinity(scip), ub, 0.0, SCIP_VARTYPE_CONTINUOUS) );
1841  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, propdata->cutoffboundvar) );
1842 
1843  SCIP_CALL( SCIPaddVar(scip, propdata->cutoffboundvar) );
1844 
1845  /* lock the variable because it should not be subject to dual presolving reductions; because we create the
1846  * linear constraints as non-check constraints, the cutoffboundvar will not be locked by the linear constraint
1847  * handler
1848  */
1849  SCIP_CALL( SCIPaddVarLocks(scip, propdata->cutoffboundvar, 1, 1) );
1850  }
1851 
1852  assert(propdata->cutoffboundvar != NULL);
1853 
1854  /* now iterate over all genvbounds in the store and construct a linear constraint for each of them */
1855  for( i = 0; i < propdata->ngenvbounds; ++i )
1856  {
1857  GENVBOUND* genvbound;
1858  SCIP_CONS* cons;
1859  SCIP_VAR** vars;
1860  SCIP_Real* vals;
1861  char name[SCIP_MAXSTRLEN];
1862  int nvars;
1863  int j;
1864 
1865  genvbound = propdata->genvboundstore[i];
1866  assert(genvbound != NULL);
1867 
1868  nvars = genvbound->ncoefs + 2;
1869  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
1870  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
1871 
1872  SCIPdebugPrintf("add cons: ");
1873 
1874  /* copy the coefs/vars array */
1875  for( j = 0; j < genvbound->ncoefs; j++ )
1876  {
1877  vars[j] = genvbound->vars[j];
1878  vals[j] = genvbound->coefs[j];
1879  SCIPdebugPrintf("%e%s + ", vals[j], SCIPvarGetName(vars[j]));
1880  }
1881 
1882  /* add the variable and the coefficient of the genvbound */
1883  vars[genvbound->ncoefs] = genvbound->var;
1884  vals[genvbound->ncoefs] = (genvbound->boundtype == SCIP_BOUNDTYPE_LOWER) ? -1.0 : 1.0;
1885 
1886  SCIPdebugPrintf("%e%s + ", vals[genvbound->ncoefs], SCIPvarGetName(vars[genvbound->ncoefs]));
1887 
1888  /* add cutoffcoef * cutoffboundvar */
1889  vars[genvbound->ncoefs + 1] = propdata->cutoffboundvar;
1890  vals[genvbound->ncoefs + 1] = genvbound->cutoffcoef;
1891 
1892  SCIPdebugPrintf("%e%s <= %e\n", vals[genvbound->ncoefs + 1], SCIPvarGetName(vars[genvbound->ncoefs + 1]), -1.0*genvbound->constant);
1893 
1894  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "genvbound_cons%d", genvbound->index);
1895 
1896  /* create linear constraint with only propagate flag as TRUE */
1897  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, name, nvars, vars, vals, -SCIPinfinity(scip), -genvbound->constant,
1899 
1900  SCIP_CALL( SCIPaddCons(scip, cons) );
1901  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
1902 
1903  /* free memory */
1904  SCIPfreeBufferArray(scip, &vars);
1905  SCIPfreeBufferArray(scip, &vals);
1906  }
1907 
1908  /* now delete all genvbounds in the genvboundstore */
1909  if( propdata->ngenvbounds > 0 )
1910  {
1911  assert(propdata->genvboundstore != NULL);
1912 
1913  for( i = propdata->ngenvbounds - 1; i >= 0; i-- )
1914  {
1915  SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
1916  }
1917 
1918  /* free genvboundstore hashmaps */
1919  SCIPhashmapFree(&(propdata->lbgenvbounds));
1920  SCIPhashmapFree(&(propdata->ubgenvbounds));
1921 
1922  /* drop and free all events */
1923  SCIP_CALL( dropAndFreeEvents(scip, propdata) );
1924 
1925  /* free componentsstart array */
1926  SCIP_CALL( freeComponentsData(scip, propdata) );
1927 
1928  /* free starting indices data */
1929  SCIP_CALL( freeStartingData(scip, propdata) );
1930 
1931  SCIPfreeMemoryArray(scip, &(propdata->genvboundstore));
1932  propdata->genvboundstore = NULL;
1933  propdata->ngenvbounds = 0;
1934  }
1935 
1936  return SCIP_OKAY;
1937 }
1938 
1939 
1940 
1941 /*
1942  * Public methods
1943  */
1944 
1945 /** adds a generalized variable bound to the genvbounds propagator; if there is already a genvbound for the bound
1946  * "boundtype" of variable "var", it will be replaced
1947  */
1949  SCIP* scip, /**< SCIP data structure */
1950  SCIP_PROP* genvboundprop, /**< genvbound propagator */
1951  SCIP_VAR** vars, /**< array of RHSs variables */
1952  SCIP_VAR* var, /**< LHSs variable */
1953  SCIP_Real* coefs, /**< array of coefficients for the RHSs variables */
1954  int ncoefs, /**< size of coefs array */
1955  SCIP_Real coefcutoffbound, /**< nonpositive value of the cutoff bounds multiplier */
1956  SCIP_Real constant, /**< constant term */
1957  SCIP_BOUNDTYPE boundtype /**< type of bound provided by the genvbound */
1958  )
1959 {
1960  /**@todo in debug mode: check if genvbound is nontrivial */
1961 
1962  SCIP_PROPDATA* propdata;
1963  GENVBOUND* genvbound;
1964 
1965  SCIP_Bool newgenvbound;
1966 
1967  assert(scip != NULL);
1968  assert(genvboundprop != NULL);
1969  assert(strcmp(SCIPpropGetName(genvboundprop), PROP_NAME) == 0);
1970  assert(vars != NULL);
1971  assert(var != NULL);
1972  assert(coefs != NULL);
1973  assert(ncoefs >= 0);
1974  assert(coefcutoffbound <= 0.0);
1975  assert(!SCIPisInfinity(scip, -constant));
1976 
1977  if( ncoefs < 0 || coefcutoffbound > 0.0 || SCIPisInfinity(scip, -constant) )
1978  {
1979  SCIPerrorMessage("cannot create generalized variable bound from invalid data\n");
1980  return SCIP_INVALIDDATA;
1981  }
1982 
1983  propdata = SCIPpropGetData(genvboundprop);
1984  assert(propdata != NULL);
1985 
1986  /* initialize propdata if not done yet */
1987  if( propdata->genvboundstore == NULL )
1988  {
1989  SCIP_CALL( initPropdata(scip, propdata) );
1990  }
1991 
1992  genvbound = getGenVBound(scip, propdata, var, boundtype);
1993  newgenvbound = (genvbound == NULL);
1994 
1995  /* check if there already is a genvbound corresponding to this bound, freeing its data and overwriting it */
1996  if( !newgenvbound && genvbound->ncoefs < ncoefs )
1997  {
1998  /* do not realloc since we do not want to keep and possibly copy the old entries */
1999  SCIPfreeMemoryArray(scip, &(genvbound->coefs));
2000  SCIPfreeMemoryArray(scip, &(genvbound->vars));
2001 
2002  /* allocate and copy arrays in genvbound */
2003  SCIP_CALL( SCIPduplicateMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
2004  SCIP_CALL( SCIPduplicateMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
2005  }
2006  else if( !newgenvbound && genvbound->ncoefs == ncoefs )
2007  {
2008  int i;
2009 
2010  /* just update entries */
2011  for( i = 0; i < ncoefs; i++ )
2012  {
2013  genvbound->coefs[i] = coefs[i];
2014  genvbound->vars[i] = vars[i];
2015  }
2016  }
2017  else if( !newgenvbound && genvbound->ncoefs > ncoefs )
2018  {
2019  int i;
2020 
2021  /* reallocate memory for arrays in genvbound to free unused memory */
2022  SCIP_CALL( SCIPreallocMemoryArray(scip, &(genvbound->coefs), ncoefs) );
2023  SCIP_CALL( SCIPreallocMemoryArray(scip, &(genvbound->vars), ncoefs) );
2024 
2025  /* update entries */
2026  for( i = 0; i < ncoefs; i++ )
2027  {
2028  genvbound->coefs[i] = coefs[i];
2029  genvbound->vars[i] = vars[i];
2030  }
2031  }
2032  else if( newgenvbound )
2033  {
2034  /* allocate memory for genvbound data */
2035  SCIP_CALL( SCIPallocMemory(scip, &genvbound) );
2036 
2037  /* allocate and copy arrays in genvbound */
2038  SCIP_CALL( SCIPduplicateMemoryArray(scip, &(genvbound->coefs), coefs, ncoefs) );
2039  SCIP_CALL( SCIPduplicateMemoryArray(scip, &(genvbound->vars), vars, ncoefs) );
2040  }
2041 
2042  /* set up data for genvbound */
2043  genvbound->boundtype = boundtype;
2044  genvbound->var = var;
2045  genvbound->ncoefs = ncoefs;
2046  genvbound->constant = constant;
2047 
2048  /* the cutoff bound is valid w.r.t. the current objective function in the transformed problem; during presolving,
2049  * however, the objective function can change (e.g., when a variable is fixed, its contribution in the objective
2050  * is subtracted from the cutoff bound and added to the objective offset); we solve this by transforming the
2051  * contribution of the cutoff bound in the generalized variable bound to the original problem as follows:
2052  *
2053  * +/- var >= ... + z * SCIPgetCutoffbound() + constant
2054  *
2055  * becomes
2056  *
2057  * +/- var >= ... + (z / SCIPgetTransObjscale()) * origcutoffbound + (constant - z * SCIPgetTransObjoffset())
2058  *
2059  * with SCIPgetCutoffbound() = origcutoffbound / SCIPgetTransObjscale() - SCIPgetTransObjoffset(); in the
2060  * propagation later, we will use (SCIPgetCutoffbound() + SCIPgetTransObjoffset()) * SCIPgetTransObjscale(), see
2061  * function getCutoffboundGenVBound()
2062  */
2063  if( SCIPisNegative(scip, coefcutoffbound) )
2064  {
2065  assert(SCIPisPositive(scip, SCIPgetTransObjscale(scip)));
2066  genvbound->cutoffcoef = coefcutoffbound / SCIPgetTransObjscale(scip);
2067  genvbound->constant -= (coefcutoffbound * SCIPgetTransObjoffset(scip));
2068  }
2069  else
2070  genvbound->cutoffcoef = 0.0;
2071 
2072  /* if genvbound is not overwritten, create a new entry in genvboundstore */
2073  if( newgenvbound )
2074  {
2075  SCIP_CALL( addNewGenVBound(scip, propdata, genvbound) );
2076  }
2077 
2078  /* mark genvbounds array to be resorted */
2079  propdata->issorted = FALSE;
2080 
2081  /* debug message */
2082  SCIPdebugMessage("added genvbound ");
2083  SCIPdebug( printGenVBound(scip, genvbound) );
2084 #ifdef SCIP_DEBUG_SOLUTION
2085  SCIP_CALL( checkDebugSolutionGenVBound(scip, genvbound) );
2086 #endif
2087 
2088  return SCIP_OKAY;
2089 }
2090 
2091 
2092 /*
2093  * Callback methods of propagator
2094  */
2095 
2096 
2097 /** initialization method of propagator (called after problem was transformed) */
2098 static
2099 SCIP_DECL_PROPINIT(propInitGenvbounds)
2100 { /*lint --e{715}*/
2101  SCIP_PROPDATA* propdata;
2102 
2103  assert(scip != NULL);
2104  assert(prop != NULL);
2105  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2106 
2107  /* get propagator data */
2108  propdata = SCIPpropGetData(prop);
2109  assert(propdata != NULL);
2110 
2111  propdata->genvboundstore = NULL;
2112  propdata->genvboundstoresize = 0;
2113  propdata->lbevents = NULL;
2114  propdata->ubevents = NULL;
2115  propdata->lbgenvbounds = NULL;
2116  propdata->ubgenvbounds = NULL;
2117  propdata->lbeventsmap = NULL;
2118  propdata->ubeventsmap = NULL;
2119  propdata->startmap = NULL;
2120  propdata->componentsstart = NULL;
2121  propdata->startindices = NULL;
2122  propdata->startcomponents = NULL;
2123  propdata->gstartindices = NULL;
2124  propdata->gstartcomponents = NULL;
2125  propdata->lastcutoff = SCIPinfinity(scip);
2126  propdata->lastnodecaught = NULL;
2127  propdata->cutoffboundvar = NULL;
2128  propdata->ngenvbounds = -1;
2129  propdata->ncomponents = -1;
2130  propdata->nindices = -1;
2131  propdata->ngindices = -1;
2132  propdata->nlbevents = -1;
2133  propdata->nubevents = -1;
2134  propdata->issorted = FALSE;
2135 
2136  propdata->prop = prop;
2137 
2138  return SCIP_OKAY;
2139 }
2140 
2141 
2142 /** presolving method of propagator */
2143 static
2144 SCIP_DECL_PROPPRESOL(propPresolGenvbounds)
2145 { /*lint --e{715}*/
2146  SCIP_PROPDATA* propdata;
2147 
2148  assert(scip != NULL);
2149  assert(prop != NULL);
2150  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2151 
2152  *result = SCIP_DIDNOTRUN;
2153 
2154  if( !SCIPallowDualReds(scip) )
2155  return SCIP_OKAY;
2156 
2157  /* get propagator data */
2158  propdata = SCIPpropGetData(prop);
2159  assert(propdata != NULL);
2160 
2161  SCIPdebugMessage("proppresol in problem <%s>\n", SCIPgetProbName(scip));
2162 
2163  /* do not run if no genvbounds were added yet */
2164  if( propdata->ngenvbounds < 1 )
2165  {
2166  SCIPdebugMessage("no bounds were added yet\n");
2167  return SCIP_OKAY;
2168  }
2169 
2170  /* propagate */
2171  SCIP_CALL( execGenVBounds(scip, propdata, result, TRUE, nchgbds) );
2172 
2173  return SCIP_OKAY;
2174 }
2175 
2176 
2177 /** presolving initialization method of propagator (called when presolving is about to begin) */
2178 static
2179 SCIP_DECL_PROPINITPRE(propInitpreGenvbounds)
2180 { /*lint --e{715}*/
2181  SCIP_PROPDATA* propdata;
2182 
2183  assert(scip != NULL);
2184  assert(prop != NULL);
2185  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2186 
2187  /* get propagator data */
2188  propdata = SCIPpropGetData(prop);
2189  assert(propdata != NULL);
2190 
2191  /* lock the variable because it should not be deleted after a restart */
2192  if( propdata->cutoffboundvar != NULL )
2193  {
2194  SCIPdebugMessage("propinitpre in problem <%s>: locking cutoffboundvar (current downlocks=%d, uplocks=%d)\n",
2195  SCIPgetProbName(scip), SCIPvarGetNLocksDown(propdata->cutoffboundvar),
2196  SCIPvarGetNLocksUp(propdata->cutoffboundvar));
2197 
2198  SCIP_CALL( SCIPaddVarLocks(scip, propdata->cutoffboundvar, 1, 1) );
2199  }
2200 
2201  return SCIP_OKAY;
2202 }
2203 
2204 
2205 /** presolving deinitialization method of propagator (called after presolving has been finished) */
2206 static
2207 SCIP_DECL_PROPEXITPRE(propExitpreGenvbounds)
2208 { /*lint --e{715}*/
2209  SCIP_PROPDATA* propdata;
2210  int i;
2212  assert(scip != NULL);
2213  assert(prop != NULL);
2214  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2215 
2216  SCIPdebugMessage("propexitpre in problem <%s>: removing fixed, aggregated, negated, and multi-aggregated variables from right-hand side\n",
2217  SCIPgetProbName(scip));
2218 
2219  /* get propagator data */
2220  propdata = SCIPpropGetData(prop);
2221  assert(propdata != NULL);
2222 
2223  /* there should be no events on the right-hand side variables */
2224  assert(propdata->lbevents == NULL);
2225  assert(propdata->ubevents == NULL);
2226 
2227  for( i = 0; i < propdata->ngenvbounds; )
2228  {
2229  GENVBOUND* genvbound;
2230  int requiredsize;
2231 
2232  genvbound = propdata->genvboundstore[i];
2233  assert(genvbound != NULL);
2234 
2235  /* replace non-active by active variables and update constant; note that this may result in coefficients where
2236  * SCIPisZero() is true; this should not create any problems
2237  */
2238  SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, genvbound->ncoefs, &genvbound->constant, &requiredsize, TRUE) );
2239 
2240  /* if space was not enough we need to resize the buffers */
2241  if( requiredsize > genvbound->ncoefs )
2242  {
2243  /* reallocate memory for arrays in genvbound to free unused memory */
2244  SCIP_CALL( SCIPreallocMemoryArray(scip, &(genvbound->coefs), requiredsize) );
2245  SCIP_CALL( SCIPreallocMemoryArray(scip, &(genvbound->vars), requiredsize) );
2246 
2247  SCIP_CALL( SCIPgetProbvarLinearSum(scip, genvbound->vars, genvbound->coefs, &genvbound->ncoefs, requiredsize, &genvbound->constant, &requiredsize, TRUE) );
2248  assert(requiredsize <= genvbound->ncoefs);
2249  }
2250 
2251  /* if the resulting genvbound is trivial, remove it */
2252  if( genvbound->ncoefs == 0 && SCIPisZero(scip, genvbound->cutoffcoef) )
2253  {
2254  SCIP_HASHMAP* hashmap;
2255 
2256  hashmap = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER ? propdata->lbgenvbounds : propdata->ubgenvbounds;
2257 
2258  /* remove genvbound from hashmap */
2259  assert(SCIPhashmapExists(hashmap, genvbound->var));
2260  SCIP_CALL( SCIPhashmapRemove(hashmap, genvbound->var) );
2261 
2262  /* free genvbound and fill gap */
2263  SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
2264  --(propdata->ngenvbounds);
2265 
2266  /* move the last genvbound to the i-th position */
2267  if( i < propdata->ngenvbounds )
2268  {
2269  propdata->genvboundstore[i] = propdata->genvboundstore[propdata->ngenvbounds];
2270  propdata->genvboundstore[i]->index = i;
2271 
2272  /* mark genvbounds array to be resorted */
2273  propdata->issorted = FALSE;
2274  }
2275  }
2276  else
2277  ++i;
2278  }
2279 
2280  return SCIP_OKAY;
2281 }
2282 
2283 
2284 /** execution method of propagator */
2285 static
2286 SCIP_DECL_PROPEXEC(propExecGenvbounds)
2287 { /*lint --e{715}*/
2288  SCIP_PROPDATA* propdata;
2289 
2290  assert(scip != NULL);
2291  assert(prop != NULL);
2292  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2293 
2294  *result = SCIP_DIDNOTRUN;
2295 
2296  /* do not run if propagation w.r.t. current objective is not allowed */
2297  if( !SCIPallowObjProp(scip) )
2298  return SCIP_OKAY;
2299 
2300  /* get propagator data */
2301  propdata = SCIPpropGetData(prop);
2302  assert(propdata != NULL);
2303 
2304  /* update upper bound of the cutoffboundvar */
2305  if( propdata->cutoffboundvar != NULL )
2306  {
2307  SCIP_Real newub;
2308  SCIP_Real oldub;
2309  SCIP_Bool infeasible;
2310  SCIP_Bool tightened;
2311 
2312  assert(propdata->propasconss);
2313 
2314  /* compute the primal bound in the original problem */
2315  newub = getCutoffboundGenVBound(scip);
2316  oldub = SCIPvarGetUbLocal(propdata->cutoffboundvar);
2317 
2318  if( SCIPisInfinity(scip, newub) == FALSE && SCIPisFeasLT(scip, newub, oldub) )
2319  {
2320  SCIP_CALL( SCIPtightenVarUbGlobal(scip, propdata->cutoffboundvar, newub, FALSE, &infeasible, &tightened) );
2321 
2322  if( tightened )
2323  {
2324  SCIPdebugMessage("tightened UB of cutoffboundvar to %e (old: %e, infeas: %u, tightened: %u)\n",
2325  newub, oldub, infeasible, tightened);
2326  }
2327 
2328  assert(infeasible == FALSE);
2329  }
2330  }
2331 
2332  SCIPdebugMessage("propexec in problem <%s> at depth %d%s\n", SCIPgetProbName(scip), SCIPgetDepth(scip),
2333  SCIPinProbing(scip) ? " in probing" : "");
2334 
2335  /* do not run if no genvbounds were added yet */
2336  if( propdata->ngenvbounds < 1 )
2337  {
2338  /**@todo is it really no performance issue to be called each time when there are no genvbounds, e.g., for MIPs? */
2339  SCIPdebugMessage("no bounds were added yet\n");
2340  return SCIP_OKAY;
2341  }
2342 
2343  /* add the genvbounds in the genvboundstore as constraints to the problem; afterwards clear the genvboundstore */
2344  if( propdata->propasconss )
2345  {
2346  SCIP_CALL( createConstraints(scip, propdata) );
2347  return SCIP_OKAY;
2348  }
2349 
2350  /* propagate locally and globally */
2351  SCIP_CALL( execGenVBounds(scip, propdata, result, !SCIPinProbing(scip), NULL) );
2352 
2353  /* when called in presolving stage the result is set to SCIP_SUCCESS instead of SCIP_REDUCEDDOM, this is corrected
2354  * here
2355  */
2356  if( *result == SCIP_SUCCESS )
2357  *result = SCIP_REDUCEDDOM;
2358 
2359  SCIPdebugMessage("end of exec\n");
2360 
2361  return SCIP_OKAY;
2362 }
2363 
2364 /** propagation conflict resolving method of propagator */
2365 static
2366 SCIP_DECL_PROPRESPROP(propRespropGenvbounds)
2367 { /*lint --e{715}*/
2368  SCIP_PROPDATA* propdata;
2369  GENVBOUND* genvbound;
2370  SCIP_Real boundval;
2371  SCIP_Bool success;
2372 
2373  SCIPdebugMessage("explain %s bound change of variable <%s>\n",
2374  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
2375 
2376  /* get propagator data */
2377  propdata = SCIPpropGetData(prop);
2378  assert(propdata != NULL);
2379  assert(propdata->genvboundstore != NULL);
2380 
2381  /* as inferinfo we passed the index of the genvbound that was used for propagation; the genvbound might have been
2382  * replaced, but also the new genvbound at this position has the same variable on the left-hand side
2383  */
2384  assert(inferinfo >= 0);
2385  assert(inferinfo < propdata->ngenvbounds);
2386 
2387  *result = SCIP_DIDNOTFIND;
2388 
2389  /* check also in optimized mode that inferinfo is correct */
2390  if( inferinfo >= propdata->ngenvbounds)
2391  {
2392  SCIPerrorMessage("generalized variable bounds propagator received inferinfo out of range; propagation not resolved, safe to continue\n");
2393  return SCIP_OKAY;
2394  }
2395 
2396  /* get genvbound responsible for the bound change */
2397  genvbound = propdata->genvboundstore[inferinfo];
2398  assert(genvbound != NULL);
2399  assert(genvbound->var == infervar);
2400 
2401  /* check also in optimized mode that inferinfo is correct */
2402  if( genvbound->var != infervar )
2403  {
2404  SCIPerrorMessage("generalized variable bounds propagator received incorrect inferinfo; propagation not resolved, but it's safe to continue\n");
2405  return SCIP_OKAY;
2406  }
2407 
2408  /* get value of bound change on left-hand side */
2409  boundval = genvbound->boundtype == SCIP_BOUNDTYPE_LOWER
2410  ? SCIPvarGetLbAtIndex(genvbound->var, bdchgidx, TRUE)
2411  : -SCIPvarGetUbAtIndex(genvbound->var, bdchgidx, TRUE);
2412 
2413  /* if left-hand side variable is integral, it suffices to explain a bound change greater than boundval - 1 */
2414  if( SCIPvarIsIntegral(genvbound->var) )
2415  {
2416  SCIP_Real roundedboundval;
2417 
2418  assert(SCIPisIntegral(scip, boundval));
2419 
2420  roundedboundval = SCIPfeasCeil(scip, boundval - 1.0) + 2 * SCIPfeastol(scip);
2421  boundval = MIN(boundval, roundedboundval);
2422  }
2423 
2424  /* resolve propagation */
2425  SCIP_CALL( resolveGenVBoundPropagation(scip, genvbound, bdchgidx, &boundval, &success) );
2426 
2427  if( success )
2428  *result = SCIP_SUCCESS;
2429 
2430  return SCIP_OKAY;
2431 }
2432 
2433 /** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
2434 static
2435 SCIP_DECL_PROPEXITSOL(propExitsolGenvbounds)
2436 { /*lint --e{715}*/
2437  SCIP_PROPDATA* propdata;
2438  int i;
2440  assert(scip != NULL);
2441  assert(prop != NULL);
2442  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2443 
2444  SCIPdebugMessage("propexitsol in problem <%s>\n", SCIPgetProbName(scip));
2445 
2446  /* get propagator data */
2447  propdata = SCIPpropGetData(prop);
2448  assert(propdata != NULL);
2449 
2450  if( !SCIPisInRestart(scip) && propdata->genvboundstore != NULL )
2451  {
2452  /* free genvbounds */
2453  for( i = propdata->ngenvbounds - 1; i >= 0; i-- )
2454  {
2455  SCIP_CALL( freeGenVBound(scip, propdata->genvboundstore[i]) );
2456  }
2457 
2458  /* free genvboundstore hashmaps */
2459  SCIPhashmapFree(&(propdata->lbgenvbounds));
2460  SCIPhashmapFree(&(propdata->ubgenvbounds));
2461 
2462  /* free genvboundstore array */
2463  SCIPfreeMemoryArray(scip, &(propdata->genvboundstore));
2464 
2465  /* set the number of genvbounds to zero */
2466  propdata->ngenvbounds = 0;
2467 
2468  /* drop and free all events */
2469  SCIP_CALL( dropAndFreeEvents(scip, propdata) );
2470 
2471  /* free componentsstart array */
2472  SCIP_CALL( freeComponentsData(scip, propdata) );
2473 
2474  /* free starting indices data */
2475  SCIP_CALL( freeStartingData(scip, propdata) );
2476  }
2477 
2478  /* release the cutoffboundvar and undo the locks */
2479  if( propdata->cutoffboundvar != NULL && SCIPisInRestart(scip) == FALSE )
2480  {
2481  SCIP_CALL( SCIPaddVarLocks(scip, propdata->cutoffboundvar, -1, -1) );
2482  SCIP_CALL( SCIPreleaseVar(scip, &(propdata->cutoffboundvar)) );
2483  propdata->cutoffboundvar = NULL;
2484  SCIPdebugMessage("release cutoffboundvar!\n");
2485  }
2486 
2487  return SCIP_OKAY;
2488 }
2489 
2490 /** destructor of propagator to free user data (called when SCIP is exiting) */
2491 static
2492 SCIP_DECL_PROPFREE(propFreeGenvbounds)
2493 { /*lint --e{715}*/
2494  SCIP_PROPDATA* propdata;
2495 
2496  assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
2497 
2498  /* free propagator data */
2499  propdata = SCIPpropGetData(prop);
2500  assert(propdata != NULL);
2501 
2502  SCIPfreeMemory(scip, &propdata);
2503 
2504  SCIPpropSetData(prop, NULL);
2505 
2506  return SCIP_OKAY;
2507 }
2508 
2509 
2510 /*
2511  * Callback methods of event handler
2512  */
2513 
2514 static
2515 SCIP_DECL_EVENTEXEC(eventExecGenvbounds)
2516 { /*lint --e{715}*/
2517  SCIP_PROPDATA* propdata;
2518  int i;
2520  assert(scip != NULL);
2521  assert(eventdata != NULL);
2522 
2523  assert(SCIPeventGetType(event) == SCIP_EVENTTYPE_LBTIGHTENED || SCIPeventGetType(event) ==
2525 
2526  assert(eventdata->startcomponents != NULL);
2527  assert(eventdata->startindices != NULL);
2528  assert(eventdata->nstarts > 0);
2529  assert(eventdata->prop != NULL);
2530 
2531  propdata = SCIPpropGetData(eventdata->prop);
2532  assert(propdata != NULL);
2533 
2534  assert(propdata->startcomponents != NULL);
2535  assert(propdata->startmap != NULL);
2536  assert(propdata->startindices != NULL);
2537 
2538  SCIPdebugMessage("catching eventdata:\n");
2539  SCIPdebug( printEventData(eventdata, SCIPeventGetType(event) == SCIP_EVENTTYPE_LBTIGHTENED ?
2541 
2542  /* check if we need to reset old local starting indices data */
2543  if( SCIPgetCurrentNode(scip) != propdata->lastnodecaught )
2544  {
2545  SCIP_CALL( resetLocalStartingData(scip, propdata) );
2546  propdata->lastnodecaught = SCIPgetCurrentNode(scip);
2547  }
2548 
2549  for( i = 0; i < eventdata->nstarts; i++ )
2550  {
2551  int component;
2552  int startidx;
2553 
2554  component = eventdata->startcomponents[i];
2555  assert(component >= 0);
2556  startidx = eventdata->startindices[i];
2557 
2558  /* there is already an entry for this component */
2559  if( SCIPhashmapExists(propdata->startmap, (void*)(size_t) (component + 1)) )
2560  {
2561  int componentidx;
2562 
2563  /* get its index */
2564  componentidx = ((int)(size_t) SCIPhashmapGetImage(propdata->startmap, (void*)(size_t) (component + 1))) - 1; /*lint !e776*/
2565  assert(componentidx >= 0);
2566  assert(propdata->startcomponents[componentidx] == component);
2567 
2568  if( propdata->startindices[componentidx] > startidx )
2569  propdata->startindices[componentidx] = startidx;
2570  }
2571  else
2572  {
2573  /* get a new entry */
2574  int componentidx;
2575  componentidx = propdata->nindices;
2576 
2577  /* store index */
2578  propdata->startcomponents[componentidx] = component;
2579  propdata->startindices[componentidx] = startidx;
2580 
2581  /* store component in hashmap */
2582  SCIP_CALL( SCIPhashmapInsert(propdata->startmap, (void*)(size_t) (component + 1),
2583  (void*)(size_t) (componentidx + 1)) );
2584 
2585  /* increase number of starting indices */
2586  propdata->nindices++;
2587  }
2588  }
2589 
2590  return SCIP_OKAY;
2591 }
2592 
2593 /*
2594  * propagator specific interface methods
2595  */
2596 
2597 /** creates the genvbounds propagator and includes it in SCIP */
2599  SCIP* scip /**< SCIP data structure */
2600  )
2601 {
2602  SCIP_PROPDATA* propdata;
2603  SCIP_PROP* prop;
2604 
2605  /* create genvbounds propagator data */
2606  SCIP_CALL( SCIPallocMemory(scip, &propdata) );
2607 
2608  /* include propagator */
2610  propExecGenvbounds, propdata) );
2611 
2612  SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeGenvbounds) );
2613  SCIP_CALL( SCIPsetPropInit(scip, prop, propInitGenvbounds) );
2614  SCIP_CALL( SCIPsetPropInitpre(scip, prop, propInitpreGenvbounds) );
2615  SCIP_CALL( SCIPsetPropExitpre(scip, prop, propExitpreGenvbounds) );
2616  SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolGenvbounds) );
2617  SCIP_CALL( SCIPsetPropPresol(scip, prop, propPresolGenvbounds, PROP_PRESOL_PRIORITY,
2619  SCIP_CALL( SCIPsetPropResprop(scip, prop, propRespropGenvbounds) );
2620 
2621  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/global",
2622  "apply global propagation?",
2623  &propdata->global, TRUE, DEFAULT_GLOBAL_PROPAGATION, NULL, NULL) );
2624 
2625  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propinrootnode",
2626  "apply genvbounds in root node if no new incumbent was found?",
2627  &propdata->propinrootnode, TRUE, DEFAULT_PROPAGATE_IN_ROOT_NODE, NULL, NULL) );
2628 
2629  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/sort",
2630  "sort genvbounds and wait for bound change events?",
2631  &propdata->sort, TRUE, DEFAULT_SORT, NULL, NULL) );
2632 
2633  SCIP_CALL( SCIPaddBoolParam(scip, "propagating/" PROP_NAME "/propasconss",
2634  "should genvbounds be transformed to (linear) constraints?",
2635  &propdata->propasconss, TRUE, DEFAULT_PROPASCONSS, NULL, NULL) );
2636 
2637  /* include event handler */
2638  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &propdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecGenvbounds, NULL) );
2639 
2640  return SCIP_OKAY;
2641 }
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:7057
SCIP_RETCODE SCIPsetPropExitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITSOL((*propexitsol)))
Definition: scip.c:7025
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
SCIP_RETCODE SCIPsetPropInit(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINIT((*propinit)))
Definition: scip.c:6977
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
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:16443
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:17373
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
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:10378
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:41920
#define SCIP_MAXSTRLEN
Definition: def.h:201
static SCIP_RETCODE dropAndFreeEvents(SCIP *scip, SCIP_PROPDATA *propdata)
SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
Definition: misc.c:6077
#define NULL
Definition: lpi_spx.cpp:130
#define PROP_PRESOL_MAXROUNDS
#define PROP_DESC
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
static SCIP_DECL_PROPEXEC(propExecGenvbounds)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
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:24320
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
static SCIP_RETCODE freeEventData(SCIP *scip, SCIP_EVENTDATA **eventdata)
#define PROP_NAME
#define PROP_FREQ
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
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:15817
#define FALSE
Definition: def.h:56
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35113
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7778
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_DECL_PROPEXITSOL(propExitsolGenvbounds)
#define SCIP_CALL(x)
Definition: def.h:266
static GENVBOUND * getGenVBound(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype)
SCIP_Real SCIPgetTransObjoffset(SCIP *scip)
Definition: scip.c:10139
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:23083
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:38561
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:6253
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15737
#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:20841
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:6266
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:2116
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
static SCIP_RETCODE fillGlobalStartingData(SCIP *scip, SCIP_PROPDATA *propdata)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:42044
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:6189
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:3547
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2159
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16634
#define PROP_TIMING
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:5892
SCIP_RETCODE SCIPanalyzeConflict(SCIP *scip, int validdepth, SCIP_Bool *success)
Definition: scip.c:24689
SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, int nnodes)
Definition: misc.c:5596
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36622
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:24342
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
static SCIP_RETCODE addNewGenVBound(SCIP *scip, SCIP_PROPDATA *propdata, GENVBOUND *genvbound)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
Definition: prop.c:735
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPdebugPrintf
Definition: pub_message.h:80
SCIP_Bool SCIPisInRestart(SCIP *scip)
Definition: scip.c:15700
static SCIP_Real getGenVBoundsBound(SCIP *scip, GENVBOUND *genvbound, SCIP_Bool global)
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15859
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:41598
#define DEFAULT_PROPAGATE_IN_ROOT_NODE
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
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:2075
SCIP_Real * coefs
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
#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:7073
SCIP_RETCODE SCIPsetPropInitpre(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITPRE((*propinitpre)))
Definition: scip.c:7041
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:20944
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:32131
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41946
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:5814
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:253
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:264
void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
Definition: prop.c:745
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16884
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:254
#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:21150
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:23119
#define SCIP_UNKNOWN
Definition: def.h:148
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_RETCODE SCIPsetPropResprop(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPRESPROP((*propresprop)))
Definition: scip.c:7106
static SCIP_RETCODE setUpEvents(SCIP *scip, SCIP_PROPDATA *propdata)
#define SCIP_Bool
Definition: def.h:53
SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
Definition: scip.c:6961
#define SCIPduplicateMemoryArray(scip, ptr, source, num)
Definition: scip.h:20540
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:6908
SCIP_BOUNDTYPE boundtype
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:2337
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:23093
#define DEFAULT_SORT
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:6398
SCIP_RETCODE SCIPaddConflictRelaxedLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedlb)
Definition: scip.c:24403
SCIP_Real cutoffcoef
#define SCIPreallocMemoryArray(scip, ptr, newnum)
Definition: scip.h:20534
static SCIP_DECL_PROPFREE(propFreeGenvbounds)
static SCIP_DECL_PROPINITPRE(propInitpreGenvbounds)
#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:36779
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
#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:36668
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11477
SCIP_Real SCIPgetTransObjscale(SCIP *scip)
Definition: scip.c:10162
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2177
int SCIPgetNFixedVars(SCIP *scip)
Definition: scip.c:11015
#define REALABS(x)
Definition: def.h:151
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
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:21260
#define SCIP_Real
Definition: def.h:127
SCIP_Real SCIPgetConflictVarLb(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:24635
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:67
static SCIP_RETCODE sortGenVBounds(SCIP *scip, SCIP_PROPDATA *propdata)
#define SCIP_INVALID
Definition: def.h:147
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:41146
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:9941
SCIP_RETCODE SCIPaddConflictRelaxedUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedub)
Definition: scip.c:24471
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:19399
#define PROP_DELAY
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
#define DEFAULT_GLOBAL_PROPAGATION
#define SCIPdebug(x)
Definition: pub_message.h:74
static SCIP_DECL_PROPRESPROP(propRespropGenvbounds)
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
SCIP_Real SCIPgetConflictVarUb(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:24659
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:5742
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