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-2019 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit 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 /** internal method for creating a constraint handler */
1987 static
1989  SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */
1990  SCIP_SET* set, /**< global SCIP settings */
1991  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1992  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
1993  const char* name, /**< name of constraint handler */
1994  const char* desc, /**< description of constraint handler */
1995  int sepapriority, /**< priority of the constraint handler for separation */
1996  int enfopriority, /**< priority of the constraint handler for constraint enforcing */
1997  int checkpriority, /**< priority of the constraint handler for checking feasibility (and propagation) */
1998  int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */
1999  int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */
2000  int eagerfreq, /**< frequency for using all instead of only the useful constraints in separation,
2001  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
2002  int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
2003  SCIP_Bool delaysepa, /**< should separation method be delayed, if other separators found cuts? */
2004  SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */
2005  SCIP_Bool needscons, /**< should the constraint handler be skipped, if no constraints are available? */
2006  SCIP_PROPTIMING proptiming, /**< positions in the node solving loop where propagation method of constraint handlers should be executed */
2007  SCIP_PRESOLTIMING presoltiming, /**< timing mask of the constraint handler's presolving method */
2008  SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
2009  SCIP_DECL_CONSFREE ((*consfree)), /**< destructor of constraint handler */
2010  SCIP_DECL_CONSINIT ((*consinit)), /**< initialize constraint handler */
2011  SCIP_DECL_CONSEXIT ((*consexit)), /**< deinitialize constraint handler */
2012  SCIP_DECL_CONSINITPRE ((*consinitpre)), /**< presolving initialization method of constraint handler */
2013  SCIP_DECL_CONSEXITPRE ((*consexitpre)), /**< presolving deinitialization method of constraint handler */
2014  SCIP_DECL_CONSINITSOL ((*consinitsol)), /**< solving process initialization method of constraint handler */
2015  SCIP_DECL_CONSEXITSOL ((*consexitsol)), /**< solving process deinitialization method of constraint handler */
2016  SCIP_DECL_CONSDELETE ((*consdelete)), /**< free specific constraint data */
2017  SCIP_DECL_CONSTRANS ((*constrans)), /**< transform constraint data into data belonging to the transformed problem */
2018  SCIP_DECL_CONSINITLP ((*consinitlp)), /**< initialize LP with relaxations of "initial" constraints */
2019  SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */
2020  SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */
2021  SCIP_DECL_CONSENFOLP ((*consenfolp)), /**< enforcing constraints for LP solutions */
2022  SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */
2023  SCIP_DECL_CONSENFOPS ((*consenfops)), /**< enforcing constraints for pseudo solutions */
2024  SCIP_DECL_CONSCHECK ((*conscheck)), /**< check feasibility of primal solution */
2025  SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */
2026  SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method */
2027  SCIP_DECL_CONSRESPROP ((*consresprop)), /**< propagation conflict resolving method */
2028  SCIP_DECL_CONSLOCK ((*conslock)), /**< variable rounding lock method */
2029  SCIP_DECL_CONSACTIVE ((*consactive)), /**< activation notification method */
2030  SCIP_DECL_CONSDEACTIVE((*consdeactive)), /**< deactivation notification method */
2031  SCIP_DECL_CONSENABLE ((*consenable)), /**< enabling notification method */
2032  SCIP_DECL_CONSDISABLE ((*consdisable)), /**< disabling notification method */
2033  SCIP_DECL_CONSDELVARS ((*consdelvars)), /**< variable deletion method */
2034  SCIP_DECL_CONSPRINT ((*consprint)), /**< constraint display method */
2035  SCIP_DECL_CONSCOPY ((*conscopy)), /**< constraint copying method */
2036  SCIP_DECL_CONSPARSE ((*consparse)), /**< constraint parsing method */
2037  SCIP_DECL_CONSGETVARS ((*consgetvars)), /**< constraint get variables method */
2038  SCIP_DECL_CONSGETNVARS((*consgetnvars)), /**< constraint get number of variable method */
2039  SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */
2040  SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */
2041  )
2042 {
2043  char paramname[SCIP_MAXSTRLEN];
2044  char paramdesc[SCIP_MAXSTRLEN];
2045 
2046  assert(conshdlr != NULL);
2047  assert(name != NULL);
2048  assert(desc != NULL);
2049  assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
2050  assert(consprop != NULL || propfreq == -1);
2051  assert(eagerfreq >= -1);
2052  assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL)));
2053 
2054  /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
2055  * error message
2056  */
2057  if( presoltiming < SCIP_PRESOLTIMING_NONE || presoltiming > SCIP_PRESOLTIMING_MAX )
2058  {
2059  SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
2060  "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", name);
2061 
2062  return SCIP_PARAMETERWRONGVAL;
2063  }
2064 
2065  /* both callbacks have to exist or not exist */
2066  assert((consgetvars != NULL) == (consgetnvars != NULL));
2067 
2068  SCIP_ALLOC( BMSallocMemory(conshdlr) );
2069  BMSclearMemory(*conshdlr);
2070 
2071  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->name, name, strlen(name)+1) );
2072  SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->desc, desc, strlen(desc)+1) );
2073  (*conshdlr)->sepapriority = sepapriority;
2074  (*conshdlr)->enfopriority = enfopriority;
2075  (*conshdlr)->checkpriority = checkpriority;
2076  (*conshdlr)->sepafreq = sepafreq;
2077  (*conshdlr)->propfreq = propfreq;
2078  (*conshdlr)->eagerfreq = eagerfreq;
2079  (*conshdlr)->maxprerounds = maxprerounds;
2080  (*conshdlr)->conshdlrcopy = conshdlrcopy;
2081  (*conshdlr)->consfree = consfree;
2082  (*conshdlr)->consinit = consinit;
2083  (*conshdlr)->consexit = consexit;
2084  (*conshdlr)->consinitpre = consinitpre;
2085  (*conshdlr)->consexitpre = consexitpre;
2086  (*conshdlr)->consinitsol = consinitsol;
2087  (*conshdlr)->consexitsol = consexitsol;
2088  (*conshdlr)->consdelete = consdelete;
2089  (*conshdlr)->constrans = constrans;
2090  (*conshdlr)->consinitlp = consinitlp;
2091  (*conshdlr)->conssepalp = conssepalp;
2092  (*conshdlr)->conssepasol = conssepasol;
2093  (*conshdlr)->consenfolp = consenfolp;
2094  (*conshdlr)->consenforelax = consenforelax;
2095  (*conshdlr)->consenfops = consenfops;
2096  (*conshdlr)->conscheck = conscheck;
2097  (*conshdlr)->consprop = consprop;
2098  (*conshdlr)->conspresol = conspresol;
2099  (*conshdlr)->consresprop = consresprop;
2100  (*conshdlr)->conslock = conslock;
2101  (*conshdlr)->consactive = consactive;
2102  (*conshdlr)->consdeactive = consdeactive;
2103  (*conshdlr)->consenable = consenable;
2104  (*conshdlr)->consdisable = consdisable;
2105  (*conshdlr)->consprint = consprint;
2106  (*conshdlr)->consdelvars = consdelvars;
2107  (*conshdlr)->conscopy = conscopy;
2108  (*conshdlr)->consparse = consparse;
2109  (*conshdlr)->consgetvars = consgetvars;
2110  (*conshdlr)->consgetnvars = consgetnvars;
2111  (*conshdlr)->conshdlrdata = conshdlrdata;
2112  (*conshdlr)->consgetdivebdchgs = consgetdivebdchgs;
2113  (*conshdlr)->conss = NULL;
2114  (*conshdlr)->consssize = 0;
2115  (*conshdlr)->nconss = 0;
2116  (*conshdlr)->nactiveconss = 0;
2117  (*conshdlr)->maxnactiveconss = 0;
2118  (*conshdlr)->startnactiveconss = 0;
2119  (*conshdlr)->initconss = NULL;
2120  (*conshdlr)->initconsssize = 0;
2121  (*conshdlr)->ninitconss = 0;
2122  (*conshdlr)->ninitconsskept = 0;
2123  (*conshdlr)->sepaconss = NULL;
2124  (*conshdlr)->sepaconsssize = 0;
2125  (*conshdlr)->nsepaconss = 0;
2126  (*conshdlr)->nusefulsepaconss = 0;
2127  (*conshdlr)->enfoconss = NULL;
2128  (*conshdlr)->enfoconsssize = 0;
2129  (*conshdlr)->nenfoconss = 0;
2130  (*conshdlr)->nusefulenfoconss = 0;
2131  (*conshdlr)->checkconss = NULL;
2132  (*conshdlr)->checkconsssize = 0;
2133  (*conshdlr)->ncheckconss = 0;
2134  (*conshdlr)->nusefulcheckconss = 0;
2135  (*conshdlr)->propconss = NULL;
2136  (*conshdlr)->propconsssize = 0;
2137  (*conshdlr)->npropconss = 0;
2138  (*conshdlr)->nusefulpropconss = 0;
2139  (*conshdlr)->nmarkedpropconss = 0;
2140  (*conshdlr)->updateconss = NULL;
2141  (*conshdlr)->updateconsssize = 0;
2142  (*conshdlr)->nupdateconss = 0;
2143  (*conshdlr)->nenabledconss = 0;
2144  (*conshdlr)->lastnusefulpropconss = 0;
2145  (*conshdlr)->lastnusefulsepaconss = 0;
2146  (*conshdlr)->lastnusefulenfoconss = 0;
2147 
2148  (*conshdlr)->storedpropconss = NULL;
2149  (*conshdlr)->storedpropconsssize = 0;
2150  (*conshdlr)->storednmarkedpropconss = 0;
2151  (*conshdlr)->storedpropdomchgcount = 0;
2152 
2153  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
2154  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->presoltime, SCIP_CLOCKTYPE_DEFAULT) );
2155  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sepatime, SCIP_CLOCKTYPE_DEFAULT) );
2156  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfolptime, SCIP_CLOCKTYPE_DEFAULT) );
2157  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfopstime, SCIP_CLOCKTYPE_DEFAULT) );
2158  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enforelaxtime, SCIP_CLOCKTYPE_DEFAULT) );
2159  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->proptime, SCIP_CLOCKTYPE_DEFAULT) );
2160  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sbproptime, SCIP_CLOCKTYPE_DEFAULT) );
2161  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->checktime, SCIP_CLOCKTYPE_DEFAULT) );
2162  SCIP_CALL( SCIPclockCreate(&(*conshdlr)->resproptime, SCIP_CLOCKTYPE_DEFAULT) );
2163 
2164  (*conshdlr)->nsepacalls = 0;
2165  (*conshdlr)->nenfolpcalls = 0;
2166  (*conshdlr)->nenfopscalls = 0;
2167  (*conshdlr)->nenforelaxcalls = 0;
2168  (*conshdlr)->npropcalls = 0;
2169  (*conshdlr)->ncheckcalls = 0;
2170  (*conshdlr)->nrespropcalls = 0;
2171  (*conshdlr)->ncutoffs = 0;
2172  (*conshdlr)->ncutsfound = 0;
2173  (*conshdlr)->ncutsapplied = 0;
2174  (*conshdlr)->nconssfound = 0;
2175  (*conshdlr)->ndomredsfound = 0;
2176  (*conshdlr)->nchildren = 0;
2177  (*conshdlr)->lastpropdomchgcount = -1;
2178  (*conshdlr)->lastsepalpcount = -1;
2179  (*conshdlr)->lastenfolplpcount = -1;
2180  (*conshdlr)->lastenfolpdomchgcount = -1;
2181  (*conshdlr)->lastenfopsdomchgcount = -1;
2182  (*conshdlr)->lastenforelaxdomchgcount = -1;
2183  (*conshdlr)->lastenforelaxrelaxcount = -1;
2184  (*conshdlr)->lastenfolpnode = -1;
2185  (*conshdlr)->lastenfopsnode = -1;
2186  (*conshdlr)->lastenfolpresult = SCIP_DIDNOTRUN;
2187  (*conshdlr)->lastenfopsresult = SCIP_DIDNOTRUN;
2188  (*conshdlr)->lastenforelaxresult = SCIP_DIDNOTRUN;
2189  (*conshdlr)->lastnfixedvars = 0;
2190  (*conshdlr)->lastnaggrvars = 0;
2191  (*conshdlr)->lastnchgvartypes = 0;
2192  (*conshdlr)->lastnchgbds = 0;
2193  (*conshdlr)->lastnaddholes = 0;
2194  (*conshdlr)->lastndelconss = 0;
2195  (*conshdlr)->lastnaddconss = 0;
2196  (*conshdlr)->lastnupgdconss = 0;
2197  (*conshdlr)->lastnchgcoefs = 0;
2198  (*conshdlr)->lastnchgsides = 0;
2199  (*conshdlr)->nfixedvars = 0;
2200  (*conshdlr)->naggrvars = 0;
2201  (*conshdlr)->nchgvartypes = 0;
2202  (*conshdlr)->nchgbds = 0;
2203  (*conshdlr)->naddholes = 0;
2204  (*conshdlr)->ndelconss = 0;
2205  (*conshdlr)->naddconss = 0;
2206  (*conshdlr)->nupgdconss = 0;
2207  (*conshdlr)->nchgcoefs = 0;
2208  (*conshdlr)->nchgsides = 0;
2209  (*conshdlr)->npresolcalls = 0;
2210  (*conshdlr)->delayupdatecount = 0;
2211  (*conshdlr)->ageresetavg = AGERESETAVG_INIT;
2212  (*conshdlr)->needscons = needscons;
2213  (*conshdlr)->sepalpwasdelayed = FALSE;
2214  (*conshdlr)->sepasolwasdelayed = FALSE;
2215  (*conshdlr)->propwasdelayed = FALSE;
2216  (*conshdlr)->duringsepa = FALSE;
2217  (*conshdlr)->duringprop = FALSE;
2218  (*conshdlr)->initialized = FALSE;
2219 
2220  /* add parameters */
2221  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/sepafreq", name);
2222  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2223  "frequency for separating cuts (-1: never, 0: only in root node)",
2224  &(*conshdlr)->sepafreq, FALSE, sepafreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2225 
2226  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/propfreq", name);
2227  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2228  "frequency for propagating domains (-1: never, 0: only in root node)",
2229  &(*conshdlr)->propfreq, FALSE, propfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2230 
2231  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/proptiming", name);
2232  (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);
2233  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
2234  (int*)(&(*conshdlr)->proptiming), TRUE, proptiming, (int) SCIP_PROPTIMING_BEFORELP, (int) SCIP_PROPTIMING_ALWAYS, NULL, NULL) ); /*lint !e713*/
2235 
2236  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/eagerfreq", name);
2237  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2238  "frequency for using all instead of only the useful constraints in separation, propagation and enforcement (-1: never, 0: only in first evaluation)",
2239  &(*conshdlr)->eagerfreq, TRUE, eagerfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2240 
2241  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/maxprerounds", name);
2242  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2243  "maximal number of presolving rounds the constraint handler participates in (-1: no limit)",
2244  &(*conshdlr)->maxprerounds, TRUE, maxprerounds, -1, INT_MAX, NULL, NULL) );
2245 
2246  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delaysepa", name);
2247  SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
2248  "should separation method be delayed, if other separators found cuts?",
2249  &(*conshdlr)->delaysepa, TRUE, delaysepa, NULL, NULL) ); /*lint !e740*/
2250 
2251  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delayprop", name);
2252  SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
2253  "should propagation method be delayed, if other propagators found reductions?",
2254  &(*conshdlr)->delayprop, TRUE, delayprop, NULL, NULL) ); /*lint !e740*/
2255 
2256  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/presoltiming", name);
2257  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing mask of the constraint handler's presolving method (%u:FAST, %u:MEDIUM, %u:EXHAUSTIVE, %u:FINAL)",
2259  SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
2260  (int*)&(*conshdlr)->presoltiming, TRUE, presoltiming, (int) SCIP_PRESOLTIMING_FAST, (int) SCIP_PRESOLTIMING_MAX, NULL, NULL) ); /*lint !e740 !e713*/
2261 
2262  return SCIP_OKAY;
2263 }
2264 
2265 /** creates a constraint handler */
2267  SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */
2268  SCIP_SET* set, /**< global SCIP settings */
2269  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2270  BMS_BLKMEM* blkmem, /**< block memory for parameter settings */
2271  const char* name, /**< name of constraint handler */
2272  const char* desc, /**< description of constraint handler */
2273  int sepapriority, /**< priority of the constraint handler for separation */
2274  int enfopriority, /**< priority of the constraint handler for constraint enforcing */
2275  int checkpriority, /**< priority of the constraint handler for checking feasibility (and propagation) */
2276  int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */
2277  int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */
2278  int eagerfreq, /**< frequency for using all instead of only the useful constraints in separation,
2279  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
2280  int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
2281  SCIP_Bool delaysepa, /**< should separation method be delayed, if other separators found cuts? */
2282  SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */
2283  SCIP_Bool needscons, /**< should the constraint handler be skipped, if no constraints are available? */
2284  SCIP_PROPTIMING proptiming, /**< positions in the node solving loop where propagation method of constraint handlers should be executed */
2285  SCIP_PRESOLTIMING presoltiming, /**< timing mask of the constraint handler's presolving method */
2286  SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
2287  SCIP_DECL_CONSFREE ((*consfree)), /**< destructor of constraint handler */
2288  SCIP_DECL_CONSINIT ((*consinit)), /**< initialize constraint handler */
2289  SCIP_DECL_CONSEXIT ((*consexit)), /**< deinitialize constraint handler */
2290  SCIP_DECL_CONSINITPRE ((*consinitpre)), /**< presolving initialization method of constraint handler */
2291  SCIP_DECL_CONSEXITPRE ((*consexitpre)), /**< presolving deinitialization method of constraint handler */
2292  SCIP_DECL_CONSINITSOL ((*consinitsol)), /**< solving process initialization method of constraint handler */
2293  SCIP_DECL_CONSEXITSOL ((*consexitsol)), /**< solving process deinitialization method of constraint handler */
2294  SCIP_DECL_CONSDELETE ((*consdelete)), /**< free specific constraint data */
2295  SCIP_DECL_CONSTRANS ((*constrans)), /**< transform constraint data into data belonging to the transformed problem */
2296  SCIP_DECL_CONSINITLP ((*consinitlp)), /**< initialize LP with relaxations of "initial" constraints */
2297  SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */
2298  SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */
2299  SCIP_DECL_CONSENFOLP ((*consenfolp)), /**< enforcing constraints for LP solutions */
2300  SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */
2301  SCIP_DECL_CONSENFOPS ((*consenfops)), /**< enforcing constraints for pseudo solutions */
2302  SCIP_DECL_CONSCHECK ((*conscheck)), /**< check feasibility of primal solution */
2303  SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */
2304  SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method */
2305  SCIP_DECL_CONSRESPROP ((*consresprop)), /**< propagation conflict resolving method */
2306  SCIP_DECL_CONSLOCK ((*conslock)), /**< variable rounding lock method */
2307  SCIP_DECL_CONSACTIVE ((*consactive)), /**< activation notification method */
2308  SCIP_DECL_CONSDEACTIVE((*consdeactive)), /**< deactivation notification method */
2309  SCIP_DECL_CONSENABLE ((*consenable)), /**< enabling notification method */
2310  SCIP_DECL_CONSDISABLE ((*consdisable)), /**< disabling notification method */
2311  SCIP_DECL_CONSDELVARS ((*consdelvars)), /**< variable deletion method */
2312  SCIP_DECL_CONSPRINT ((*consprint)), /**< constraint display method */
2313  SCIP_DECL_CONSCOPY ((*conscopy)), /**< constraint copying method */
2314  SCIP_DECL_CONSPARSE ((*consparse)), /**< constraint parsing method */
2315  SCIP_DECL_CONSGETVARS ((*consgetvars)), /**< constraint get variables method */
2316  SCIP_DECL_CONSGETNVARS((*consgetnvars)), /**< constraint get number of variable method */
2317  SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */
2318  SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */
2319  )
2320 {
2321  assert(conshdlr != NULL);
2322  assert(name != NULL);
2323  assert(desc != NULL);
2324  assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
2325  assert(consprop != NULL || propfreq == -1);
2326  assert(eagerfreq >= -1);
2327  assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL)));
2328 
2329  SCIP_CALL_FINALLY( doConshdlrCreate(conshdlr, set, messagehdlr, blkmem, name, desc, sepapriority, enfopriority,
2330  checkpriority, sepafreq, propfreq, eagerfreq, maxprerounds, delaysepa, delayprop, needscons, proptiming,
2331  presoltiming, conshdlrcopy, consfree, consinit, consexit, consinitpre, consexitpre, consinitsol, consexitsol,
2332  consdelete, constrans, consinitlp, conssepalp, conssepasol, consenfolp, consenforelax, consenfops, conscheck,
2333  consprop, conspresol, consresprop, conslock, consactive, consdeactive, consenable, consdisable, consdelvars,
2334  consprint, conscopy, consparse, consgetvars, consgetnvars, consgetdivebdchgs, conshdlrdata),
2335  (void) SCIPconshdlrFree(conshdlr, set) );
2336 
2337  return SCIP_OKAY;
2338 } /*lint !e715*/
2339 
2340 /** calls destructor and frees memory of constraint handler */
2342  SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */
2343  SCIP_SET* set /**< global SCIP settings */
2344  )
2345 {
2346  assert(conshdlr != NULL);
2347  if( *conshdlr == NULL )
2348  return SCIP_OKAY;
2349  assert(!(*conshdlr)->initialized);
2350  assert((*conshdlr)->nconss == 0);
2351  assert(set != NULL);
2352 
2353  /* call destructor of constraint handler */
2354  if( (*conshdlr)->consfree != NULL )
2355  {
2356  SCIP_CALL( (*conshdlr)->consfree(set->scip, *conshdlr) );
2357  }
2358 
2359  SCIPclockFree(&(*conshdlr)->resproptime);
2360  SCIPclockFree(&(*conshdlr)->checktime);
2361  SCIPclockFree(&(*conshdlr)->sbproptime);
2362  SCIPclockFree(&(*conshdlr)->proptime);
2363  SCIPclockFree(&(*conshdlr)->enforelaxtime);
2364  SCIPclockFree(&(*conshdlr)->enfopstime);
2365  SCIPclockFree(&(*conshdlr)->enfolptime);
2366  SCIPclockFree(&(*conshdlr)->sepatime);
2367  SCIPclockFree(&(*conshdlr)->presoltime);
2368  SCIPclockFree(&(*conshdlr)->setuptime);
2369 
2370  BMSfreeMemoryArrayNull(&(*conshdlr)->name);
2371  BMSfreeMemoryArrayNull(&(*conshdlr)->desc);
2372  BMSfreeMemoryArrayNull(&(*conshdlr)->conss);
2373  BMSfreeMemoryArrayNull(&(*conshdlr)->initconss);
2374  BMSfreeMemoryArrayNull(&(*conshdlr)->sepaconss);
2375  BMSfreeMemoryArrayNull(&(*conshdlr)->enfoconss);
2376  BMSfreeMemoryArrayNull(&(*conshdlr)->checkconss);
2377  BMSfreeMemoryArrayNull(&(*conshdlr)->propconss);
2378  BMSfreeMemoryArrayNull(&(*conshdlr)->updateconss);
2379  BMSfreeMemoryArrayNull(&(*conshdlr)->storedpropconss);
2380  BMSfreeMemory(conshdlr);
2381 
2382  return SCIP_OKAY;
2383 }
2384 
2385 /** calls initialization method of constraint handler */
2387  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2388  BMS_BLKMEM* blkmem, /**< block memory */
2389  SCIP_SET* set, /**< global SCIP settings */
2390  SCIP_STAT* stat /**< dynamic problem statistics */
2391  )
2392 {
2393  assert(conshdlr != NULL);
2394  assert(set != NULL);
2395 
2396  if( conshdlr->initialized )
2397  {
2398  SCIPerrorMessage("constraint handler <%s> already initialized\n", conshdlr->name);
2399  return SCIP_INVALIDCALL;
2400  }
2401 
2402  if( set->misc_resetstat )
2403  {
2404  SCIPclockReset(conshdlr->setuptime);
2405  SCIPclockReset(conshdlr->presoltime);
2406  SCIPclockReset(conshdlr->sepatime);
2407  SCIPclockReset(conshdlr->enfolptime);
2408  SCIPclockReset(conshdlr->enfopstime);
2409  SCIPclockReset(conshdlr->enforelaxtime);
2410  SCIPclockReset(conshdlr->proptime);
2411  SCIPclockReset(conshdlr->sbproptime);
2412  SCIPclockReset(conshdlr->checktime);
2413  SCIPclockReset(conshdlr->resproptime);
2414 
2415  conshdlr->nsepacalls = 0;
2416  conshdlr->nenfolpcalls = 0;
2417  conshdlr->nenfopscalls = 0;
2418  conshdlr->nenforelaxcalls = 0;
2419  conshdlr->npropcalls = 0;
2420  conshdlr->ncheckcalls = 0;
2421  conshdlr->nrespropcalls = 0;
2422  conshdlr->ncutoffs = 0;
2423  conshdlr->ncutsfound = 0;
2424  conshdlr->ncutsapplied = 0;
2425  conshdlr->nconssfound = 0;
2426  conshdlr->ndomredsfound = 0;
2427  conshdlr->nchildren = 0;
2428  conshdlr->lastpropdomchgcount = -1;
2429  conshdlr->lastenfolpdomchgcount = -1;
2430  conshdlr->lastenfopsdomchgcount = -1;
2431  conshdlr->lastenforelaxdomchgcount = -1;
2432  conshdlr->lastenforelaxrelaxcount = -1;
2433  conshdlr->lastenfolpnode = -1;
2434  conshdlr->lastenfopsnode = -1;
2435  conshdlr->lastenfolpresult = SCIP_DIDNOTRUN;
2436  conshdlr->lastenfopsresult = SCIP_DIDNOTRUN;
2437  conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2438  conshdlr->startnactiveconss = 0;
2439  conshdlr->lastsepalpcount = -1;
2440  conshdlr->lastenfolplpcount = -1;
2441  conshdlr->lastnusefulpropconss = 0;
2442  conshdlr->lastnusefulsepaconss = 0;
2443  conshdlr->lastnusefulenfoconss = 0;
2444  conshdlr->lastnfixedvars = 0;
2445  conshdlr->lastnaggrvars = 0;
2446  conshdlr->lastnchgvartypes = 0;
2447  conshdlr->lastnchgbds = 0;
2448  conshdlr->lastnaddholes = 0;
2449  conshdlr->lastndelconss = 0;
2450  conshdlr->lastnaddconss = 0;
2451  conshdlr->lastnupgdconss = 0;
2452  conshdlr->lastnchgcoefs = 0;
2453  conshdlr->lastnchgsides = 0;
2454  conshdlr->nfixedvars = 0;
2455  conshdlr->naggrvars = 0;
2456  conshdlr->nchgvartypes = 0;
2457  conshdlr->nchgbds = 0;
2458  conshdlr->naddholes = 0;
2459  conshdlr->ndelconss = 0;
2460  conshdlr->naddconss = 0;
2461  conshdlr->nupgdconss = 0;
2462  conshdlr->nchgcoefs = 0;
2463  conshdlr->nchgsides = 0;
2464  conshdlr->npresolcalls = 0;
2465  conshdlr->ageresetavg = AGERESETAVG_INIT;
2466  conshdlr->sepalpwasdelayed = FALSE;
2467  conshdlr->sepasolwasdelayed = FALSE;
2468  conshdlr->propwasdelayed = FALSE;
2469  }
2470 
2471  /* call initialization method of constraint handler */
2472  if( conshdlr->consinit != NULL )
2473  {
2474  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2475  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2476  * external method; to avoid this, these changes will be buffered and processed after the method call
2477  */
2478  conshdlrDelayUpdates(conshdlr);
2479 
2480  /* start timing */
2481  SCIPclockStart(conshdlr->setuptime, set);
2482 
2483  /* call external method */
2484  SCIP_CALL( conshdlr->consinit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2485 
2486  /* stop timing */
2487  SCIPclockStop(conshdlr->setuptime, set);
2488 
2489  /* perform the cached constraint updates */
2490  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2491  }
2492  conshdlr->initialized = TRUE;
2493  assert(!conshdlrAreUpdatesDelayed(conshdlr));
2494 
2495  return SCIP_OKAY;
2496 }
2497 
2498 /** calls exit method of constraint handler */
2500  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2501  BMS_BLKMEM* blkmem, /**< block memory */
2502  SCIP_SET* set, /**< global SCIP settings */
2503  SCIP_STAT* stat /**< dynamic problem statistics */
2504  )
2505 {
2506  assert(conshdlr != NULL);
2507  assert(set != NULL);
2508 
2509  if( !conshdlr->initialized )
2510  {
2511  SCIPerrorMessage("constraint handler <%s> not initialized\n", conshdlr->name);
2512  return SCIP_INVALIDCALL;
2513  }
2514 
2515  /* call deinitialization method of constraint handler */
2516  if( conshdlr->consexit != NULL )
2517  {
2518  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2519  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2520  * external method; to avoid this, these changes will be buffered and processed after the method call
2521  */
2522  conshdlrDelayUpdates(conshdlr);
2523 
2524  /* start timing */
2525  SCIPclockStart(conshdlr->setuptime, set);
2526 
2527  /* call external method */
2528  SCIP_CALL( conshdlr->consexit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2529 
2530  /* stop timing */
2531  SCIPclockStop(conshdlr->setuptime, set);
2532 
2533  /* perform the cached constraint updates */
2534  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2535  }
2536  conshdlr->initialized = FALSE;
2537 
2538  return SCIP_OKAY;
2539 }
2540 
2541 /** informs constraint handler that the presolving process is being started */
2543  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2544  BMS_BLKMEM* blkmem, /**< block memory */
2545  SCIP_SET* set, /**< global SCIP settings */
2546  SCIP_STAT* stat /**< dynamic problem statistics */
2547  )
2548 {
2549  assert(conshdlr != NULL);
2550  assert(set != NULL);
2551 
2552  /* reset conshdlr last presolved data in case of a restart */
2553  conshdlr->lastpropdomchgcount = -1;
2554  conshdlr->lastenfolpdomchgcount = -1;
2555  conshdlr->lastenfopsdomchgcount = -1;
2556  conshdlr->lastenforelaxdomchgcount = -1;
2557  conshdlr->lastenforelaxrelaxcount = -1;
2558  conshdlr->lastenfolpnode = -1;
2559  conshdlr->lastenfopsnode = -1;
2560  conshdlr->lastenfolpresult = SCIP_DIDNOTRUN;
2561  conshdlr->lastenfopsresult = SCIP_DIDNOTRUN;
2562  conshdlr->lastenforelaxresult = SCIP_DIDNOTRUN;
2563  conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2564  conshdlr->startnactiveconss = 0;
2565  conshdlr->lastsepalpcount = -1;
2566  conshdlr->lastenfolplpcount = -1;
2567  conshdlr->lastnusefulpropconss = 0;
2568  conshdlr->lastnusefulsepaconss = 0;
2569  conshdlr->lastnusefulenfoconss = 0;
2570  conshdlr->lastnfixedvars = 0;
2571  conshdlr->lastnaggrvars = 0;
2572  conshdlr->lastnchgvartypes = 0;
2573  conshdlr->lastnchgbds = 0;
2574  conshdlr->lastnaddholes = 0;
2575  conshdlr->lastndelconss = 0;
2576  conshdlr->lastnaddconss = 0;
2577  conshdlr->lastnupgdconss = 0;
2578  conshdlr->lastnchgcoefs = 0;
2579  conshdlr->lastnchgsides = 0;
2580  conshdlr->propwasdelayed = FALSE;
2581 
2582  /* call presolving initialization method of constraint handler */
2583  if( conshdlr->consinitpre != NULL )
2584  {
2585  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2586  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2587  * external method; to avoid this, these changes will be buffered and processed after the method call
2588  */
2589  conshdlrDelayUpdates(conshdlr);
2590 
2591  /* start timing */
2592  SCIPclockStart(conshdlr->setuptime, set);
2593 
2594  /* call external method */
2595  SCIP_CALL( conshdlr->consinitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2596 
2597  /* stop timing */
2598  SCIPclockStop(conshdlr->setuptime, set);
2599 
2600  /* perform the cached constraint updates */
2601  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2602  }
2603 
2604  /* after a restart the LP is empty but the initial constraints are not included in the initialconss array anymore;
2605  * we have to put them back into this array in order to obtain the correct initial root relaxation
2606  */
2607  if( stat->nruns >= 2 )
2608  {
2609  int c;
2610 
2611  for( c = 0; c < conshdlr->nconss; ++c )
2612  {
2613  /**@todo should only active constraints be added to the initconss array? at least cons->active is asserted in
2614  * conshdlrAddInitcons(conshdlr, set, conshdlr->conss[c])
2615  */
2616  if( conshdlr->conss[c]->addarraypos >= 0 && !conshdlr->conss[c]->deleted &&
2617  conshdlr->conss[c]->initial && conshdlr->conss[c]->initconsspos == -1 )
2618  {
2619  SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->conss[c]) );
2620  }
2621  }
2622  }
2623 
2624 #if 0
2625  /* check if all initial constraints are included in the initconss array */
2626  {
2627  int c;
2628 
2629  for( c = 0; c < conshdlr->nconss; ++c )
2630  {
2631  assert(conshdlr->conss[c]->deleted || conshdlr->conss[c]->initial == (conshdlr->conss[c]->initconsspos >= 0));
2632  assert(conshdlr->conss[c]->deleted || !conshdlr->conss[c]->initial
2633  || conshdlr->initconss[conshdlr->conss[c]->initconsspos] == conshdlr->conss[c]);
2634  }
2635  }
2636 #endif
2637 
2638  return SCIP_OKAY;
2639 }
2640 
2641 /** informs constraint handler that the presolving is finished */
2643  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2644  BMS_BLKMEM* blkmem, /**< block memory */
2645  SCIP_SET* set, /**< global SCIP settings */
2646  SCIP_STAT* stat /**< dynamic problem statistics */
2647  )
2648 {
2649  assert(conshdlr != NULL);
2650  assert(set != NULL);
2651 
2652  /* call presolving deinitialization method of constraint handler */
2653  if( conshdlr->consexitpre != NULL )
2654  {
2655  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2656  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2657  * external method; to avoid this, these changes will be buffered and processed after the method call
2658  */
2659  conshdlrDelayUpdates(conshdlr);
2660 
2661  /* start timing */
2662  SCIPclockStart(conshdlr->setuptime, set);
2663 
2664  /* call external method */
2665  SCIP_CALL( conshdlr->consexitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2666 
2667  /* stop timing */
2668  SCIPclockStop(conshdlr->setuptime, set);
2669 
2670  /* perform the cached constraint updates */
2671  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2672  }
2673 
2674  /* update statistics */
2675  conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2676  conshdlr->startnactiveconss = conshdlr->nactiveconss;
2677 
2678  return SCIP_OKAY;
2679 }
2680 
2681 /** informs constraint handler that the branch and bound process is being started */
2683  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2684  BMS_BLKMEM* blkmem, /**< block memory */
2685  SCIP_SET* set, /**< global SCIP settings */
2686  SCIP_STAT* stat /**< dynamic problem statistics */
2687  )
2688 {
2689  assert(conshdlr != NULL);
2690  assert(set != NULL);
2691  assert(stat != NULL);
2692 
2693  conshdlr->sepalpwasdelayed = FALSE;
2694  conshdlr->sepasolwasdelayed = FALSE;
2695 
2696  /* call solving process initialization method of constraint handler */
2697  if( conshdlr->consinitsol != NULL )
2698  {
2699  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2700  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2701  * external method; to avoid this, these changes will be buffered and processed after the method call
2702  */
2703  conshdlrDelayUpdates(conshdlr);
2704 
2705  /* start timing */
2706  SCIPclockStart(conshdlr->setuptime, set);
2707 
2708  /* call external method */
2709  SCIP_CALL( conshdlr->consinitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2710 
2711  /* stop timing */
2712  SCIPclockStop(conshdlr->setuptime, set);
2713 
2714  /* perform the cached constraint updates */
2715  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2716  }
2717 
2718  return SCIP_OKAY;
2719 }
2720 
2721 /** informs constraint handler that the branch and bound process data is being freed */
2723  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2724  BMS_BLKMEM* blkmem, /**< block memory */
2725  SCIP_SET* set, /**< global SCIP settings */
2726  SCIP_STAT* stat, /**< dynamic problem statistics */
2727  SCIP_Bool restart /**< was this exit solve call triggered by a restart? */
2728  )
2729 {
2730  assert(conshdlr != NULL);
2731  assert(set != NULL);
2732 
2733  /* call solving process deinitialization method of constraint handler */
2734  if( conshdlr->consexitsol != NULL )
2735  {
2736  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2737  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2738  * external method; to avoid this, these changes will be buffered and processed after the method call
2739  */
2740  conshdlrDelayUpdates(conshdlr);
2741 
2742  /* start timing */
2743  SCIPclockStart(conshdlr->setuptime, set);
2744 
2745  /* call external method */
2746  SCIP_CALL( conshdlr->consexitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss, restart) );
2747 
2748  /* stop timing */
2749  SCIPclockStop(conshdlr->setuptime, set);
2750 
2751  /* perform the cached constraint updates */
2752  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2753  }
2754 
2755  return SCIP_OKAY;
2756 }
2757 
2758 /** calls LP initialization method of constraint handler to separate all initial active constraints */
2760  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2761  BMS_BLKMEM* blkmem, /**< block memory */
2762  SCIP_SET* set, /**< global SCIP settings */
2763  SCIP_STAT* stat, /**< dynamic problem statistics */
2764  SCIP_TREE* tree, /**< branch and bound tree */
2765  SCIP_Bool initkeptconss, /**< Also initialize constraints which are valid at a more global node,
2766  * but were not activated there? Should be FALSE for repeated calls at
2767  * one node or if the current focusnode is a child of the former one */
2768  SCIP_Bool* cutoff /**< pointer to store whether infeasibility was detected while building the LP */
2769  )
2770 {
2771  assert(conshdlr != NULL);
2772  assert(cutoff != NULL);
2773 #ifdef MORE_DEBUG
2774  assert(stat->nnodes > 1 || conshdlr->ninitconsskept == 0 || SCIPtreeProbing(tree));
2775 #endif
2776 
2777  *cutoff = FALSE;
2778 
2779  if( conshdlr->consinitlp != NULL )
2780  {
2781  int currentdepth;
2782  int oldninitconss;
2783  int c;
2784 
2785  SCIPsetDebugMsg(set, "initializing LP with %d initial constraints of handler <%s> (ninitconss=%d, kept=%d, initkept=%u)\n",
2786  initkeptconss ? conshdlr->ninitconss : conshdlr->ninitconss - conshdlr->ninitconsskept, conshdlr->name,
2787  conshdlr->ninitconss, conshdlr->ninitconsskept, initkeptconss);
2788 
2789  /* no constraints to initialize (or only kept constraints which do not need to be initialized this time) -> return */
2790  if( conshdlr->needscons && (conshdlr->ninitconss == 0 || (!initkeptconss && conshdlr->ninitconss == conshdlr->ninitconsskept)) )
2791  return SCIP_OKAY;
2792 
2793  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2794  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2795  * external method; to avoid this, these changes will be buffered and processed after the method call
2796  */
2797  conshdlrDelayUpdates(conshdlr);
2798 
2799  oldninitconss = conshdlr->ninitconss;
2800 
2801  /* start timing */
2802  SCIPclockStart(conshdlr->sepatime, set);
2803 
2804  if( initkeptconss )
2805  {
2806  /* add all kept initial constraints which are currently active to the second part of the initconss array */
2807  /* @todo keep track of where a constraint was already initialized (e.g., in the conssetchg)? */
2808  for( c = 0; c < conshdlr->ninitconsskept; ++c )
2809  {
2810  assert(conshdlr->initconss[c]->initconsspos == c);
2811 
2812  if( SCIPconsIsActive(conshdlr->initconss[c]) )
2813  {
2814  SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->initconss[c]) );
2815  }
2816  }
2817  }
2818 
2819  /* call external method */
2820  SCIP_CALL( conshdlr->consinitlp(set->scip, conshdlr, &conshdlr->initconss[conshdlr->ninitconsskept],
2821  conshdlr->ninitconss - conshdlr->ninitconsskept, cutoff) );
2822 
2823  /* stop timing */
2824  SCIPclockStop(conshdlr->sepatime, set);
2825 
2826  /* perform the cached constraint updates */
2827  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2828 
2829  currentdepth = SCIPtreeGetCurrentDepth(tree);
2830  assert(currentdepth >= 0);
2831 
2832  /* clear the initconss array */
2833  for( c = conshdlr->ninitconsskept; c < oldninitconss; ++c )
2834  {
2835  assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) >= -1);
2836  assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) <= currentdepth);
2837 
2838  /* if the constraint was not initialized at its valid node, we keep it */
2839  if( currentdepth > 0 ? SCIPconsGetActiveDepth(conshdlr->initconss[c]) != currentdepth :
2840  SCIPconsGetActiveDepth(conshdlr->initconss[c]) > 0 )
2841  {
2842  conshdlr->initconss[conshdlr->ninitconsskept] = conshdlr->initconss[c];
2843  conshdlr->initconss[conshdlr->ninitconsskept]->initconsspos = conshdlr->ninitconsskept;
2844  ++(conshdlr->ninitconsskept);
2845  }
2846  else
2847  conshdlr->initconss[c]->initconsspos = -1;
2848  }
2849 #ifndef NDEBUG
2850  for( ; c < conshdlr->ninitconss; ++c )
2851  assert(conshdlr->initconss[c]->initconsspos < conshdlr->ninitconsskept);
2852 #endif
2853  conshdlr->ninitconss = conshdlr->ninitconsskept;
2854 
2855  if( conshdlr->ninitconss == 0 )
2856  {
2857  BMSfreeMemoryArrayNull(&conshdlr->initconss);
2858  conshdlr->initconsssize = 0;
2859  }
2860  }
2861 
2862  return SCIP_OKAY;
2863 }
2864 
2865 /** calls separator method of constraint handler to separate LP solution */
2867  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2868  BMS_BLKMEM* blkmem, /**< block memory */
2869  SCIP_SET* set, /**< global SCIP settings */
2870  SCIP_STAT* stat, /**< dynamic problem statistics */
2871  SCIP_SEPASTORE* sepastore, /**< separation storage */
2872  int depth, /**< depth of current node */
2873  SCIP_Bool execdelayed, /**< execute separation method even if it is marked to be delayed */
2874  SCIP_RESULT* result /**< pointer to store the result of the callback method */
2875  )
2876 {
2877  assert(conshdlr != NULL);
2878  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
2879  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
2880  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
2881  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
2882  assert(stat != NULL);
2883  assert(conshdlr->lastsepalpcount != stat->lpcount
2884  || (0 <= conshdlr->lastnusefulsepaconss && conshdlr->lastnusefulsepaconss <= conshdlr->nusefulsepaconss));
2885  assert(set != NULL);
2886  assert(result != NULL);
2887 
2888  *result = SCIP_DIDNOTRUN;
2889 
2890  if( conshdlr->conssepalp != NULL
2891  && ((depth == 0 && conshdlr->sepafreq == 0)
2892  || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0)
2893  || conshdlr->sepalpwasdelayed) )
2894  {
2895  /* check, if separation method should be delayed */
2896  if( !conshdlr->delaysepa || execdelayed )
2897  {
2898  int nconss;
2899  int nusefulconss;
2900  int firstcons;
2901 
2902  /* check, if this LP solution was already separated */
2903  if( conshdlr->lastsepalpcount == stat->lpcount )
2904  {
2905  /* all constraints that were not yet separated on the new LP solution must be useful constraints, which means,
2906  * that the new constraints are the last constraints of the useful ones
2907  */
2908  nconss = conshdlr->nusefulsepaconss - conshdlr->lastnusefulsepaconss;
2909  nusefulconss = nconss;
2910  firstcons = conshdlr->lastnusefulsepaconss;
2911  }
2912  else
2913  {
2914  /* on a new LP solution, we want to separate all constraints */
2915  nconss = conshdlr->nsepaconss;
2916  nusefulconss = conshdlr->nusefulsepaconss;
2917  firstcons = 0;
2918  }
2919  assert(firstcons >= 0);
2920  assert(firstcons + nconss <= conshdlr->nsepaconss);
2921  assert(nusefulconss <= nconss);
2922 
2923  /* constraint handlers without constraints should only be called once */
2924  if( nconss > 0 || (!conshdlr->needscons && conshdlr->lastsepalpcount != stat->lpcount) )
2925  {
2926  SCIP_CONS** conss;
2927  SCIP_Longint oldndomchgs;
2928  SCIP_Longint oldnprobdomchgs;
2929  SCIP_Longint lastsepalpcount;
2930  int oldncuts;
2931  int oldnactiveconss;
2932  int lastnusefulsepaconss;
2933 
2934  SCIPsetDebugMsg(set, "separating constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n",
2935  firstcons, firstcons + nconss - 1, conshdlr->nsepaconss, conshdlr->name,
2936  conshdlr->lastsepalpcount == stat->lpcount ? "old" : "new");
2937 
2938  /* remember the number of processed constraints on the current LP solution */
2939  lastsepalpcount = stat->lpcount;
2940  lastnusefulsepaconss = conshdlr->nusefulsepaconss;
2941 
2942  /* get the array of the constraints to be processed */
2943  conss = &(conshdlr->sepaconss[firstcons]);
2944 
2945  oldndomchgs = stat->nboundchgs + stat->nholechgs;
2946  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
2947  oldncuts = SCIPsepastoreGetNCuts(sepastore);
2948  oldnactiveconss = stat->nactiveconss;
2949 
2950  /* check, if we want to use eager evaluation */
2951  if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0)
2952  || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) )
2953  nusefulconss = nconss;
2954 
2955  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2956  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2957  * external method; to avoid this, these changes will be buffered and processed after the method call
2958  */
2959  conshdlrDelayUpdates(conshdlr);
2960  conshdlr->duringsepa = TRUE;
2961 
2962  /* start timing */
2963  SCIPclockStart(conshdlr->sepatime, set);
2964 
2965  /* call external method */
2966  SCIP_CALL( conshdlr->conssepalp(set->scip, conshdlr, conss, nconss, nusefulconss, result) );
2967  SCIPsetDebugMsg(set, " -> separating LP returned result <%d>\n", *result);
2968 
2969  /* stop timing */
2970  SCIPclockStop(conshdlr->sepatime, set);
2971 
2972  /* perform the cached constraint updates */
2973  conshdlr->duringsepa = FALSE;
2974  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2975 
2976  /* update statistics */
2977  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
2978  {
2979  conshdlr->lastsepalpcount = lastsepalpcount;
2980  conshdlr->lastnusefulsepaconss = MIN(lastnusefulsepaconss, conshdlr->nusefulsepaconss);
2981  conshdlr->nsepacalls++;
2982  }
2983  if( *result == SCIP_CUTOFF )
2984  conshdlr->ncutoffs++;
2985  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
2986  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
2987 
2988  /* update domain reductions; therefore remove the domain
2989  * reduction counts which were generated in probing mode */
2990  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
2991  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
2992 
2993  /* evaluate result */
2994  if( *result != SCIP_CUTOFF
2995  && *result != SCIP_CONSADDED
2996  && *result != SCIP_REDUCEDDOM
2997  && *result != SCIP_SEPARATED
2998  && *result != SCIP_NEWROUND
2999  && *result != SCIP_DIDNOTFIND
3000  && *result != SCIP_DIDNOTRUN
3001  && *result != SCIP_DELAYED )
3002  {
3003  SCIPerrorMessage("LP separation method of constraint handler <%s> returned invalid result <%d>\n",
3004  conshdlr->name, *result);
3005  return SCIP_INVALIDRESULT;
3006  }
3007  }
3008  }
3009  else
3010  {
3011  SCIPsetDebugMsg(set, "LP separation method of constraint handler <%s> was delayed\n", conshdlr->name);
3012  *result = SCIP_DELAYED;
3013  }
3014 
3015  /* remember whether separation method was delayed */
3016  conshdlr->sepalpwasdelayed = (*result == SCIP_DELAYED);
3017  }
3018 
3019  return SCIP_OKAY;
3020 }
3021 
3022 /** calls separator method of constraint handler to separate given primal solution */
3024  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3025  BMS_BLKMEM* blkmem, /**< block memory */
3026  SCIP_SET* set, /**< global SCIP settings */
3027  SCIP_STAT* stat, /**< dynamic problem statistics */
3028  SCIP_SEPASTORE* sepastore, /**< separation storage */
3029  SCIP_SOL* sol, /**< primal solution that should be separated */
3030  int depth, /**< depth of current node */
3031  SCIP_Bool execdelayed, /**< execute separation method even if it is marked to be delayed */
3032  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3033  )
3034 {
3035  assert(conshdlr != NULL);
3036  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3037  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3038  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3039  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3040  assert(set != NULL);
3041  assert(stat != NULL);
3042  assert(result != NULL);
3043 
3044  *result = SCIP_DIDNOTRUN;
3045 
3046  if( conshdlr->conssepasol != NULL
3047  && ((depth == 0 && conshdlr->sepafreq == 0)
3048  || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0)
3049  || conshdlr->sepasolwasdelayed) )
3050  {
3051  /* check, if separation method should be delayed */
3052  if( !conshdlr->delaysepa || execdelayed )
3053  {
3054  int nconss;
3055  int nusefulconss;
3056 
3057  /* always separate all constraints */
3058  nconss = conshdlr->nsepaconss;
3059  nusefulconss = conshdlr->nusefulsepaconss;
3060  assert(nusefulconss <= nconss);
3061 
3062  if( nconss > 0 || !conshdlr->needscons )
3063  {
3064  SCIP_CONS** conss;
3065  SCIP_Longint oldndomchgs;
3066  SCIP_Longint oldnprobdomchgs;
3067  int oldncuts;
3068  int oldnactiveconss;
3069 
3070  SCIPsetDebugMsg(set, "separating %d constraints of handler <%s> (primal solution %p)\n",
3071  nconss, conshdlr->name, (void*)sol);
3072 
3073  /* get the array of the constraints to be processed */
3074  conss = conshdlr->sepaconss;
3075 
3076  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3077  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3078  oldncuts = SCIPsepastoreGetNCuts(sepastore);
3079  oldnactiveconss = stat->nactiveconss;
3080 
3081  /* check, if we want to use eager evaluation */
3082  if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0)
3083  || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) )
3084  nusefulconss = nconss;
3085 
3086  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3087  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3088  * external method; to avoid this, these changes will be buffered and processed after the method call
3089  */
3090  conshdlrDelayUpdates(conshdlr);
3091  conshdlr->duringsepa = TRUE;
3092 
3093  /* start timing */
3094  SCIPclockStart(conshdlr->sepatime, set);
3095 
3096  /* call external method */
3097  SCIP_CALL( conshdlr->conssepasol(set->scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
3098  SCIPsetDebugMsg(set, " -> separating sol returned result <%d>\n", *result);
3099 
3100  /* stop timing */
3101  SCIPclockStop(conshdlr->sepatime, set);
3102 
3103  /* perform the cached constraint updates */
3104  conshdlr->duringsepa = FALSE;
3105  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3106 
3107  /* update statistics */
3108  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
3109  conshdlr->nsepacalls++;
3110  if( *result == SCIP_CUTOFF )
3111  conshdlr->ncutoffs++;
3112  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3113  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3114 
3115  /* update domain reductions; therefore remove the domain
3116  * reduction counts which were generated in probing mode */
3117  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3118  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3119 
3120  /* evaluate result */
3121  if( *result != SCIP_CUTOFF
3122  && *result != SCIP_CONSADDED
3123  && *result != SCIP_REDUCEDDOM
3124  && *result != SCIP_SEPARATED
3125  && *result != SCIP_NEWROUND
3126  && *result != SCIP_DIDNOTFIND
3127  && *result != SCIP_DIDNOTRUN
3128  && *result != SCIP_DELAYED )
3129  {
3130  SCIPerrorMessage("SOL separation method of constraint handler <%s> returned invalid result <%d>\n",
3131  conshdlr->name, *result);
3132  return SCIP_INVALIDRESULT;
3133  }
3134  }
3135  }
3136  else
3137  {
3138  SCIPsetDebugMsg(set, "SOL separation method of constraint handler <%s> was delayed\n", conshdlr->name);
3139  *result = SCIP_DELAYED;
3140  }
3141 
3142  /* remember whether separation method was delayed */
3143  conshdlr->sepasolwasdelayed = (*result == SCIP_DELAYED);
3144  }
3145 
3146  return SCIP_OKAY;
3147 }
3148 
3149 /** calls enforcing method of constraint handler for a relaxation solution for all constraints added after last
3150  * conshdlrResetEnfo() call
3151  */
3153  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3154  BMS_BLKMEM* blkmem, /**< block memory */
3155  SCIP_SET* set, /**< global SCIP settings */
3156  SCIP_STAT* stat, /**< dynamic problem statistics */
3157  SCIP_TREE* tree, /**< branch and bound tree */
3158  SCIP_SEPASTORE* sepastore, /**< separation storage */
3159  SCIP_SOL* relaxsol, /**< solution to be enforced */
3160  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3161  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3162  )
3163 {
3164  int nconss;
3165  int nusefulconss;
3166  int firstcons;
3167  SCIP_Bool relaxchanged;
3168  SCIP_Bool lastinfeasible;
3169 
3170  assert(conshdlr != NULL);
3171  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3172  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3173  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3174  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3175  assert(stat != NULL);
3176  assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount
3177  || conshdlr->lastenfopsnode != stat->nnodes
3178  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3179  assert(set != NULL);
3180  assert(tree != NULL);
3181  assert(tree->nchildren == 0);
3182  assert(relaxsol != NULL);
3183  assert(result != NULL);
3184 
3185  *result = SCIP_FEASIBLE;
3186 
3187  /* check, if this relaxation solution was already enforced at this node
3188  * the integrality constraint handler always needs to be enforced for all constraints since external branching
3189  * candidates are cleared before each resolve
3190  */
3191  if( conshdlr->lastenforelaxrelaxcount == stat->relaxcount
3192  && conshdlr->lastenforelaxdomchgcount == stat->domchgcount
3193  && conshdlr->lastenforelaxnode == stat->nnodes
3194  && conshdlr->lastenforelaxresult != SCIP_CONSADDED
3195  && conshdlr->lastenforelaxresult != SCIP_SOLVELP
3196  && ( strcmp(conshdlr->name, "integral") != 0 )
3197  )
3198  {
3199  assert(conshdlr->lastenforelaxresult != SCIP_CUTOFF);
3200  assert(conshdlr->lastenforelaxresult != SCIP_BRANCHED);
3201  assert(conshdlr->lastenforelaxresult != SCIP_REDUCEDDOM);
3202  assert(conshdlr->lastenforelaxresult != SCIP_DIDNOTRUN);
3203 
3204  /* if we already enforced the same relaxation solution at this node, we will only enforce new constraints in the
3205  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3206  * that an infeasibility in the last call is not lost because we only enforce new constraints
3207  */
3208  if( conshdlr->lastenforelaxresult == SCIP_INFEASIBLE )
3209  {
3210  *result = SCIP_INFEASIBLE;
3211  lastinfeasible = TRUE;
3212  }
3213  else
3214  lastinfeasible = FALSE;
3215 
3216  /* all constraints that were not yet enforced on the new relaxation solution must be useful constraints, which means,
3217  * that the new constraints are the last constraints of the useful ones
3218  */
3219  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3220  nusefulconss = nconss;
3221  firstcons = conshdlr->lastnusefulenfoconss;
3222  relaxchanged = FALSE;
3223  }
3224  else
3225  {
3226  /* on a new relaxation solution or a new node, we want to enforce all constraints */
3227  nconss = conshdlr->nenfoconss;
3228  nusefulconss = conshdlr->nusefulenfoconss;
3229  firstcons = 0;
3230  relaxchanged = TRUE;
3231  lastinfeasible = FALSE;
3232  }
3233  assert(firstcons >= 0);
3234  assert(firstcons + nconss <= conshdlr->nenfoconss);
3235  assert(nusefulconss <= nconss);
3236 
3237  /* constraint handlers without constraints should only be called once */
3238  if( nconss > 0 || (!conshdlr->needscons && relaxchanged) )
3239  {
3240  SCIP_CONS** conss;
3241  SCIP_Longint oldndomchgs;
3242  SCIP_Longint oldnprobdomchgs;
3243  int oldncuts;
3244  int oldnactiveconss;
3245 
3246  assert(conshdlr->consenforelax != NULL);
3247 
3248  SCIPdebugMessage("enforcing constraints %d to %d of %d constraints of handler <%s> (%s relaxation solution)\n",
3249  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, relaxchanged ? "new" : "old");
3250 
3251  /* remember the number of processed constraints on the current relaxation solution */
3252  conshdlr->lastenforelaxrelaxcount = stat->relaxcount;
3253  conshdlr->lastenforelaxdomchgcount = stat->domchgcount;
3254  conshdlr->lastenforelaxnode = stat->nnodes;
3255  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3256 
3257  /* get the array of the constraints to be processed */
3258  conss = &(conshdlr->enfoconss[firstcons]);
3259 
3260  oldncuts = SCIPsepastoreGetNCuts(sepastore);
3261  oldnactiveconss = stat->nactiveconss;
3262  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3263  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3264 
3265  /* check, if we want to use eager evaluation */
3266  if( (conshdlr->eagerfreq == 0 && conshdlr->nenforelaxcalls == 0)
3267  || (conshdlr->eagerfreq > 0 && conshdlr->nenforelaxcalls % conshdlr->eagerfreq == 0) )
3268  nusefulconss = nconss;
3269 
3270  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3271  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3272  * external method; to avoid this, these changes will be buffered and processed after the method call
3273  */
3274  conshdlrDelayUpdates(conshdlr);
3275 
3276  /* start timing */
3277  SCIPclockStart(conshdlr->enforelaxtime, set);
3278 
3279  /* call external method */
3280  SCIP_CALL( conshdlr->consenforelax(set->scip, relaxsol, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) );
3281  SCIPdebugMessage(" -> enforcing returned result <%d>\n", *result);
3282 
3283  /* stop timing */
3284  SCIPclockStop(conshdlr->enforelaxtime, set);
3285 
3286  /* perform the cached constraint updates */
3287  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3288 
3289  /* update statistics */
3290  if( *result != SCIP_DIDNOTRUN )
3291  conshdlr->nenforelaxcalls++;
3292  else
3293  {
3294  SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation returned an invalid result %d\n",
3295  conshdlr->name, *result);
3296  conshdlr->lastenforelaxresult = *result;
3297 
3298  return SCIP_INVALIDRESULT;
3299  }
3300 
3301  if( *result == SCIP_CUTOFF )
3302  conshdlr->ncutoffs++;
3303  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3304  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3305 
3306  if( *result != SCIP_BRANCHED )
3307  {
3308  assert(tree->nchildren == 0);
3309 
3310  /* update domain reductions; therefore remove the domain
3311  * reduction counts which were generated in probing mode */
3312  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3313  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3314  }
3315  else
3316  conshdlr->nchildren += tree->nchildren;
3317 
3318  /* remember the result of the enforcement call */
3319  conshdlr->lastenforelaxresult = *result;
3320 
3321  /* evaluate result */
3322  if( *result != SCIP_CUTOFF
3323  && *result != SCIP_CONSADDED
3324  && *result != SCIP_REDUCEDDOM
3325  && *result != SCIP_SEPARATED
3326  && *result != SCIP_BRANCHED
3327  && *result != SCIP_SOLVELP
3328  && *result != SCIP_INFEASIBLE
3329  && *result != SCIP_FEASIBLE
3330  && *result != SCIP_DIDNOTRUN )
3331  {
3332  SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation solutions returned invalid result <%d>\n",
3333  conshdlr->name, *result);
3334  return SCIP_INVALIDRESULT;
3335  }
3336 
3337  /* if the same relaxation solution was already enforced at this node, we only enforced new constraints this time;
3338  * if the enforelax call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3339  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3340  */
3341  if( lastinfeasible && *result == SCIP_FEASIBLE )
3342  *result = SCIP_INFEASIBLE;
3343  }
3344 
3345  return SCIP_OKAY;
3346 }
3347 
3348 /** calls enforcing method of constraint handler for LP solution for all constraints added after last
3349  * conshdlrResetEnfo() call
3350  */
3352  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3353  BMS_BLKMEM* blkmem, /**< block memory */
3354  SCIP_SET* set, /**< global SCIP settings */
3355  SCIP_STAT* stat, /**< dynamic problem statistics */
3356  SCIP_TREE* tree, /**< branch and bound tree */
3357  SCIP_SEPASTORE* sepastore, /**< separation storage */
3358  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3359  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3360  )
3361 {
3362  assert(conshdlr != NULL);
3363  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3364  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3365  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3366  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3367  assert(stat != NULL);
3368  assert(conshdlr->lastenfolplpcount != stat->lpcount
3369  || conshdlr->lastenfolpdomchgcount != stat->domchgcount
3370  || conshdlr->lastenfolpnode != stat->nnodes
3371  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3372  assert(set != NULL);
3373  assert(tree != NULL);
3374  assert(tree->nchildren == 0);
3375  assert(result != NULL);
3376 
3377  *result = SCIP_FEASIBLE;
3378 
3379  if( conshdlr->consenfolp != NULL )
3380  {
3381  int nconss;
3382  int nusefulconss;
3383  int firstcons;
3384  SCIP_Bool lpchanged;
3385  SCIP_Bool lastinfeasible;
3386 
3387  /* check, if this LP solution was already enforced at this node */
3388  if( conshdlr->lastenfolplpcount == stat->lpcount
3389  && conshdlr->lastenfolpdomchgcount == stat->domchgcount
3390  && conshdlr->lastenfolpnode == stat->nnodes
3391  && conshdlr->lastenfolpresult != SCIP_CONSADDED )
3392  {
3393  assert(conshdlr->lastenfolpresult == SCIP_FEASIBLE || conshdlr->lastenfolpresult == SCIP_INFEASIBLE
3394  || conshdlr->lastenfolpresult == SCIP_SEPARATED );
3395 
3396  /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3397  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3398  * that an infeasibility in the last call is not lost because we only enforce new constraints
3399  */
3400  if( conshdlr->lastenfolpresult == SCIP_FEASIBLE )
3401  lastinfeasible = FALSE;
3402  else
3403  {
3404  assert(conshdlr->lastenfolpresult == SCIP_INFEASIBLE || conshdlr->lastenfolpresult == SCIP_SEPARATED);
3405  *result = SCIP_INFEASIBLE;
3406  lastinfeasible = TRUE;
3407  }
3408 
3409  /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3410  * that the new constraints are the last constraints of the useful ones
3411  */
3412  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3413  nusefulconss = nconss;
3414  firstcons = conshdlr->lastnusefulenfoconss;
3415  lpchanged = FALSE;
3416  }
3417  else
3418  {
3419  /* on a new LP solution or a new node, we want to enforce all constraints */
3420  nconss = conshdlr->nenfoconss;
3421  nusefulconss = conshdlr->nusefulenfoconss;
3422  firstcons = 0;
3423  lpchanged = TRUE;
3424  lastinfeasible = FALSE;
3425  }
3426  assert(firstcons >= 0);
3427  assert(firstcons + nconss <= conshdlr->nenfoconss);
3428  assert(nusefulconss <= nconss);
3429 
3430  /* constraint handlers without constraints should only be called once */
3431  if( nconss > 0 || (!conshdlr->needscons && lpchanged) )
3432  {
3433  SCIP_CONS** conss;
3434  SCIP_Longint oldndomchgs;
3435  SCIP_Longint oldnprobdomchgs;
3436  int oldncuts;
3437  int oldnactiveconss;
3438 
3439  SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n",
3440  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, lpchanged ? "new" : "old");
3441 
3442  /* remember the number of processed constraints on the current LP solution */
3443  conshdlr->lastenfolplpcount = stat->lpcount;
3444  conshdlr->lastenfolpdomchgcount = stat->domchgcount;
3445  conshdlr->lastenfolpnode = stat->nnodes;
3446  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3447 
3448  /* get the array of the constraints to be processed */
3449  conss = &(conshdlr->enfoconss[firstcons]);
3450 
3451  oldncuts = SCIPsepastoreGetNCuts(sepastore);
3452  oldnactiveconss = stat->nactiveconss;
3453  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3454  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3455 
3456  /* check, if we want to use eager evaluation */
3457  if( (conshdlr->eagerfreq == 0 && conshdlr->nenfolpcalls == 0)
3458  || (conshdlr->eagerfreq > 0 && conshdlr->nenfolpcalls % conshdlr->eagerfreq == 0) )
3459  nusefulconss = nconss;
3460 
3461  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3462  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3463  * external method; to avoid this, these changes will be buffered and processed after the method call
3464  */
3465  conshdlrDelayUpdates(conshdlr);
3466 
3467  /* start timing */
3468  SCIPclockStart(conshdlr->enfolptime, set);
3469 
3470  /* call external method */
3471  SCIP_CALL( conshdlr->consenfolp(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) );
3472  SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3473 
3474  /* stop timing */
3475  SCIPclockStop(conshdlr->enfolptime, set);
3476 
3477  /* perform the cached constraint updates */
3478  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3479 
3480  /* remember the result of the enforcement call */
3481  conshdlr->lastenfolpresult = *result;
3482 
3483  /* update statistics */
3484  if( *result != SCIP_DIDNOTRUN )
3485  conshdlr->nenfolpcalls++;
3486  if( *result == SCIP_CUTOFF )
3487  conshdlr->ncutoffs++;
3488  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3489  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3490  if( *result != SCIP_BRANCHED )
3491  {
3492  assert(tree->nchildren == 0);
3493 
3494  /* update domain reductions; therefore remove the domain
3495  * reduction counts which were generated in probing mode */
3496  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3497  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3498  }
3499  else
3500  conshdlr->nchildren += tree->nchildren;
3501 
3502  /* evaluate result */
3503  if( *result != SCIP_CUTOFF
3504  && *result != SCIP_CONSADDED
3505  && *result != SCIP_REDUCEDDOM
3506  && *result != SCIP_SEPARATED
3507  && *result != SCIP_BRANCHED
3508  && *result != SCIP_INFEASIBLE
3509  && *result != SCIP_FEASIBLE )
3510  {
3511  SCIPerrorMessage("enforcing method of constraint handler <%s> for LP solutions returned invalid result <%d>\n",
3512  conshdlr->name, *result);
3513  return SCIP_INVALIDRESULT;
3514  }
3515 
3516  /* if the same LP solution was already enforced at this node, we only enforced new constraints this time;
3517  * if the enfolp call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3518  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3519  */
3520  if( lastinfeasible && *result == SCIP_FEASIBLE )
3521  *result = SCIP_INFEASIBLE;
3522  }
3523  }
3524 
3525  return SCIP_OKAY;
3526 }
3527 
3528 /** calls diving solution enforcement callback of constraint handler, if it exists */
3530  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3531  SCIP_SET* set, /**< global SCIP settings */
3532  SCIP_DIVESET* diveset, /**< diving settings to control scoring */
3533  SCIP_SOL* sol, /**< current solution of diving mode */
3534  SCIP_Bool* success, /**< pointer to store whether constraint handler successfully found a variable */
3535  SCIP_Bool* infeasible /**< pointer to store whether the current node was detected to be infeasible */
3536  )
3537 {
3538  assert(conshdlr != NULL);
3539  assert(set != NULL);
3540  assert(diveset != NULL);
3541  assert(sol != NULL);
3542  assert(success != NULL);
3543  assert(infeasible != NULL);
3544 
3545  if( conshdlr->consgetdivebdchgs != NULL )
3546  {
3547  SCIP_CALL( conshdlr->consgetdivebdchgs(set->scip, conshdlr, diveset, sol, success, infeasible) );
3548  }
3549 
3550  return SCIP_OKAY;
3551 }
3552 
3553 /** calls enforcing method of constraint handler for pseudo solution for all constraints added after last
3554  * conshdlrResetEnfo() call
3555  */
3557  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3558  BMS_BLKMEM* blkmem, /**< block memory */
3559  SCIP_SET* set, /**< global SCIP settings */
3560  SCIP_STAT* stat, /**< dynamic problem statistics */
3561  SCIP_TREE* tree, /**< branch and bound tree */
3562  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3563  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3564  SCIP_Bool objinfeasible, /**< is the solution infeasible anyway due to violating lower objective bound? */
3565  SCIP_Bool forced, /**< should enforcement of pseudo solution be forced? */
3566  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3567  )
3568 {
3569  assert(conshdlr != NULL);
3570  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3571  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3572  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3573  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3574  assert(stat != NULL);
3575  assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount
3576  || conshdlr->lastenfopsnode != stat->nnodes
3577  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3578  assert(set != NULL);
3579  assert(tree != NULL);
3580  assert(tree->nchildren == 0);
3581  assert(result != NULL);
3582 
3583  /* no enforcing of pseudo solution */
3584  if( set->cons_disableenfops && SCIPbranchcandGetNPseudoCands(branchcand) > 0 )
3585  {
3586  *result = SCIP_INFEASIBLE;
3587  return SCIP_OKAY;
3588  }
3589 
3590  *result = SCIP_FEASIBLE;
3591  if( conshdlr->consenfops != NULL )
3592  {
3593  int nconss;
3594  int nusefulconss;
3595  int firstcons;
3596  SCIP_Bool pschanged;
3597  SCIP_Bool lastinfeasible;
3598 
3599  /* check, if this pseudo solution was already enforced at this node */
3600  if( !forced && conshdlr->lastenfopsdomchgcount == stat->domchgcount
3601  && conshdlr->lastenfopsnode == stat->nnodes
3602  && conshdlr->lastenfopsresult != SCIP_CONSADDED
3603  && conshdlr->lastenfopsresult != SCIP_SOLVELP
3604  )
3605  {
3606  assert(conshdlr->lastenfopsresult != SCIP_CUTOFF);
3607  assert(conshdlr->lastenfopsresult != SCIP_BRANCHED);
3608  assert(conshdlr->lastenfopsresult != SCIP_REDUCEDDOM);
3609  assert(conshdlr->lastenfopsresult != SCIP_DIDNOTRUN || objinfeasible);
3610 
3611  /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3612  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3613  * that an infeasibility in the last call is not lost because we only enforce new constraints
3614  */
3615  if( conshdlr->lastenfopsresult == SCIP_INFEASIBLE )
3616  {
3617  *result = SCIP_INFEASIBLE;
3618  lastinfeasible = TRUE;
3619  }
3620  else
3621  lastinfeasible = FALSE;
3622 
3623  /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3624  * that the new constraints are the last constraints of the useful ones
3625  */
3626  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3627  nusefulconss = nconss;
3628  firstcons = conshdlr->lastnusefulenfoconss;
3629  pschanged = FALSE;
3630  }
3631  else
3632  {
3633  /* on a new pseudo solution or a new node, we want to enforce all constraints */
3634  nconss = conshdlr->nenfoconss;
3635  nusefulconss = conshdlr->nusefulenfoconss;
3636  firstcons = 0;
3637  pschanged = TRUE;
3638  lastinfeasible = FALSE;
3639  }
3640  assert(firstcons >= 0);
3641  assert(firstcons + nconss <= conshdlr->nenfoconss);
3642  assert(nusefulconss <= nconss);
3643 
3644  /* constraint handlers without constraints should only be called once */
3645  if( nconss > 0 || (!conshdlr->needscons && pschanged) )
3646  {
3647  SCIP_CONS** conss;
3648  SCIP_Longint oldndomchgs;
3649  SCIP_Longint oldnprobdomchgs;
3650 
3651  SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, objinfeasible=%u)\n",
3652  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, pschanged ? "new" : "old", objinfeasible);
3653 
3654  /* remember the number of processed constraints on the current pseudo solution */
3655  conshdlr->lastenfopsdomchgcount = stat->domchgcount;
3656  conshdlr->lastenfopsnode = stat->nnodes;
3657  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3658 
3659  /* get the array of the constraints to be processed */
3660  conss = &(conshdlr->enfoconss[firstcons]);
3661 
3662  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3663  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3664 
3665  /* check, if we want to use eager evaluation */
3666  if( (conshdlr->eagerfreq == 0 && conshdlr->nenfopscalls == 0)
3667  || (conshdlr->eagerfreq > 0 && conshdlr->nenfopscalls % conshdlr->eagerfreq == 0) )
3668  nusefulconss = nconss;
3669 
3670  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3671  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3672  * external method; to avoid this, these changes will be buffered and processed after the method call
3673  */
3674  conshdlrDelayUpdates(conshdlr);
3675 
3676  /* start timing */
3677  SCIPclockStart(conshdlr->enfopstime, set);
3678 
3679  /* call external method */
3680  SCIP_CALL( conshdlr->consenfops(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, objinfeasible, result) );
3681  SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3682 
3683  /* stop timing */
3684  SCIPclockStop(conshdlr->enfopstime, set);
3685 
3686  /* perform the cached constraint updates */
3687  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3688 
3689  /* update statistics */
3690  if( *result != SCIP_DIDNOTRUN )
3691  conshdlr->nenfopscalls++;
3692  else if( !objinfeasible )
3693  {
3694  SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions was skipped, even though the solution was not objective-infeasible\n",
3695  conshdlr->name);
3696  conshdlr->lastenfopsresult = *result;
3697 
3698  return SCIP_INVALIDRESULT;
3699  }
3700  /* A constraint handler might return SCIP_DIDNOTRUN and not check any constraints in case objinfeasible was
3701  * TRUE; we change the result pointer to SCIP_INFEASIBLE in this case.
3702  */
3703  else
3704  *result = SCIP_INFEASIBLE;
3705 
3706  if( *result == SCIP_CUTOFF )
3707  conshdlr->ncutoffs++;
3708 
3709  if( *result != SCIP_BRANCHED )
3710  {
3711  assert(tree->nchildren == 0);
3712 
3713  /* update domain reductions; therefore remove the domain
3714  * reduction counts which were generated in probing mode */
3715  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3716  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3717  }
3718  else
3719  conshdlr->nchildren += tree->nchildren;
3720 
3721  /* remember the result of the enforcement call */
3722  conshdlr->lastenfopsresult = *result;
3723 
3724  /* evaluate result */
3725  if( *result != SCIP_CUTOFF
3726  && *result != SCIP_CONSADDED
3727  && *result != SCIP_REDUCEDDOM
3728  && *result != SCIP_BRANCHED
3729  && *result != SCIP_SOLVELP
3730  && *result != SCIP_INFEASIBLE
3731  && *result != SCIP_FEASIBLE
3732  && *result != SCIP_DIDNOTRUN )
3733  {
3734  SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions returned invalid result <%d>\n",
3735  conshdlr->name, *result);
3736  return SCIP_INVALIDRESULT;
3737  }
3738 
3739  /* if the same pseudo solution was already enforced at this node, we only enforced new constraints this time;
3740  * if the enfops call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3741  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3742  */
3743  if( lastinfeasible && *result == SCIP_FEASIBLE )
3744  *result = SCIP_INFEASIBLE;
3745  }
3746  }
3747 
3748  return SCIP_OKAY;
3749 }
3750 
3751 /** calls feasibility check method of constraint handler */
3753  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3754  BMS_BLKMEM* blkmem, /**< block memory */
3755  SCIP_SET* set, /**< global SCIP settings */
3756  SCIP_STAT* stat, /**< dynamic problem statistics */
3757  SCIP_SOL* sol, /**< primal CIP solution */
3758  SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
3759  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
3760  SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
3761  SCIP_Bool completely, /**< Should all violations be checked? */
3762  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3763  )
3764 {
3765  assert(conshdlr != NULL);
3766  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3767  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3768  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3769  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3770  assert(set != NULL);
3771  assert(result != NULL);
3772 
3773  *result = SCIP_FEASIBLE;
3774 
3775  if( conshdlr->conscheck != NULL && (!conshdlr->needscons || conshdlr->ncheckconss > 0) )
3776  {
3777  SCIPsetDebugMsg(set, "checking %d constraints of handler <%s>\n", conshdlr->ncheckconss, conshdlr->name);
3778 
3779  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3780  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3781  * external method; to avoid this, these changes will be buffered and processed after the method call
3782  */
3783  conshdlrDelayUpdates(conshdlr);
3784 
3785  /* start timing */
3786  SCIPclockStart(conshdlr->checktime, set);
3787 
3788  /* call external method */
3789  SCIP_CALL( conshdlr->conscheck(set->scip, conshdlr, conshdlr->checkconss, conshdlr->ncheckconss,
3790  sol, checkintegrality, checklprows, printreason, completely, result) );
3791  SCIPsetDebugMsg(set, " -> checking returned result <%d>\n", *result);
3792 
3793  /* stop timing */
3794  SCIPclockStop(conshdlr->checktime, set);
3795 
3796  /* update statistics */
3797  conshdlr->ncheckcalls++;
3798 
3799  /* perform the cached constraint updates */
3800  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3801 
3802  /* evaluate result */
3803  if( *result != SCIP_INFEASIBLE && *result != SCIP_FEASIBLE )
3804  {
3805  SCIPerrorMessage("feasibility check of constraint handler <%s> returned invalid result <%d>\n", conshdlr->name, *result);
3806  return SCIP_INVALIDRESULT;
3807  }
3808  }
3809 
3810  return SCIP_OKAY;
3811 }
3812 
3813 /** calls propagation method of constraint handler */
3815  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3816  BMS_BLKMEM* blkmem, /**< block memory */
3817  SCIP_SET* set, /**< global SCIP settings */
3818  SCIP_STAT* stat, /**< dynamic problem statistics */
3819  int depth, /**< depth of current node */
3820  SCIP_Bool fullpropagation, /**< should all constraints be propagated (or only new ones)? */
3821  SCIP_Bool execdelayed, /**< execute propagation method even if it is marked to be delayed */
3822  SCIP_Bool instrongbranching, /**< are we currently doing strong branching? */
3823  SCIP_PROPTIMING proptiming, /**< current point in the node solving process */
3824  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3825  )
3826 {
3827  assert(conshdlr != NULL);
3828  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3829  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3830  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3831  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3832  assert(stat != NULL);
3833  assert(conshdlr->lastpropdomchgcount != stat->domchgcount
3834  || (0 <= conshdlr->lastnusefulpropconss && conshdlr->lastnusefulpropconss <= conshdlr->nusefulpropconss));
3835  assert(set != NULL);
3836  assert(depth >= 0);
3837  assert(result != NULL);
3838 
3839  *result = SCIP_DIDNOTRUN;
3840 
3841  if( conshdlr->consprop != NULL
3842  && (!conshdlr->needscons || conshdlr->npropconss > 0)
3843  && ((depth == 0 && conshdlr->propfreq == 0)
3844  || (conshdlr->propfreq > 0 && depth % conshdlr->propfreq == 0)
3845  || conshdlr->propwasdelayed) )
3846  {
3847  /* check, if propagation method should be delayed */
3848  if( !conshdlr->delayprop || execdelayed )
3849  {
3850  int nconss;
3851  int nusefulconss;
3852  int nmarkedpropconss;
3853  int firstcons;
3854 
3855  /* check, if the current domains were already propagated */
3856  if( !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount && conshdlr->nmarkedpropconss == 0 )
3857  {
3858  /* all constraints that were not yet propagated on the new domains must be useful constraints, which means,
3859  * that the new constraints are the last constraints of the useful ones
3860  */
3861  nconss = conshdlr->nusefulpropconss - conshdlr->lastnusefulpropconss;
3862  nusefulconss = nconss;
3863  firstcons = conshdlr->lastnusefulpropconss;
3864  }
3865  else
3866  {
3867  /* on new domains, we want to propagate all constraints */
3868  nconss = conshdlr->npropconss;
3869  nusefulconss = conshdlr->nusefulpropconss;
3870  firstcons = 0;
3871  }
3872  assert(firstcons >= 0);
3873  assert(firstcons + nconss <= conshdlr->npropconss);
3874  assert(nusefulconss <= nconss);
3875 
3876  nmarkedpropconss = conshdlr->nmarkedpropconss;
3877 
3878  /* constraint handlers without constraints should only be called once */
3879  if( nconss > 0 || fullpropagation
3880  || (!conshdlr->needscons && conshdlr->lastpropdomchgcount != stat->domchgcount) )
3881  {
3882  SCIP_CONS** conss;
3883  SCIP_Longint oldndomchgs;
3884  SCIP_Longint oldnprobdomchgs;
3885  SCIP_Longint lastpropdomchgcount;
3886  int lastnusefulpropconss;
3887 
3888  SCIPsetDebugMsg(set, "propagating constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, %d useful)\n",
3889  firstcons, firstcons + nconss - 1, conshdlr->npropconss, conshdlr->name,
3890  !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount ? "old" : "new", nusefulconss);
3891 
3892  /* remember the number of processed constraints on the current domains */
3893  lastpropdomchgcount = stat->domchgcount;
3894  lastnusefulpropconss = conshdlr->nusefulpropconss;
3895 
3896  /* get the array of the constraints to be processed */
3897  conss = &(conshdlr->propconss[firstcons]);
3898 
3899  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3900  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3901 
3902  /* check, if we want to use eager evaluation */
3903  if( (conshdlr->eagerfreq == 0 && conshdlr->npropcalls == 0)
3904  || (conshdlr->eagerfreq > 0 && conshdlr->npropcalls % conshdlr->eagerfreq == 0) )
3905  nusefulconss = nconss;
3906 
3907  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3908  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3909  * external method; to avoid this, these changes will be buffered and processed after the method call
3910  */
3911  conshdlrDelayUpdates(conshdlr);
3912  conshdlr->duringprop = TRUE;
3913 
3914  /* start timing */
3915  if( instrongbranching )
3916  SCIPclockStart(conshdlr->sbproptime, set);
3917  else
3918  SCIPclockStart(conshdlr->proptime, set);
3919 
3920  assert(nusefulconss <= nconss);
3921  assert(nmarkedpropconss <= nconss);
3922 
3923  /* call external method */
3924  SCIP_CALL( conshdlr->consprop(set->scip, conshdlr, conss, nconss, nusefulconss, nmarkedpropconss, proptiming, result) );
3925  SCIPsetDebugMsg(set, " -> propagation returned result <%d>\n", *result);
3926 
3927  /* stop timing */
3928  if( instrongbranching )
3929  SCIPclockStop(conshdlr->sbproptime, set);
3930  else
3931  SCIPclockStop(conshdlr->proptime, set);
3932 
3933  /* perform the cached constraint updates */
3934  conshdlr->duringprop = FALSE;
3935  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3936 
3937  /* update statistics */
3938  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
3939  {
3940  conshdlr->lastpropdomchgcount = lastpropdomchgcount;
3941  conshdlr->lastnusefulpropconss = MIN(conshdlr->nusefulpropconss, lastnusefulpropconss);
3942  conshdlr->npropcalls++;
3943  }
3944  else
3945  {
3946  assert(lastpropdomchgcount == stat->domchgcount);
3947  assert(lastnusefulpropconss == conshdlr->nusefulpropconss);
3948  }
3949  if( *result == SCIP_CUTOFF )
3950  conshdlr->ncutoffs++;
3951 
3952  /* update domain reductions; therefore remove the domain
3953  * reduction counts which were generated in probing mode */
3954  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3955  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3956 
3957  /* check result code of callback method */
3958  if( *result != SCIP_CUTOFF
3959  && *result != SCIP_REDUCEDDOM
3960  && *result != SCIP_DIDNOTFIND
3961  && *result != SCIP_DIDNOTRUN
3962  && *result != SCIP_DELAYED
3963  && *result != SCIP_DELAYNODE )
3964  {
3965  SCIPerrorMessage("propagation method of constraint handler <%s> returned invalid result <%d>\n",
3966  conshdlr->name, *result);
3967  return SCIP_INVALIDRESULT;
3968  }
3969  }
3970  }
3971  else
3972  {
3973  SCIPsetDebugMsg(set, "propagation method of constraint handler <%s> was delayed\n", conshdlr->name);
3974  *result = SCIP_DELAYED;
3975  }
3976 
3977  /* remember whether propagation method was delayed */
3978  conshdlr->propwasdelayed = (*result == SCIP_DELAYED);
3979  }
3980 
3981  return SCIP_OKAY;
3982 }
3983 
3984 /** calls presolving method of constraint handler */
3986  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3987  BMS_BLKMEM* blkmem, /**< block memory */
3988  SCIP_SET* set, /**< global SCIP settings */
3989  SCIP_STAT* stat, /**< dynamic problem statistics */
3990  SCIP_PRESOLTIMING timing, /**< current presolving timing */
3991  int nrounds, /**< number of presolving rounds already done */
3992  int* nfixedvars, /**< pointer to total number of variables fixed of all presolvers */
3993  int* naggrvars, /**< pointer to total number of variables aggregated of all presolvers */
3994  int* nchgvartypes, /**< pointer to total number of variable type changes of all presolvers */
3995  int* nchgbds, /**< pointer to total number of variable bounds tightened of all presolvers */
3996  int* naddholes, /**< pointer to total number of domain holes added of all presolvers */
3997  int* ndelconss, /**< pointer to total number of deleted constraints of all presolvers */
3998  int* naddconss, /**< pointer to total number of added constraints of all presolvers */
3999  int* nupgdconss, /**< pointer to total number of upgraded constraints of all presolvers */
4000  int* nchgcoefs, /**< pointer to total number of changed coefficients of all presolvers */
4001  int* nchgsides, /**< pointer to total number of changed left/right hand sides of all presolvers */
4002  SCIP_RESULT* result /**< pointer to store the result of the callback method */
4003  )
4004 {
4005  assert(conshdlr != NULL);
4006  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
4007  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
4008  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
4009  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
4010  assert(set != NULL);
4011  assert(nfixedvars != NULL);
4012  assert(naggrvars != NULL);
4013  assert(nchgvartypes != NULL);
4014  assert(nchgbds != NULL);
4015  assert(naddholes != NULL);
4016  assert(ndelconss != NULL);
4017  assert(naddconss != NULL);
4018  assert(nupgdconss != NULL);
4019  assert(nchgcoefs != NULL);
4020  assert(nchgsides != NULL);
4021  assert(result != NULL);
4022 
4023  *result = SCIP_DIDNOTRUN;
4024 
4025  if( conshdlr->conspresol != NULL
4026  && (!conshdlr->needscons || conshdlr->nactiveconss > 0)
4027  && (conshdlr->maxprerounds == -1 || conshdlr->npresolcalls < conshdlr->maxprerounds ) )
4028  {
4029  SCIPsetDebugMsg(set, "presolving %d constraints of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4030 
4031  /* check, if presolving method should be executed for the current timing */
4032  if( timing & conshdlr->presoltiming )
4033  {
4034  int nnewfixedvars;
4035  int nnewaggrvars;
4036  int nnewchgvartypes;
4037  int nnewchgbds;
4038  int nnewholes;
4039  int nnewdelconss;
4040  int nnewaddconss;
4041  int nnewupgdconss;
4042  int nnewchgcoefs;
4043  int nnewchgsides;
4044 
4045  /* calculate the number of changes since last call */
4046  nnewfixedvars = *nfixedvars - conshdlr->lastnfixedvars;
4047  nnewaggrvars = *naggrvars - conshdlr->lastnaggrvars;
4048  nnewchgvartypes = *nchgvartypes - conshdlr->lastnchgvartypes;
4049  nnewchgbds = *nchgbds - conshdlr->lastnchgbds;
4050  nnewholes = *naddholes - conshdlr->lastnaddholes;
4051  nnewdelconss = *ndelconss - conshdlr->lastndelconss;
4052  nnewaddconss = *naddconss - conshdlr->lastnaddconss;
4053  nnewupgdconss = *nupgdconss - conshdlr->lastnupgdconss;
4054  nnewchgcoefs = *nchgcoefs - conshdlr->lastnchgcoefs;
4055  nnewchgsides = *nchgsides - conshdlr->lastnchgsides;
4056 
4057  /* remember the old number of changes */
4058  conshdlr->lastnfixedvars = *nfixedvars;
4059  conshdlr->lastnaggrvars = *naggrvars;
4060  conshdlr->lastnchgvartypes = *nchgvartypes;
4061  conshdlr->lastnchgbds = *nchgbds;
4062  conshdlr->lastnaddholes = *naddholes;
4063  conshdlr->lastndelconss = *ndelconss;
4064  conshdlr->lastnaddconss = *naddconss;
4065  conshdlr->lastnupgdconss = *nupgdconss;
4066  conshdlr->lastnchgcoefs = *nchgcoefs;
4067  conshdlr->lastnchgsides = *nchgsides;
4068 
4069  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4070  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4071  * external method; to avoid this, these changes will be buffered and processed after the method call
4072  */
4073  conshdlrDelayUpdates(conshdlr);
4074 
4075  /* start timing */
4076  SCIPclockStart(conshdlr->presoltime, set);
4077 
4078  /* call external method */
4079  SCIP_CALL( conshdlr->conspresol(set->scip, conshdlr, conshdlr->conss, conshdlr->nactiveconss, nrounds, timing,
4080  nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewholes,
4081  nnewdelconss, nnewaddconss, nnewupgdconss, nnewchgcoefs, nnewchgsides,
4082  nfixedvars, naggrvars, nchgvartypes, nchgbds, naddholes,
4083  ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) );
4084 
4085  /* stop timing */
4086  SCIPclockStop(conshdlr->presoltime, set);
4087 
4088  /* perform the cached constraint updates */
4089  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4090 
4091  /* count the new changes */
4092  conshdlr->nfixedvars += *nfixedvars - conshdlr->lastnfixedvars;
4093  conshdlr->naggrvars += *naggrvars - conshdlr->lastnaggrvars;
4094  conshdlr->nchgvartypes += *nchgvartypes - conshdlr->lastnchgvartypes;
4095  conshdlr->nchgbds += *nchgbds - conshdlr->lastnchgbds;
4096  conshdlr->naddholes += *naddholes - conshdlr->lastnaddholes;
4097  conshdlr->ndelconss += *ndelconss - conshdlr->lastndelconss;
4098  conshdlr->naddconss += *naddconss - conshdlr->lastnaddconss;
4099  conshdlr->nupgdconss += *nupgdconss - conshdlr->lastnupgdconss;
4100  conshdlr->nchgcoefs += *nchgcoefs - conshdlr->lastnchgcoefs;
4101  conshdlr->nchgsides += *nchgsides - conshdlr->lastnchgsides;
4102 
4103  /* check result code of callback method */
4104  if( *result != SCIP_CUTOFF
4105  && *result != SCIP_UNBOUNDED
4106  && *result != SCIP_SUCCESS
4107  && *result != SCIP_DIDNOTFIND
4108  && *result != SCIP_DIDNOTRUN
4109  && *result != SCIP_DELAYED )
4110  {
4111  SCIPerrorMessage("presolving method of constraint handler <%s> returned invalid result <%d>\n",
4112  conshdlr->name, *result);
4113  return SCIP_INVALIDRESULT;
4114  }
4115 
4116  /* increase the number of calls, if the presolving method tried to find reductions */
4117  if( *result != SCIP_DIDNOTRUN )
4118  ++(conshdlr->npresolcalls);
4119  }
4120 
4121  SCIPsetDebugMsg(set, "after presolving %d constraints left of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4122  }
4123 
4124  return SCIP_OKAY;
4125 }
4126 
4127 /** calls variable deletion method of constraint handler */
4129  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4130  BMS_BLKMEM* blkmem, /**< block memory */
4131  SCIP_SET* set, /**< global SCIP settings */
4132  SCIP_STAT* stat /**< dynamic problem statistics */
4133  )
4134 {
4135  assert(conshdlr != NULL);
4136  assert(set != NULL);
4137 
4138  if( conshdlr->consdelvars != NULL )
4139  {
4140  SCIPsetDebugMsg(set, "deleting variables in constraints of handler <%s>\n", conshdlr->name);
4141 
4142  /* during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4143  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4144  * external method; to avoid this, these changes will be buffered and processed after the method call
4145  */
4146  conshdlrDelayUpdates(conshdlr);
4147 
4148  /* call external method */
4149  SCIP_CALL( conshdlr->consdelvars(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
4150 
4151  /* perform the cached constraint updates */
4152  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4153  }
4154 
4155  return SCIP_OKAY;
4156 }
4157 
4158 /** locks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
4160  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4161  SCIP_SET* set /**< global SCIP settings */
4162  )
4163 {
4164  assert(conshdlr != NULL);
4165  assert(conshdlr->conslock != NULL);
4166  assert(!conshdlr->needscons);
4167 
4168  SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, +1, 0) );
4169 
4170  return SCIP_OKAY;
4171 }
4172 
4173 /** unlocks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
4175  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4176  SCIP_SET* set /**< global SCIP settings */
4177  )
4178 {
4179  assert(conshdlr != NULL);
4180  assert(conshdlr->conslock != NULL);
4181  assert(!conshdlr->needscons);
4182 
4183  SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, -1, 0) );
4184 
4185  return SCIP_OKAY;
4186 }
4187 
4188 /** gets name of constraint handler */
4189 const char* SCIPconshdlrGetName(
4190  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4191  )
4192 {
4193  assert(conshdlr != NULL);
4194 
4195  return conshdlr->name;
4196 }
4197 
4198 /** gets description of constraint handler */
4199 const char* SCIPconshdlrGetDesc(
4200  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4201  )
4202 {
4203  assert(conshdlr != NULL);
4204 
4205  return conshdlr->desc;
4206 }
4207 
4208 /** gets user data of constraint handler */
4210  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4211  )
4212 {
4213  assert(conshdlr != NULL);
4214 
4215  return conshdlr->conshdlrdata;
4216 }
4217 
4218 /** sets user data of constraint handler; user has to free old data in advance! */
4219 void SCIPconshdlrSetData(
4220  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4221  SCIP_CONSHDLRDATA* conshdlrdata /**< new constraint handler user data */
4222  )
4223 {
4224  assert(conshdlr != NULL);
4225 
4226  conshdlr->conshdlrdata = conshdlrdata;
4227 }
4228 
4229 /** sets all separation related callbacks of the constraint handler */
4230 void SCIPconshdlrSetSepa(
4231  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4232  SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */
4233  SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */
4234  int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */
4235  int sepapriority, /**< priority of the constraint handler for separation */
4236  SCIP_Bool delaysepa /**< should separation method be delayed, if other separators found cuts? */
4237  )
4238 {
4239  assert(conshdlr != NULL);
4240 
4241  assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
4242 
4243  conshdlr->conssepalp = conssepalp;
4244  conshdlr->conssepasol = conssepasol;
4245  conshdlr->sepafreq = sepafreq;
4246  conshdlr->sepapriority = sepapriority;
4247  conshdlr->delaysepa = delaysepa;
4248 }
4249 
4250 /** sets both the propagation callback and the propagation frequency of the constraint handler */
4251 void SCIPconshdlrSetProp(
4252  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4253  SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */
4254  int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */
4255  SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */
4256  SCIP_PROPTIMING timingmask /**< positions in the node solving loop where propagators should be executed */
4257  )
4258 {
4259  assert(conshdlr != NULL);
4260 
4261  assert(consprop != NULL || propfreq == -1);
4262 
4263  conshdlr->consprop = consprop;
4264  conshdlr->propfreq = propfreq;
4265  conshdlr->delayprop = delayprop;
4266  conshdlr->proptiming = timingmask;
4267 }
4268 
4269 /** sets copy method of both the constraint handler and each associated constraint */
4271  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4272  SCIP_DECL_CONSENFORELAX ((*consenforelax)) /**< constraint copying method */
4273  )
4274 {
4275  assert(conshdlr != NULL);
4276 
4277  conshdlr->consenforelax = consenforelax;
4278 }
4279 
4280 /** sets copy method of both the constraint handler and each associated constraint */
4281 void SCIPconshdlrSetCopy(
4282  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4283  SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
4284  SCIP_DECL_CONSCOPY ((*conscopy)) /**< constraint copying method */
4285  )
4286 {
4287  assert(conshdlr != NULL);
4288 
4289  assert(!conshdlr->needscons || (conshdlrcopy == NULL) == (conscopy == NULL));
4290 
4291  conshdlr->conshdlrcopy = conshdlrcopy;
4292  conshdlr->conscopy = conscopy;
4293 }
4294 
4295 /** sets destructor method of constraint handler */
4296 void SCIPconshdlrSetFree(
4297  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4298  SCIP_DECL_CONSFREE ((*consfree)) /**< destructor of constraint handler */
4299  )
4300 {
4301  assert(conshdlr != NULL);
4302 
4303  conshdlr->consfree = consfree;
4304 }
4305 
4306 /** sets initialization method of constraint handler */
4307 void SCIPconshdlrSetInit(
4308  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4309  SCIP_DECL_CONSINIT ((*consinit)) /**< initialize constraint handler */
4310  )
4311 {
4312  assert(conshdlr != NULL);
4313 
4314  conshdlr->consinit = consinit;
4315 }
4316 
4317 /** sets deinitialization method of constraint handler */
4318 void SCIPconshdlrSetExit(
4319  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4320  SCIP_DECL_CONSEXIT ((*consexit)) /**< deinitialize constraint handler */
4321  )
4322 {
4323  assert(conshdlr != NULL);
4324 
4325  conshdlr->consexit = consexit;
4326 }
4327 
4328 /** sets solving process initialization method of constraint handler */
4330  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4331  SCIP_DECL_CONSINITSOL((*consinitsol)) /**< solving process initialization method of constraint handler */
4332  )
4333 {
4334  assert(conshdlr != NULL);
4335 
4336  conshdlr->consinitsol = consinitsol;
4337 }
4338 
4339 /** sets solving process deinitialization method of constraint handler */
4341  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4342  SCIP_DECL_CONSEXITSOL ((*consexitsol)) /**< solving process deinitialization method of constraint handler */
4343  )
4344 {
4345  assert(conshdlr != NULL);
4346 
4347  conshdlr->consexitsol = consexitsol;
4348 }
4349 
4350 /** sets preprocessing initialization method of constraint handler */
4352  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4353  SCIP_DECL_CONSINITPRE((*consinitpre)) /**< preprocessing initialization method of constraint handler */
4354  )
4355 {
4356  assert(conshdlr != NULL);
4357 
4358  conshdlr->consinitpre = consinitpre;
4359 }
4360 
4361 /** sets preprocessing deinitialization method of constraint handler */
4363  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4364  SCIP_DECL_CONSEXITPRE((*consexitpre)) /**< preprocessing deinitialization method of constraint handler */
4365  )
4366 {
4367  assert(conshdlr != NULL);
4368 
4369  conshdlr->consexitpre = consexitpre;
4370 }
4371 
4372 /** sets presolving method of constraint handler */
4374  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4375  SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method of constraint handler */
4376  int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
4377  SCIP_PRESOLTIMING presoltiming /**< timing mask of the constraint handler's presolving method */
4378  )
4379 {
4380  assert(conshdlr != NULL);
4381 
4382  conshdlr->conspresol = conspresol;
4383  conshdlr->maxprerounds = maxprerounds;
4384 
4385  /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
4386  * error message
4387  */
4388  if( presoltiming < SCIP_PRESOLTIMING_FAST || presoltiming > SCIP_PRESOLTIMING_MAX )
4389  {
4390  SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
4391  "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", conshdlr->name);
4392 
4393  return SCIP_PARAMETERWRONGVAL;
4394  }
4395 
4396  conshdlr->presoltiming = presoltiming;
4397 
4398  return SCIP_OKAY;
4399 }
4400 
4401 /** sets method of constraint handler to free specific constraint data */
4403  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4404  SCIP_DECL_CONSDELETE ((*consdelete)) /**< free specific constraint data */
4405  )
4406 {
4407  assert(conshdlr != NULL);
4408 
4409  conshdlr->consdelete = consdelete;
4410 }
4411 
4412 /** sets method of constraint handler to transform constraint data into data belonging to the transformed problem */
4414  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4415  SCIP_DECL_CONSTRANS ((*constrans)) /**< transform constraint data into data belonging to the transformed problem */
4416  )
4417 {
4418  assert(conshdlr != NULL);
4419 
4420  conshdlr->constrans = constrans;
4421 }
4422 
4423 /** sets method of constraint handler to initialize LP with relaxations of "initial" constraints */
4425  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4426  SCIP_DECL_CONSINITLP ((*consinitlp)) /**< initialize LP with relaxations of "initial" constraints */
4427  )
4428 {
4429  assert(conshdlr != NULL);
4430 
4431  conshdlr->consinitlp = consinitlp;
4432 }
4433 
4434 /** sets propagation conflict resolving method of constraint handler */
4436  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4437  SCIP_DECL_CONSRESPROP ((*consresprop)) /**< propagation conflict resolving method */
4438  )
4439 {
4440  assert(conshdlr != NULL);
4441 
4442  conshdlr->consresprop = consresprop;
4443 }
4444 
4445 /** sets activation notification method of constraint handler */
4447  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4448  SCIP_DECL_CONSACTIVE ((*consactive)) /**< activation notification method */
4449  )
4450 {
4451  assert(conshdlr != NULL);
4452 
4453  conshdlr->consactive = consactive;
4454 }
4455 
4456 /** sets deactivation notification method of constraint handler */
4458  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4459  SCIP_DECL_CONSDEACTIVE((*consdeactive)) /**< deactivation notification method */
4460  )
4461 {
4462  assert(conshdlr != NULL);
4463 
4464  conshdlr->consdeactive = consdeactive;
4465 }
4466 
4467 /** sets enabling notification method of constraint handler */
4469  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4470  SCIP_DECL_CONSENABLE ((*consenable)) /**< enabling notification method */
4471  )
4472 {
4473  assert(conshdlr != NULL);
4474 
4475  conshdlr->consenable = consenable;
4476 }
4477 
4478 /** sets disabling notification method of constraint handler */
4480  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4481  SCIP_DECL_CONSDISABLE ((*consdisable)) /**< disabling notification method */
4482  )
4483 {
4484  assert(conshdlr != NULL);
4485 
4486  conshdlr->consdisable = consdisable;
4487 }
4488 
4489 /** sets variable deletion method of constraint handler */
4491  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4492  SCIP_DECL_CONSDELVARS ((*consdelvars)) /**< variable deletion method */
4493  )
4494 {
4495  assert(conshdlr != NULL);
4496 
4497  conshdlr->consdelvars = consdelvars;
4498 }
4499 
4500 /** sets constraint display method of constraint handler */
4502  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4503  SCIP_DECL_CONSPRINT ((*consprint)) /**< constraint display method */
4504  )
4505 {
4506  assert(conshdlr != NULL);
4507 
4508  conshdlr->consprint = consprint;
4509 }
4510 
4511 /** sets constraint parsing method of constraint handler */
4513  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4514  SCIP_DECL_CONSPARSE ((*consparse)) /**< constraint parsing method */
4515  )
4516 {
4517  assert(conshdlr != NULL);
4518 
4519  conshdlr->consparse = consparse;
4520 }
4521 
4522 /** sets constraint variable getter method of constraint handler */
4524  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4525  SCIP_DECL_CONSGETVARS ((*consgetvars)) /**< constraint variable getter method */
4526  )
4527 {
4528  assert(conshdlr != NULL);
4529 
4530  conshdlr->consgetvars = consgetvars;
4531 }
4532 
4533 /** sets constraint variable number getter method of constraint handler */
4535  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4536  SCIP_DECL_CONSGETNVARS((*consgetnvars)) /**< constraint variable number getter method */
4537  )
4538 {
4539  assert(conshdlr != NULL);
4540 
4541  conshdlr->consgetnvars = consgetnvars;
4542 }
4543 
4544 /** sets diving enforcement method of constraint handler */
4546  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4547  SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)) /**< constraint handler diving solution enforcement method */
4548  )
4549 {
4550  assert(conshdlr != NULL);
4551 
4552  conshdlr->consgetdivebdchgs = consgetdivebdchgs;
4553 }
4554 
4555 /** gets array with constraints of constraint handler; the first SCIPconshdlrGetNActiveConss() entries are the active
4556  * constraints, the last SCIPconshdlrGetNConss() - SCIPconshdlrGetNActiveConss() constraints are deactivated
4557  *
4558  * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4559  * flag is TRUE) and the current node belongs to the corresponding sub tree.
4560  */
4562  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4563  )
4564 {
4565  assert(conshdlr != NULL);
4566 
4567  return conshdlr->conss;
4568 }
4569 
4570 /** gets array with enforced constraints of constraint handler; this is local information */
4572  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4573  )
4574 {
4575  assert(conshdlr != NULL);
4576 
4577  return conshdlr->enfoconss;
4578 }
4579 
4580 /** gets array with checked constraints of constraint handler; this is local information */
4582  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4583  )
4584 {
4585  assert(conshdlr != NULL);
4586 
4587  return conshdlr->checkconss;
4588 }
4589 
4590 /** gets total number of existing transformed constraints of constraint handler */
4592  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4593  )
4594 {
4595  assert(conshdlr != NULL);
4596 
4597  return conshdlr->nconss;
4598 }
4599 
4600 /** gets number of enforced constraints of constraint handler; this is local information */
4602  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4603  )
4604 {
4605  assert(conshdlr != NULL);
4606 
4607  return conshdlr->nenfoconss;
4608 }
4609 
4610 /** gets number of checked constraints of constraint handler; this is local information */
4612  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4613  )
4614 {
4615  assert(conshdlr != NULL);
4616 
4617  return conshdlr->ncheckconss;
4618 }
4619 
4620 /** gets number of active constraints of constraint handler
4621  *
4622  * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4623  * flag is TRUE) and the current node belongs to the corresponding sub tree.
4624  */
4626  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4627  )
4628 {
4629  assert(conshdlr != NULL);
4630 
4631  return conshdlr->nactiveconss;
4632 }
4633 
4634 /** gets number of enabled constraints of constraint handler */
4636  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4637  )
4638 {
4639  assert(conshdlr != NULL);
4640 
4641  return conshdlr->nenabledconss;
4642 }
4643 
4644 /** enables or disables all clocks of \p conshdlr, depending on the value of the flag */
4646  SCIP_CONSHDLR* conshdlr, /**< the constraint handler for which all clocks should be enabled or disabled */
4647  SCIP_Bool enable /**< should the clocks of the constraint handler be enabled? */
4648  )
4649 {
4650  assert(conshdlr != NULL);
4651 
4652  SCIPclockEnableOrDisable(conshdlr->setuptime, enable);
4653  SCIPclockEnableOrDisable(conshdlr->checktime, enable);
4654  SCIPclockEnableOrDisable(conshdlr->enfolptime, enable);
4655  SCIPclockEnableOrDisable(conshdlr->enfopstime, enable);
4656  SCIPclockEnableOrDisable(conshdlr->enforelaxtime, enable);
4657  SCIPclockEnableOrDisable(conshdlr->presoltime, enable);
4658  SCIPclockEnableOrDisable(conshdlr->proptime, enable);
4659  SCIPclockEnableOrDisable(conshdlr->resproptime, enable);
4660  SCIPclockEnableOrDisable(conshdlr->sbproptime, enable);
4661  SCIPclockEnableOrDisable(conshdlr->sepatime, enable);
4662 }
4663 
4664 /** gets time in seconds used for setting up this constraint handler for new stages */
4666  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4667  )
4668 {
4669  assert(conshdlr != NULL);
4670 
4671  return SCIPclockGetTime(conshdlr->setuptime);
4672 }
4673 
4674 /** gets time in seconds used for presolving in this constraint handler */
4676  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4677  )
4678 {
4679  assert(conshdlr != NULL);
4680 
4681  return SCIPclockGetTime(conshdlr->presoltime);
4682 }
4683 
4684 /** gets time in seconds used for separation in this constraint handler */
4686  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4687  )
4688 {
4689  assert(conshdlr != NULL);
4690 
4691  return SCIPclockGetTime(conshdlr->sepatime);
4692 }
4693 
4694 /** gets time in seconds used for LP enforcement in this constraint handler */
4696  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4697  )
4698 {
4699  assert(conshdlr != NULL);
4700 
4701  return SCIPclockGetTime(conshdlr->enfolptime);
4702 }
4703 
4704 /** gets time in seconds used for pseudo enforcement in this constraint handler */
4706  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4707  )
4708 {
4709  assert(conshdlr != NULL);
4710 
4711  return SCIPclockGetTime(conshdlr->enfopstime);
4712 }
4713 
4714 /** gets time in seconds used for relaxation enforcement in this constraint handler */
4716  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4717  )
4718 {
4719  assert(conshdlr != NULL);
4720 
4721  return SCIPclockGetTime(conshdlr->enforelaxtime);
4722 }
4723 
4724 /** gets time in seconds used for propagation in this constraint handler */
4726  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4727  )
4728 {
4729  assert(conshdlr != NULL);
4730 
4731  return SCIPclockGetTime(conshdlr->proptime);
4732 }
4733 
4734 /** gets time in seconds used for propagation in this constraint handler during strong branching */
4736  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4737  )
4738 {
4739  assert(conshdlr != NULL);
4740 
4741  return SCIPclockGetTime(conshdlr->sbproptime);
4742 }
4743 
4744 /** gets time in seconds used for feasibility checking in this constraint handler */
4746  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4747  )
4748 {
4749  assert(conshdlr != NULL);
4750 
4751  return SCIPclockGetTime(conshdlr->checktime);
4752 }
4753 
4754 /** gets time in seconds used for resolving propagation in this constraint handler */
4756  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4757  )
4758 {
4759  assert(conshdlr != NULL);
4760 
4761  return SCIPclockGetTime(conshdlr->resproptime);
4762 }
4763 
4764 /** gets number of calls to the constraint handler's separation method */
4766  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4767  )
4768 {
4769  assert(conshdlr != NULL);
4770 
4771  return conshdlr->nsepacalls;
4772 }
4773 
4774 /** gets number of calls to the constraint handler's LP enforcing method */
4776  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4777  )
4778 {
4779  assert(conshdlr != NULL);
4780 
4781  return conshdlr->nenfolpcalls;
4782 }
4783 
4784 /** gets number of calls to the constraint handler's pseudo enforcing method */
4786  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4787  )
4788 {
4789  assert(conshdlr != NULL);
4790 
4791  return conshdlr->nenfopscalls;
4792 }
4793 
4794 /** gets number of calls to the constraint handler's relaxation enforcing method */
4796  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4797  )
4798 {
4799  assert(conshdlr != NULL);
4800 
4801  return conshdlr->nenforelaxcalls;
4802 }
4803 
4804 /** gets number of calls to the constraint handler's propagation method */
4806  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4807  )
4808 {
4809  assert(conshdlr != NULL);
4810 
4811  return conshdlr->npropcalls;
4812 }
4813 
4814 /** gets number of calls to the constraint handler's checking method */
4816  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4817  )
4818 {
4819  assert(conshdlr != NULL);
4820 
4821  return conshdlr->ncheckcalls;
4822 }
4823 
4824 /** gets number of calls to the constraint handler's resolve propagation method */
4826  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4827  )
4828 {
4829  assert(conshdlr != NULL);
4830 
4831  return conshdlr->nrespropcalls;
4832 }
4833 
4834 /** gets total number of times, this constraint handler detected a cutoff */
4836  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4837  )
4838 {
4839  assert(conshdlr != NULL);
4840 
4841  return conshdlr->ncutoffs;
4842 }
4843 
4844 /** gets total number of cuts found by this constraint handler */
4846  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4847  )
4848 {
4849  assert(conshdlr != NULL);
4850 
4851  return conshdlr->ncutsfound;
4852 }
4853 
4854 /** gets total number of cuts found by this constraint handler applied to lp */
4856  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4857  )
4858 {
4859  assert(conshdlr != NULL);
4860 
4861  return conshdlr->ncutsapplied;
4862 }
4863 
4864 /** increase count of applied cuts */
4866  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4867  )
4868 {
4869  assert(conshdlr != NULL);
4870 
4871  ++conshdlr->ncutsapplied;
4872 }
4873 
4874 /** increase count of found cuts */
4876  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4877  )
4878 {
4879  assert(conshdlr != NULL);
4880 
4881  ++conshdlr->ncutsfound;
4882 }
4883 
4884 /** gets total number of additional constraints added by this constraint handler */
4886  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4887  )
4888 {
4889  assert(conshdlr != NULL);
4890 
4891  return conshdlr->nconssfound;
4892 }
4893 
4894 /** gets total number of domain reductions found by this constraint handler */
4896  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4897  )
4898 {
4899  assert(conshdlr != NULL);
4900 
4901  return conshdlr->ndomredsfound;
4902 }
4903 
4904 /** gets number of children created by this constraint handler */
4906  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4907  )
4908 {
4909  assert(conshdlr != NULL);
4910 
4911  return conshdlr->nchildren;
4912 }
4913 
4914 /** gets maximum number of active constraints of constraint handler existing at the same time */
4916  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4917  )
4918 {
4919  assert(conshdlr != NULL);
4920 
4921  return conshdlr->maxnactiveconss;
4922 }
4923 
4924 /** gets initial number of active constraints of constraint handler */
4926  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4927  )
4928 {
4929  assert(conshdlr != NULL);
4930 
4931  return conshdlr->startnactiveconss;
4932 }
4933 
4934 /** gets number of variables fixed in presolving method of constraint handler */
4936  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4937  )
4938 {
4939  assert(conshdlr != NULL);
4940 
4941  return conshdlr->nfixedvars;
4942 }
4943 
4944 /** gets number of variables aggregated in presolving method of constraint handler */
4946  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4947  )
4948 {
4949  assert(conshdlr != NULL);
4950 
4951  return conshdlr->naggrvars;
4952 }
4953 
4954 /** gets number of variable types changed in presolving method of constraint handler */
4956  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4957  )
4958 {
4959  assert(conshdlr != NULL);
4960 
4961  return conshdlr->nchgvartypes;
4962 }
4963 
4964 /** gets number of bounds changed in presolving method of constraint handler */
4966  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4967  )
4968 {
4969  assert(conshdlr != NULL);
4970 
4971  return conshdlr->nchgbds;
4972 }
4973 
4974 /** gets number of holes added to domains of variables in presolving method of constraint handler */
4976  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4977  )
4978 {
4979  assert(conshdlr != NULL);
4980 
4981  return conshdlr->naddholes;
4982 }
4983 
4984 /** gets number of constraints deleted in presolving method of constraint handler */
4986  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4987  )
4988 {
4989  assert(conshdlr != NULL);
4990 
4991  return conshdlr->ndelconss;
4992 }
4993 
4994 /** gets number of constraints added in presolving method of constraint handler */
4996  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4997  )
4998 {
4999  assert(conshdlr != NULL);
5000 
5001  return conshdlr->naddconss;
5002 }
5003 
5004 /** gets number of constraints upgraded in presolving method of constraint handler */
5006  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5007  )
5008 {
5009  assert(conshdlr != NULL);
5010 
5011  return conshdlr->nupgdconss;
5012 }
5013 
5014 /** gets number of coefficients changed in presolving method of constraint handler */
5016  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5017  )
5018 {
5019  assert(conshdlr != NULL);
5020 
5021  return conshdlr->nchgcoefs;
5022 }
5023 
5024 /** gets number of constraint sides changed in presolving method of constraint handler */
5026  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5027  )
5028 {
5029  assert(conshdlr != NULL);
5030 
5031  return conshdlr->nchgsides;
5032 }
5033 
5034 /** gets number of times the presolving method of the constraint handler was called and tried to find reductions */
5036  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5037  )
5038 {
5039  assert(conshdlr != NULL);
5040 
5041  return conshdlr->npresolcalls;
5042 }
5043 
5044 /** gets separation priority of constraint handler */
5046  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5047  )
5048 {
5049  assert(conshdlr != NULL);
5050 
5051  return conshdlr->sepapriority;
5052 }
5053 
5054 /** gets enforcing priority of constraint handler */
5056  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5057  )
5058 {
5059  assert(conshdlr != NULL);
5060 
5061  return conshdlr->enfopriority;
5062 }
5063 
5064 /** gets checking priority of constraint handler */
5066  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5067  )
5068 {
5069  assert(conshdlr != NULL);
5070 
5071  return conshdlr->checkpriority;
5072 }
5073 
5074 /** gets separation frequency of constraint handler */
5076  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5077  )
5078 {
5079  assert(conshdlr != NULL);
5080 
5081  return conshdlr->sepafreq;
5082 }
5083 
5084 /** gets propagation frequency of constraint handler */
5086  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5087  )
5088 {
5089  assert(conshdlr != NULL);
5090 
5091  return conshdlr->propfreq;
5092 }
5093 
5094 /** gets frequency of constraint handler for eager evaluations in separation, propagation and enforcement */
5096  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5097  )
5098 {
5099  assert(conshdlr != NULL);
5100 
5101  return conshdlr->eagerfreq;
5102 }
5103 
5104 /** needs constraint handler a constraint to be called? */
5106  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5107  )
5108 {
5109  assert(conshdlr != NULL);
5110 
5111  return conshdlr->needscons;
5112 }
5113 
5114 /** does the constraint handler perform presolving? */
5116  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5117  )
5118 {
5119  assert(conshdlr != NULL);
5120 
5121  return (conshdlr->conspresol != NULL);
5122 }
5123 
5124 /** should separation method be delayed, if other separators found cuts? */
5126  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5127  )
5128 {
5129  assert(conshdlr != NULL);
5130 
5131  return conshdlr->delaysepa;
5132 }
5133 
5134 /** should propagation method be delayed, if other propagators found reductions? */
5136  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5137  )
5138 {
5139  assert(conshdlr != NULL);
5140 
5141  return conshdlr->delayprop;
5142 }
5143 
5144 /** was LP separation method delayed at the last call? */
5146  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5147  )
5148 {
5149  assert(conshdlr != NULL);
5150 
5151  return conshdlr->sepalpwasdelayed;
5152 }
5153 
5154 /** was primal solution separation method delayed at the last call? */
5156  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5157  )
5158 {
5159  assert(conshdlr != NULL);
5160 
5161  return conshdlr->sepasolwasdelayed;
5162 }
5163 
5164 /** was propagation method delayed at the last call? */
5166  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5167  )
5168 {
5169  assert(conshdlr != NULL);
5170 
5171  return conshdlr->propwasdelayed;
5172 }
5173 
5174 /** is constraint handler initialized? */
5176  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5177  )
5178 {
5179  assert(conshdlr != NULL);
5180 
5181  return conshdlr->initialized;
5182 }
5183 
5184 /** does the constraint handler have a copy function? */
5186  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5187  )
5188 {
5189  assert(conshdlr != NULL);
5190 
5191  return (conshdlr->conshdlrcopy != NULL);
5192 }
5193 
5194 /** returns the timing mask of the propagation method of the constraint handler */
5196  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5197  )
5198 {
5199  assert(conshdlr != NULL);
5200 
5201  return conshdlr->proptiming;
5202 }
5203 
5204 /** sets the timing mask of the propagation method of the constraint handler */
5206  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
5207  SCIP_PROPTIMING proptiming /**< timing mask to be set */
5208  )
5209 {
5210  assert(conshdlr != NULL);
5211 
5212  conshdlr->proptiming = proptiming;
5213 }
5214 
5215 
5216 /** returns the timing mask of the presolving method of the constraint handler */
5218  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5219  )
5220 {
5221  assert(conshdlr != NULL);
5222 
5223  return conshdlr->presoltiming;
5224 }
5225 
5226 /** sets the timing mask of the presolving method of the constraint handler */
5228  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
5229  SCIP_PRESOLTIMING presoltiming /** timing mask to be set */
5230  )
5231 {
5232  assert(conshdlr != NULL);
5233 
5234  conshdlr->presoltiming = presoltiming;
5235 }
5236 
5237 
5238 /*
5239  * Constraint set change methods
5240  */
5241 
5242 /** creates empty constraint set change data */
5243 static
5245  SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change data */
5246  BMS_BLKMEM* blkmem /**< block memory */
5247  )
5248 {
5249  assert(conssetchg != NULL);
5250  assert(blkmem != NULL);
5251 
5252  SCIP_ALLOC( BMSallocBlockMemory(blkmem, conssetchg) );
5253  (*conssetchg)->addedconss = NULL;
5254  (*conssetchg)->disabledconss = NULL;
5255  (*conssetchg)->addedconsssize = 0;
5256  (*conssetchg)->naddedconss = 0;
5257  (*conssetchg)->disabledconsssize = 0;
5258  (*conssetchg)->ndisabledconss = 0;
5259 
5260  return SCIP_OKAY;
5261 }
5262 
5263 /** releases all constraints of the constraint set change data */
5264 static
5266  SCIP_CONSSETCHG* conssetchg, /**< constraint set change data */
5267  BMS_BLKMEM* blkmem, /**< block memory */
5268  SCIP_SET* set /**< global SCIP settings */
5269  )
5270 {
5271  int i;
5272 
5273  assert(conssetchg != NULL);
5274 
5275  /* release constraints */
5276  for( i = 0; i < conssetchg->naddedconss; ++i )
5277  {
5278  if( conssetchg->addedconss[i] != NULL )
5279  {
5280  SCIP_CALL( SCIPconsRelease(&conssetchg->addedconss[i], blkmem, set) );
5281  }
5282  }
5283  for( i = 0; i < conssetchg->ndisabledconss; ++i )
5284  {
5285  if( conssetchg->disabledconss[i] != NULL )
5286  {
5287  SCIP_CALL( SCIPconsRelease(&conssetchg->disabledconss[i], blkmem, set) );
5288  }
5289  }
5290 
5291  return SCIP_OKAY;
5292 }
5293 
5294 /** frees constraint set change data and releases all included constraints */
5296  SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change */
5297  BMS_BLKMEM* blkmem, /**< block memory */
5298  SCIP_SET* set /**< global SCIP settings */
5299  )
5300 {
5301  assert(conssetchg != NULL);
5302  assert(blkmem != NULL);
5303 
5304  if( *conssetchg != NULL )
5305  {
5306  /* release constraints */
5307  SCIP_CALL( conssetchgRelease(*conssetchg, blkmem, set) );
5308 
5309  /* free memory */
5310  BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->addedconss, (*conssetchg)->addedconsssize);
5311  BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->disabledconss, (*conssetchg)->disabledconsssize);
5312  BMSfreeBlockMemory(blkmem, conssetchg);
5313  }
5314 
5315  return SCIP_OKAY;
5316 }
5317 
5318 /** ensures, that addedconss array can store at least num entries */
5319 static
5321  SCIP_CONSSETCHG* conssetchg, /**< constraint set change data structure */
5322  BMS_BLKMEM* blkmem, /**< block memory */
5323  SCIP_SET* set, /**< global SCIP settings */
5324  int num /**< minimum number of entries to store */
5325  )
5326 {
5327  assert(conssetchg != NULL);
5328 
5329  if( num > conssetchg->addedconsssize )
5330  {
5331  int newsize;
5332 
5333  newsize = SCIPsetCalcMemGrowSize(set, num);
5334  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conssetchg->addedconss, conssetchg->addedconsssize, newsize) );
5335  conssetchg->addedconsssize = newsize;
5336  }
5337  assert(num <= conssetchg->addedconsssize);
5338 
5339  return SCIP_OKAY;
5340 }
5341 
5342 /** ensures, that disabledconss array can store at least num entries */
5343 static
5345  SCIP_CONSSETCHG* conssetchg, /**< constraint set change data structure */
5346  BMS_BLKMEM* blkmem,