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