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