Scippy

SCIP

Solving Constraint Integer Programs

cons.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-2022 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 visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons.c
17  * @ingroup OTHER_CFILES
18  * @brief methods for constraints and constraint handlers
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include <assert.h>
26 #include <string.h>
27 #include <ctype.h>
28 
29 #include "scip/def.h"
30 #include "scip/set.h"
31 #include "scip/stat.h"
32 #include "scip/clock.h"
33 #include "scip/var.h"
34 #include "scip/prob.h"
35 #include "scip/tree.h"
36 #include "scip/scip.h"
37 #include "scip/sepastore.h"
38 #include "scip/cons.h"
39 #include "scip/branch.h"
40 #include "scip/reopt.h"
41 #include "scip/pub_misc.h"
42 
43 #ifndef NDEBUG
44 #include "scip/struct_cons.h"
45 #endif
46 
47 
48 #define AGERESETAVG_INIT 1000.0 /**< initial value of the exponentially decaying weighted sum for ages */
49 #define AGERESETAVG_MIN 100.0 /**< minimal value to use for weighted sum of ages */
50 #define AGERESETAVG_DECAY 0.0005 /**< weight of a new addend in the exponentially decyaing sum */
51 #define AGERESETAVG_AGELIMIT 2.0 /**< in dynamic setting, a constraint is deleted if its age exceeds the
52  * average reset age by this factor */
53 #define AGERESETAVG_OBSOLETEAGE 1.8 /**< in dynamic setting, a constraint is marked obsolete if its age exceeds the
54  * average reset age by this factor */
55 
56 
57 /* #define CHECKCONSARRAYS */
58 
59 
60 /*
61  * dynamic memory arrays
62  */
63 
64 
65 /** resizes conss array to be able to store at least num constraints */
66 static
68  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
69  SCIP_SET* set, /**< global SCIP settings */
70  int num /**< minimal number of slots in array */
71  )
72 {
73  assert(conshdlr != NULL);
74  assert(set != NULL);
75 
76  if( num > conshdlr->consssize )
77  {
78  int newsize;
79 
80  newsize = SCIPsetCalcMemGrowSize(set, num);
81  SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->conss, newsize) );
82  conshdlr->consssize = newsize;
83  }
84  assert(num <= conshdlr->consssize);
85 
86  return SCIP_OKAY;
87 }
88 
89 /** resizes initconss array to be able to store at least num constraints */
90 static
92  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
93  SCIP_SET* set, /**< global SCIP settings */
94  int num /**< minimal number of slots in array */
95  )
96 {
97  assert(conshdlr != NULL);
98  assert(set != NULL);
99 
100  if( num > conshdlr->initconsssize )
101  {
102  int newsize;
103 
104  newsize = SCIPsetCalcMemGrowSize(set, num);
105  SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->initconss, newsize) );
106  conshdlr->initconsssize = newsize;
107  }
108  assert(num <= conshdlr->initconsssize);
109 
110  return SCIP_OKAY;
111 }
112 
113 /** resizes sepaconss array to be able to store at least num constraints */
114 static
116  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
117  SCIP_SET* set, /**< global SCIP settings */
118  int num /**< minimal number of slots in array */
119  )
120 {
121  assert(conshdlr != NULL);
122  assert(set != NULL);
123 
124  if( num > conshdlr->sepaconsssize )
125  {
126  int newsize;
127 
128  newsize = SCIPsetCalcMemGrowSize(set, num);
129  SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->sepaconss, newsize) );
130  conshdlr->sepaconsssize = newsize;
131  }
132  assert(num <= conshdlr->sepaconsssize);
133 
134  return SCIP_OKAY;
135 }
136 
137 /** resizes enfoconss array to be able to store at least num constraints */
138 static
140  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
141  SCIP_SET* set, /**< global SCIP settings */
142  int num /**< minimal number of slots in array */
143  )
144 {
145  assert(conshdlr != NULL);
146  assert(set != NULL);
147 
148  if( num > conshdlr->enfoconsssize )
149  {
150  int newsize;
151 
152  newsize = SCIPsetCalcMemGrowSize(set, num);
153  SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->enfoconss, newsize) );
154  conshdlr->enfoconsssize = newsize;
155  }
156  assert(num <= conshdlr->enfoconsssize);
157 
158  return SCIP_OKAY;
159 }
160 
161 /** resizes checkconss array to be able to store at least num constraints */
162 static
164  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
165  SCIP_SET* set, /**< global SCIP settings */
166  int num /**< minimal number of slots in array */
167  )
168 {
169  assert(conshdlr != NULL);
170  assert(set != NULL);
171 
172  if( num > conshdlr->checkconsssize )
173  {
174  int newsize;
175 
176  newsize = SCIPsetCalcMemGrowSize(set, num);
177  SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->checkconss, newsize) );
178  conshdlr->checkconsssize = newsize;
179  }
180  assert(num <= conshdlr->checkconsssize);
181 
182  return SCIP_OKAY;
183 }
184 
185 /** resizes propconss array to be able to store at least num constraints */
186 static
188  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
189  SCIP_SET* set, /**< global SCIP settings */
190  int num /**< minimal number of slots in array */
191  )
192 {
193  assert(conshdlr != NULL);
194  assert(set != NULL);
195 
196  if( num > conshdlr->propconsssize )
197  {
198  int newsize;
199 
200  newsize = SCIPsetCalcMemGrowSize(set, num);
201  SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->propconss, newsize) );
202  conshdlr->propconsssize = newsize;
203  }
204  assert(num <= conshdlr->propconsssize);
205 
206  return SCIP_OKAY;
207 }
208 
209 /** resizes updateconss array to be able to store at least num constraints */
210 static
212  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
213  SCIP_SET* set, /**< global SCIP settings */
214  int num /**< minimal number of slots in array */
215  )
216 {
217  assert(conshdlr != NULL);
218  assert(set != NULL);
219 
220  if( num > conshdlr->updateconsssize )
221  {
222  int newsize;
223 
224  newsize = SCIPsetCalcMemGrowSize(set, num);
225  SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->updateconss, newsize) );
226  conshdlr->updateconsssize = newsize;
227  }
228  assert(num <= conshdlr->updateconsssize);
229 
230  return SCIP_OKAY;
231 }
232 
233 
234 
235 
236 /*
237  * Constraint handler methods
238  */
239 
240 #define checkConssArrays(conshdlr) /**/
241 #ifndef NDEBUG
242 #ifdef CHECKCONSARRAYS
243 #undef checkConssArrays
244 /** sanity check for the constraint arrays of the constraint handler (only in debug mode) */
245 static
246 void checkConssArrays(
247  SCIP_CONSHDLR* conshdlr /**< constraint handler */
248  )
249 {
250  int c;
251 
252  assert(conshdlr != NULL);
253  assert(0 <= conshdlr->nactiveconss && conshdlr->nactiveconss <= conshdlr->nconss);
254 
255  for( c = 0; c < conshdlr->nconss; ++c )
256  {
257  assert(conshdlr->conss[c] != NULL);
258  assert(!conshdlr->conss[c]->original);
259  assert(conshdlr->conss[c]->active == (c < conshdlr->nactiveconss));
260  assert(conshdlr->conss[c]->consspos == c);
261  }
262 
263  for( c = 0; c < conshdlr->ninitconss; ++c )
264  {
265  assert(conshdlr->initconss[c] != NULL);
266  assert(!conshdlr->initconss[c]->original);
267  assert(c < conshdlr->ninitconsskept || conshdlr->initconss[c]->active);
268  assert(conshdlr->initconss[c]->initial);
269  }
270 
271  for( c = 0; c < conshdlr->nsepaconss; ++c )
272  {
273  assert(conshdlr->sepaconss[c] != NULL);
274  assert(!conshdlr->sepaconss[c]->original);
275  assert(conshdlr->sepaconss[c]->active);
276  assert(conshdlr->sepaconss[c]->separate);
277  assert(conshdlr->sepaconss[c]->sepaenabled);
278  assert(conshdlr->sepaconss[c]->obsolete == (c >= conshdlr->nusefulsepaconss));
279  }
280 
281  for( c = 0; c < conshdlr->nenfoconss; ++c )
282  {
283  assert(conshdlr->enfoconss[c] != NULL);
284  assert(!conshdlr->enfoconss[c]->original);
285  assert(conshdlr->enfoconss[c]->active);
286  assert(conshdlr->enfoconss[c]->enforce);
287  assert(conshdlr->enfoconss[c]->obsolete == (c >= conshdlr->nusefulenfoconss));
288  }
289 
290  for( c = 0; c < conshdlr->ncheckconss; ++c )
291  {
292  assert(conshdlr->checkconss[c] != NULL);
293  assert(!conshdlr->checkconss[c]->original);
294  assert(conshdlr->checkconss[c]->active);
295  assert(conshdlr->checkconss[c]->check);
296  assert(conshdlr->checkconss[c]->obsolete == (c >= conshdlr->nusefulcheckconss));
297  }
298 
299  for( c = 0; c < conshdlr->npropconss; ++c )
300  {
301  assert(conshdlr->propconss[c] != NULL);
302  assert(!conshdlr->propconss[c]->original);
303  assert(conshdlr->propconss[c]->active);
304  assert(conshdlr->propconss[c]->propagate);
305  assert(conshdlr->propconss[c]->propenabled);
306  assert(conshdlr->propconss[c]->markpropagate == (c < conshdlr->nmarkedpropconss));
307  assert(conshdlr->propconss[c]->markpropagate || (conshdlr->propconss[c]->obsolete == (c >= conshdlr->nusefulpropconss)));
308  }
309  assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss);
310 }
311 #endif
312 #endif
313 
314 /** returns whether the constraint updates of the constraint handler are currently delayed */
315 static
317  SCIP_CONSHDLR* conshdlr /**< constraint handler */
318  )
319 {
320  return (conshdlr->delayupdatecount > 0);
321 }
322 
323 /** returns the exponentially decaying weighted age average for age resets */
324 static
326  SCIP_CONSHDLR* conshdlr /**< constraint handler */
327  )
328 {
329  assert(conshdlr != NULL);
330 
331  return MAX(conshdlr->ageresetavg, AGERESETAVG_MIN);
332 }
333 
334 /** updates the exponentially decaying weighted age average for age resets after a constraint age was reset */
335 static
337  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
338  SCIP_Real age /**< age of the constraint that is reset to zero */
339  )
340 {
341  assert(conshdlr != NULL);
342 
343  conshdlr->ageresetavg *= (1.0-AGERESETAVG_DECAY);
344  conshdlr->ageresetavg += AGERESETAVG_DECAY * age;
345 }
346 
347 /** returns whether the constraint's age exceeds the age limit */
348 static
350  SCIP_CONS* cons, /**< constraint to check */
351  SCIP_SET* set /**< global SCIP settings */
352  )
353 {
354  assert(cons != NULL);
355  assert(set != NULL);
356 
357  return (cons->dynamic
358  && ((set->cons_agelimit > 0 && cons->age > set->cons_agelimit)
359  || (set->cons_agelimit == 0 && cons->age > AGERESETAVG_AGELIMIT * conshdlrGetAgeresetavg(cons->conshdlr))));
360 }
361 
362 /** returns whether the constraint's age exceeds the obsolete age limit */
363 static
365  SCIP_CONS* cons, /**< constraint to check */
366  SCIP_SET* set /**< global SCIP settings */
367  )
368 {
369  assert(cons != NULL);
370  assert(set != NULL);
371 
372  return (cons->dynamic
373  && ((set->cons_obsoleteage > 0 && cons->age > set->cons_obsoleteage)
374  || (set->cons_obsoleteage == 0 && cons->age > AGERESETAVG_OBSOLETEAGE * conshdlrGetAgeresetavg(cons->conshdlr))));
375 }
376 
377 /** marks constraint to be obsolete; it will be moved to the last part of the constraint arrays, such that
378  * it is checked, enforced, separated, and propagated after the useful constraints
379  */
380 static
382  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
383  SCIP_CONS* cons /**< constraint to be marked obsolete */
384  )
385 {
386  SCIP_CONS* tmpcons;
387 
388  assert(conshdlr != NULL);
389  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
390  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
391  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
392  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
393  assert(cons != NULL);
394  assert(!cons->original);
395  assert(!cons->obsolete);
396  assert(!conshdlrAreUpdatesDelayed(conshdlr));
397 
398  cons->obsolete = TRUE;
399 
400  if( cons->active )
401  {
402  if( cons->check )
403  {
404  assert(0 <= cons->checkconsspos && cons->checkconsspos < conshdlr->nusefulcheckconss);
405 
406  /* switch the last useful (non-obsolete) check constraint with this constraint */
407  tmpcons = conshdlr->checkconss[conshdlr->nusefulcheckconss-1];
408  assert(tmpcons->checkconsspos == conshdlr->nusefulcheckconss-1);
409 
410  conshdlr->checkconss[conshdlr->nusefulcheckconss-1] = cons;
411  conshdlr->checkconss[cons->checkconsspos] = tmpcons;
412  tmpcons->checkconsspos = cons->checkconsspos;
413  cons->checkconsspos = conshdlr->nusefulcheckconss-1;
414 
415  conshdlr->nusefulcheckconss--;
416  }
417  }
418  if( cons->enabled )
419  {
420  if( cons->separate && cons->sepaenabled )
421  {
422  assert(0 <= cons->sepaconsspos && cons->sepaconsspos < conshdlr->nusefulsepaconss);
423 
424  if( cons->sepaconsspos < conshdlr->lastnusefulsepaconss )
425  conshdlr->lastnusefulsepaconss--;
426 
427  /* switch the last useful (non-obsolete) sepa constraint with this constraint */
428  tmpcons = conshdlr->sepaconss[conshdlr->nusefulsepaconss-1];
429  assert(tmpcons->sepaconsspos == conshdlr->nusefulsepaconss-1);
430 
431  conshdlr->sepaconss[conshdlr->nusefulsepaconss-1] = cons;
432  conshdlr->sepaconss[cons->sepaconsspos] = tmpcons;
433  tmpcons->sepaconsspos = cons->sepaconsspos;
434  cons->sepaconsspos = conshdlr->nusefulsepaconss-1;
435 
436  conshdlr->nusefulsepaconss--;
437  }
438  if( cons->enforce )
439  {
440  assert(0 <= cons->enfoconsspos && cons->enfoconsspos < conshdlr->nusefulenfoconss);
441 
442  if( cons->enfoconsspos < conshdlr->lastnusefulenfoconss )
443  conshdlr->lastnusefulenfoconss--;
444  else
445  {
446  /* the constraint that becomes obsolete is not yet enforced on the current solution:
447  * we have to make sure that it will be enforced the next time; this is not done, if the current
448  * solution was already enforced and only enforcement on the additional constraints is performed
449  * (because in this case, only the new useful constraints are enforced);
450  * thus, we have to reset the enforcement counters in order to enforce all constraints again, especially
451  * the now obsolete one;
452  * this case should occur almost never, because a constraint that was not enforced in the last enforcement
453  * is a newly added one, and it is very unlikely that this constraint will become obsolete before the next
454  * enforcement call;
455  * this reset is not performed for separation and propagation, because they are not vital for correctness
456  */
457  conshdlr->lastenfolplpcount = -1;
458  conshdlr->lastenfolpdomchgcount = -1;
459  conshdlr->lastenfopsdomchgcount = -1;
460  conshdlr->lastenforelaxdomchgcount = -1;
461  conshdlr->lastenforelaxrelaxcount = -1;
462  conshdlr->lastenfolpnode = -1;
463  conshdlr->lastenfopsnode = -1;
464  }
465 
466  /* switch the last useful (non-obsolete) enfo constraint with this constraint */
467  tmpcons = conshdlr->enfoconss[conshdlr->nusefulenfoconss-1];
468  assert(tmpcons->enfoconsspos == conshdlr->nusefulenfoconss-1);
469 
470  conshdlr->enfoconss[conshdlr->nusefulenfoconss-1] = cons;
471  conshdlr->enfoconss[cons->enfoconsspos] = tmpcons;
472  tmpcons->enfoconsspos = cons->enfoconsspos;
473  cons->enfoconsspos = conshdlr->nusefulenfoconss-1;
474 
475  conshdlr->nusefulenfoconss--;
476  }
477  /* in case the constraint is marked to be propagated, we do not move it in the propconss array since the first
478  * part of the array contains all marked constraints independently of their age
479  */
480  assert((!cons->markpropagate) == (cons->propconsspos < conshdlr->nmarkedpropconss));
481  if( cons->propagate && cons->propenabled && !cons->markpropagate )
482  {
483  assert(0 <= cons->propconsspos && cons->propconsspos < conshdlr->nusefulpropconss);
484 
485  if( cons->propconsspos < conshdlr->lastnusefulpropconss )
486  conshdlr->lastnusefulpropconss--;
487 
488  /* switch the last useful (non-obsolete) prop constraint with this constraint */
489  tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss-1];
490  assert(tmpcons->propconsspos == conshdlr->nusefulpropconss-1);
491 
492  conshdlr->propconss[conshdlr->nusefulpropconss-1] = cons;
493  conshdlr->propconss[cons->propconsspos] = tmpcons;
494  tmpcons->propconsspos = cons->propconsspos;
495  cons->propconsspos = conshdlr->nusefulpropconss-1;
496 
497  conshdlr->nusefulpropconss--;
498  }
499  }
500 
501  checkConssArrays(conshdlr);
502 
503  return SCIP_OKAY;
504 }
505 
506 /** marks obsolete constraint to be not obsolete anymore;
507  * it will be moved to the first part of the constraint arrays, such that it is checked, enforced, separated,
508  * and propagated before the obsolete constraints
509  */
510 static
512  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
513  SCIP_CONS* cons /**< constraint to be marked obsolete */
514  )
515 {
516  SCIP_CONS* tmpcons;
517 
518  assert(conshdlr != NULL);
519  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
520  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
521  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
522  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
523  assert(cons != NULL);
524  assert(!cons->original);
525  assert(cons->obsolete);
526  assert(!conshdlrAreUpdatesDelayed(conshdlr));
527 
528  cons->obsolete = FALSE;
529 
530  if( cons->active )
531  {
532  if( cons->check )
533  {
534  assert(conshdlr->nusefulcheckconss <= cons->checkconsspos && cons->checkconsspos < conshdlr->ncheckconss);
535 
536  /* switch the first obsolete check constraint with this constraint */
537  tmpcons = conshdlr->checkconss[conshdlr->nusefulcheckconss];
538  assert(tmpcons->checkconsspos == conshdlr->nusefulcheckconss);
539 
540  conshdlr->checkconss[conshdlr->nusefulcheckconss] = cons;
541  conshdlr->checkconss[cons->checkconsspos] = tmpcons;
542  tmpcons->checkconsspos = cons->checkconsspos;
543  cons->checkconsspos = conshdlr->nusefulcheckconss;
544 
545  conshdlr->nusefulcheckconss++;
546  }
547  }
548  if( cons->enabled )
549  {
550  if( cons->separate && cons->sepaenabled )
551  {
552  assert(conshdlr->nusefulsepaconss <= cons->sepaconsspos && cons->sepaconsspos < conshdlr->nsepaconss);
553 
554  /* switch the first obsolete sepa constraint with this constraint */
555  tmpcons = conshdlr->sepaconss[conshdlr->nusefulsepaconss];
556  assert(tmpcons->sepaconsspos == conshdlr->nusefulsepaconss);
557 
558  conshdlr->sepaconss[conshdlr->nusefulsepaconss] = cons;
559  conshdlr->sepaconss[cons->sepaconsspos] = tmpcons;
560  tmpcons->sepaconsspos = cons->sepaconsspos;
561  cons->sepaconsspos = conshdlr->nusefulsepaconss;
562 
563  conshdlr->nusefulsepaconss++;
564  }
565  if( cons->enforce )
566  {
567  assert(conshdlr->nusefulenfoconss <= cons->enfoconsspos && cons->enfoconsspos < conshdlr->nenfoconss);
568 
569  /* switch the first obsolete enfo constraint with this constraint */
570  tmpcons = conshdlr->enfoconss[conshdlr->nusefulenfoconss];
571  assert(tmpcons->enfoconsspos == conshdlr->nusefulenfoconss);
572 
573  conshdlr->enfoconss[conshdlr->nusefulenfoconss] = cons;
574  conshdlr->enfoconss[cons->enfoconsspos] = tmpcons;
575  tmpcons->enfoconsspos = cons->enfoconsspos;
576  cons->enfoconsspos = conshdlr->nusefulenfoconss;
577 
578  conshdlr->nusefulenfoconss++;
579  }
580  /* in case the constraint is marked to be propagated, we do not move it in the propconss array since the first
581  * part of the array contains all marked constraints independently of their age
582  */
583  assert((!cons->markpropagate) == (cons->propconsspos < conshdlr->nmarkedpropconss));
584  if( cons->propagate && cons->propenabled && !cons->markpropagate)
585  {
586  assert(conshdlr->nusefulpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->npropconss);
587 
588  /* switch the first obsolete prop constraint with this constraint */
589  tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss];
590  assert(tmpcons->propconsspos == conshdlr->nusefulpropconss);
591 
592  conshdlr->propconss[conshdlr->nusefulpropconss] = cons;
593  conshdlr->propconss[cons->propconsspos] = tmpcons;
594  tmpcons->propconsspos = cons->propconsspos;
595  cons->propconsspos = conshdlr->nusefulpropconss;
596 
597  conshdlr->nusefulpropconss++;
598  }
599  }
600 
601  checkConssArrays(conshdlr);
602 
603  return SCIP_OKAY;
604 }
605 
606 /** marks constraint to be propagated in the next propagation round;
607  *
608  * @note the propagation array is divided into three parts in contrast to the other constraint arrays;
609  * the first part contains constraints which were marked to be propagated (independently of its age)
610  * the second part contains the useful (non-obsolete) constraints which are not marked to be propagated
611  * finally, the third part contains obsolete constraints which are not marked to be propagated
612  *
613  * @note if a constraint gets marked for propagation we put it into the first part regardless of its age
614  */
615 static
617  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
618  SCIP_CONS* cons /**< constraint to be marked obsolete */
619  )
620 {
621  SCIP_CONS* tmpcons;
622 
623  assert(conshdlr != NULL);
624  assert(conshdlr->nmarkedpropconss <= conshdlr->nusefulpropconss);
625  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
626  assert(cons != NULL);
627  assert(!cons->original);
628 
629  /* it may happen that the constraint is deleted while updates are delayed: in this case we just return */
630  if( !cons->enabled )
631  return;
632 
633  if( cons->markpropagate )
634  return;
635 
636  cons->markpropagate = TRUE;
637 
638  /* propagation of the constraint is globally or locally disabled, so we do not have to move the constraint in the
639  * propconss array
640  */
641  if( !cons->propagate || !cons->propenabled )
642  {
643  assert(cons->propconsspos == -1);
644  return;
645  }
646  assert(cons->propconsspos >= conshdlr->nmarkedpropconss);
647 
648  /* if the constraint is obsolete, we need to move it first to the non-obsolete part of the array */
649  if( cons->obsolete )
650  {
651  assert(conshdlr->nusefulpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->npropconss);
652 
653  /* switch the first obsolete prop constraint with this constraint */
654  tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss];
655  assert(tmpcons->propconsspos == conshdlr->nusefulpropconss);
656 
657  conshdlr->propconss[conshdlr->nusefulpropconss] = cons;
658  conshdlr->propconss[cons->propconsspos] = tmpcons;
659  tmpcons->propconsspos = cons->propconsspos;
660  cons->propconsspos = conshdlr->nusefulpropconss;
661 
662  conshdlr->nusefulpropconss++;
663  }
664  assert(conshdlr->nmarkedpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->nusefulpropconss);
665 
666  /* switch the first useful prop constraint with this constraint */
667  tmpcons = conshdlr->propconss[conshdlr->nmarkedpropconss];
668  assert(tmpcons->propconsspos == conshdlr->nmarkedpropconss);
669 
670  conshdlr->propconss[conshdlr->nmarkedpropconss] = cons;
671  conshdlr->propconss[cons->propconsspos] = tmpcons;
672  tmpcons->propconsspos = cons->propconsspos;
673  cons->propconsspos = conshdlr->nmarkedpropconss;
674 
675  conshdlr->nmarkedpropconss++;
676  assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss);
677 
678  checkConssArrays(conshdlr);
679 }
680 
681 /** unmarks constraint to be propagated in the next propagation round;
682  *
683  * @note the propagation array is divided into three parts in contrast to the other constraint arrays;
684  * the first part contains constraints which were marked to be propagated (independently of its age)
685  * the second part contains the useful (non-obsolete) constraints which are not marked to be propagated
686  * finally, the third part contains obsolete constraints which are not marked to be propagated
687  *
688  * @note if a constraint gets unmarked for propagation, it is put into the right part depending on its age
689  */
690 static
692  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
693  SCIP_CONS* cons /**< constraint to be marked obsolete */
694  )
695 {
696  SCIP_CONS* tmpcons;
697 
698  assert(conshdlr != NULL);
699  assert(conshdlr->nmarkedpropconss <= conshdlr->nusefulpropconss);
700  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
701  assert(cons != NULL);
702  assert(!cons->original);
703 
704  /* it may happen that the constraint is deleted while updates are delayed: in this case we just return */
705  if( !cons->enabled )
706  return;
707 
708  if( !cons->markpropagate )
709  return;
710 
711  cons->markpropagate = FALSE;
712 
713  /* propagation of the constraint is globally or locally disabled, so we do not have to move the constraint in the
714  * propconss array
715  */
716  if( !cons->propagate || !cons->propenabled )
717  {
718  assert(cons->propconsspos == -1);
719  return;
720  }
721  assert(cons->propconsspos >= 0);
722  assert(cons->propconsspos < conshdlr->nmarkedpropconss);
723 
724  /* first, move the constraint out of the first part to the second part of the constraint array */
725  if( cons->propconsspos < conshdlr->nmarkedpropconss - 1 )
726  {
727  conshdlr->nmarkedpropconss--;
728 
729  /* switch the last marked prop constraint with this constraint */
730  tmpcons = conshdlr->propconss[conshdlr->nmarkedpropconss];
731  assert(tmpcons->propconsspos == conshdlr->nmarkedpropconss);
732 
733  conshdlr->propconss[conshdlr->nmarkedpropconss] = cons;
734  conshdlr->propconss[cons->propconsspos] = tmpcons;
735  tmpcons->propconsspos = cons->propconsspos;
736  cons->propconsspos = conshdlr->nmarkedpropconss;
737  }
738  else if( cons->propconsspos == conshdlr->nmarkedpropconss - 1 )
739  conshdlr->nmarkedpropconss--;
740  assert(cons->propconsspos == conshdlr->nmarkedpropconss);
741 
742  /* if the constraint is obsolete, move it to the last part of the constraint array */
743  if( cons->obsolete )
744  {
745  conshdlr->nusefulpropconss--;
746 
747  /* switch the last useful prop constraint with this constraint */
748  tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss];
749  assert(tmpcons->propconsspos == conshdlr->nusefulpropconss);
750 
751  conshdlr->propconss[conshdlr->nusefulpropconss] = cons;
752  conshdlr->propconss[cons->propconsspos] = tmpcons;
753  tmpcons->propconsspos = cons->propconsspos;
754  cons->propconsspos = conshdlr->nusefulpropconss;
755  }
756 
757  checkConssArrays(conshdlr);
758 }
759 
760 
761 /** adds constraint to the conss array of constraint handler */
762 static
764  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
765  SCIP_SET* set, /**< global SCIP settings */
766  SCIP_CONS* cons /**< constraint to add */
767  )
768 {
769  assert(conshdlr != NULL);
770  assert(cons != NULL);
771  assert(cons->conshdlr == conshdlr);
772  assert(!cons->original);
773  assert(!cons->active);
774  assert(cons->consspos == -1);
775  assert(set != NULL);
776  assert(cons->scip == set->scip);
777 
778  /* insert the constraint as inactive constraint into the transformed constraints array */
779  SCIP_CALL( conshdlrEnsureConssMem(conshdlr, set, conshdlr->nconss+1) );
780  conshdlr->conss[conshdlr->nconss] = cons;
781  cons->consspos = conshdlr->nconss;
782  conshdlr->nconss++;
783 
784  return SCIP_OKAY;
785 }
786 
787 /** deletes constraint from the conss array of constraint handler */
788 static
789 void conshdlrDelCons(
790  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
791  SCIP_CONS* cons /**< constraint to remove */
792  )
793 {
794  assert(conshdlr != NULL);
795  assert(cons != NULL);
796  assert(cons->conshdlr == conshdlr);
797  assert(!cons->original);
798  assert(!cons->active);
799  assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss);
800 
801  conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nconss-1];
802  conshdlr->conss[cons->consspos]->consspos = cons->consspos;
803  conshdlr->nconss--;
804  cons->consspos = -1;
805 }
806 
807 /** adds constraint to the initconss array of constraint handler */
808 static
810  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
811  SCIP_SET* set, /**< global SCIP settings */
812  SCIP_STAT* stat, /**< dynamic problem statistics */
813  SCIP_CONS* cons /**< constraint to add */
814  )
815 {
816  int insertpos;
817 
818  assert(conshdlr != NULL);
819  assert(cons != NULL);
820  assert(cons->conshdlr == conshdlr);
821  assert(!cons->original);
822  assert(cons->active);
823  assert(cons->initial);
824  assert(cons->initconsspos == -1 || cons->initconsspos < conshdlr->ninitconsskept);
825 
826  SCIP_CALL( conshdlrEnsureInitconssMem(conshdlr, set, conshdlr->ninitconss+1) );
827 
828  insertpos = conshdlr->ninitconss;
829 
830  conshdlr->initconss[insertpos] = cons;
831  conshdlr->ninitconss++;
832  stat->ninitconssadded++;
833 
834  /* if the constraint is kept, we keep the stored position at the beginning of the array */
835  if( cons->initconsspos == -1 )
836  cons->initconsspos = insertpos;
837 
838  checkConssArrays(conshdlr);
839 
840  return SCIP_OKAY;
841 }
842 
843 /** deletes constraint from the initconss array of constraint handler */
844 static
846  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
847  SCIP_CONS* cons /**< constraint to remove */
848  )
849 {
850  int delpos;
851 
852  assert(conshdlr != NULL);
853  assert(cons != NULL);
854  assert(cons->conshdlr == conshdlr);
855  assert(!cons->original);
856  assert(0 <= cons->initconsspos && cons->initconsspos < conshdlr->ninitconss);
857 
858  delpos = cons->initconsspos;
859  if( delpos < conshdlr->ninitconsskept )
860  {
861  conshdlr->ninitconsskept--;
862  conshdlr->initconss[delpos] = conshdlr->initconss[conshdlr->ninitconsskept];
863  conshdlr->initconss[delpos]->initconsspos = delpos;
864  delpos = conshdlr->ninitconsskept;
865  }
866 
867  if( delpos < conshdlr->ninitconss-1 )
868  {
869  conshdlr->initconss[delpos] = conshdlr->initconss[conshdlr->ninitconss-1];
870  conshdlr->initconss[delpos]->initconsspos = delpos;
871  }
872  conshdlr->ninitconss--;
873  cons->initconsspos = -1;
874 
875  checkConssArrays(conshdlr);
876 }
877 
878 /** adds constraint to the sepaconss array of constraint handler */
879 static
881  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
882  SCIP_SET* set, /**< global SCIP settings */
883  SCIP_CONS* cons /**< constraint to add */
884  )
885 {
886  int insertpos;
887 
888  assert(conshdlr != NULL);
889  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
890  assert(cons != NULL);
891  assert(cons->conshdlr == conshdlr);
892  assert(!cons->original);
893  assert(cons->active);
894  assert(cons->separate);
895  assert(cons->sepaenabled);
896  assert(cons->sepaconsspos == -1);
897  assert(set != NULL);
898  assert(cons->scip == set->scip);
899  assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringsepa);
900 
901  SCIP_CALL( conshdlrEnsureSepaconssMem(conshdlr, set, conshdlr->nsepaconss+1) );
902  insertpos = conshdlr->nsepaconss;
903  if( !cons->obsolete )
904  {
905  if( conshdlr->nusefulsepaconss < conshdlr->nsepaconss )
906  {
907  conshdlr->sepaconss[conshdlr->nsepaconss] = conshdlr->sepaconss[conshdlr->nusefulsepaconss];
908  conshdlr->sepaconss[conshdlr->nsepaconss]->sepaconsspos = conshdlr->nsepaconss;
909  insertpos = conshdlr->nusefulsepaconss;
910  }
911  conshdlr->nusefulsepaconss++;
912  }
913  conshdlr->sepaconss[insertpos] = cons;
914  cons->sepaconsspos = insertpos;
915  conshdlr->nsepaconss++;
916 
917  checkConssArrays(conshdlr);
918 
919  return SCIP_OKAY;
920 }
921 
922 /** deletes constraint from the sepaconss array of constraint handler */
923 static
925  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
926  SCIP_CONS* cons /**< constraint to remove */
927  )
928 {
929  int delpos;
930 
931  assert(conshdlr != NULL);
932  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
933  assert(cons != NULL);
934  assert(cons->conshdlr == conshdlr);
935  assert(!cons->original);
936  assert(cons->separate);
937  assert(cons->sepaenabled);
938  assert(cons->sepaconsspos != -1);
939  assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringsepa);
940 
941  delpos = cons->sepaconsspos;
942  if( !cons->obsolete )
943  {
944  assert(0 <= delpos && delpos < conshdlr->nusefulsepaconss);
945 
946  if( delpos < conshdlr->lastnusefulsepaconss )
947  conshdlr->lastnusefulsepaconss--;
948 
949  conshdlr->sepaconss[delpos] = conshdlr->sepaconss[conshdlr->nusefulsepaconss-1];
950  conshdlr->sepaconss[delpos]->sepaconsspos = delpos;
951  delpos = conshdlr->nusefulsepaconss-1;
952  conshdlr->nusefulsepaconss--;
953  assert(conshdlr->nusefulsepaconss >= 0);
954  assert(conshdlr->lastnusefulsepaconss >= 0);
955  }
956  assert(conshdlr->nusefulsepaconss <= delpos && delpos < conshdlr->nsepaconss);
957  if( delpos < conshdlr->nsepaconss-1 )
958  {
959  conshdlr->sepaconss[delpos] = conshdlr->sepaconss[conshdlr->nsepaconss-1];
960  conshdlr->sepaconss[delpos]->sepaconsspos = delpos;
961  }
962  conshdlr->nsepaconss--;
963  cons->sepaconsspos = -1;
964 
965  checkConssArrays(conshdlr);
966 }
967 
968 /** adds constraint to the enfoconss array of constraint handler */
969 static
971  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
972  SCIP_SET* set, /**< global SCIP settings */
973  SCIP_CONS* cons /**< constraint to add */
974  )
975 {
976  int insertpos;
977 
978  assert(conshdlr != NULL);
979  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
980  assert(cons != NULL);
981  assert(cons->conshdlr == conshdlr);
982  assert(!cons->original);
983  assert(cons->active);
984  assert(cons->enforce);
985  assert(cons->enfoconsspos == -1);
986  assert(set != NULL);
987  assert(cons->scip == set->scip);
988 
989  SCIP_CALL( conshdlrEnsureEnfoconssMem(conshdlr, set, conshdlr->nenfoconss+1) );
990  insertpos = conshdlr->nenfoconss;
991  if( !cons->obsolete )
992  {
993  if( conshdlr->nusefulenfoconss < conshdlr->nenfoconss )
994  {
995  conshdlr->enfoconss[conshdlr->nenfoconss] = conshdlr->enfoconss[conshdlr->nusefulenfoconss];
996  conshdlr->enfoconss[conshdlr->nenfoconss]->enfoconsspos = conshdlr->nenfoconss;
997  insertpos = conshdlr->nusefulenfoconss;
998  }
999  conshdlr->nusefulenfoconss++;
1000  }
1001  else
1002  {
1003  /* we have to make sure that even this obsolete constraint is enforced in the next enforcement call;
1004  * if the same LP or pseudo solution is enforced again, only the newly added useful constraints are
1005  * enforced; thus, we have to reset the enforcement counters and force all constraints to be
1006  * enforced again; this is not needed for separation and propagation, because they are not vital for correctness
1007  */
1008  conshdlr->lastenfolplpcount = -1;
1009  conshdlr->lastenfolpdomchgcount = -1;
1010  conshdlr->lastenfopsdomchgcount = -1;
1011  conshdlr->lastenforelaxdomchgcount = -1;
1012  conshdlr->lastenforelaxrelaxcount = -1;
1013  conshdlr->lastenfolpnode = -1;
1014  conshdlr->lastenfopsnode = -1;
1015  }
1016  conshdlr->enfoconss[insertpos] = cons;
1017  cons->enfoconsspos = insertpos;
1018  conshdlr->nenfoconss++;
1019 
1020  checkConssArrays(conshdlr);
1021 
1022  return SCIP_OKAY;
1023 }
1024 
1025 /** deletes constraint from the enfoconss array of constraint handler */
1026 static
1027 void conshdlrDelEnfocons(
1028  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1029  SCIP_CONS* cons /**< constraint to remove */
1030  )
1031 {
1032  int delpos;
1033 
1034  assert(conshdlr != NULL);
1035  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1036  assert(cons != NULL);
1037  assert(cons->conshdlr == conshdlr);
1038  assert(!cons->original);
1039  assert(cons->enforce);
1040  assert(cons->enfoconsspos != -1);
1041 
1042  delpos = cons->enfoconsspos;
1043  if( !cons->obsolete )
1044  {
1045  assert(0 <= delpos && delpos < conshdlr->nusefulenfoconss);
1046 
1047  if( delpos < conshdlr->lastnusefulenfoconss )
1048  conshdlr->lastnusefulenfoconss--;
1049 
1050  conshdlr->enfoconss[delpos] = conshdlr->enfoconss[conshdlr->nusefulenfoconss-1];
1051  conshdlr->enfoconss[delpos]->enfoconsspos = delpos;
1052  delpos = conshdlr->nusefulenfoconss-1;
1053  conshdlr->nusefulenfoconss--;
1054 
1055  /* if the constraint that moved to the free position was a newly added constraint and not enforced in the last
1056  * enforcement, we have to make sure it will be enforced in the next run;
1057  * this check is not performed for separation and propagation, because they are not vital for correctness
1058  */
1059  if( delpos >= conshdlr->lastnusefulenfoconss )
1060  conshdlr->lastnusefulenfoconss = cons->enfoconsspos;
1061 
1062  assert(conshdlr->nusefulenfoconss >= 0);
1063  assert(conshdlr->lastnusefulenfoconss >= 0);
1064  }
1065  assert(conshdlr->nusefulenfoconss <= delpos && delpos < conshdlr->nenfoconss);
1066  if( delpos < conshdlr->nenfoconss-1 )
1067  {
1068  conshdlr->enfoconss[delpos] = conshdlr->enfoconss[conshdlr->nenfoconss-1];
1069  conshdlr->enfoconss[delpos]->enfoconsspos = delpos;
1070  }
1071  conshdlr->nenfoconss--;
1072  cons->enfoconsspos = -1;
1073 
1074  checkConssArrays(conshdlr);
1075 }
1076 
1077 /** adds constraint to the checkconss array of constraint handler */
1078 static
1080  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1081  SCIP_SET* set, /**< global SCIP settings */
1082  SCIP_CONS* cons /**< constraint to add */
1083  )
1084 {
1085  int insertpos;
1086 
1087  assert(conshdlr != NULL);
1088  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1089  assert(cons != NULL);
1090  assert(cons->conshdlr == conshdlr);
1091  assert(!cons->original);
1092  assert(cons->active);
1093  assert(cons->check);
1094  assert(cons->checkconsspos == -1);
1095  assert(set != NULL);
1096  assert(cons->scip == set->scip);
1097 
1098  SCIP_CALL( conshdlrEnsureCheckconssMem(conshdlr, set, conshdlr->ncheckconss+1) );
1099  insertpos = conshdlr->ncheckconss;
1100  if( !cons->obsolete )
1101  {
1102  if( conshdlr->nusefulcheckconss < conshdlr->ncheckconss )
1103  {
1104  assert(conshdlr->checkconss[conshdlr->nusefulcheckconss] != NULL);
1105  conshdlr->checkconss[conshdlr->ncheckconss] = conshdlr->checkconss[conshdlr->nusefulcheckconss];
1106  conshdlr->checkconss[conshdlr->ncheckconss]->checkconsspos = conshdlr->ncheckconss;
1107  insertpos = conshdlr->nusefulcheckconss;
1108  }
1109  conshdlr->nusefulcheckconss++;
1110  }
1111  assert(0 <= insertpos && insertpos <= conshdlr->ncheckconss);
1112  conshdlr->checkconss[insertpos] = cons;
1113  cons->checkconsspos = insertpos;
1114  conshdlr->ncheckconss++;
1115 
1116  checkConssArrays(conshdlr);
1117 
1118  return SCIP_OKAY;
1119 }
1120 
1121 /** deletes constraint from the checkconss array of constraint handler */
1122 static
1124  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1125  SCIP_CONS* cons /**< constraint to add */
1126  )
1127 {
1128  int delpos;
1129 
1130  assert(conshdlr != NULL);
1131  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1132  assert(cons != NULL);
1133  assert(cons->conshdlr == conshdlr);
1134  assert(!cons->original);
1135  assert(cons->active);
1136  assert(cons->check);
1137  assert(cons->checkconsspos != -1);
1138 
1139  delpos = cons->checkconsspos;
1140  if( !cons->obsolete )
1141  {
1142  assert(0 <= delpos && delpos < conshdlr->nusefulcheckconss);
1143  conshdlr->checkconss[delpos] = conshdlr->checkconss[conshdlr->nusefulcheckconss-1];
1144  conshdlr->checkconss[delpos]->checkconsspos = delpos;
1145  delpos = conshdlr->nusefulcheckconss-1;
1146  conshdlr->nusefulcheckconss--;
1147  }
1148  assert(conshdlr->nusefulcheckconss <= delpos && delpos < conshdlr->ncheckconss);
1149  if( delpos < conshdlr->ncheckconss-1 )
1150  {
1151  conshdlr->checkconss[delpos] = conshdlr->checkconss[conshdlr->ncheckconss-1];
1152  conshdlr->checkconss[delpos]->checkconsspos = delpos;
1153  }
1154  conshdlr->ncheckconss--;
1155  cons->checkconsspos = -1;
1156 
1157  checkConssArrays(conshdlr);
1158 }
1159 
1160 /** adds constraint to the propconss array of constraint handler */
1161 static
1163  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1164  SCIP_SET* set, /**< global SCIP settings */
1165  SCIP_CONS* cons /**< constraint to add */
1166  )
1167 {
1168  int insertpos;
1169 
1170  assert(conshdlr != NULL);
1171  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1172  assert(cons != NULL);
1173  assert(cons->conshdlr == conshdlr);
1174  assert(!cons->original);
1175  assert(cons->active);
1176  assert(cons->enabled);
1177  assert(cons->propagate);
1178  assert(cons->propenabled);
1179  assert(cons->propconsspos == -1);
1180  assert(set != NULL);
1181  assert(cons->scip == set->scip);
1182  assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringprop);
1183 
1184  /* add constraint to the propagation array */
1185  SCIP_CALL( conshdlrEnsurePropconssMem(conshdlr, set, conshdlr->npropconss+1) );
1186  insertpos = conshdlr->npropconss;
1187  if( !cons->obsolete )
1188  {
1189  if( conshdlr->nusefulpropconss < conshdlr->npropconss )
1190  {
1191  conshdlr->propconss[conshdlr->npropconss] = conshdlr->propconss[conshdlr->nusefulpropconss];
1192  conshdlr->propconss[conshdlr->npropconss]->propconsspos = conshdlr->npropconss;
1193  insertpos = conshdlr->nusefulpropconss;
1194  }
1195  conshdlr->nusefulpropconss++;
1196  }
1197  conshdlr->propconss[insertpos] = cons;
1198  cons->propconsspos = insertpos;
1199  conshdlr->npropconss++;
1200 
1201  /* if the constraint is marked to be propagated, we have to move it to the first part of the array */
1202  if( cons->markpropagate )
1203  {
1204  /* temporarily unmark the constraint to be propagated, such that we can use the method below */
1205  cons->markpropagate = FALSE;
1206 
1207  conshdlrMarkConsPropagate(cons->conshdlr, cons);
1208  assert(cons->markpropagate);
1209  }
1210 
1211  checkConssArrays(conshdlr);
1212 
1213  return SCIP_OKAY;
1214 }
1215 
1216 /** deletes constraint from the propconss array of constraint handler */
1217 static
1218 void conshdlrDelPropcons(
1219  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1220  SCIP_CONS* cons /**< constraint to remove */
1221  )
1222 {
1223  int delpos;
1224 
1225  assert(conshdlr != NULL);
1226  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1227  assert(cons != NULL);
1228  assert(cons->conshdlr == conshdlr);
1229  assert(!cons->original);
1230  assert(cons->propagate);
1231  assert(cons->propenabled);
1232  assert(cons->propconsspos != -1);
1233  assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringprop);
1234 
1235  /* unmark constraint to be propagated; this will move the constraint to the obsolete or non-obsolete part of the
1236  * array, depending on its age
1237  */
1238  if( cons->markpropagate )
1239  {
1241  assert(!cons->markpropagate);
1242  }
1243 
1244  /* delete constraint from the propagation array */
1245  delpos = cons->propconsspos;
1246  assert(delpos >= conshdlr->nmarkedpropconss);
1247  if( !cons->obsolete )
1248  {
1249  assert(0 <= delpos && delpos < conshdlr->nusefulpropconss);
1250 
1251  if( delpos < conshdlr->lastnusefulpropconss )
1252  conshdlr->lastnusefulpropconss--;
1253 
1254  conshdlr->propconss[delpos] = conshdlr->propconss[conshdlr->nusefulpropconss-1];
1255  conshdlr->propconss[delpos]->propconsspos = delpos;
1256  delpos = conshdlr->nusefulpropconss-1;
1257  conshdlr->nusefulpropconss--;
1258  assert(conshdlr->nusefulpropconss >= 0);
1259  assert(conshdlr->lastnusefulpropconss >= 0);
1260  }
1261  assert(conshdlr->nusefulpropconss <= delpos && delpos < conshdlr->npropconss);
1262 
1263  if( delpos < conshdlr->npropconss-1 )
1264  {
1265  conshdlr->propconss[delpos] = conshdlr->propconss[conshdlr->npropconss-1];
1266  conshdlr->propconss[delpos]->propconsspos = delpos;
1267  }
1268  conshdlr->npropconss--;
1269  cons->propconsspos = -1;
1270  assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss);
1271 
1272  checkConssArrays(conshdlr);
1273 }
1274 
1275 /** enables separation of constraint */
1276 static
1278  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1279  SCIP_SET* set, /**< global SCIP settings */
1280  SCIP_CONS* cons /**< constraint to add */
1281  )
1282 {
1283  assert(conshdlr != NULL);
1284  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1285  assert(cons != NULL);
1286  assert(cons->conshdlr == conshdlr);
1287  assert(!cons->sepaenabled);
1288  assert(cons->sepaconsspos == -1);
1289  assert(set != NULL);
1290  assert(cons->scip == set->scip);
1291 
1292  SCIPsetDebugMsg(set, "enable separation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1293 
1294  /* enable separation of constraint */
1295  cons->sepaenabled = TRUE;
1296 
1297  /* add constraint to the separation array */
1298  if( cons->enabled && cons->separate )
1299  {
1300  SCIP_CALL( conshdlrAddSepacons(conshdlr, set, cons) );
1301  }
1302 
1303  return SCIP_OKAY;
1304 }
1305 
1306 /** disables separation of constraint */
1307 static
1309  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1310  SCIP_CONS* cons /**< constraint to remove */
1311  )
1312 {
1313  assert(conshdlr != NULL);
1314  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1315  assert(cons != NULL);
1316  assert(cons->conshdlr == conshdlr);
1317  assert(cons->sepaenabled);
1318  assert((cons->separate && cons->enabled) == (cons->sepaconsspos != -1));
1319 
1320  SCIPdebugMessage("disable separation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1321 
1322  /* delete constraint from the separation array */
1323  if( cons->separate && cons->enabled )
1324  {
1325  conshdlrDelSepacons(conshdlr, cons);
1326  }
1327  assert(cons->sepaconsspos == -1);
1328 
1329  /* disable separation of constraint */
1330  cons->sepaenabled = FALSE;
1331 
1332  return SCIP_OKAY;
1333 }
1334 
1335 /** enables propagation of constraint */
1336 static
1338  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1339  SCIP_SET* set, /**< global SCIP settings */
1340  SCIP_CONS* cons /**< constraint to add */
1341  )
1342 {
1343  assert(conshdlr != NULL);
1344  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1345  assert(cons != NULL);
1346  assert(cons->conshdlr == conshdlr);
1347  assert(!cons->propenabled);
1348  assert(cons->propconsspos == -1);
1349  assert(set != NULL);
1350  assert(cons->scip == set->scip);
1351 
1352  SCIPsetDebugMsg(set, "enable propagation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1353 
1354  /* enable propagation of constraint */
1355  cons->propenabled = TRUE;
1356 
1357  /* add constraint to the propagation array */
1358  if( cons->enabled && cons->propagate )
1359  {
1360  SCIP_CALL( conshdlrAddPropcons(conshdlr, set, cons) );
1361  }
1362 
1363  return SCIP_OKAY;
1364 }
1365 
1366 /** disables propagation of constraint */
1367 static
1369  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1370  SCIP_CONS* cons /**< constraint to remove */
1371  )
1372 {
1373  assert(conshdlr != NULL);
1374  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1375  assert(cons != NULL);
1376  assert(cons->conshdlr == conshdlr);
1377  assert(cons->propenabled);
1378  assert((cons->propagate && cons->enabled) == (cons->propconsspos != -1));
1379 
1380  SCIPdebugMessage("disable propagation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1381 
1382  /* delete constraint from the propagation array */
1383  if( cons->propagate && cons->enabled )
1384  {
1385  conshdlrDelPropcons(conshdlr, cons);
1386  }
1387  assert(cons->propconsspos == -1);
1388 
1389  /* disable propagation of constraint */
1390  cons->propenabled = FALSE;
1391 
1392  return SCIP_OKAY;
1393 }
1394 
1395 /** enables separation, enforcement, and propagation of constraint */
1396 static
1398  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1399  SCIP_SET* set, /**< global SCIP settings */
1400  SCIP_STAT* stat, /**< dynamic problem statistics */
1401  SCIP_CONS* cons /**< constraint to add */
1402  )
1403 {
1404  assert(conshdlr != NULL);
1405  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1406  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1407  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1408  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1409  assert(set != NULL);
1410  assert(stat != NULL);
1411  assert(cons != NULL);
1412  assert(cons->scip == set->scip);
1413  assert(cons->conshdlr == conshdlr);
1414  assert(!cons->original);
1415  assert(cons->active);
1416  assert(!cons->enabled);
1417  assert(cons->sepaconsspos == -1);
1418  assert(cons->enfoconsspos == -1);
1419  assert(cons->propconsspos == -1);
1420 
1421  SCIPsetDebugMsg(set, "enable constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1422 
1423  /* enable constraint */
1424  cons->enabled = TRUE;
1425  conshdlr->nenabledconss++;
1426  stat->nenabledconss++;
1427 
1428  /* add constraint to the separation array */
1429  if( cons->separate && cons->sepaenabled )
1430  {
1431  SCIP_CALL( conshdlrAddSepacons(conshdlr, set, cons) );
1432  }
1433 
1434  /* add constraint to the enforcement array */
1435  if( cons->enforce )
1436  {
1437  SCIP_CALL( conshdlrAddEnfocons(conshdlr, set, cons) );
1438  }
1439 
1440  /* add constraint to the propagation array */
1441  if( cons->propagate && cons->propenabled )
1442  {
1443  SCIP_CALL( conshdlrAddPropcons(conshdlr, set, cons) );
1444  }
1445 
1446  /* call constraint handler's enabling notification method */
1447  if( conshdlr->consenable != NULL )
1448  {
1449  SCIP_CALL( conshdlr->consenable(set->scip, conshdlr, cons) );
1450  }
1451 
1452  checkConssArrays(conshdlr);
1453 
1454  return SCIP_OKAY;
1455 }
1456 
1457 /** disables separation, enforcement, and propagation of constraint */
1458 static
1460  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1461  SCIP_SET* set, /**< global SCIP settings */
1462  SCIP_STAT* stat, /**< dynamic problem statistics */
1463  SCIP_CONS* cons /**< constraint to remove */
1464  )
1465 {
1466  assert(conshdlr != NULL);
1467  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1468  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1469  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1470  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1471  assert(set != NULL);
1472  assert(stat != NULL);
1473  assert(cons != NULL);
1474  assert(cons->scip == set->scip);
1475  assert(cons->conshdlr == conshdlr);
1476  assert(!cons->original);
1477  assert(cons->active);
1478  assert(cons->enabled);
1479  assert((cons->separate && cons->sepaenabled) == (cons->sepaconsspos != -1));
1480  assert(cons->enforce == (cons->enfoconsspos != -1));
1481  assert((cons->propagate && cons->propenabled) == (cons->propconsspos != -1));
1482 
1483  SCIPsetDebugMsg(set, "disable constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1484 
1485  /* call constraint handler's disabling notification method */
1486  if( conshdlr->consdisable != NULL )
1487  {
1488  SCIP_CALL( conshdlr->consdisable(set->scip, conshdlr, cons) );
1489  }
1490 
1491  /* delete constraint from the separation array */
1492  if( cons->separate && cons->sepaenabled )
1493  {
1494  conshdlrDelSepacons(conshdlr, cons);
1495  }
1496 
1497  /* delete constraint from the enforcement array */
1498  if( cons->enforce )
1499  {
1500  conshdlrDelEnfocons(conshdlr, cons);
1501  }
1502 
1503  /* delete constraint from the propagation array */
1504  if( cons->propagate && cons->propenabled )
1505  {
1506  conshdlrDelPropcons(conshdlr, cons);
1507  }
1508 
1509  assert(cons->sepaconsspos == -1);
1510  assert(cons->enfoconsspos == -1);
1511  assert(cons->propconsspos == -1);
1512 
1513  /* disable constraint */
1514  cons->enabled = FALSE;
1515  conshdlr->nenabledconss--;
1516  stat->nenabledconss--;
1517 
1518  checkConssArrays(conshdlr);
1519 
1520  return SCIP_OKAY;
1521 }
1522 
1523 /** activates and adds constraint to constraint handler's constraint arrays */
1524 static
1526  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1527  SCIP_SET* set, /**< global SCIP settings */
1528  SCIP_STAT* stat, /**< dynamic problem statistics */
1529  SCIP_CONS* cons, /**< constraint to add */
1530  int depth, /**< depth in the tree where the activation takes place, or -1 for global problem */
1531  SCIP_Bool focusnode /**< does the constraint activation take place at the focus node? */
1532  )
1533 {
1534  assert(conshdlr != NULL);
1535  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1536  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1537  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1538  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1539  assert(set != NULL);
1540  assert(stat != NULL);
1541  assert(cons != NULL);
1542  assert(cons->scip == set->scip);
1543  assert(cons->conshdlr == conshdlr);
1544  assert(!cons->original);
1545  assert(!cons->active);
1546  assert(!cons->enabled);
1547  assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss);
1548  assert(conshdlr->conss[cons->consspos] == cons);
1549  assert(cons->initconsspos < conshdlr->ninitconsskept);
1550  assert(cons->sepaconsspos == -1);
1551  assert(cons->enfoconsspos == -1);
1552  assert(cons->checkconsspos == -1);
1553  assert(cons->propconsspos == -1);
1554  assert(depth >= -1);
1555 
1556  SCIPsetDebugMsg(set, "activate constraint <%s> in constraint handler <%s> (depth %d, focus=%u)\n",
1557  cons->name, conshdlr->name, depth, focusnode);
1558 
1559  /* activate constraint, switch positions with first inactive constraint */
1560  cons->active = TRUE;
1561  cons->activedepth = depth;
1562  conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nactiveconss];
1563  conshdlr->conss[cons->consspos]->consspos = cons->consspos;
1564  conshdlr->conss[conshdlr->nactiveconss] = cons;
1565  cons->consspos = conshdlr->nactiveconss;
1566  conshdlr->nactiveconss++;
1567  conshdlr->maxnactiveconss = MAX(conshdlr->maxnactiveconss, conshdlr->nactiveconss);
1568  stat->nactiveconss++;
1569 
1570  /* add constraint to the check array */
1571  if( cons->check )
1572  {
1573  SCIP_CALL( conshdlrAddCheckcons(conshdlr, set, cons) );
1574  }
1575 
1576  /* add constraint to the initconss array if the constraint is initial and added to the focus node */
1577  if( cons->initial )
1578  {
1579  SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, cons) );
1580  }
1581 
1582  /* call constraint handler's activation notification method */
1583  if( conshdlr->consactive != NULL )
1584  {
1585  SCIP_CALL( conshdlr->consactive(set->scip, conshdlr, cons) );
1586  }
1587 
1588  /* enable separation, enforcement, and propagation of constraint */
1589  SCIP_CALL( conshdlrEnableCons(conshdlr, set, stat, cons) );
1590 
1591  assert(0 <= cons->consspos && cons->consspos < conshdlr->nactiveconss);
1592 
1593  checkConssArrays(conshdlr);
1594 
1595  return SCIP_OKAY;
1596 }
1597 
1598 /** deactivates and removes constraint from constraint handler's conss array */
1599 static
1601  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1602  SCIP_SET* set, /**< global SCIP settings */
1603  SCIP_STAT* stat, /**< dynamic problem statistics */
1604  SCIP_CONS* cons /**< constraint to remove */
1605  )
1606 {
1607  assert(conshdlr != NULL);
1608  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1609  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1610  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1611  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1612  assert(set != NULL);
1613  assert(stat != NULL);
1614  assert(cons != NULL);
1615  assert(cons->scip == set->scip);
1616  assert(cons->conshdlr == conshdlr);
1617  assert(!cons->original);
1618  assert(cons->active);
1619  assert(0 <= cons->consspos && cons->consspos < conshdlr->nactiveconss);
1620  assert(conshdlr->conss[cons->consspos] == cons);
1621  assert(cons->check == (cons->checkconsspos != -1));
1622 
1623  SCIPsetDebugMsg(set, "deactivate constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1624 
1625  /* disable constraint */
1626  if( cons->enabled )
1627  {
1628  SCIP_CALL( conshdlrDisableCons(conshdlr, set, stat, cons) );
1629  }
1630  assert(!cons->enabled);
1631 
1632  /* call constraint handler's deactivation notification method */
1633  if( conshdlr->consdeactive != NULL )
1634  {
1635  SCIP_CALL( conshdlr->consdeactive(set->scip, conshdlr, cons) );
1636  }
1637 
1638  /* delete constraint from the initconss array */
1639  if( cons->initconsspos >= 0 )
1640  {
1641  conshdlrDelInitcons(conshdlr, cons);
1642  }
1643 
1644  /* delete constraint from the check array */
1645  if( cons->check )
1646  {
1647  conshdlrDelCheckcons(conshdlr, cons);
1648  }
1649 
1650  /* switch constraint with the last active constraint in the conss array */
1651  conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nactiveconss-1];
1652  conshdlr->conss[cons->consspos]->consspos = cons->consspos;
1653  conshdlr->conss[conshdlr->nactiveconss-1] = cons;
1654  cons->consspos = conshdlr->nactiveconss-1;
1655  conshdlr->nactiveconss--;
1656  cons->active = FALSE;
1657  cons->activedepth = -2;
1658  stat->nactiveconss--;
1659 
1660  assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss);
1661  assert(cons->initconsspos == -1);
1662  assert(cons->sepaconsspos == -1);
1663  assert(cons->enfoconsspos == -1);
1664  assert(cons->checkconsspos == -1);
1665  assert(cons->propconsspos == -1);
1666 
1667  checkConssArrays(conshdlr);
1668 
1669  return SCIP_OKAY;
1670 }
1671 
1672 /** processes all delayed updates of constraints:
1673  * recently (de)activated constraints will be (de)activated;
1674  * recently en/disabled constraints will be en/disabled;
1675  * recent obsolete non-check constraints will be globally deleted;
1676  * recent obsolete check constraints will be moved to the last positions in the sepa-, enfo-, check-, and prop-arrays;
1677  * recent useful constraints will be moved to the first positions in the sepa-, enfo-, check-, and prop-arrays;
1678  * constraints which were recently marked to be propagated are moved to the first positions in the prop-array;
1679  * no longer used constraints will be freed and removed from the conss array
1680  */
1681 static
1683  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1684  BMS_BLKMEM* blkmem, /**< block memory */
1685  SCIP_SET* set, /**< global SCIP settings */
1686  SCIP_STAT* stat /**< dynamic problem statistics */
1687  )
1688 {
1689  SCIP_CONS* cons;
1690  int i;
1691 
1692  assert(conshdlr != NULL);
1693  assert(!conshdlrAreUpdatesDelayed(conshdlr));
1694  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1695  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1696  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1697  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1698 
1699  SCIPsetDebugMsg(set, "processing %d constraints that have to be updated in constraint handler <%s>\n",
1700  conshdlr->nupdateconss, conshdlr->name);
1701 
1702  for( i = conshdlr->nupdateconss - 1; i >= 0; --i )
1703  {
1704  cons = conshdlr->updateconss[i];
1705  assert(cons != NULL);
1706  assert(cons->conshdlr == conshdlr);
1707  assert(cons->update);
1708  assert(cons->updateinsert || cons->updateactivate || cons->updatedeactivate
1709  || cons->updateenable || cons->updatedisable
1710  || cons->updatesepaenable || cons->updatesepadisable
1711  || cons->updatepropenable || cons->updatepropdisable
1712  || cons->updateobsolete || cons->updatefree
1713  || cons->updatemarkpropagate || cons->updateunmarkpropagate);
1714 
1715  SCIPsetDebugMsg(set, " -> constraint <%s>: insert=%u, activate=%u, deactivate=%u, enable=%u, disable=%u, sepaenable=%u, sepadisable=%u, propenable=%u, propdisable=%u, obsolete=%u, free=%u (consdata=%p)\n",
1716  cons->name, cons->updateinsert, cons->updateactivate, cons->updatedeactivate,
1717  cons->updateenable, cons->updatedisable,
1718  cons->updatesepaenable, cons->updatesepadisable,
1719  cons->updatepropenable, cons->updatepropdisable,
1720  cons->updateobsolete, cons->updatefree, (void*)cons->consdata);
1721 
1722  if( cons->updateinsert )
1723  {
1724  SCIP_CALL( conshdlrAddCons(conshdlr, set, cons) );
1725  cons->updateinsert = FALSE;
1726  }
1727 
1728  if( cons->updateactivate )
1729  {
1730  assert(!cons->active);
1731  assert(!cons->updatedeactivate);
1732  assert(!cons->updateenable);
1733  assert(!cons->updatedisable);
1734  assert(!cons->updateobsolete);
1735  assert(!cons->updatefree);
1736 
1737  /* the activation depth was already stored in SCIPconsActivate() */
1738  SCIP_CALL( conshdlrActivateCons(conshdlr, set, stat, cons, cons->activedepth, cons->updateactfocus) );
1739  assert(cons->active);
1740  cons->updateactivate = FALSE;
1741  }
1742  else if( cons->updatedeactivate )
1743  {
1744  assert(cons->active);
1745 
1746  SCIP_CALL( conshdlrDeactivateCons(conshdlr, set, stat, cons) );
1747  assert(!cons->active);
1748  cons->updatedeactivate = FALSE;
1749  cons->updateenable = FALSE;
1750  cons->updatedisable = FALSE;
1751  cons->obsolete = consExceedsObsoleteage(cons, set);
1752  cons->updateobsolete = FALSE;
1753  }
1754  else if( cons->updateenable )
1755  {
1756  assert(!cons->enabled);
1757  assert(!cons->updatedisable);
1758 
1759  SCIP_CALL( conshdlrEnableCons(conshdlr, set, stat, cons) );
1760  assert(cons->enabled);
1761  cons->updateenable = FALSE;
1762  }
1763  else if( cons->updatedisable )
1764  {
1765  assert(cons->enabled);
1766 
1767  SCIP_CALL( conshdlrDisableCons(conshdlr, set, stat, cons) );
1768  assert(!cons->enabled);
1769  cons->updatedisable = FALSE;
1770  }
1771 
1772  if( cons->updatesepaenable )
1773  {
1774  assert(!cons->updatesepadisable);
1775  if( !cons->sepaenabled )
1776  {
1777  SCIP_CALL( conshdlrEnableConsSeparation(conshdlr, set, cons) );
1778  assert(cons->sepaenabled);
1779  }
1780  cons->updatesepaenable = FALSE;
1781  }
1782  else if( cons->updatesepadisable )
1783  {
1784  if( cons->sepaenabled )
1785  {
1786  SCIP_CALL( conshdlrDisableConsSeparation(conshdlr, cons) );
1787  assert(!cons->sepaenabled);
1788  }
1789  cons->updatesepadisable = FALSE;
1790  }
1791 
1792  if( cons->updatepropenable )
1793  {
1794  assert(!cons->updatepropdisable);
1795  if( !cons->propenabled )
1796  {
1797  SCIP_CALL( conshdlrEnableConsPropagation(conshdlr, set, cons) );
1798  assert(cons->propenabled);
1799  }
1800  cons->updatepropenable = FALSE;
1801  }
1802  else if( cons->updatepropdisable )
1803  {
1804  if( cons->propenabled )
1805  {
1806  SCIP_CALL( conshdlrDisableConsPropagation(conshdlr, cons) );
1807  assert(!cons->propenabled);
1808  }
1809  cons->updatepropdisable = FALSE;
1810  }
1811 
1812  if( cons->updatefree )
1813  {
1814  /* nothing to do here: the constraint is freed, when it is released from the updateconss array */
1815  assert(cons->nuses == 1); /* it only exists in the updateconss array */
1816  cons->updatefree = FALSE;
1817  cons->updateobsolete = FALSE;
1818  }
1819  else
1820  {
1821  if( cons->updateobsolete )
1822  {
1823  if( !cons->obsolete && consExceedsObsoleteage(cons, set) )
1824  {
1825  /* the constraint's status must be switched to obsolete */
1826  SCIP_CALL( conshdlrMarkConsObsolete(conshdlr, cons) );
1827  }
1828  else if( cons->obsolete && !consExceedsObsoleteage(cons, set) )
1829  {
1830  /* the constraint's status must be switched to useful */
1831  SCIP_CALL( conshdlrMarkConsUseful(conshdlr, cons) );
1832  }
1833  cons->updateobsolete = FALSE;
1834  }
1835 
1836  if( cons->updatemarkpropagate )
1837  {
1838  /* the constraint must be marked to be propagated */
1839  conshdlrMarkConsPropagate(conshdlr, cons);
1840  cons->updatemarkpropagate = FALSE;
1841  }
1842  else if( cons->updateunmarkpropagate )
1843  {
1844  /* the constraint must be unmarked to be propagated */
1845  conshdlrUnmarkConsPropagate(conshdlr, cons);
1846  cons->updateunmarkpropagate = FALSE;
1847  }
1848  }
1849 
1850  assert(!cons->updateinsert);
1851  assert(!cons->updateactivate);
1852  assert(!cons->updatedeactivate);
1853  assert(!cons->updateenable);
1854  assert(!cons->updatedisable);
1855  assert(!cons->updatesepaenable);
1856  assert(!cons->updatesepadisable);
1857  assert(!cons->updatepropenable);
1858  assert(!cons->updatepropdisable);
1859  assert(!cons->updateobsolete);
1860  assert(!cons->updatemarkpropagate);
1861  assert(!cons->updateunmarkpropagate);
1862  assert(!cons->updatefree);
1863  cons->update = FALSE;
1864 
1865  /* release the constraint */
1866  SCIP_CALL( SCIPconsRelease(&conshdlr->updateconss[i], blkmem, set) );
1867  }
1868 
1869  conshdlr->nupdateconss = 0;
1870 
1871  return SCIP_OKAY;
1872 }
1873 
1874 /** marks constraint handler to delay all constraint updates until the next conshdlrProcessUpdates() call */
1875 static
1877  SCIP_CONSHDLR* conshdlr /**< constraint handler */
1878  )
1879 {
1880  assert(conshdlr != NULL);
1881 
1882  SCIPdebugMessage("constraint updates of constraint handler <%s> will be delayed (count:%d)\n",
1883  conshdlr->name, conshdlr->delayupdatecount+1);
1884 
1885  conshdlr->delayupdatecount++;
1886 }
1887 
1888 /** marks constraint handler to perform all constraint updates immediately;
1889  * all delayed constraint updates will be processed
1890  */
1891 static
1893  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1894  BMS_BLKMEM* blkmem, /**< block memory */
1895  SCIP_SET* set, /**< global SCIP settings */
1896  SCIP_STAT* stat /**< dynamic problem statistics */
1897  )
1898 {
1899  assert(conshdlr != NULL);
1900  assert(conshdlrAreUpdatesDelayed(conshdlr));
1901 
1902  SCIPsetDebugMsg(set, "constraint updates of constraint handler <%s> will be processed immediately (count:%d)\n",
1903  conshdlr->name, conshdlr->delayupdatecount);
1904  conshdlr->delayupdatecount--;
1905 
1906  /* only run the update if all delays are taken away (reference counting) */
1907  if( !conshdlrAreUpdatesDelayed(conshdlr) )
1908  {
1909  SCIP_CALL( conshdlrProcessUpdates(conshdlr, blkmem, set, stat) );
1910  assert(conshdlr->nupdateconss == 0);
1911  }
1912 
1913  return SCIP_OKAY;
1914 }
1915 
1916 /** adds constraint to constraint handler's update constraint array and captures it */
1917 static
1919  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1920  SCIP_SET* set, /**< global SCIP settings */
1921  SCIP_CONS* cons /**< constraint to add */
1922  )
1923 {
1924  assert(conshdlr != NULL);
1925  assert(set != NULL);
1926  assert(cons != NULL);
1927  assert(cons->conshdlr == conshdlr);
1928 
1929  if( !cons->update )
1930  {
1931  SCIPsetDebugMsg(set, "constraint <%s> of age %g has to be updated in constraint handler <%s> (consdata=%p)\n",
1932  cons->name, cons->age, conshdlr->name, (void*)cons->consdata);
1933 
1934  /* add constraint to the updateconss array */
1935  SCIP_CALL( conshdlrEnsureUpdateconssMem(conshdlr, set, conshdlr->nupdateconss+1) );
1936  conshdlr->updateconss[conshdlr->nupdateconss] = cons;
1937  conshdlr->nupdateconss++;
1938 
1939  /* capture constraint */
1940  SCIPconsCapture(cons);
1941 
1942  cons->update = TRUE;
1943  }
1944 
1945  return SCIP_OKAY;
1946 }
1947 
1948 /** compares two constraint handlers w. r. to their separation priority */
1949 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompSepa)
1950 { /*lint --e{715}*/
1951  return ((SCIP_CONSHDLR*)elem2)->sepapriority - ((SCIP_CONSHDLR*)elem1)->sepapriority;
1952 }
1953 
1954 /** compares two constraint handlers w. r. to their enforcing priority */
1955 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompEnfo)
1956 { /*lint --e{715}*/
1957  return ((SCIP_CONSHDLR*)elem2)->enfopriority - ((SCIP_CONSHDLR*)elem1)->enfopriority;
1958 }
1959 
1960 /** compares two constraint handlers w. r. to their feasibility check priority */
1961 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompCheck)
1962 { /*lint --e{715}*/
1963  return ((SCIP_CONSHDLR*)elem2)->checkpriority - ((SCIP_CONSHDLR*)elem1)->checkpriority;
1964 }
1965 
1966 /** copies the given constraint handler to a new scip */
1968  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1969  SCIP_SET* set, /**< SCIP_SET of SCIP to copy to */
1970  SCIP_Bool* valid /**< was the copying process valid? */
1971  )
1972 {
1973  assert(conshdlr != NULL);
1974  assert(set != NULL);
1975  assert(valid != NULL);
1976  assert(set->scip != NULL);
1977 
1978  if( conshdlr->conshdlrcopy != NULL )
1979  {
1980  SCIPsetDebugMsg(set, "including constraint handler %s in subscip %p\n", SCIPconshdlrGetName(conshdlr), (void*)set->scip);
1981  SCIP_CALL( conshdlr->conshdlrcopy(set->scip, conshdlr, valid) );
1982  }
1983 
1984  return SCIP_OKAY;
1985 }
1986 
1987 /** internal method for creating a constraint handler */
1988 static
1990  SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */
1991  SCIP_SET* set, /**< global SCIP settings */
1992  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1993  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
1994  const char* name, /**< name of constraint handler */
1995  const char* desc, /**< description of constraint handler */
1996  int sepapriority, /**< priority of the constraint handler for separation */
1997  int enfopriority, /**< priority of the constraint handler for constraint enforcing */
1998  int checkpriority, /**< priority of the constraint handler for checking feasibility (and propagation) */
1999  int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */
2000  int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */
2001  int eagerfreq, /**< frequency for using all instead of only the useful constraints in separation,
2002  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
2003  int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
2004  SCIP_Bool delaysepa, /**< should separation method be delayed, if other separators found cuts? */
2005  SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */
2006  SCIP_Bool needscons, /**< should the constraint handler be skipped, if no constraints are available? */
2007  SCIP_PROPTIMING proptiming, /**< positions in the node solving loop where propagation method of constraint handlers should be executed */
2008  SCIP_PRESOLTIMING presoltiming, /**< timing mask of the constraint handler's presolving method */
2009  SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
2010  SCIP_DECL_CONSFREE ((*consfree)), /**< destructor of constraint handler */
2011  SCIP_DECL_CONSINIT ((*consinit)), /**< initialize constraint handler */
2012  SCIP_DECL_CONSEXIT ((*consexit)), /**< deinitialize constraint handler */
2013  SCIP_DECL_CONSINITPRE ((*consinitpre)), /**< presolving initialization method of constraint handler */
2014  SCIP_DECL_CONSEXITPRE ((*consexitpre)), /**< presolving deinitialization method of constraint handler */
2015  SCIP_DECL_CONSINITSOL ((*consinitsol)), /**< solving process initialization method of constraint handler */
2016  SCIP_DECL_CONSEXITSOL ((*consexitsol)), /**< solving process deinitialization method of constraint handler */
2017  SCIP_DECL_CONSDELETE ((*consdelete)), /**< free specific constraint data */
2018  SCIP_DECL_CONSTRANS ((*constrans)), /**< transform constraint data into data belonging to the transformed problem */
2019  SCIP_DECL_CONSINITLP ((*consinitlp)), /**< initialize LP with relaxations of "initial" constraints */
2020  SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */
2021  SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */
2022  SCIP_DECL_CONSENFOLP ((*consenfolp)), /**< enforcing constraints for LP solutions */
2023  SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */
2024  SCIP_DECL_CONSENFOPS ((*consenfops)), /**< enforcing constraints for pseudo solutions */
2025  SCIP_DECL_CONSCHECK ((*conscheck)), /**< check feasibility of primal solution */
2026  SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */
2027  SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method */
2028  SCIP_DECL_CONSRESPROP ((*consresprop)), /**< propagation conflict resolving method */
2029  SCIP_DECL_CONSLOCK ((*conslock)), /**< variable rounding lock method */
2030  SCIP_DECL_CONSACTIVE ((*consactive)), /**< activation notification method */
2031  SCIP_DECL_CONSDEACTIVE((*consdeactive)), /**< deactivation notification method */
2032  SCIP_DECL_CONSENABLE ((*consenable)), /**< enabling notification method */
2033  SCIP_DECL_CONSDISABLE ((*consdisable)), /**< disabling notification method */
2034  SCIP_DECL_CONSDELVARS ((*consdelvars)), /**< variable deletion method */
2035  SCIP_DECL_CONSPRINT ((*consprint)), /**< constraint display method */
2036  SCIP_DECL_CONSCOPY ((*conscopy)), /**< constraint copying method */
2037  SCIP_DECL_CONSPARSE ((*consparse)), /**< constraint parsing method */
2038  SCIP_DECL_CONSGETVARS ((*consgetvars)), /**< constraint get variables method */
2039  SCIP_DECL_CONSGETNVARS((*consgetnvars)), /**< constraint get number of variable method */
2040  SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */
2041  SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */
2042  )
2043 {
2044  char paramname[SCIP_MAXSTRLEN];
2045  char paramdesc[SCIP_MAXSTRLEN];
2046 
2047  assert(conshdlr != NULL);
2048  assert(name != NULL);
2049  assert(desc != NULL);
2050  assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
2051  assert(consprop != NULL || propfreq == -1);
2052  assert(eagerfreq >= -1);
2053  assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL)));
2054 
2055  /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
2056  * error message
2057  */
2058  if( presoltiming < SCIP_PRESOLTIMING_NONE || presoltiming > SCIP_PRESOLTIMING_MAX )
2059  {
2060  SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
2061  "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", name);
2062 
2063  return SCIP_PARAMETERWRONGVAL;
2064  }
2065 
2066  /* both callbacks have to exist or not exist */
2067  assert((consgetvars != NULL) == (consgetnvars != NULL));
2068 
2069  SCIP_ALLOC( BMSallocMemory(conshdlr) );
2070  BMSclearMemory(*conshdlr);
2071 
2072  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->name, name, strlen(name)+1) );
2073  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->desc, desc, strlen(desc)+1) );
2074  (*conshdlr)->sepapriority = sepapriority;
2075  (*conshdlr)->enfopriority = enfopriority;
2076  (*conshdlr)->checkpriority = checkpriority;
2077  (*conshdlr)->sepafreq = sepafreq;
2078  (*conshdlr)->propfreq = propfreq;
2079  (*conshdlr)->eagerfreq = eagerfreq;
2080  (*conshdlr)->maxprerounds = maxprerounds;
2081  (*conshdlr)->conshdlrcopy = conshdlrcopy;
2082  (*conshdlr)->consfree = consfree;
2083  (*conshdlr)->consinit = consinit;
2084  (*conshdlr)->consexit = consexit;
2085  (*conshdlr)->consinitpre = consinitpre;
2086  (*conshdlr)->consexitpre = consexitpre;
2087  (*conshdlr)->consinitsol = consinitsol;
2088  (*conshdlr)->consexitsol = consexitsol;
2089  (*conshdlr)->consdelete = consdelete;
2090  (*conshdlr)->constrans = constrans;
2091  (*conshdlr)->consinitlp = consinitlp;
2092  (*conshdlr)->conssepalp = conssepalp;
2093  (*conshdlr)->conssepasol = conssepasol;
2094  (*conshdlr)->consenfolp = consenfolp;
2095  (*conshdlr)->consenforelax = consenforelax;
2096  (*conshdlr)->consenfops = consenfops;
2097  (*conshdlr)->conscheck = conscheck;
2098  (*conshdlr)->consprop = consprop;
2099  (*conshdlr)->conspresol = conspresol;
2100  (*conshdlr)->consresprop = consresprop;
2101  (*conshdlr)->conslock = conslock;
2102  (*conshdlr)->consactive = consactive;
2103  (*conshdlr)->consdeactive = consdeactive;
2104  (*conshdlr)->consenable = consenable;
2105  (*conshdlr)->consdisable = consdisable;
2106  (*conshdlr)->consprint = consprint;
2107  (*conshdlr)->consdelvars = consdelvars;
2108  (*conshdlr)->conscopy = conscopy;
2109  (*conshdlr)->consparse = consparse;
2110  (*conshdlr)->consgetvars = consgetvars;
2111  (*conshdlr)->consgetnvars = consgetnvars;
2112  (*conshdlr)->conshdlrdata = conshdlrdata;
2113  (*conshdlr)->consgetdivebdchgs = consgetdivebdchgs;
2114  (*conshdlr)->conss = NULL;
2115  (*conshdlr)->consssize = 0;
2116  (*conshdlr)->nconss = 0;
2117  (*conshdlr)->nactiveconss = 0;
2118  (*conshdlr)->maxnactiveconss = 0;
2119  (*conshdlr)->startnactiveconss = 0;
2120  (*conshdlr)->initconss = NULL;
2121  (*conshdlr)->initconsssize = 0;
2122  (*conshdlr)->ninitconss = 0;
2123  (*conshdlr)->ninitconsskept = 0;
2124  (*conshdlr)->sepaconss = NULL;
2125  (*conshdlr)->sepaconsssize = 0;
2126  (*conshdlr)->nsepaconss = 0;
2127  (*conshdlr)->nusefulsepaconss = 0;
2128  (*conshdlr)->enfoconss = NULL;
2129  (*conshdlr)->enfoconsssize = 0;
2130  (*conshdlr)->nenfoconss = 0;
2131  (*conshdlr)->nusefulenfoconss = 0;
2132  (*conshdlr)->checkconss = NULL;
2133  (*conshdlr)->checkconsssize = 0;
2134  (*conshdlr)->ncheckconss = 0;
2135  (*conshdlr)->nusefulcheckconss = 0;
2136  (*conshdlr)->propconss = NULL;
2137  (*conshdlr)->propconsssize = 0;
2138  (*conshdlr)->npropconss = 0;
2139  (*conshdlr)->nusefulpropconss = 0;
2140  (*conshdlr)->nmarkedpropconss = 0;
2141  (*conshdlr)->updateconss = NULL;
2142  (*conshdlr)->updateconsssize = 0;
2143  (*conshdlr)->nupdateconss = 0;
2144  (*conshdlr)->nenabledconss = 0;
2145  (*conshdlr)->lastnusefulpropconss = 0;
2146  (*conshdlr)->lastnusefulsepaconss = 0;
2147  (*conshdlr)->lastnusefulenfoconss = 0;
2148 
2149  (*conshdlr)->storedpropconss = NULL;
2150  (*conshdlr)->storedpropconsssize = 0;
2151  (*conshdlr)->storednmarkedpropconss = 0;
2152  (*conshdlr)->storedpropdomchgcount = 0;
2153 
2154  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
2155  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->presoltime, SCIP_CLOCKTYPE_DEFAULT) );
2156  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sepatime, SCIP_CLOCKTYPE_DEFAULT) );
2157  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfolptime, SCIP_CLOCKTYPE_DEFAULT) );
2158  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfopstime, SCIP_CLOCKTYPE_DEFAULT) );
2159  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enforelaxtime, SCIP_CLOCKTYPE_DEFAULT) );
2160  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->proptime, SCIP_CLOCKTYPE_DEFAULT) );
2161  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sbproptime, SCIP_CLOCKTYPE_DEFAULT) );
2162  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->checktime, SCIP_CLOCKTYPE_DEFAULT) );
2163  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->resproptime, SCIP_CLOCKTYPE_DEFAULT) );
2164 
2165  (*conshdlr)->nsepacalls = 0;
2166  (*conshdlr)->nenfolpcalls = 0;
2167  (*conshdlr)->nenfopscalls = 0;
2168  (*conshdlr)->nenforelaxcalls = 0;
2169  (*conshdlr)->npropcalls = 0;
2170  (*conshdlr)->ncheckcalls = 0;
2171  (*conshdlr)->nrespropcalls = 0;
2172  (*conshdlr)->ncutoffs = 0;
2173  (*conshdlr)->ncutsfound = 0;
2174  (*conshdlr)->ncutsapplied = 0;
2175  (*conshdlr)->nconssfound = 0;
2176  (*conshdlr)->ndomredsfound = 0;
2177  (*conshdlr)->nchildren = 0;
2178  (*conshdlr)->lastpropdomchgcount = -1;
2179  (*conshdlr)->lastsepalpcount = -1;
2180  (*conshdlr)->lastenfolplpcount = -1;
2181  (*conshdlr)->lastenfolpdomchgcount = -1;
2182  (*conshdlr)->lastenfopsdomchgcount = -1;
2183  (*conshdlr)->lastenforelaxdomchgcount = -1;
2184  (*conshdlr)->lastenforelaxrelaxcount = -1;
2185  (*conshdlr)->lastenfolpnode = -1;
2186  (*conshdlr)->lastenfopsnode = -1;
2187  (*conshdlr)->lastenfolpresult = SCIP_DIDNOTRUN;
2188  (*conshdlr)->lastenfopsresult = SCIP_DIDNOTRUN;
2189  (*conshdlr)->lastenforelaxresult = SCIP_DIDNOTRUN;
2190  (*conshdlr)->lastnfixedvars = 0;
2191  (*conshdlr)->lastnaggrvars = 0;
2192  (*conshdlr)->lastnchgvartypes = 0;
2193  (*conshdlr)->lastnchgbds = 0;
2194  (*conshdlr)->lastnaddholes = 0;
2195  (*conshdlr)->lastndelconss = 0;
2196  (*conshdlr)->lastnaddconss = 0;
2197  (*conshdlr)->lastnupgdconss = 0;
2198  (*conshdlr)->lastnchgcoefs = 0;
2199  (*conshdlr)->lastnchgsides = 0;
2200  (*conshdlr)->nfixedvars = 0;
2201  (*conshdlr)->naggrvars = 0;
2202  (*conshdlr)->nchgvartypes = 0;
2203  (*conshdlr)->nchgbds = 0;
2204  (*conshdlr)->naddholes = 0;
2205  (*conshdlr)->ndelconss = 0;
2206  (*conshdlr)->naddconss = 0;
2207  (*conshdlr)->nupgdconss = 0;
2208  (*conshdlr)->nchgcoefs = 0;
2209  (*conshdlr)->nchgsides = 0;
2210  (*conshdlr)->npresolcalls = 0;
2211  (*conshdlr)->delayupdatecount = 0;
2212  (*conshdlr)->ageresetavg = AGERESETAVG_INIT;
2213  (*conshdlr)->needscons = needscons;
2214  (*conshdlr)->sepalpwasdelayed = FALSE;
2215  (*conshdlr)->sepasolwasdelayed = FALSE;
2216  (*conshdlr)->propwasdelayed = FALSE;
2217  (*conshdlr)->duringsepa = FALSE;
2218  (*conshdlr)->duringprop = FALSE;
2219  (*conshdlr)->initialized = FALSE;
2220 
2221  /* add parameters */
2222  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/sepafreq", name);
2223  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2224  "frequency for separating cuts (-1: never, 0: only in root node)",
2225  &(*conshdlr)->sepafreq, FALSE, sepafreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2226 
2227  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/propfreq", name);
2228  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2229  "frequency for propagating domains (-1: never, 0: only in root node)",
2230  &(*conshdlr)->propfreq, FALSE, propfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2231 
2232  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/proptiming", name);
2233  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing when constraint propagation should be called (%u:BEFORELP, %u:DURINGLPLOOP, %u:AFTERLPLOOP, %u:ALWAYS)", SCIP_PROPTIMING_BEFORELP, SCIP_PROPTIMING_DURINGLPLOOP, SCIP_PROPTIMING_AFTERLPLOOP, SCIP_PROPTIMING_ALWAYS);
2234  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
2235  (int*)(&(*conshdlr)->proptiming), TRUE, (int) proptiming, (int) SCIP_PROPTIMING_BEFORELP, (int) SCIP_PROPTIMING_ALWAYS, NULL, NULL) ); /*lint !e713*/
2236 
2237  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/eagerfreq", name);
2238  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2239  "frequency for using all instead of only the useful constraints in separation, propagation and enforcement (-1: never, 0: only in first evaluation)",
2240  &(*conshdlr)->eagerfreq, TRUE, eagerfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2241 
2242  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/maxprerounds", name);
2243  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2244  "maximal number of presolving rounds the constraint handler participates in (-1: no limit)",
2245  &(*conshdlr)->maxprerounds, TRUE, maxprerounds, -1, INT_MAX, NULL, NULL) );
2246 
2247  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delaysepa", name);
2248  SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
2249  "should separation method be delayed, if other separators found cuts?",
2250  &(*conshdlr)->delaysepa, TRUE, delaysepa, NULL, NULL) ); /*lint !e740*/
2251 
2252  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delayprop", name);
2253  SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
2254  "should propagation method be delayed, if other propagators found reductions?",
2255  &(*conshdlr)->delayprop, TRUE, delayprop, NULL, NULL) ); /*lint !e740*/
2256 
2257  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/presoltiming", name);
2258  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing mask of the constraint handler's presolving method (%u:FAST, %u:MEDIUM, %u:EXHAUSTIVE, %u:FINAL)",
2260  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
2261  (int*)&(*conshdlr)->presoltiming, TRUE, (int) presoltiming, (int) SCIP_PRESOLTIMING_FAST, (int) SCIP_PRESOLTIMING_MAX, NULL, NULL) ); /*lint !e740 !e713*/
2262 
2263  return SCIP_OKAY;
2264 }
2265 
2266 /** creates a constraint handler */
2268  SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */
2269  SCIP_SET* set, /**< global SCIP settings */
2270  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2271  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
2272  const char* name, /**< name of constraint handler */
2273  const char* desc, /**< description of constraint handler */
2274  int sepapriority, /**< priority of the constraint handler for separation */
2275  int enfopriority, /**< priority of the constraint handler for constraint enforcing */
2276  int checkpriority, /**< priority of the constraint handler for checking feasibility (and propagation) */
2277  int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */
2278  int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */
2279  int eagerfreq, /**< frequency for using all instead of only the useful constraints in separation,
2280  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
2281  int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
2282  SCIP_Bool delaysepa, /**< should separation method be delayed, if other separators found cuts? */
2283  SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */
2284  SCIP_Bool needscons, /**< should the constraint handler be skipped, if no constraints are available? */
2285  SCIP_PROPTIMING proptiming, /**< positions in the node solving loop where propagation method of constraint handlers should be executed */
2286  SCIP_PRESOLTIMING presoltiming, /**< timing mask of the constraint handler's presolving method */
2287  SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
2288  SCIP_DECL_CONSFREE ((*consfree)), /**< destructor of constraint handler */
2289  SCIP_DECL_CONSINIT ((*consinit)), /**< initialize constraint handler */
2290  SCIP_DECL_CONSEXIT ((*consexit)), /**< deinitialize constraint handler */
2291  SCIP_DECL_CONSINITPRE ((*consinitpre)), /**< presolving initialization method of constraint handler */
2292  SCIP_DECL_CONSEXITPRE ((*consexitpre)), /**< presolving deinitialization method of constraint handler */
2293  SCIP_DECL_CONSINITSOL ((*consinitsol)), /**< solving process initialization method of constraint handler */
2294  SCIP_DECL_CONSEXITSOL ((*consexitsol)), /**< solving process deinitialization method of constraint handler */
2295  SCIP_DECL_CONSDELETE ((*consdelete)), /**< free specific constraint data */
2296  SCIP_DECL_CONSTRANS ((*constrans)), /**< transform constraint data into data belonging to the transformed problem */
2297  SCIP_DECL_CONSINITLP ((*consinitlp)), /**< initialize LP with relaxations of "initial" constraints */
2298  SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */
2299  SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */
2300  SCIP_DECL_CONSENFOLP ((*consenfolp)), /**< enforcing constraints for LP solutions */
2301  SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */
2302  SCIP_DECL_CONSENFOPS ((*consenfops)), /**< enforcing constraints for pseudo solutions */
2303  SCIP_DECL_CONSCHECK ((*conscheck)), /**< check feasibility of primal solution */
2304  SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */
2305  SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method */
2306  SCIP_DECL_CONSRESPROP ((*consresprop)), /**< propagation conflict resolving method */
2307  SCIP_DECL_CONSLOCK ((*conslock)), /**< variable rounding lock method */
2308  SCIP_DECL_CONSACTIVE ((*consactive)), /**< activation notification method */
2309  SCIP_DECL_CONSDEACTIVE((*consdeactive)), /**< deactivation notification method */
2310  SCIP_DECL_CONSENABLE ((*consenable)), /**< enabling notification method */
2311  SCIP_DECL_CONSDISABLE ((*consdisable)), /**< disabling notification method */
2312  SCIP_DECL_CONSDELVARS ((*consdelvars)), /**< variable deletion method */
2313  SCIP_DECL_CONSPRINT ((*consprint)), /**< constraint display method */
2314  SCIP_DECL_CONSCOPY ((*conscopy)), /**< constraint copying method */
2315  SCIP_DECL_CONSPARSE ((*consparse)), /**< constraint parsing method */
2316  SCIP_DECL_CONSGETVARS ((*consgetvars)), /**< constraint get variables method */
2317  SCIP_DECL_CONSGETNVARS((*consgetnvars)), /**< constraint get number of variable method */
2318  SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */
2319  SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */
2320  )
2321 {
2322  assert(conshdlr != NULL);
2323  assert(name != NULL);
2324  assert(desc != NULL);
2325  assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
2326  assert(consprop != NULL || propfreq == -1);
2327  assert(eagerfreq >= -1);
2328  assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL)));
2329 
2330  SCIP_CALL_FINALLY( doConshdlrCreate(conshdlr, set, messagehdlr, blkmem, name, desc, sepapriority, enfopriority,
2331  checkpriority, sepafreq, propfreq, eagerfreq, maxprerounds, delaysepa, delayprop, needscons, proptiming,
2332  presoltiming, conshdlrcopy, consfree, consinit, consexit, consinitpre, consexitpre, consinitsol, consexitsol,
2333  consdelete, constrans, consinitlp, conssepalp, conssepasol, consenfolp, consenforelax, consenfops, conscheck,
2334  consprop, conspresol, consresprop, conslock, consactive, consdeactive, consenable, consdisable, consdelvars,
2335  consprint, conscopy, consparse, consgetvars, consgetnvars, consgetdivebdchgs, conshdlrdata),
2336  (void) SCIPconshdlrFree(conshdlr, set) );
2337 
2338  return SCIP_OKAY;
2339 } /*lint !e715*/
2340 
2341 /** calls destructor and frees memory of constraint handler */
2343  SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */
2344  SCIP_SET* set /**< global SCIP settings */
2345  )
2346 {
2347  assert(conshdlr != NULL);
2348  if( *conshdlr == NULL )
2349  return SCIP_OKAY;
2350  assert(!(*conshdlr)->initialized);
2351  assert((*conshdlr)->nconss == 0);
2352  assert(set != NULL);
2353 
2354  /* call destructor of constraint handler */
2355  if( (*conshdlr)->consfree != NULL )
2356  {
2357  SCIP_CALL( (*conshdlr)->consfree(set->scip, *conshdlr) );
2358  }
2359 
2360  SCIPclockFree(&(*conshdlr)->resproptime);
2361  SCIPclockFree(&(*conshdlr)->checktime);
2362  SCIPclockFree(&(*conshdlr)->sbproptime);
2363  SCIPclockFree(&(*conshdlr)->proptime);
2364  SCIPclockFree(&(*conshdlr)->enforelaxtime);
2365  SCIPclockFree(&(*conshdlr)->enfopstime);
2366  SCIPclockFree(&(*conshdlr)->enfolptime);
2367  SCIPclockFree(&(*conshdlr)->sepatime);
2368  SCIPclockFree(&(*conshdlr)->presoltime);
2369  SCIPclockFree(&(*conshdlr)->setuptime);
2370 
2371  BMSfreeMemoryArrayNull(&(*conshdlr)->name);
2372  BMSfreeMemoryArrayNull(&(*conshdlr)->desc);
2373  BMSfreeMemoryArrayNull(&(*conshdlr)->conss);
2374  BMSfreeMemoryArrayNull(&(*conshdlr)->initconss);
2375  BMSfreeMemoryArrayNull(&(*conshdlr)->sepaconss);
2376  BMSfreeMemoryArrayNull(&(*conshdlr)->enfoconss);
2377  BMSfreeMemoryArrayNull(&(*conshdlr)->checkconss);
2378  BMSfreeMemoryArrayNull(&(*conshdlr)->propconss);
2379  BMSfreeMemoryArrayNull(&(*conshdlr)->updateconss);
2380  BMSfreeMemoryArrayNull(&(*conshdlr)->storedpropconss);
2381  BMSfreeMemory(conshdlr);
2382 
2383  return SCIP_OKAY;
2384 }
2385 
2386 /** calls initialization method of constraint handler */
2388  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2389  BMS_BLKMEM* blkmem, /**< block memory */
2390  SCIP_SET* set, /**< global SCIP settings */
2391  SCIP_STAT* stat /**< dynamic problem statistics */
2392  )
2393 {
2394  assert(conshdlr != NULL);
2395  assert(set != NULL);
2396 
2397  if( conshdlr->initialized )
2398  {
2399  SCIPerrorMessage("constraint handler <%s> already initialized\n", conshdlr->name);
2400  return SCIP_INVALIDCALL;
2401  }
2402 
2403  if( set->misc_resetstat )
2404  {
2405  SCIPclockReset(conshdlr->setuptime);
2406  SCIPclockReset(conshdlr->presoltime);
2407  SCIPclockReset(conshdlr->sepatime);
2408  SCIPclockReset(conshdlr->enfolptime);
2409  SCIPclockReset(conshdlr->enfopstime);
2410  SCIPclockReset(conshdlr->enforelaxtime);
2411  SCIPclockReset(conshdlr->proptime);
2412  SCIPclockReset(conshdlr->sbproptime);
2413  SCIPclockReset(conshdlr->checktime);
2414  SCIPclockReset(conshdlr->resproptime);
2415 
2416  conshdlr->nsepacalls = 0;
2417  conshdlr->nenfolpcalls = 0;
2418  conshdlr->nenfopscalls = 0;
2419  conshdlr->nenforelaxcalls = 0;
2420  conshdlr->npropcalls = 0;
2421  conshdlr->ncheckcalls = 0;
2422  conshdlr->nrespropcalls = 0;
2423  conshdlr->ncutoffs = 0;
2424  conshdlr->ncutsfound = 0;
2425  conshdlr->ncutsapplied = 0;
2426  conshdlr->nconssfound = 0;
2427  conshdlr->ndomredsfound = 0;
2428  conshdlr->nchildren = 0;
2429  conshdlr->lastpropdomchgcount = -1;
2430  conshdlr->lastenfolpdomchgcount = -1;
2431  conshdlr->lastenfopsdomchgcount = -1;
2432  conshdlr->lastenforelaxdomchgcount = -1;
2433  conshdlr->lastenforelaxrelaxcount = -1;
2434  conshdlr->lastenfolpnode = -1;
2435  conshdlr->lastenfopsnode = -1;
2436  conshdlr->lastenfolpresult = SCIP_DIDNOTRUN;
2437  conshdlr->lastenfopsresult = SCIP_DIDNOTRUN;
2438  conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2439  conshdlr->startnactiveconss = 0;
2440  conshdlr->lastsepalpcount = -1;
2441  conshdlr->lastenfolplpcount = -1;
2442  conshdlr->lastnusefulpropconss = 0;
2443  conshdlr->lastnusefulsepaconss = 0;
2444  conshdlr->lastnusefulenfoconss = 0;
2445  conshdlr->lastnfixedvars = 0;
2446  conshdlr->lastnaggrvars = 0;
2447  conshdlr->lastnchgvartypes = 0;
2448  conshdlr->lastnchgbds = 0;
2449  conshdlr->lastnaddholes = 0;
2450  conshdlr->lastndelconss = 0;
2451  conshdlr->lastnaddconss = 0;
2452  conshdlr->lastnupgdconss = 0;
2453  conshdlr->lastnchgcoefs = 0;
2454  conshdlr->lastnchgsides = 0;
2455  conshdlr->nfixedvars = 0;
2456  conshdlr->naggrvars = 0;
2457  conshdlr->nchgvartypes = 0;
2458  conshdlr->nchgbds = 0;
2459  conshdlr->naddholes = 0;
2460  conshdlr->ndelconss = 0;
2461  conshdlr->naddconss = 0;
2462  conshdlr->nupgdconss = 0;
2463  conshdlr->nchgcoefs = 0;
2464  conshdlr->nchgsides = 0;
2465  conshdlr->npresolcalls = 0;
2466  conshdlr->ageresetavg = AGERESETAVG_INIT;
2467  conshdlr->sepalpwasdelayed = FALSE;
2468  conshdlr->sepasolwasdelayed = FALSE;
2469  conshdlr->propwasdelayed = FALSE;
2470  }
2471 
2472  /* call initialization method of constraint handler */
2473  if( conshdlr->consinit != NULL )
2474  {
2475  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2476  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2477  * external method; to avoid this, these changes will be buffered and processed after the method call
2478  */
2479  conshdlrDelayUpdates(conshdlr);
2480 
2481  /* start timing */
2482  SCIPclockStart(conshdlr->setuptime, set);
2483 
2484  /* call external method */
2485  SCIP_CALL( conshdlr->consinit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2486 
2487  /* stop timing */
2488  SCIPclockStop(conshdlr->setuptime, set);
2489 
2490  /* perform the cached constraint updates */
2491  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2492  }
2493  conshdlr->initialized = TRUE;
2494  assert(!conshdlrAreUpdatesDelayed(conshdlr));
2495 
2496  return SCIP_OKAY;
2497 }
2498 
2499 /** calls exit method of constraint handler */
2501  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2502  BMS_BLKMEM* blkmem, /**< block memory */
2503  SCIP_SET* set, /**< global SCIP settings */
2504  SCIP_STAT* stat /**< dynamic problem statistics */
2505  )
2506 {
2507  assert(conshdlr != NULL);
2508  assert(set != NULL);
2509 
2510  if( !conshdlr->initialized )
2511  {
2512  SCIPerrorMessage("constraint handler <%s> not initialized\n", conshdlr->name);
2513  return SCIP_INVALIDCALL;
2514  }
2515 
2516  /* call deinitialization method of constraint handler */
2517  if( conshdlr->consexit != NULL )
2518  {
2519  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2520  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2521  * external method; to avoid this, these changes will be buffered and processed after the method call
2522  */
2523  conshdlrDelayUpdates(conshdlr);
2524 
2525  /* start timing */
2526  SCIPclockStart(conshdlr->setuptime, set);
2527 
2528  /* call external method */
2529  SCIP_CALL( conshdlr->consexit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2530 
2531  /* stop timing */
2532  SCIPclockStop(conshdlr->setuptime, set);
2533 
2534  /* perform the cached constraint updates */
2535  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2536  }
2537  conshdlr->initialized = FALSE;
2538 
2539  return SCIP_OKAY;
2540 }
2541 
2542 /** informs constraint handler that the presolving process is being started */
2544  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2545  BMS_BLKMEM* blkmem, /**< block memory */
2546  SCIP_SET* set, /**< global SCIP settings */
2547  SCIP_STAT* stat /**< dynamic problem statistics */
2548  )
2549 {
2550  assert(conshdlr != NULL);
2551  assert(set != NULL);
2552 
2553  /* reset conshdlr last presolved data in case of a restart */
2554  conshdlr->lastpropdomchgcount = -1;
2555  conshdlr->lastenfolpdomchgcount = -1;
2556  conshdlr->lastenfopsdomchgcount = -1;
2557  conshdlr->lastenforelaxdomchgcount = -1;
2558  conshdlr->lastenforelaxrelaxcount = -1;
2559  conshdlr->lastenfolpnode = -1;
2560  conshdlr->lastenfopsnode = -1;
2561  conshdlr->lastenfolpresult = SCIP_DIDNOTRUN;
2562  conshdlr->lastenfopsresult = SCIP_DIDNOTRUN;
2563  conshdlr->lastenforelaxresult = SCIP_DIDNOTRUN;
2564  conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2565  conshdlr->startnactiveconss = 0;
2566  conshdlr->lastsepalpcount = -1;
2567  conshdlr->lastenfolplpcount = -1;
2568  conshdlr->lastnusefulpropconss = 0;
2569  conshdlr->lastnusefulsepaconss = 0;
2570  conshdlr->lastnusefulenfoconss = 0;
2571  conshdlr->lastnfixedvars = 0;
2572  conshdlr->lastnaggrvars = 0;
2573  conshdlr->lastnchgvartypes = 0;
2574  conshdlr->lastnchgbds = 0;
2575  conshdlr->lastnaddholes = 0;
2576  conshdlr->lastndelconss = 0;
2577  conshdlr->lastnaddconss = 0;
2578  conshdlr->lastnupgdconss = 0;
2579  conshdlr->lastnchgcoefs = 0;
2580  conshdlr->lastnchgsides = 0;
2581  conshdlr->propwasdelayed = FALSE;
2582 
2583  /* call presolving initialization method of constraint handler */
2584  if( conshdlr->consinitpre != NULL )
2585  {
2586  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2587  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2588  * external method; to avoid this, these changes will be buffered and processed after the method call
2589  */
2590  conshdlrDelayUpdates(conshdlr);
2591 
2592  /* start timing */
2593  SCIPclockStart(conshdlr->setuptime, set);
2594 
2595  /* call external method */
2596  SCIP_CALL( conshdlr->consinitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2597 
2598  /* stop timing */
2599  SCIPclockStop(conshdlr->setuptime, set);
2600 
2601  /* perform the cached constraint updates */
2602  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2603  }
2604 
2605  /* after a restart the LP is empty but the initial constraints are not included in the initialconss array anymore;
2606  * we have to put them back into this array in order to obtain the correct initial root relaxation
2607  */
2608  if( stat->nruns >= 2 )
2609  {
2610  int c;
2611 
2612  for( c = 0; c < conshdlr->nconss; ++c )
2613  {
2614  /**@todo should only active constraints be added to the initconss array? at least cons->active is asserted in
2615  * conshdlrAddInitcons(conshdlr, set, conshdlr->conss[c])
2616  */
2617  if( conshdlr->conss[c]->addarraypos >= 0 && !conshdlr->conss[c]->deleted &&
2618  conshdlr->conss[c]->initial && conshdlr->conss[c]->initconsspos == -1 )
2619  {
2620  SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->conss[c]) );
2621  }
2622  }
2623  }
2624 
2625  return SCIP_OKAY;
2626 }
2627 
2628 /** informs constraint handler that the presolving is finished */
2630  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2631  BMS_BLKMEM* blkmem, /**< block memory */
2632  SCIP_SET* set, /**< global SCIP settings */
2633  SCIP_STAT* stat /**< dynamic problem statistics */
2634  )
2635 {
2636  assert(conshdlr != NULL);
2637  assert(set != NULL);
2638 
2639  /* call presolving deinitialization method of constraint handler */
2640  if( conshdlr->consexitpre != NULL )
2641  {
2642  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2643  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2644  * external method; to avoid this, these changes will be buffered and processed after the method call
2645  */
2646  conshdlrDelayUpdates(conshdlr);
2647 
2648  /* start timing */
2649  SCIPclockStart(conshdlr->setuptime, set);
2650 
2651  /* call external method */
2652  SCIP_CALL( conshdlr->consexitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2653 
2654  /* stop timing */
2655  SCIPclockStop(conshdlr->setuptime, set);
2656 
2657  /* perform the cached constraint updates */
2658  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2659  }
2660 
2661  /* update statistics */
2662  conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2663  conshdlr->startnactiveconss = conshdlr->nactiveconss;
2664 
2665  return SCIP_OKAY;
2666 }
2667 
2668 /** informs constraint handler that the branch and bound process is being started */
2670  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2671  BMS_BLKMEM* blkmem, /**< block memory */
2672  SCIP_SET* set, /**< global SCIP settings */
2673  SCIP_STAT* stat /**< dynamic problem statistics */
2674  )
2675 {
2676  assert(conshdlr != NULL);
2677  assert(set != NULL);
2678  assert(stat != NULL);
2679 
2680  conshdlr->sepalpwasdelayed = FALSE;
2681  conshdlr->sepasolwasdelayed = FALSE;
2682 
2683  /* call solving process initialization method of constraint handler */
2684  if( conshdlr->consinitsol != NULL )
2685  {
2686  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2687  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2688  * external method; to avoid this, these changes will be buffered and processed after the method call
2689  */
2690  conshdlrDelayUpdates(conshdlr);
2691 
2692  /* start timing */
2693  SCIPclockStart(conshdlr->setuptime, set);
2694 
2695  /* call external method */
2696  SCIP_CALL( conshdlr->consinitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2697 
2698  /* stop timing */
2699  SCIPclockStop(conshdlr->setuptime, set);
2700 
2701  /* perform the cached constraint updates */
2702  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2703  }
2704 
2705  return SCIP_OKAY;
2706 }
2707 
2708 /** informs constraint handler that the branch and bound process data is being freed */
2710  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2711  BMS_BLKMEM* blkmem, /**< block memory */
2712  SCIP_SET* set, /**< global SCIP settings */
2713  SCIP_STAT* stat, /**< dynamic problem statistics */
2714  SCIP_Bool restart /**< was this exit solve call triggered by a restart? */
2715  )
2716 {
2717  assert(conshdlr != NULL);
2718  assert(set != NULL);
2719 
2720  /* call solving process deinitialization method of constraint handler */
2721  if( conshdlr->consexitsol != NULL )
2722  {
2723  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2724  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2725  * external method; to avoid this, these changes will be buffered and processed after the method call
2726  */
2727  conshdlrDelayUpdates(conshdlr);
2728 
2729  /* start timing */
2730  SCIPclockStart(conshdlr->setuptime, set);
2731 
2732  /* call external method */
2733  SCIP_CALL( conshdlr->consexitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss, restart) );
2734 
2735  /* stop timing */
2736  SCIPclockStop(conshdlr->setuptime, set);
2737 
2738  /* perform the cached constraint updates */
2739  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2740  }
2741 
2742  return SCIP_OKAY;
2743 }
2744 
2745 /** calls LP initialization method of constraint handler to separate all initial active constraints */
2747  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2748  BMS_BLKMEM* blkmem, /**< block memory */
2749  SCIP_SET* set, /**< global SCIP settings */
2750  SCIP_STAT* stat, /**< dynamic problem statistics */
2751  SCIP_TREE* tree, /**< branch and bound tree */
2752  SCIP_Bool initkeptconss, /**< Also initialize constraints which are valid at a more global node,
2753  * but were not activated there? Should be FALSE for repeated calls at
2754  * one node or if the current focusnode is a child of the former one */
2755  SCIP_Bool* cutoff /**< pointer to store whether infeasibility was detected while building the LP */
2756  )
2757 {
2758  assert(conshdlr != NULL);
2759  assert(cutoff != NULL);
2760 #ifdef MORE_DEBUG
2761  assert(stat->nnodes > 1 || conshdlr->ninitconsskept == 0 || SCIPtreeProbing(tree));
2762 #endif
2763 
2764  *cutoff = FALSE;
2765 
2766  if( conshdlr->consinitlp != NULL )
2767  {
2768  int currentdepth;
2769  int oldninitconss;
2770  int c;
2771 
2772  SCIPsetDebugMsg(set, "initializing LP with %d initial constraints of handler <%s> (ninitconss=%d, kept=%d, initkept=%u)\n",
2773  initkeptconss ? conshdlr->ninitconss : conshdlr->ninitconss - conshdlr->ninitconsskept, conshdlr->name,
2774  conshdlr->ninitconss, conshdlr->ninitconsskept, initkeptconss);
2775 
2776  /* no constraints to initialize (or only kept constraints which do not need to be initialized this time) -> return */
2777  if( conshdlr->needscons && (conshdlr->ninitconss == 0 || (!initkeptconss && conshdlr->ninitconss == conshdlr->ninitconsskept)) )
2778  return SCIP_OKAY;
2779 
2780  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2781  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2782  * external method; to avoid this, these changes will be buffered and processed after the method call
2783  */
2784  conshdlrDelayUpdates(conshdlr);
2785 
2786  oldninitconss = conshdlr->ninitconss;
2787 
2788  /* start timing */
2789  SCIPclockStart(conshdlr->sepatime, set);
2790 
2791  if( initkeptconss )
2792  {
2793  /* add all kept initial constraints which are currently active to the second part of the initconss array */
2794  /* @todo keep track of where a constraint was already initialized (e.g., in the conssetchg)? */
2795  for( c = 0; c < conshdlr->ninitconsskept; ++c )
2796  {
2797  assert(conshdlr->initconss[c]->initconsspos == c);
2798 
2799  if( SCIPconsIsActive(conshdlr->initconss[c]) )
2800  {
2801  SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->initconss[c]) );
2802  }
2803  }
2804  }
2805 
2806  /* call external method */
2807  SCIP_CALL( conshdlr->consinitlp(set->scip, conshdlr, &conshdlr->initconss[conshdlr->ninitconsskept],
2808  conshdlr->ninitconss - conshdlr->ninitconsskept, cutoff) );
2809 
2810  /* stop timing */
2811  SCIPclockStop(conshdlr->sepatime, set);
2812 
2813  /* perform the cached constraint updates */
2814  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2815 
2816  currentdepth = SCIPtreeGetCurrentDepth(tree);
2817  assert(currentdepth >= 0);
2818 
2819  /* clear the initconss array */
2820  for( c = conshdlr->ninitconsskept; c < oldninitconss; ++c )
2821  {
2822  assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) >= -1);
2823  assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) <= currentdepth);
2824 
2825  /* if the constraint was not initialized at its valid node, we keep it */
2826  if( currentdepth > 0 ? SCIPconsGetActiveDepth(conshdlr->initconss[c]) != currentdepth :
2827  SCIPconsGetActiveDepth(conshdlr->initconss[c]) > 0 )
2828  {
2829  conshdlr->initconss[conshdlr->ninitconsskept] = conshdlr->initconss[c];
2830  conshdlr->initconss[conshdlr->ninitconsskept]->initconsspos = conshdlr->ninitconsskept;
2831  ++(conshdlr->ninitconsskept);
2832  }
2833  else
2834  conshdlr->initconss[c]->initconsspos = -1;
2835  }
2836 #ifndef NDEBUG
2837  for( ; c < conshdlr->ninitconss; ++c )
2838  assert(conshdlr->initconss[c]->initconsspos < conshdlr->ninitconsskept);
2839 #endif
2840  conshdlr->ninitconss = conshdlr->ninitconsskept;
2841 
2842  if( conshdlr->ninitconss == 0 )
2843  {
2844  BMSfreeMemoryArrayNull(&conshdlr->initconss);
2845  conshdlr->initconsssize = 0;
2846  }
2847  }
2848 
2849  return SCIP_OKAY;
2850 }
2851 
2852 /** calls separator method of constraint handler to separate LP solution */
2854  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2855  BMS_BLKMEM* blkmem, /**< block memory */
2856  SCIP_SET* set, /**< global SCIP settings */
2857  SCIP_STAT* stat, /**< dynamic problem statistics */
2858  SCIP_SEPASTORE* sepastore, /**< separation storage */
2859  int depth, /**< depth of current node */
2860  SCIP_Bool execdelayed, /**< execute separation method even if it is marked to be delayed */
2861  SCIP_RESULT* result /**< pointer to store the result of the callback method */
2862  )
2863 {
2864  assert(conshdlr != NULL);
2865  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
2866  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
2867  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
2868  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
2869  assert(stat != NULL);
2870  assert(conshdlr->lastsepalpcount != stat->lpcount
2871  || (0 <= conshdlr->lastnusefulsepaconss && conshdlr->lastnusefulsepaconss <= conshdlr->nusefulsepaconss));
2872  assert(set != NULL);
2873  assert(result != NULL);
2874 
2875  *result = SCIP_DIDNOTRUN;
2876 
2877  if( conshdlr->conssepalp != NULL
2878  && ((depth == 0 && conshdlr->sepafreq == 0)
2879  || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0)
2880  || conshdlr->sepalpwasdelayed) )
2881  {
2882  /* check, if separation method should be delayed */
2883  if( !conshdlr->delaysepa || execdelayed )
2884  {
2885  int nconss;
2886  int nusefulconss;
2887  int firstcons;
2888 
2889  /* check, if this LP solution was already separated */
2890  if( conshdlr->lastsepalpcount == stat->lpcount )
2891  {
2892  /* all constraints that were not yet separated on the new LP solution must be useful constraints, which means,
2893  * that the new constraints are the last constraints of the useful ones
2894  */
2895  nconss = conshdlr->nusefulsepaconss - conshdlr->lastnusefulsepaconss;
2896  nusefulconss = nconss;
2897  firstcons = conshdlr->lastnusefulsepaconss;
2898  }
2899  else
2900  {
2901  /* on a new LP solution, we want to separate all constraints */
2902  nconss = conshdlr->nsepaconss;
2903  nusefulconss = conshdlr->nusefulsepaconss;
2904  firstcons = 0;
2905  }
2906  assert(firstcons >= 0);
2907  assert(firstcons + nconss <= conshdlr->nsepaconss);
2908  assert(nusefulconss <= nconss);
2909 
2910  /* constraint handlers without constraints should only be called once */
2911  if( nconss > 0 || (!conshdlr->needscons && conshdlr->lastsepalpcount != stat->lpcount) )
2912  {
2913  SCIP_CONS** conss;
2914  SCIP_Longint oldndomchgs;
2915  SCIP_Longint oldnprobdomchgs;
2916  SCIP_Longint lastsepalpcount;
2917  int oldncuts;
2918  int oldnactiveconss;
2919  int lastnusefulsepaconss;
2920 
2921  SCIPsetDebugMsg(set, "separating constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n",
2922  firstcons, firstcons + nconss - 1, conshdlr->nsepaconss, conshdlr->name,
2923  conshdlr->lastsepalpcount == stat->lpcount ? "old" : "new");
2924 
2925  /* remember the number of processed constraints on the current LP solution */
2926  lastsepalpcount = stat->lpcount;
2927  lastnusefulsepaconss = conshdlr->nusefulsepaconss;
2928 
2929  /* get the array of the constraints to be processed */
2930  conss = &(conshdlr->sepaconss[firstcons]);
2931 
2932  oldndomchgs = stat->nboundchgs + stat->nholechgs;
2933  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
2934  oldncuts = SCIPsepastoreGetNCuts(sepastore);
2935  oldnactiveconss = stat->nactiveconss;
2936 
2937  /* check, if we want to use eager evaluation */
2938  if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0)
2939  || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) )
2940  nusefulconss = nconss;
2941 
2942  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2943  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2944  * external method; to avoid this, these changes will be buffered and processed after the method call
2945  */
2946  conshdlrDelayUpdates(conshdlr);
2947  conshdlr->duringsepa = TRUE;
2948 
2949  /* start timing */
2950  SCIPclockStart(conshdlr->sepatime, set);
2951 
2952  /* call external method */
2953  SCIP_CALL( conshdlr->conssepalp(set->scip, conshdlr, conss, nconss, nusefulconss, result) );
2954  SCIPsetDebugMsg(set, " -> separating LP returned result <%d>\n", *result);
2955 
2956  /* stop timing */
2957  SCIPclockStop(conshdlr->sepatime, set);
2958 
2959  /* perform the cached constraint updates */
2960  conshdlr->duringsepa = FALSE;
2961  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2962 
2963  /* update statistics */
2964  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
2965  {
2966  conshdlr->lastsepalpcount = lastsepalpcount;
2967  conshdlr->lastnusefulsepaconss = MIN(lastnusefulsepaconss, conshdlr->nusefulsepaconss);
2968  conshdlr->nsepacalls++;
2969  }
2970  if( *result == SCIP_CUTOFF )
2971  conshdlr->ncutoffs++;
2972  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
2973  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
2974 
2975  /* update domain reductions; therefore remove the domain
2976  * reduction counts which were generated in probing mode */
2977  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
2978  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
2979 
2980  /* evaluate result */
2981  if( *result != SCIP_CUTOFF
2982  && *result != SCIP_CONSADDED
2983  && *result != SCIP_REDUCEDDOM
2984  && *result != SCIP_SEPARATED
2985  && *result != SCIP_NEWROUND
2986  && *result != SCIP_DIDNOTFIND
2987  && *result != SCIP_DIDNOTRUN
2988  && *result != SCIP_DELAYED )
2989  {
2990  SCIPerrorMessage("LP separation method of constraint handler <%s> returned invalid result <%d>\n",
2991  conshdlr->name, *result);
2992  return SCIP_INVALIDRESULT;
2993  }
2994  }
2995  }
2996  else
2997  {
2998  SCIPsetDebugMsg(set, "LP separation method of constraint handler <%s> was delayed\n", conshdlr->name);
2999  *result = SCIP_DELAYED;
3000  }
3001 
3002  /* remember whether separation method was delayed */
3003  conshdlr->sepalpwasdelayed = (*result == SCIP_DELAYED);
3004  }
3005 
3006  return SCIP_OKAY;
3007 }
3008 
3009 /** calls separator method of constraint handler to separate given primal solution */
3011  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3012  BMS_BLKMEM* blkmem, /**< block memory */
3013  SCIP_SET* set, /**< global SCIP settings */
3014  SCIP_STAT* stat, /**< dynamic problem statistics */
3015  SCIP_SEPASTORE* sepastore, /**< separation storage */
3016  SCIP_SOL* sol, /**< primal solution that should be separated */
3017  int depth, /**< depth of current node */
3018  SCIP_Bool execdelayed, /**< execute separation method even if it is marked to be delayed */
3019  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3020  )
3021 {
3022  assert(conshdlr != NULL);
3023  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3024  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3025  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3026  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3027  assert(set != NULL);
3028  assert(stat != NULL);
3029  assert(result != NULL);
3030 
3031  *result = SCIP_DIDNOTRUN;
3032 
3033  if( conshdlr->conssepasol != NULL
3034  && ((depth == 0 && conshdlr->sepafreq == 0)
3035  || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0)
3036  || conshdlr->sepasolwasdelayed) )
3037  {
3038  /* check, if separation method should be delayed */
3039  if( !conshdlr->delaysepa || execdelayed )
3040  {
3041  int nconss;
3042  int nusefulconss;
3043 
3044  /* always separate all constraints */
3045  nconss = conshdlr->nsepaconss;
3046  nusefulconss = conshdlr->nusefulsepaconss;
3047  assert(nusefulconss <= nconss);
3048 
3049  if( nconss > 0 || !conshdlr->needscons )
3050  {
3051  SCIP_CONS** conss;
3052  SCIP_Longint oldndomchgs;
3053  SCIP_Longint oldnprobdomchgs;
3054  int oldncuts;
3055  int oldnactiveconss;
3056 
3057  SCIPsetDebugMsg(set, "separating %d constraints of handler <%s> (primal solution %p)\n",
3058  nconss, conshdlr->name, (void*)sol);
3059 
3060  /* get the array of the constraints to be processed */
3061  conss = conshdlr->sepaconss;
3062 
3063  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3064  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3065  oldncuts = SCIPsepastoreGetNCuts(sepastore);
3066  oldnactiveconss = stat->nactiveconss;
3067 
3068  /* check, if we want to use eager evaluation */
3069  if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0)
3070  || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) )
3071  nusefulconss = nconss;
3072 
3073  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3074  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3075  * external method; to avoid this, these changes will be buffered and processed after the method call
3076  */
3077  conshdlrDelayUpdates(conshdlr);
3078  conshdlr->duringsepa = TRUE;
3079 
3080  /* start timing */
3081  SCIPclockStart(conshdlr->sepatime, set);
3082 
3083  /* call external method */
3084  SCIP_CALL( conshdlr->conssepasol(set->scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
3085  SCIPsetDebugMsg(set, " -> separating sol returned result <%d>\n", *result);
3086 
3087  /* stop timing */
3088  SCIPclockStop(conshdlr->sepatime, set);
3089 
3090  /* perform the cached constraint updates */
3091  conshdlr->duringsepa = FALSE;
3092  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3093 
3094  /* update statistics */
3095  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
3096  conshdlr->nsepacalls++;
3097  if( *result == SCIP_CUTOFF )
3098  conshdlr->ncutoffs++;
3099  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3100  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3101 
3102  /* update domain reductions; therefore remove the domain
3103  * reduction counts which were generated in probing mode */
3104  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3105  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3106 
3107  /* evaluate result */
3108  if( *result != SCIP_CUTOFF
3109  && *result != SCIP_CONSADDED
3110  && *result != SCIP_REDUCEDDOM
3111  && *result != SCIP_SEPARATED
3112  && *result != SCIP_NEWROUND
3113  && *result != SCIP_DIDNOTFIND
3114  && *result != SCIP_DIDNOTRUN
3115  && *result != SCIP_DELAYED )
3116  {
3117  SCIPerrorMessage("SOL separation method of constraint handler <%s> returned invalid result <%d>\n",
3118  conshdlr->name, *result);
3119  return SCIP_INVALIDRESULT;
3120  }
3121  }
3122  }
3123  else
3124  {
3125  SCIPsetDebugMsg(set, "SOL separation method of constraint handler <%s> was delayed\n", conshdlr->name);
3126  *result = SCIP_DELAYED;
3127  }
3128 
3129  /* remember whether separation method was delayed */
3130  conshdlr->sepasolwasdelayed = (*result == SCIP_DELAYED);
3131  }
3132 
3133  return SCIP_OKAY;
3134 }
3135 
3136 /** calls enforcing method of constraint handler for a relaxation solution for all constraints added after last
3137  * conshdlrResetEnfo() call
3138  */
3140  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3141  BMS_BLKMEM* blkmem, /**< block memory */
3142  SCIP_SET* set, /**< global SCIP settings */
3143  SCIP_STAT* stat, /**< dynamic problem statistics */
3144  SCIP_TREE* tree, /**< branch and bound tree */
3145  SCIP_SEPASTORE* sepastore, /**< separation storage */
3146  SCIP_SOL* relaxsol, /**< solution to be enforced */
3147  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3148  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3149  )
3150 {
3151  int nconss;
3152  int nusefulconss;
3153  int firstcons;
3154  SCIP_Bool relaxchanged;
3155  SCIP_Bool lastinfeasible;
3156 
3157  assert(conshdlr != NULL);
3158  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3159  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3160  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3161  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3162  assert(stat != NULL);
3163  assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount
3164  || conshdlr->lastenfopsnode != stat->nnodes
3165  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3166  assert(set != NULL);
3167  assert(tree != NULL);
3168  assert(tree->nchildren == 0);
3169  assert(relaxsol != NULL);
3170  assert(result != NULL);
3171 
3172  *result = SCIP_FEASIBLE;
3173 
3174  /* check, if this relaxation solution was already enforced at this node
3175  * the integrality constraint handler always needs to be enforced for all constraints since external branching
3176  * candidates are cleared before each resolve
3177  */
3178  if( conshdlr->lastenforelaxrelaxcount == stat->relaxcount
3179  && conshdlr->lastenforelaxdomchgcount == stat->domchgcount
3180  && conshdlr->lastenforelaxnode == stat->nnodes
3181  && conshdlr->lastenforelaxresult != SCIP_CONSADDED
3182  && conshdlr->lastenforelaxresult != SCIP_SOLVELP
3183  && ( strcmp(conshdlr->name, "integral") != 0 )
3184  )
3185  {
3186  assert(conshdlr->lastenforelaxresult != SCIP_CUTOFF);
3187  assert(conshdlr->lastenforelaxresult != SCIP_BRANCHED);
3188  assert(conshdlr->lastenforelaxresult != SCIP_REDUCEDDOM);
3189  assert(conshdlr->lastenforelaxresult != SCIP_DIDNOTRUN);
3190 
3191  /* if we already enforced the same relaxation solution at this node, we will only enforce new constraints in the
3192  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3193  * that an infeasibility in the last call is not lost because we only enforce new constraints
3194  */
3195  if( conshdlr->lastenforelaxresult == SCIP_INFEASIBLE )
3196  {
3197  *result = SCIP_INFEASIBLE;
3198  lastinfeasible = TRUE;
3199  }
3200  else
3201  lastinfeasible = FALSE;
3202 
3203  /* all constraints that were not yet enforced on the new relaxation solution must be useful constraints, which means,
3204  * that the new constraints are the last constraints of the useful ones
3205  */
3206  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3207  nusefulconss = nconss;
3208  firstcons = conshdlr->lastnusefulenfoconss;
3209  relaxchanged = FALSE;
3210  }
3211  else
3212  {
3213  /* on a new relaxation solution or a new node, we want to enforce all constraints */
3214  nconss = conshdlr->nenfoconss;
3215  nusefulconss = conshdlr->nusefulenfoconss;
3216  firstcons = 0;
3217  relaxchanged = TRUE;
3218  lastinfeasible = FALSE;
3219  }
3220  assert(firstcons >= 0);
3221  assert(firstcons + nconss <= conshdlr->nenfoconss);
3222  assert(nusefulconss <= nconss);
3223 
3224  /* constraint handlers without constraints should only be called once */
3225  if( nconss > 0 || (!conshdlr->needscons && relaxchanged) )
3226  {
3227  SCIP_CONS** conss;
3228  SCIP_Longint oldndomchgs;
3229  SCIP_Longint oldnprobdomchgs;
3230  int oldncuts;
3231  int oldnactiveconss;
3232 
3233  assert(conshdlr->consenforelax != NULL);
3234 
3235  SCIPdebugMessage("enforcing constraints %d to %d of %d constraints of handler <%s> (%s relaxation solution)\n",
3236  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, relaxchanged ? "new" : "old");
3237 
3238  /* remember the number of processed constraints on the current relaxation solution */
3239  conshdlr->lastenforelaxrelaxcount = stat->relaxcount;
3240  conshdlr->lastenforelaxdomchgcount = stat->domchgcount;
3241  conshdlr->lastenforelaxnode = stat->nnodes;
3242  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3243 
3244  /* get the array of the constraints to be processed */
3245  conss = &(conshdlr->enfoconss[firstcons]);
3246 
3247  oldncuts = SCIPsepastoreGetNCuts(sepastore);
3248  oldnactiveconss = stat->nactiveconss;
3249  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3250  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3251 
3252  /* check, if we want to use eager evaluation */
3253  if( (conshdlr->eagerfreq == 0 && conshdlr->nenforelaxcalls == 0)
3254  || (conshdlr->eagerfreq > 0 && conshdlr->nenforelaxcalls % conshdlr->eagerfreq == 0) )
3255  nusefulconss = nconss;
3256 
3257  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3258  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3259  * external method; to avoid this, these changes will be buffered and processed after the method call
3260  */
3261  conshdlrDelayUpdates(conshdlr);
3262 
3263  /* start timing */
3264  SCIPclockStart(conshdlr->enforelaxtime, set);
3265 
3266  /* call external method */
3267  SCIP_CALL( conshdlr->consenforelax(set->scip, relaxsol, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) );
3268  SCIPdebugMessage(" -> enforcing returned result <%d>\n", *result);
3269 
3270  /* stop timing */
3271  SCIPclockStop(conshdlr->enforelaxtime, set);
3272 
3273  /* perform the cached constraint updates */
3274  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3275 
3276  /* update statistics */
3277  conshdlr->nenforelaxcalls++;
3278  if( *result == SCIP_CUTOFF )
3279  conshdlr->ncutoffs++;
3280  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3281  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3282 
3283  if( *result != SCIP_BRANCHED )
3284  {
3285  assert(tree->nchildren == 0);
3286 
3287  /* update domain reductions; therefore remove the domain
3288  * reduction counts which were generated in probing mode */
3289  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3290  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3291  }
3292  else
3293  conshdlr->nchildren += tree->nchildren;
3294 
3295  /* remember the result of the enforcement call */
3296  conshdlr->lastenforelaxresult = *result;
3297 
3298  /* evaluate result */
3299  if( *result != SCIP_CUTOFF
3300  && *result != SCIP_CONSADDED
3301  && *result != SCIP_REDUCEDDOM
3302  && *result != SCIP_SEPARATED
3303  && *result != SCIP_BRANCHED
3304  && *result != SCIP_SOLVELP
3305  && *result != SCIP_INFEASIBLE
3306  && *result != SCIP_FEASIBLE )
3307  {
3308  SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation solutions returned invalid result <%d>\n",
3309  conshdlr->name, *result);
3310  return SCIP_INVALIDRESULT;
3311  }
3312 
3313  /* if the same relaxation solution was already enforced at this node, we only enforced new constraints this time;
3314  * if the enforelax call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3315  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3316  */
3317  if( lastinfeasible && *result == SCIP_FEASIBLE )
3318  *result = SCIP_INFEASIBLE;
3319  }
3320 
3321  return SCIP_OKAY;
3322 }
3323 
3324 /** calls enforcing method of constraint handler for LP solution for all constraints added after last
3325  * conshdlrResetEnfo() call
3326  */
3328  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3329  BMS_BLKMEM* blkmem, /**< block memory */
3330  SCIP_SET* set, /**< global SCIP settings */
3331  SCIP_STAT* stat, /**< dynamic problem statistics */
3332  SCIP_TREE* tree, /**< branch and bound tree */
3333  SCIP_SEPASTORE* sepastore, /**< separation storage */
3334  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3335  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3336  )
3337 {
3338  assert(conshdlr != NULL);
3339  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3340  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3341  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3342  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3343  assert(stat != NULL);
3344  assert(conshdlr->lastenfolplpcount != stat->lpcount
3345  || conshdlr->lastenfolpdomchgcount != stat->domchgcount
3346  || conshdlr->lastenfolpnode != stat->nnodes
3347  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3348  assert(set != NULL);
3349  assert(tree != NULL);
3350  assert(tree->nchildren == 0);
3351  assert(result != NULL);
3352 
3353  *result = SCIP_FEASIBLE;
3354 
3355  if( conshdlr->consenfolp != NULL )
3356  {
3357  int nconss;
3358  int nusefulconss;
3359  int firstcons;
3360  SCIP_Bool lpchanged;
3361  SCIP_Bool lastinfeasible;
3362 
3363  /* check, if this LP solution was already enforced at this node */
3364  if( conshdlr->lastenfolplpcount == stat->lpcount
3365  && conshdlr->lastenfolpdomchgcount == stat->domchgcount
3366  && conshdlr->lastenfolpnode == stat->nnodes
3367  && conshdlr->lastenfolpresult != SCIP_CONSADDED )
3368  {
3369  assert(conshdlr->lastenfolpresult == SCIP_FEASIBLE || conshdlr->lastenfolpresult == SCIP_INFEASIBLE
3370  || conshdlr->lastenfolpresult == SCIP_SEPARATED );
3371 
3372  /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3373  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3374  * that an infeasibility in the last call is not lost because we only enforce new constraints
3375  */
3376  if( conshdlr->lastenfolpresult == SCIP_FEASIBLE )
3377  lastinfeasible = FALSE;
3378  else
3379  {
3380  assert(conshdlr->lastenfolpresult == SCIP_INFEASIBLE || conshdlr->lastenfolpresult == SCIP_SEPARATED);
3381  *result = SCIP_INFEASIBLE;
3382  lastinfeasible = TRUE;
3383  }
3384 
3385  /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3386  * that the new constraints are the last constraints of the useful ones
3387  */
3388  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3389  nusefulconss = nconss;
3390  firstcons = conshdlr->lastnusefulenfoconss;
3391  lpchanged = FALSE;
3392  }
3393  else
3394  {
3395  /* on a new LP solution or a new node, we want to enforce all constraints */
3396  nconss = conshdlr->nenfoconss;
3397  nusefulconss = conshdlr->nusefulenfoconss;
3398  firstcons = 0;
3399  lpchanged = TRUE;
3400  lastinfeasible = FALSE;
3401  }
3402  assert(firstcons >= 0);
3403  assert(firstcons + nconss <= conshdlr->nenfoconss);
3404  assert(nusefulconss <= nconss);
3405 
3406  /* constraint handlers without constraints should only be called once */
3407  if( nconss > 0 || (!conshdlr->needscons && lpchanged) )
3408  {
3409  SCIP_CONS** conss;
3410  SCIP_Longint oldndomchgs;
3411  SCIP_Longint oldnprobdomchgs;
3412  int oldncuts;
3413  int oldnactiveconss;
3414 
3415  SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n",
3416  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, lpchanged ? "new" : "old");
3417 
3418  /* remember the number of processed constraints on the current LP solution */
3419  conshdlr->lastenfolplpcount = stat->lpcount;
3420  conshdlr->lastenfolpdomchgcount = stat->domchgcount;
3421  conshdlr->lastenfolpnode = stat->nnodes;
3422  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3423 
3424  /* get the array of the constraints to be processed */
3425  conss = nconss > 0 ? conshdlr->enfoconss + firstcons : NULL;
3426 
3427  oldncuts = SCIPsepastoreGetNCuts(sepastore);
3428  oldnactiveconss = stat->nactiveconss;
3429  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3430  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3431 
3432  /* check, if we want to use eager evaluation */
3433  if( (conshdlr->eagerfreq == 0 && conshdlr->nenfolpcalls == 0)
3434  || (conshdlr->eagerfreq > 0 && conshdlr->nenfolpcalls % conshdlr->eagerfreq == 0) )
3435  nusefulconss = nconss;
3436 
3437  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3438  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3439  * external method; to avoid this, these changes will be buffered and processed after the method call
3440  */
3441  conshdlrDelayUpdates(conshdlr);
3442 
3443  /* start timing */
3444  SCIPclockStart(conshdlr->enfolptime, set);
3445 
3446  /* call external method */
3447  SCIP_CALL( conshdlr->consenfolp(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) );
3448  SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3449 
3450  /* stop timing */
3451  SCIPclockStop(conshdlr->enfolptime, set);
3452 
3453  /* perform the cached constraint updates */
3454  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3455 
3456  /* remember the result of the enforcement call */
3457  conshdlr->lastenfolpresult = *result;
3458 
3459  /* update statistics */
3460  conshdlr->nenfolpcalls++;
3461  if( *result == SCIP_CUTOFF )
3462  conshdlr->ncutoffs++;
3463  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3464  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3465  if( *result != SCIP_BRANCHED )
3466  {
3467  assert(tree->nchildren == 0);
3468 
3469  /* update domain reductions; therefore remove the domain
3470  * reduction counts which were generated in probing mode */
3471  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3472  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3473  }
3474  else
3475  conshdlr->nchildren += tree->nchildren;
3476 
3477  /* evaluate result */
3478  if( *result != SCIP_CUTOFF
3479  && *result != SCIP_CONSADDED
3480  && *result != SCIP_REDUCEDDOM
3481  && *result != SCIP_SEPARATED
3482  && *result != SCIP_SOLVELP
3483  && *result != SCIP_BRANCHED
3484  && *result != SCIP_INFEASIBLE
3485  && *result != SCIP_FEASIBLE )
3486  {
3487  SCIPerrorMessage("enforcing method of constraint handler <%s> for LP solutions returned invalid result <%d>\n",
3488  conshdlr->name, *result);
3489  return SCIP_INVALIDRESULT;
3490  }
3491 
3492  /* if the same LP solution was already enforced at this node, we only enforced new constraints this time;
3493  * if the enfolp call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3494  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3495  */
3496  if( lastinfeasible && *result == SCIP_FEASIBLE )
3497  *result = SCIP_INFEASIBLE;
3498  }
3499  }
3500 
3501  return SCIP_OKAY;
3502 }
3503 
3504 /** calls diving solution enforcement callback of constraint handler, if it exists */
3506  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3507  SCIP_SET* set, /**< global SCIP settings */
3508  SCIP_DIVESET* diveset, /**< diving settings to control scoring */
3509  SCIP_SOL* sol, /**< current solution of diving mode */
3510  SCIP_Bool* success, /**< pointer to store whether constraint handler successfully found a variable */
3511  SCIP_Bool* infeasible /**< pointer to store whether the current node was detected to be infeasible */
3512  )
3513 {
3514  assert(conshdlr != NULL);
3515  assert(set != NULL);
3516  assert(diveset != NULL);
3517  assert(sol != NULL);
3518  assert(success != NULL);
3519  assert(infeasible != NULL);
3520 
3521  if( conshdlr->consgetdivebdchgs != NULL )
3522  {
3523  SCIP_CALL( conshdlr->consgetdivebdchgs(set->scip, conshdlr, diveset, sol, success, infeasible) );
3524  }
3525 
3526  return SCIP_OKAY;
3527 }
3528 
3529 /** calls enforcing method of constraint handler for pseudo solution for all constraints added after last
3530  * conshdlrResetEnfo() call
3531  */
3533  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3534  BMS_BLKMEM* blkmem, /**< block memory */
3535  SCIP_SET* set, /**< global SCIP settings */
3536  SCIP_STAT* stat, /**< dynamic problem statistics */
3537  SCIP_TREE* tree, /**< branch and bound tree */
3538  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3539  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3540  SCIP_Bool objinfeasible, /**< is the solution infeasible anyway due to violating lower objective bound? */
3541  SCIP_Bool forced, /**< should enforcement of pseudo solution be forced? */
3542  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3543  )
3544 {
3545  assert(conshdlr != NULL);
3546  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3547  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3548  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3549  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3550  assert(stat != NULL);
3551  assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount
3552  || conshdlr->lastenfopsnode != stat->nnodes
3553  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3554  assert(set != NULL);
3555  assert(tree != NULL);
3556  assert(tree->nchildren == 0);
3557  assert(result != NULL);
3558 
3559  /* no enforcing of pseudo solution */
3560  if( set->cons_disableenfops && SCIPbranchcandGetNPseudoCands(branchcand) > 0 )
3561  {
3562  *result = SCIP_INFEASIBLE;
3563  return SCIP_OKAY;
3564  }
3565 
3566  *result = SCIP_FEASIBLE;
3567  if( conshdlr->consenfops != NULL )
3568  {
3569  int nconss;
3570  int nusefulconss;
3571  int firstcons;
3572  SCIP_Bool pschanged;
3573  SCIP_Bool lastinfeasible;
3574 
3575  /* check, if this pseudo solution was already enforced at this node */
3576  if( !forced && conshdlr->lastenfopsdomchgcount == stat->domchgcount
3577  && conshdlr->lastenfopsnode == stat->nnodes
3578  && conshdlr->lastenfopsresult != SCIP_CONSADDED
3579  && conshdlr->lastenfopsresult != SCIP_SOLVELP
3580  )
3581  {
3582  assert(conshdlr->lastenfopsresult != SCIP_CUTOFF);
3583  assert(conshdlr->lastenfopsresult != SCIP_BRANCHED);
3584  assert(conshdlr->lastenfopsresult != SCIP_REDUCEDDOM);
3585  assert(conshdlr->lastenfopsresult != SCIP_DIDNOTRUN || objinfeasible);
3586 
3587  /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3588  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3589  * that an infeasibility in the last call is not lost because we only enforce new constraints
3590  */
3591  if( conshdlr->lastenfopsresult == SCIP_INFEASIBLE )
3592  {
3593  *result = SCIP_INFEASIBLE;
3594  lastinfeasible = TRUE;
3595  }
3596  else
3597  lastinfeasible = FALSE;
3598 
3599  /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3600  * that the new constraints are the last constraints of the useful ones
3601  */
3602  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3603  nusefulconss = nconss;
3604  firstcons = conshdlr->lastnusefulenfoconss;
3605  pschanged = FALSE;
3606  }
3607  else
3608  {
3609  /* on a new pseudo solution or a new node, we want to enforce all constraints */
3610  nconss = conshdlr->nenfoconss;
3611  nusefulconss = conshdlr->nusefulenfoconss;
3612  firstcons = 0;
3613  pschanged = TRUE;
3614  lastinfeasible = FALSE;
3615  }
3616  assert(firstcons >= 0);
3617  assert(firstcons + nconss <= conshdlr->nenfoconss);
3618  assert(nusefulconss <= nconss);
3619 
3620  /* constraint handlers without constraints should only be called once */
3621  if( nconss > 0 || (!conshdlr->needscons && pschanged) )
3622  {
3623  SCIP_CONS** conss;
3624  SCIP_Longint oldndomchgs;
3625  SCIP_Longint oldnprobdomchgs;
3626 
3627  SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, objinfeasible=%u)\n",
3628  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, pschanged ? "new" : "old", objinfeasible);
3629 
3630  /* remember the number of processed constraints on the current pseudo solution */
3631  conshdlr->lastenfopsdomchgcount = stat->domchgcount;
3632  conshdlr->lastenfopsnode = stat->nnodes;
3633  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3634 
3635  /* get the array of the constraints to be processed */
3636  conss = &(conshdlr->enfoconss[firstcons]);
3637 
3638  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3639  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3640 
3641  /* check, if we want to use eager evaluation */
3642  if( (conshdlr->eagerfreq == 0 && conshdlr->nenfopscalls == 0)
3643  || (conshdlr->eagerfreq > 0 && conshdlr->nenfopscalls % conshdlr->eagerfreq == 0) )
3644  nusefulconss = nconss;
3645 
3646  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3647  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3648  * external method; to avoid this, these changes will be buffered and processed after the method call
3649  */
3650  conshdlrDelayUpdates(conshdlr);
3651 
3652  /* start timing */
3653  SCIPclockStart(conshdlr->enfopstime, set);
3654 
3655  /* call external method */
3656  SCIP_CALL( conshdlr->consenfops(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, objinfeasible, result) );
3657  SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3658 
3659  /* stop timing */
3660  SCIPclockStop(conshdlr->enfopstime, set);
3661 
3662  /* perform the cached constraint updates */
3663  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3664 
3665  /* update statistics */
3666  if( *result != SCIP_DIDNOTRUN )
3667  conshdlr->nenfopscalls++;
3668  else if( !objinfeasible )
3669  {
3670  SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions was skipped, even though the solution was not objective-infeasible\n",
3671  conshdlr->name);
3672  conshdlr->lastenfopsresult = *result;
3673 
3674  return SCIP_INVALIDRESULT;
3675  }
3676  /* A constraint handler might return SCIP_DIDNOTRUN and not check any constraints in case objinfeasible was
3677  * TRUE; we change the result pointer to SCIP_INFEASIBLE in this case.
3678  */
3679  else
3680  *result = SCIP_INFEASIBLE;
3681 
3682  if( *result == SCIP_CUTOFF )
3683  conshdlr->ncutoffs++;
3684 
3685  if( *result != SCIP_BRANCHED )
3686  {
3687  assert(tree->nchildren == 0);
3688 
3689  /* update domain reductions; therefore remove the domain
3690  * reduction counts which were generated in probing mode */
3691  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3692  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3693  }
3694  else
3695  conshdlr->nchildren += tree->nchildren;
3696 
3697  /* remember the result of the enforcement call */
3698  conshdlr->lastenfopsresult = *result;
3699 
3700  /* evaluate result */
3701  if( *result != SCIP_CUTOFF
3702  && *result != SCIP_CONSADDED
3703  && *result != SCIP_REDUCEDDOM
3704  && *result != SCIP_BRANCHED
3705  && *result != SCIP_SOLVELP
3706  && *result != SCIP_INFEASIBLE
3707  && *result != SCIP_FEASIBLE
3708  && *result != SCIP_DIDNOTRUN )
3709  {
3710  SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions returned invalid result <%d>\n",
3711  conshdlr->name, *result);
3712  return SCIP_INVALIDRESULT;
3713  }
3714 
3715  /* if the same pseudo solution was already enforced at this node, we only enforced new constraints this time;
3716  * if the enfops call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3717  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3718  */
3719  if( lastinfeasible && *result == SCIP_FEASIBLE )
3720  *result = SCIP_INFEASIBLE;
3721  }
3722  else if( objinfeasible )
3723  {
3724  /*
3725  * Even if nothing is enforced, the solution might still be infeasible due to violating lower bound.
3726  * Make sure the result is updated in this case as well.
3727  */
3728  *result = SCIP_INFEASIBLE;
3729  }
3730  }
3731 
3732  return SCIP_OKAY;
3733 }
3734 
3735 /** calls feasibility check method of constraint handler */
3737  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3738  BMS_BLKMEM* blkmem, /**< block memory */
3739  SCIP_SET* set, /**< global SCIP settings */
3740  SCIP_STAT* stat, /**< dynamic problem statistics */
3741  SCIP_SOL* sol, /**< primal CIP solution */
3742  SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
3743  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
3744  SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
3745  SCIP_Bool completely, /**< Should all violations be checked? */
3746  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3747  )
3748 {
3749  assert(conshdlr != NULL);
3750  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3751  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3752  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3753  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3754  assert(set != NULL);
3755  assert(result != NULL);
3756 
3757  *result = SCIP_FEASIBLE;
3758 
3759  if( conshdlr->conscheck != NULL && (!conshdlr->needscons || conshdlr->ncheckconss > 0) )
3760  {
3761  SCIPsetDebugMsg(set, "checking %d constraints of handler <%s>\n", conshdlr->ncheckconss, conshdlr->name);
3762 
3763  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3764  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3765  * external method; to avoid this, these changes will be buffered and processed after the method call
3766  */
3767  conshdlrDelayUpdates(conshdlr);
3768 
3769  /* start timing */
3770  SCIPclockStart(conshdlr->checktime, set);
3771 
3772  /* call external method */
3773  SCIP_CALL( conshdlr->conscheck(set->scip, conshdlr, conshdlr->checkconss, conshdlr->ncheckconss,
3774  sol, checkintegrality, checklprows, printreason, completely, result) );
3775  SCIPsetDebugMsg(set, " -> checking returned result <%d>\n", *result);
3776 
3777  /* stop timing */
3778  SCIPclockStop(conshdlr->checktime, set);
3779 
3780  /* update statistics */
3781  conshdlr->ncheckcalls++;
3782 
3783  /* perform the cached constraint updates */
3784  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3785 
3786  /* evaluate result */
3787  if( *result != SCIP_INFEASIBLE && *result != SCIP_FEASIBLE )
3788  {
3789  SCIPerrorMessage("feasibility check of constraint handler <%s> returned invalid result <%d>\n", conshdlr->name, *result);
3790  return SCIP_INVALIDRESULT;
3791  }
3792  }
3793 
3794  return SCIP_OKAY;
3795 }
3796 
3797 /** calls propagation method of constraint handler */
3799  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3800  BMS_BLKMEM* blkmem, /**< block memory */
3801  SCIP_SET* set, /**< global SCIP settings */
3802  SCIP_STAT* stat, /**< dynamic problem statistics */
3803  int depth, /**< depth of current node */
3804  SCIP_Bool fullpropagation, /**< should all constraints be propagated (or only new ones)? */
3805  SCIP_Bool execdelayed, /**< execute propagation method even if it is marked to be delayed */
3806  SCIP_Bool instrongbranching, /**< are we currently doing strong branching? */
3807  SCIP_PROPTIMING proptiming, /**< current point in the node solving process */
3808  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3809  )
3810 {
3811  assert(conshdlr != NULL);
3812  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3813  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3814  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3815  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3816  assert(stat != NULL);
3817  assert(conshdlr->lastpropdomchgcount != stat->domchgcount
3818  || (0 <= conshdlr->lastnusefulpropconss && conshdlr->lastnusefulpropconss <= conshdlr->nusefulpropconss));
3819  assert(set != NULL);
3820  assert(depth >= 0);
3821  assert(result != NULL);
3822 
3823  *result = SCIP_DIDNOTRUN;
3824 
3825  if( conshdlr->consprop != NULL
3826  && (!conshdlr->needscons || conshdlr->npropconss > 0)
3827  && ((depth == 0 && conshdlr->propfreq == 0)
3828  || (conshdlr->propfreq > 0 && depth % conshdlr->propfreq == 0)
3829  || conshdlr->propwasdelayed) )
3830  {
3831  /* check, if propagation method should be delayed */
3832  if( !conshdlr->delayprop || execdelayed )
3833  {
3834  int nconss;
3835  int nusefulconss;
3836  int nmarkedpropconss;
3837  int firstcons;
3838 
3839  /* check, if the current domains were already propagated */
3840  if( !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount && conshdlr->nmarkedpropconss == 0 )
3841  {
3842  /* all constraints that were not yet propagated on the new domains must be useful constraints, which means,
3843  * that the new constraints are the last constraints of the useful ones
3844  */
3845  nconss = conshdlr->nusefulpropconss - conshdlr->lastnusefulpropconss;
3846  nusefulconss = nconss;
3847  firstcons = conshdlr->lastnusefulpropconss;
3848  }
3849  else
3850  {
3851  /* on new domains, we want to propagate all constraints */
3852  nconss = conshdlr->npropconss;
3853  nusefulconss = conshdlr->nusefulpropconss;
3854  firstcons = 0;
3855  }
3856  assert(firstcons >= 0);
3857  assert(firstcons + nconss <= conshdlr->npropconss);
3858  assert(nusefulconss <= nconss);
3859 
3860  nmarkedpropconss = conshdlr->nmarkedpropconss;
3861 
3862  /* constraint handlers without constraints should only be called once */
3863  if( nconss > 0 || fullpropagation
3864  || (!conshdlr->needscons && conshdlr->lastpropdomchgcount != stat->domchgcount) )
3865  {
3866  SCIP_CONS** conss;
3867  SCIP_Longint oldndomchgs;
3868  SCIP_Longint oldnprobdomchgs;
3869  SCIP_Longint lastpropdomchgcount;
3870  int lastnusefulpropconss;
3871 
3872  SCIPsetDebugMsg(set, "propagating constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, %d useful)\n",
3873  firstcons, firstcons + nconss - 1, conshdlr->npropconss, conshdlr->name,
3874  !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount ? "old" : "new", nusefulconss);
3875 
3876  /* remember the number of processed constraints on the current domains */
3877  lastpropdomchgcount = stat->domchgcount;
3878  lastnusefulpropconss = conshdlr->nusefulpropconss;
3879 
3880  /* get the array of the constraints to be processed */
3881  conss = nconss > 0 ? (conshdlr->propconss + firstcons) : NULL;
3882 
3883  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3884  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3885 
3886  /* check, if we want to use eager evaluation */
3887  if( (conshdlr->eagerfreq == 0 && conshdlr->npropcalls == 0)
3888  || (conshdlr->eagerfreq > 0 && conshdlr->npropcalls % conshdlr->eagerfreq == 0) )
3889  nusefulconss = nconss;
3890 
3891  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3892  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3893  * external method; to avoid this, these changes will be buffered and processed after the method call
3894  */
3895  conshdlrDelayUpdates(conshdlr);
3896  conshdlr->duringprop = TRUE;
3897 
3898  /* start timing */
3899  if( instrongbranching )
3900  SCIPclockStart(conshdlr->sbproptime, set);
3901  else
3902  SCIPclockStart(conshdlr->proptime, set);
3903 
3904  assert(nusefulconss <= nconss);
3905  assert(nmarkedpropconss <= nconss);
3906 
3907  /* call external method */
3908  SCIP_CALL( conshdlr->consprop(set->scip, conshdlr, conss, nconss, nusefulconss, nmarkedpropconss, proptiming, result) );
3909  SCIPsetDebugMsg(set, " -> propagation returned result <%d>\n", *result);
3910 
3911  /* stop timing */
3912  if( instrongbranching )
3913  SCIPclockStop(conshdlr->sbproptime, set);
3914  else
3915  SCIPclockStop(conshdlr->proptime, set);
3916 
3917  /* perform the cached constraint updates */
3918  conshdlr->duringprop = FALSE;
3919  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3920 
3921  /* update statistics */
3922  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
3923  {
3924  conshdlr->lastpropdomchgcount = lastpropdomchgcount;
3925  conshdlr->lastnusefulpropconss = MIN(conshdlr->nusefulpropconss, lastnusefulpropconss);
3926  conshdlr->npropcalls++;
3927  }
3928  else
3929  {
3930  assert(lastpropdomchgcount == stat->domchgcount);
3931  assert(lastnusefulpropconss == conshdlr->nusefulpropconss);
3932  }
3933  if( *result == SCIP_CUTOFF )
3934  conshdlr->ncutoffs++;
3935 
3936  /* update domain reductions; therefore remove the domain
3937  * reduction counts which were generated in probing mode */
3938  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3939  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3940 
3941  /* check result code of callback method */
3942  if( *result != SCIP_CUTOFF
3943  && *result != SCIP_REDUCEDDOM
3944  && *result != SCIP_DIDNOTFIND
3945  && *result != SCIP_DIDNOTRUN
3946  && *result != SCIP_DELAYED
3947  && *result != SCIP_DELAYNODE )
3948  {
3949  SCIPerrorMessage("propagation method of constraint handler <%s> returned invalid result <%d>\n",
3950  conshdlr->name, *result);
3951  return SCIP_INVALIDRESULT;
3952  }
3953  }
3954  }
3955  else
3956  {
3957  SCIPsetDebugMsg(set, "propagation method of constraint handler <%s> was delayed\n", conshdlr->name);
3958  *result = SCIP_DELAYED;
3959  }
3960 
3961  /* remember whether propagation method was delayed */
3962  conshdlr->propwasdelayed = (*result == SCIP_DELAYED);
3963  }
3964 
3965  return SCIP_OKAY;
3966 }
3967 
3968 /** calls presolving method of constraint handler */
3970  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3971  BMS_BLKMEM* blkmem, /**< block memory */
3972  SCIP_SET* set, /**< global SCIP settings */
3973  SCIP_STAT* stat, /**< dynamic problem statistics */
3974  SCIP_PRESOLTIMING timing, /**< current presolving timing */
3975  int nrounds, /**< number of presolving rounds already done */
3976  int* nfixedvars, /**< pointer to total number of variables fixed of all presolvers */
3977  int* naggrvars, /**< pointer to total number of variables aggregated of all presolvers */
3978  int* nchgvartypes, /**< pointer to total number of variable type changes of all presolvers */
3979  int* nchgbds, /**< pointer to total number of variable bounds tightened of all presolvers */
3980  int* naddholes, /**< pointer to total number of domain holes added of all presolvers */
3981  int* ndelconss, /**< pointer to total number of deleted constraints of all presolvers */
3982  int* naddconss, /**< pointer to total number of added constraints of all presolvers */
3983  int* nupgdconss, /**< pointer to total number of upgraded constraints of all presolvers */
3984  int* nchgcoefs, /**< pointer to total number of changed coefficients of all presolvers */
3985  int* nchgsides, /**< pointer to total number of changed left/right hand sides of all presolvers */
3986  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3987  )
3988 {
3989  assert(conshdlr != NULL);
3990  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3991  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3992  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3993  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3994  assert(set != NULL);
3995  assert(nfixedvars != NULL);
3996  assert(naggrvars != NULL);
3997  assert(nchgvartypes != NULL);
3998  assert(nchgbds != NULL);
3999  assert(naddholes != NULL);
4000  assert(ndelconss != NULL);
4001  assert(naddconss != NULL);
4002  assert(nupgdconss != NULL);
4003  assert(nchgcoefs != NULL);
4004  assert(nchgsides != NULL);
4005  assert(result != NULL);
4006 
4007  *result = SCIP_DIDNOTRUN;
4008 
4009  if( conshdlr->conspresol != NULL
4010  && (!conshdlr->needscons || conshdlr->nactiveconss > 0)
4011  && (conshdlr->maxprerounds == -1 || conshdlr->npresolcalls < conshdlr->maxprerounds ) )
4012  {
4013  SCIPsetDebugMsg(set, "presolving %d constraints of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4014 
4015  /* check, if presolving method should be executed for the current timing */
4016  if( timing & conshdlr->presoltiming )
4017  {
4018  int nnewfixedvars;
4019  int nnewaggrvars;
4020  int nnewchgvartypes;
4021  int nnewchgbds;
4022  int nnewholes;
4023  int nnewdelconss;
4024  int nnewaddconss;
4025  int nnewupgdconss;
4026  int nnewchgcoefs;
4027  int nnewchgsides;
4028 
4029  /* calculate the number of changes since last call */
4030  nnewfixedvars = *nfixedvars - conshdlr->lastnfixedvars;
4031  nnewaggrvars = *naggrvars - conshdlr->lastnaggrvars;
4032  nnewchgvartypes = *nchgvartypes - conshdlr->lastnchgvartypes;
4033  nnewchgbds = *nchgbds - conshdlr->lastnchgbds;
4034  nnewholes = *naddholes - conshdlr->lastnaddholes;
4035  nnewdelconss = *ndelconss - conshdlr->lastndelconss;
4036  nnewaddconss = *naddconss - conshdlr->lastnaddconss;
4037  nnewupgdconss = *nupgdconss - conshdlr->lastnupgdconss;
4038  nnewchgcoefs = *nchgcoefs - conshdlr->lastnchgcoefs;
4039  nnewchgsides = *nchgsides - conshdlr->lastnchgsides;
4040 
4041  /* remember the old number of changes */
4042  conshdlr->lastnfixedvars = *nfixedvars;
4043  conshdlr->lastnaggrvars = *naggrvars;
4044  conshdlr->lastnchgvartypes = *nchgvartypes;
4045  conshdlr->lastnchgbds = *nchgbds;
4046  conshdlr->lastnaddholes = *naddholes;
4047  conshdlr->lastndelconss = *ndelconss;
4048  conshdlr->lastnaddconss = *naddconss;
4049  conshdlr->lastnupgdconss = *nupgdconss;
4050  conshdlr->lastnchgcoefs = *nchgcoefs;
4051  conshdlr->lastnchgsides = *nchgsides;
4052 
4053  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4054  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4055  * external method; to avoid this, these changes will be buffered and processed after the method call
4056  */
4057  conshdlrDelayUpdates(conshdlr);
4058 
4059  /* start timing */
4060  SCIPclockStart(conshdlr->presoltime, set);
4061 
4062  /* call external method */
4063  SCIP_CALL( conshdlr->conspresol(set->scip, conshdlr, conshdlr->conss, conshdlr->nactiveconss, nrounds, timing,
4064  nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewholes,
4065  nnewdelconss, nnewaddconss, nnewupgdconss, nnewchgcoefs, nnewchgsides,
4066  nfixedvars, naggrvars, nchgvartypes, nchgbds, naddholes,
4067  ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) );
4068 
4069  /* stop timing */
4070  SCIPclockStop(conshdlr->presoltime, set);
4071 
4072  /* perform the cached constraint updates */
4073  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4074 
4075  /* count the new changes */
4076  conshdlr->nfixedvars += *nfixedvars - conshdlr->lastnfixedvars;
4077  conshdlr->naggrvars += *naggrvars - conshdlr->lastnaggrvars;
4078  conshdlr->nchgvartypes += *nchgvartypes - conshdlr->lastnchgvartypes;
4079  conshdlr->nchgbds += *nchgbds - conshdlr->lastnchgbds;
4080  conshdlr->naddholes += *naddholes - conshdlr->lastnaddholes;
4081  conshdlr->ndelconss += *ndelconss - conshdlr->lastndelconss;
4082  conshdlr->naddconss += *naddconss - conshdlr->lastnaddconss;
4083  conshdlr->nupgdconss += *nupgdconss - conshdlr->lastnupgdconss;
4084  conshdlr->nchgcoefs += *nchgcoefs - conshdlr->lastnchgcoefs;
4085  conshdlr->nchgsides += *nchgsides - conshdlr->lastnchgsides;
4086 
4087  /* check result code of callback method */
4088  if( *result != SCIP_CUTOFF
4089  && *result != SCIP_UNBOUNDED
4090  && *result != SCIP_SUCCESS
4091  && *result != SCIP_DIDNOTFIND
4092  && *result != SCIP_DIDNOTRUN
4093  && *result != SCIP_DELAYED )
4094  {
4095  SCIPerrorMessage("presolving method of constraint handler <%s> returned invalid result <%d>\n",
4096  conshdlr->name, *result);
4097  return SCIP_INVALIDRESULT;
4098  }
4099 
4100  /* increase the number of calls, if the presolving method tried to find reductions */
4101  if( *result != SCIP_DIDNOTRUN )
4102  ++(conshdlr->npresolcalls);
4103  }
4104 
4105  SCIPsetDebugMsg(set, "after presolving %d constraints left of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4106  }
4107 
4108  return SCIP_OKAY;
4109 }
4110 
4111 /** calls variable deletion method of constraint handler */
4113  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4114  BMS_BLKMEM* blkmem, /**< block memory */
4115  SCIP_SET* set, /**< global SCIP settings */
4116  SCIP_STAT* stat /**< dynamic problem statistics */
4117  )
4118 {
4119  assert(conshdlr != NULL);
4120  assert(set != NULL);
4121 
4122  if( conshdlr->consdelvars != NULL )
4123  {
4124  SCIPsetDebugMsg(set, "deleting variables in constraints of handler <%s>\n", conshdlr->name);
4125 
4126  /* during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4127  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4128  * external method; to avoid this, these changes will be buffered and processed after the method call
4129  */
4130  conshdlrDelayUpdates(conshdlr);
4131 
4132  /* call external method */
4133  SCIP_CALL( conshdlr->consdelvars(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
4134 
4135  /* perform the cached constraint updates */
4136  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4137  }
4138 
4139  return SCIP_OKAY;
4140 }
4141 
4142 /** locks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
4144  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4145  SCIP_SET* set /**< global SCIP settings */
4146  )
4147 {
4148  assert(conshdlr != NULL);
4149  assert(conshdlr->conslock != NULL);
4150  assert(!conshdlr->needscons);
4151 
4152  SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, +1, 0) );
4153 
4154  return SCIP_OKAY;
4155 }
4156 
4157 /** unlocks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
4159  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4160  SCIP_SET* set /**< global SCIP settings */
4161  )
4162 {
4163  assert(conshdlr != NULL);
4164  assert(conshdlr->conslock != NULL);
4165  assert(!conshdlr->needscons);
4166 
4167  SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, -1, 0) );
4168 
4169  return SCIP_OKAY;
4170 }
4171 
4172 /** gets name of constraint handler */
4173 const char* SCIPconshdlrGetName(
4174  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4175  )
4176 {
4177  assert(conshdlr != NULL);
4178 
4179  return conshdlr->name;
4180 }
4181 
4182 /** gets description of constraint handler */
4183 const char* SCIPconshdlrGetDesc(
4184  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4185  )
4186 {
4187  assert(conshdlr != NULL);
4188 
4189  return conshdlr->desc;
4190 }
4191 
4192 /** gets user data of constraint handler */
4194  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4195  )
4196 {
4197  assert(conshdlr != NULL);
4198 
4199  return conshdlr->conshdlrdata;
4200 }
4201 
4202 /** sets user data of constraint handler; user has to free old data in advance! */
4203 void SCIPconshdlrSetData(
4204  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4205  SCIP_CONSHDLRDATA* conshdlrdata /**< new constraint handler user data */
4206  )
4207 {
4208  assert(conshdlr != NULL);
4209 
4210  conshdlr->conshdlrdata = conshdlrdata;
4211 }
4212 
4213 /** sets all separation related callbacks of the constraint handler */
4214 void SCIPconshdlrSetSepa(
4215  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4216  SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */
4217  SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */
4218  int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */
4219  int sepapriority, /**< priority of the constraint handler for separation */
4220  SCIP_Bool delaysepa /**< should separation method be delayed, if other separators found cuts? */
4221  )
4222 {
4223  assert(conshdlr != NULL);
4224 
4225  assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
4226 
4227  conshdlr->conssepalp = conssepalp;
4228  conshdlr->conssepasol = conssepasol;
4229  conshdlr->sepafreq = sepafreq;
4230  conshdlr->sepapriority = sepapriority;
4231  conshdlr->delaysepa = delaysepa;
4232 }
4233 
4234 /** sets both the propagation callback and the propagation frequency of the constraint handler */
4235 void SCIPconshdlrSetProp(
4236  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4237  SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */
4238  int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */
4239  SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */
4240  SCIP_PROPTIMING timingmask /**< positions in the node solving loop where propagators should be executed */
4241  )
4242 {
4243  assert(conshdlr != NULL);
4244 
4245  assert(consprop != NULL || propfreq == -1);
4246 
4247  conshdlr->consprop = consprop;
4248  conshdlr->propfreq = propfreq;
4249  conshdlr->delayprop = delayprop;
4250  conshdlr->proptiming = timingmask;
4251 }
4252 
4253 /** sets copy method of both the constraint handler and each associated constraint */
4255  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4256  SCIP_DECL_CONSENFORELAX ((*consenforelax)) /**< constraint copying method */
4257  )
4258 {
4259  assert(conshdlr != NULL);
4260 
4261  conshdlr->consenforelax = consenforelax;
4262 }
4263 
4264 /** sets copy method of both the constraint handler and each associated constraint */
4265 void SCIPconshdlrSetCopy(
4266  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4267  SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
4268  SCIP_DECL_CONSCOPY ((*conscopy)) /**< constraint copying method */
4269  )
4270 {
4271  assert(conshdlr != NULL);
4272 
4273  assert(!conshdlr->needscons || (conshdlrcopy == NULL) == (conscopy == NULL));
4274 
4275  conshdlr->conshdlrcopy = conshdlrcopy;
4276  conshdlr->conscopy = conscopy;
4277 }
4278 
4279 /** sets destructor method of constraint handler */
4280 void SCIPconshdlrSetFree(
4281  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4282  SCIP_DECL_CONSFREE ((*consfree)) /**< destructor of constraint handler */
4283  )
4284 {
4285  assert(conshdlr != NULL);
4286 
4287  conshdlr->consfree = consfree;
4288 }
4289 
4290 /** sets initialization method of constraint handler */
4291 void SCIPconshdlrSetInit(
4292  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4293  SCIP_DECL_CONSINIT ((*consinit)) /**< initialize constraint handler */
4294  )
4295 {
4296  assert(conshdlr != NULL);
4297 
4298  conshdlr->consinit = consinit;
4299 }
4300 
4301 /** sets deinitialization method of constraint handler */
4302 void SCIPconshdlrSetExit(
4303  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4304  SCIP_DECL_CONSEXIT ((*consexit)) /**< deinitialize constraint handler */
4305  )
4306 {
4307  assert(conshdlr != NULL);
4308 
4309  conshdlr->consexit = consexit;
4310 }
4311 
4312 /** sets solving process initialization method of constraint handler */
4314  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4315  SCIP_DECL_CONSINITSOL((*consinitsol)) /**< solving process initialization method of constraint handler */
4316  )
4317 {
4318  assert(conshdlr != NULL);
4319 
4320  conshdlr->consinitsol = consinitsol;
4321 }
4322 
4323 /** sets solving process deinitialization method of constraint handler */
4325  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4326  SCIP_DECL_CONSEXITSOL ((*consexitsol)) /**< solving process deinitialization method of constraint handler */
4327  )
4328 {
4329  assert(conshdlr != NULL);
4330 
4331  conshdlr->consexitsol = consexitsol;
4332 }
4333 
4334 /** sets preprocessing initialization method of constraint handler */
4336  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4337  SCIP_DECL_CONSINITPRE((*consinitpre)) /**< preprocessing initialization method of constraint handler */
4338  )
4339 {
4340  assert(conshdlr != NULL);
4341 
4342  conshdlr->consinitpre = consinitpre;
4343 }
4344 
4345 /** sets preprocessing deinitialization method of constraint handler */
4347  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4348  SCIP_DECL_CONSEXITPRE((*consexitpre)) /**< preprocessing deinitialization method of constraint handler */
4349  )
4350 {
4351  assert(conshdlr != NULL);
4352 
4353  conshdlr->consexitpre = consexitpre;
4354 }
4355 
4356 /** sets presolving method of constraint handler */
4358  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4359  SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method of constraint handler */
4360  int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
4361  SCIP_PRESOLTIMING presoltiming /**< timing mask of the constraint handler's presolving method */
4362  )
4363 {
4364  assert(conshdlr != NULL);
4365 
4366  conshdlr->conspresol = conspresol;
4367  conshdlr->maxprerounds = maxprerounds;
4368 
4369  /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
4370  * error message
4371  */
4372  if( presoltiming < SCIP_PRESOLTIMING_FAST || presoltiming > SCIP_PRESOLTIMING_MAX )
4373  {
4374  SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
4375  "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", conshdlr->name);
4376 
4377  return SCIP_PARAMETERWRONGVAL;
4378  }
4379 
4380  conshdlr->presoltiming = presoltiming;
4381 
4382  return SCIP_OKAY;
4383 }
4384 
4385 /** sets method of constraint handler to free specific constraint data */
4387  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4388  SCIP_DECL_CONSDELETE ((*consdelete)) /**< free specific constraint data */
4389  )
4390 {
4391  assert(conshdlr != NULL);
4392 
4393  conshdlr->consdelete = consdelete;
4394 }
4395 
4396 /** sets method of constraint handler to transform constraint data into data belonging to the transformed problem */
4398  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4399  SCIP_DECL_CONSTRANS ((*constrans)) /**< transform constraint data into data belonging to the transformed problem */
4400  )
4401 {
4402  assert(conshdlr != NULL);
4403 
4404  conshdlr->constrans = constrans;
4405 }
4406 
4407 /** sets method of constraint handler to initialize LP with relaxations of "initial" constraints */
4409  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4410  SCIP_DECL_CONSINITLP ((*consinitlp)) /**< initialize LP with relaxations of "initial" constraints */
4411  )
4412 {
4413  assert(conshdlr != NULL);
4414 
4415  conshdlr->consinitlp = consinitlp;
4416 }
4417 
4418 /** sets propagation conflict resolving method of constraint handler */
4420  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4421  SCIP_DECL_CONSRESPROP ((*consresprop)) /**< propagation conflict resolving method */
4422  )
4423 {
4424  assert(conshdlr != NULL);
4425 
4426  conshdlr->consresprop = consresprop;
4427 }
4428 
4429 /** sets activation notification method of constraint handler */
4431  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4432  SCIP_DECL_CONSACTIVE ((*consactive)) /**< activation notification method */
4433  )
4434 {
4435  assert(conshdlr != NULL);
4436 
4437  conshdlr->consactive = consactive;
4438 }
4439 
4440 /** sets deactivation notification method of constraint handler */
4442  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4443  SCIP_DECL_CONSDEACTIVE((*consdeactive)) /**< deactivation notification method */
4444  )
4445 {
4446  assert(conshdlr != NULL);
4447 
4448  conshdlr->consdeactive = consdeactive;
4449 }
4450 
4451 /** sets enabling notification method of constraint handler */
4453  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4454  SCIP_DECL_CONSENABLE ((*consenable)) /**< enabling notification method */
4455  )
4456 {
4457  assert(conshdlr != NULL);
4458 
4459  conshdlr->consenable = consenable;
4460 }
4461 
4462 /** sets disabling notification method of constraint handler */
4464  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4465  SCIP_DECL_CONSDISABLE ((*consdisable)) /**< disabling notification method */
4466  )
4467 {
4468  assert(conshdlr != NULL);
4469 
4470  conshdlr->consdisable = consdisable;
4471 }
4472 
4473 /** sets variable deletion method of constraint handler */
4475  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4476  SCIP_DECL_CONSDELVARS ((*consdelvars)) /**< variable deletion method */
4477  )
4478 {
4479  assert(conshdlr != NULL);
4480 
4481  conshdlr->consdelvars = consdelvars;
4482 }
4483 
4484 /** sets constraint display method of constraint handler */
4486  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4487  SCIP_DECL_CONSPRINT ((*consprint)) /**< constraint display method */
4488  )
4489 {
4490  assert(conshdlr != NULL);
4491 
4492  conshdlr->consprint = consprint;
4493 }
4494 
4495 /** sets constraint parsing method of constraint handler */
4497  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4498  SCIP_DECL_CONSPARSE ((*consparse)) /**< constraint parsing method */
4499  )
4500 {
4501  assert(conshdlr != NULL);
4502 
4503  conshdlr->consparse = consparse;
4504 }
4505 
4506 /** sets constraint variable getter method of constraint handler */
4508  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4509  SCIP_DECL_CONSGETVARS ((*consgetvars)) /**< constraint variable getter method */
4510  )
4511 {
4512  assert(conshdlr != NULL);
4513 
4514  conshdlr->consgetvars = consgetvars;
4515 }
4516 
4517 /** sets constraint variable number getter method of constraint handler */
4519  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4520  SCIP_DECL_CONSGETNVARS((*consgetnvars)) /**< constraint variable number getter method */
4521  )
4522 {
4523  assert(conshdlr != NULL);
4524 
4525  conshdlr->consgetnvars = consgetnvars;
4526 }
4527 
4528 /** sets diving enforcement method of constraint handler */
4530  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4531  SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)) /**< constraint handler diving solution enforcement method */
4532  )
4533 {
4534  assert(conshdlr != NULL);
4535 
4536  conshdlr->consgetdivebdchgs = consgetdivebdchgs;
4537 }
4538 
4539 /** gets array with constraints of constraint handler; the first SCIPconshdlrGetNActiveConss() entries are the active
4540  * constraints, the last SCIPconshdlrGetNConss() - SCIPconshdlrGetNActiveConss() constraints are deactivated
4541  *
4542  * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4543  * flag is TRUE) and the current node belongs to the corresponding sub tree.
4544  */
4546  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4547  )
4548 {
4549  assert(conshdlr != NULL);
4550 
4551  return conshdlr->conss;
4552 }
4553 
4554 /** gets array with enforced constraints of constraint handler; this is local information */
4556  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4557  )
4558 {
4559  assert(conshdlr != NULL);
4560 
4561  return conshdlr->enfoconss;
4562 }
4563 
4564 /** gets array with checked constraints of constraint handler; this is local information */
4566  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4567  )
4568 {
4569  assert(conshdlr != NULL);
4570 
4571  return conshdlr->checkconss;
4572 }
4573 
4574 /** gets array with delayed update constraints
4575  *
4576  * @attention Usually, there should be no need to access this array. Use this only if you are absolutely sure what you are doing.
4577  */
4579  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4580  )
4581 {
4582  assert(conshdlr != NULL);
4583 
4584  return conshdlr->updateconss;
4585 }
4586 
4587 /** gets total number of existing transformed constraints of constraint handler */
4589  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4590  )
4591 {
4592  assert(conshdlr != NULL);
4593 
4594  return conshdlr->nconss;
4595 }
4596 
4597 /** gets number of enforced constraints of constraint handler; this is local information */
4599  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4600  )
4601 {
4602  assert(conshdlr != NULL);
4603 
4604  return conshdlr->nenfoconss;
4605 }
4606 
4607 /** gets number of checked constraints of constraint handler; this is local information */
4609  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4610  )
4611 {
4612  assert(conshdlr != NULL);
4613 
4614  return conshdlr->ncheckconss;
4615 }
4616 
4617 /** gets number of active constraints of constraint handler
4618  *
4619  * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4620  * flag is TRUE) and the current node belongs to the corresponding sub tree.
4621  */
4623  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4624  )
4625 {
4626  assert(conshdlr != NULL);
4627 
4628  return conshdlr->nactiveconss;
4629 }
4630 
4631 /** gets number of enabled constraints of constraint handler */
4633  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4634  )
4635 {
4636  assert(conshdlr != NULL);
4637 
4638  return conshdlr->nenabledconss;
4639 }
4640 
4641 /** gets number of constraints that have delayed updates */
4643  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4644  )
4645 {
4646  assert(conshdlr != NULL);
4647 
4648  return conshdlr->nupdateconss;
4649 }
4650 
4651 /** enables or disables all clocks of \p conshdlr, depending on the value of the flag */
4653  SCIP_CONSHDLR* conshdlr, /**< the constraint handler for which all clocks should be enabled or disabled */
4654  SCIP_Bool enable /**< should the clocks of the constraint handler be enabled? */
4655  )
4656 {
4657  assert(conshdlr != NULL);
4658 
4659  SCIPclockEnableOrDisable(conshdlr->setuptime, enable);
4660  SCIPclockEnableOrDisable(conshdlr->checktime, enable);
4661  SCIPclockEnableOrDisable(conshdlr->enfolptime, enable);
4662  SCIPclockEnableOrDisable(conshdlr->enfopstime, enable);
4663  SCIPclockEnableOrDisable(conshdlr->enforelaxtime, enable);
4664  SCIPclockEnableOrDisable(conshdlr->presoltime, enable);
4665  SCIPclockEnableOrDisable(conshdlr->proptime, enable);
4666  SCIPclockEnableOrDisable(conshdlr->resproptime, enable);
4667  SCIPclockEnableOrDisable(conshdlr->sbproptime, enable);
4668  SCIPclockEnableOrDisable(conshdlr->sepatime, enable);
4669 }
4670 
4671 /** gets time in seconds used for setting up this constraint handler for new stages */
4673  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4674  )
4675 {
4676  assert(conshdlr != NULL);
4677 
4678  return SCIPclockGetTime(conshdlr->setuptime);
4679 }
4680 
4681 /** gets time in seconds used for presolving in this constraint handler */
4683  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4684  )
4685 {
4686  assert(conshdlr != NULL);
4687 
4688  return SCIPclockGetTime(conshdlr->presoltime);
4689 }
4690 
4691 /** gets time in seconds used for separation in this constraint handler */
4693  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4694  )
4695 {
4696  assert(conshdlr != NULL);
4697 
4698  return SCIPclockGetTime(conshdlr->sepatime);
4699 }
4700 
4701 /** gets time in seconds used for LP enforcement in this constraint handler */
4703  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4704  )
4705 {
4706  assert(conshdlr != NULL);
4707 
4708  return SCIPclockGetTime(conshdlr->enfolptime);
4709 }
4710 
4711 /** gets time in seconds used for pseudo enforcement in this constraint handler */
4713  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4714  )
4715 {
4716  assert(conshdlr != NULL);
4717 
4718  return SCIPclockGetTime(conshdlr->enfopstime);
4719 }
4720 
4721 /** gets time in seconds used for relaxation enforcement in this constraint handler */
4723  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4724  )
4725 {
4726  assert(conshdlr != NULL);
4727 
4728  return SCIPclockGetTime(conshdlr->enforelaxtime);
4729 }
4730 
4731 /** gets time in seconds used for propagation in this constraint handler */
4733  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4734  )
4735 {
4736  assert(conshdlr != NULL);
4737 
4738  return SCIPclockGetTime(conshdlr->proptime);
4739 }
4740 
4741 /** gets time in seconds used for propagation in this constraint handler during strong branching */
4743  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4744  )
4745 {
4746  assert(conshdlr != NULL);
4747 
4748  return SCIPclockGetTime(conshdlr->sbproptime);
4749 }
4750 
4751 /** gets time in seconds used for feasibility checking in this constraint handler */
4753  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4754  )
4755 {
4756  assert(conshdlr != NULL);
4757 
4758  return SCIPclockGetTime(conshdlr->checktime);
4759 }
4760 
4761 /** gets time in seconds used for resolving propagation in this constraint handler */
4763  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4764  )
4765 {
4766  assert(conshdlr != NULL);
4767 
4768  return SCIPclockGetTime(conshdlr->resproptime);
4769 }
4770 
4771 /** gets number of calls to the constraint handler's separation method */
4773  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4774  )
4775 {
4776  assert(conshdlr != NULL);
4777 
4778  return conshdlr->nsepacalls;
4779 }
4780 
4781 /** gets number of calls to the constraint handler's LP enforcing method */
4783  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4784  )
4785 {
4786  assert(conshdlr != NULL);
4787 
4788  return conshdlr->nenfolpcalls;
4789 }
4790 
4791 /** gets number of calls to the constraint handler's pseudo enforcing method */
4793  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4794  )
4795 {
4796  assert(conshdlr != NULL);
4797 
4798  return conshdlr->nenfopscalls;
4799 }
4800 
4801 /** gets number of calls to the constraint handler's relaxation enforcing method */
4803  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4804  )
4805 {
4806  assert(conshdlr != NULL);
4807 
4808  return conshdlr->nenforelaxcalls;
4809 }
4810 
4811 /** gets number of calls to the constraint handler's propagation method */
4813  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4814  )
4815 {
4816  assert(conshdlr != NULL);
4817 
4818  return conshdlr->npropcalls;
4819 }
4820 
4821 /** gets number of calls to the constraint handler's checking method */
4823  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4824  )
4825 {
4826  assert(conshdlr != NULL);
4827 
4828  return conshdlr->ncheckcalls;
4829 }
4830 
4831 /** gets number of calls to the constraint handler's resolve propagation method */
4833  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4834  )
4835 {
4836  assert(conshdlr != NULL);
4837 
4838  return conshdlr->nrespropcalls;
4839 }
4840 
4841 /** gets total number of times, this constraint handler detected a cutoff */
4843  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4844  )
4845 {
4846  assert(conshdlr != NULL);
4847 
4848  return conshdlr->ncutoffs;
4849 }
4850 
4851 /** gets total number of cuts found by this constraint handler */
4853  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4854  )
4855 {
4856  assert(conshdlr != NULL);
4857 
4858  return conshdlr->ncutsfound;
4859 }
4860 
4861 /** gets total number of cuts found by this constraint handler applied to lp */
4863  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4864  )
4865 {
4866  assert(conshdlr != NULL);
4867 
4868  return conshdlr->ncutsapplied;
4869 }
4870 
4871 /** increase count of applied cuts */
4873  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4874  )
4875 {
4876  assert(conshdlr != NULL);
4877 
4878  ++conshdlr->ncutsapplied;
4879 }
4880 
4881 /** increase count of found cuts */
4883  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4884  )
4885 {
4886  assert(conshdlr != NULL);
4887 
4888  ++conshdlr->ncutsfound;
4889 }
4890 
4891 /** gets total number of additional constraints added by this constraint handler */
4893  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4894  )
4895 {
4896  assert(conshdlr != NULL);
4897 
4898  return conshdlr->nconssfound;
4899 }
4900 
4901 /** gets total number of domain reductions found by this constraint handler */
4903  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4904  )
4905 {
4906  assert(conshdlr != NULL);
4907 
4908  return conshdlr->ndomredsfound;
4909 }
4910 
4911 /** gets number of children created by this constraint handler */
4913  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4914  )
4915 {
4916  assert(conshdlr != NULL);
4917 
4918  return conshdlr->nchildren;
4919 }
4920 
4921 /** gets maximum number of active constraints of constraint handler existing at the same time */
4923  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4924  )
4925 {
4926  assert(conshdlr != NULL);
4927 
4928  return conshdlr->maxnactiveconss;
4929 }
4930 
4931 /** gets initial number of active constraints of constraint handler */
4933  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4934  )
4935 {
4936  assert(conshdlr != NULL);
4937 
4938  return conshdlr->startnactiveconss;
4939 }
4940 
4941 /** gets number of variables fixed in presolving method of constraint handler */
4943  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4944  )
4945 {
4946  assert(conshdlr != NULL);
4947 
4948  return conshdlr->nfixedvars;
4949 }
4950 
4951 /** gets number of variables aggregated in presolving method of constraint handler */
4953  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4954  )
4955 {
4956  assert(conshdlr != NULL);
4957 
4958  return conshdlr->naggrvars;
4959 }
4960 
4961 /** gets number of variable types changed in presolving method of constraint handler */
4963  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4964  )
4965 {
4966  assert(conshdlr != NULL);
4967 
4968  return conshdlr->nchgvartypes;
4969 }
4970 
4971 /** gets number of bounds changed in presolving method of constraint handler */
4973  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4974  )
4975 {
4976  assert(conshdlr != NULL);
4977 
4978  return conshdlr->nchgbds;
4979 }
4980 
4981 /** gets number of holes added to domains of variables in presolving method of constraint handler */
4983  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4984  )
4985 {
4986  assert(conshdlr != NULL);
4987 
4988  return conshdlr->naddholes;
4989 }
4990 
4991 /** gets number of constraints deleted in presolving method of constraint handler */
4993  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4994  )
4995 {
4996  assert(conshdlr != NULL);
4997 
4998  return conshdlr->ndelconss;
4999 }
5000 
5001 /** gets number of constraints added in presolving method of constraint handler */
5003  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5004  )
5005 {
5006  assert(conshdlr != NULL);
5007 
5008  return conshdlr->naddconss;
5009 }
5010 
5011 /** gets number of constraints upgraded in presolving method of constraint handler */
5013  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5014  )
5015 {
5016  assert(conshdlr != NULL);
5017 
5018  return conshdlr->nupgdconss;
5019 }
5020 
5021 /** gets number of coefficients changed in presolving method of constraint handler */
5023  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5024  )
5025 {
5026  assert(conshdlr != NULL);
5027 
5028  return conshdlr->nchgcoefs;
5029 }
5030 
5031 /** gets number of constraint sides changed in presolving method of constraint handler */
5033  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5034  )
5035 {
5036  assert(conshdlr != NULL);
5037 
5038  return conshdlr->nchgsides;
5039 }
5040 
5041 /** gets number of times the presolving method of the constraint handler was called and tried to find reductions */
5043  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5044  )
5045 {
5046  assert(conshdlr != NULL);
5047 
5048  return conshdlr->npresolcalls;
5049 }
5050 
5051 /** gets separation priority of constraint handler */
5053  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5054  )
5055 {
5056  assert(conshdlr != NULL);
5057 
5058  return conshdlr->sepapriority;
5059 }
5060 
5061 /** gets enforcing priority of constraint handler */
5063  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5064  )
5065 {
5066  assert(conshdlr != NULL);
5067 
5068  return conshdlr->enfopriority;
5069 }
5070 
5071 /** gets checking priority of constraint handler */
5073  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5074  )
5075 {
5076  assert(conshdlr != NULL);
5077 
5078  return conshdlr->checkpriority;
5079 }
5080 
5081 /** gets separation frequency of constraint handler */
5083  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5084  )
5085 {
5086  assert(conshdlr != NULL);
5087 
5088  return conshdlr->sepafreq;
5089 }
5090 
5091 /** gets propagation frequency of constraint handler */
5093  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5094  )
5095 {
5096  assert(conshdlr != NULL);
5097 
5098  return conshdlr->propfreq;
5099 }
5100 
5101 /** gets frequency of constraint handler for eager evaluations in separation, propagation and enforcement */
5103  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5104  )
5105 {
5106  assert(conshdlr != NULL);
5107 
5108  return conshdlr->eagerfreq;
5109 }
5110 
5111 /** needs constraint handler a constraint to be called? */
5113  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5114  )
5115 {
5116  assert(conshdlr != NULL);
5117 
5118  return conshdlr->needscons;
5119 }
5120 
5121 /** does the constraint handler perform presolving? */
5123  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5124  )
5125 {
5126  assert(conshdlr != NULL);
5127 
5128  return (conshdlr->conspresol != NULL);
5129 }
5130 
5131 /** should separation method be delayed, if other separators found cuts? */
5133  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5134  )
5135 {
5136  assert(conshdlr != NULL);
5137 
5138  return conshdlr->delaysepa;
5139 }
5140 
5141 /** should propagation method be delayed, if other propagators found reductions? */
5143  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5144  )
5145 {
5146  assert(conshdlr != NULL);
5147 
5148  return conshdlr->delayprop;
5149 }
5150 
5151 /** was LP separation method delayed at the last call? */
5153  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5154  )
5155 {
5156  assert(conshdlr != NULL);
5157 
5158  return conshdlr->sepalpwasdelayed;
5159 }
5160 
5161 /** was primal solution separation method delayed at the last call? */
5163  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5164  )
5165 {
5166  assert(conshdlr != NULL);
5167 
5168  return conshdlr->sepasolwasdelayed;
5169 }
5170 
5171 /** was propagation method delayed at the last call? */
5173  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5174  )
5175 {
5176  assert(conshdlr != NULL);
5177 
5178  return conshdlr->propwasdelayed;
5179 }
5180 
5181 /** is constraint handler initialized? */
5183  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5184  )
5185 {
5186  assert(conshdlr != NULL);
5187 
5188  return conshdlr->initialized;
5189 }
5190 
5191 /** does the constraint handler have a copy function? */
5193  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5194  )
5195 {
5196  assert(conshdlr != NULL);
5197 
5198  return (conshdlr->conshdlrcopy != NULL);
5199 }
5200 
5201 /** returns the timing mask of the propagation method of the constraint handler */
5203  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5204  )
5205 {
5206  assert(conshdlr != NULL);
5207 
5208  return conshdlr->proptiming;
5209 }
5210 
5211 /** sets the timing mask of the propagation method of the constraint handler */
5213  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
5214  SCIP_PROPTIMING proptiming /**< timing mask to be set */
5215  )
5216 {
5217  assert(conshdlr != NULL);
5218 
5219  conshdlr->proptiming = proptiming;
5220 }
5221 
5222 
5223 /** returns the timing mask of the presolving method of the constraint handler */
5225  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5226  )
5227 {
5228  assert(conshdlr != NULL);
5229 
5230  return conshdlr->presoltiming;
5231 }
5232 
5233 /** sets the timing mask of the presolving method of the constraint handler */
5235  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
5236  SCIP_PRESOLTIMING presoltiming /** timing mask to be set */
5237  )
5238 {
5239  assert(conshdlr != NULL);
5240 
5241  conshdlr->presoltiming = presoltiming;
5242 }
5243 
5244 
5245 /*
5246  * Constraint set change methods
5247  */
5248 
5249 /** creates empty constraint set change data */
5250 static
5252  SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change data */
5253  BMS_BLKMEM* blkmem /**< block memory */
5254  )
5255 {
5256  assert(conssetchg != NULL);
5257  assert(blkmem != NULL);
5258 
5259  SCIP_ALLOC( BMSallocBlockMemory(blkmem, conssetchg) );
5260  (*conssetchg)->addedconss = NULL;
5261  (*conssetchg)->disabledconss = NULL;
5262  (*conssetchg)->addedconsssize = 0;
5263  (*conssetchg)->naddedconss = 0;
5264  (*conssetchg)->disabledconsssize = 0;
5265  (*conssetchg)->ndisabledconss = 0;
5266 
5267  return SCIP_OKAY;
5268 }
5269 
5270 /** releases all constraints of the constraint set change data */
5271 static
5273  SCIP_CONSSETCHG* conssetchg, /**< constraint set change data */
5274  BMS_BLKMEM* blkmem, /**< block memory */
5275  SCIP_SET* set /**< global SCIP settings */
5276  )
5277 {
5278  int i;
5279 
5280  assert(conssetchg != NULL);
5281 
5282  /* release constraints */
5283  for( i = 0; i < conssetchg->naddedconss; ++i )
5284  {
5285  if( conssetchg->addedconss[i] != NULL )
5286  {
5287  SCIP_CALL( SCIPconsRelease(&conssetchg->addedconss[i], blkmem, set) );
5288  }
5289  }
5290  for( i = 0; i < conssetchg->ndisabledconss; ++i )
5291  {
5292  if( conssetchg->disabledconss[i] != NULL )
5293  {
5294  SCIP_CALL( SCIPconsRelease(&conssetchg->disabledconss[i], blkmem, set) );
5295  }
5296  }
5297 
5298  return SCIP_OKAY;
5299 }
5300 
5301 /** frees constraint set change data and releases all included constraints */
5303  SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change */
5304  BMS_BLKMEM* blkmem, /**< block memory */
5305  SCIP_SET* set /**< global SCIP settings */
5306  )
5307 {
5308  assert(conssetchg != NULL);
5309  assert(blkmem != NULL);
5310 
5311  if( *conssetchg != NULL )
5312  {
5313  /* release constraints */
5314  SCIP_CALL( conssetchgRelease(*conssetchg, blkmem, set) );
5315 
5316  /* free memory */
5317  BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->addedconss, (*conssetchg)->addedconsssize);
5318  BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->disabledconss, (*conssetchg)->disabledconsssize);
5319  BMSfreeBlockMemory(blkmem, conssetchg);
5320  }
5321 
5322  return SCIP_OKAY;
5323 }
5324 
5325 /** ensures, that addedconss array can store at least num entries */
5326 static
5327