Scippy

SCIP

Solving Constraint Integer Programs

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