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  conshdlr->nenforelaxcalls++;
3278  if( *result == SCIP_CUTOFF )
3279  conshdlr->ncutoffs++;
3280  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3281  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3282 
3283  if( *result != SCIP_BRANCHED )
3284  {
3285  assert(tree->nchildren == 0);
3286 
3287  /* update domain reductions; therefore remove the domain
3288  * reduction counts which were generated in probing mode */
3289  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3290  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3291  }
3292  else
3293  conshdlr->nchildren += tree->nchildren;
3294 
3295  /* remember the result of the enforcement call */
3296  conshdlr->lastenforelaxresult = *result;
3297 
3298  /* evaluate result */
3299  if( *result != SCIP_CUTOFF
3300  && *result != SCIP_CONSADDED
3301  && *result != SCIP_REDUCEDDOM
3302  && *result != SCIP_SEPARATED
3303  && *result != SCIP_BRANCHED
3304  && *result != SCIP_SOLVELP
3305  && *result != SCIP_INFEASIBLE
3306  && *result != SCIP_FEASIBLE )
3307  {
3308  SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation solutions returned invalid result <%d>\n",
3309  conshdlr->name, *result);
3310  return SCIP_INVALIDRESULT;
3311  }
3312 
3313  /* if the same relaxation solution was already enforced at this node, we only enforced new constraints this time;
3314  * if the enforelax call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3315  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3316  */
3317  if( lastinfeasible && *result == SCIP_FEASIBLE )
3318  *result = SCIP_INFEASIBLE;
3319  }
3320 
3321  return SCIP_OKAY;
3322 }
3323 
3324 /** calls enforcing method of constraint handler for LP solution for all constraints added after last
3325  * conshdlrResetEnfo() call
3326  */
3328  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3329  BMS_BLKMEM* blkmem, /**< block memory */
3330  SCIP_SET* set, /**< global SCIP settings */
3331  SCIP_STAT* stat, /**< dynamic problem statistics */
3332  SCIP_TREE* tree, /**< branch and bound tree */
3333  SCIP_SEPASTORE* sepastore, /**< separation storage */
3334  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3335  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3336  )
3337 {
3338  assert(conshdlr != NULL);
3339  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3340  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3341  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3342  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3343  assert(stat != NULL);
3344  assert(conshdlr->lastenfolplpcount != stat->lpcount
3345  || conshdlr->lastenfolpdomchgcount != stat->domchgcount
3346  || conshdlr->lastenfolpnode != stat->nnodes
3347  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3348  assert(set != NULL);
3349  assert(tree != NULL);
3350  assert(tree->nchildren == 0);
3351  assert(result != NULL);
3352 
3353  *result = SCIP_FEASIBLE;
3354 
3355  if( conshdlr->consenfolp != NULL )
3356  {
3357  int nconss;
3358  int nusefulconss;
3359  int firstcons;
3360  SCIP_Bool lpchanged;
3361  SCIP_Bool lastinfeasible;
3362 
3363  /* check, if this LP solution was already enforced at this node */
3364  if( conshdlr->lastenfolplpcount == stat->lpcount
3365  && conshdlr->lastenfolpdomchgcount == stat->domchgcount
3366  && conshdlr->lastenfolpnode == stat->nnodes
3367  && conshdlr->lastenfolpresult != SCIP_CONSADDED )
3368  {
3369  assert(conshdlr->lastenfolpresult == SCIP_FEASIBLE || conshdlr->lastenfolpresult == SCIP_INFEASIBLE
3370  || conshdlr->lastenfolpresult == SCIP_SEPARATED );
3371 
3372  /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3373  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3374  * that an infeasibility in the last call is not lost because we only enforce new constraints
3375  */
3376  if( conshdlr->lastenfolpresult == SCIP_FEASIBLE )
3377  lastinfeasible = FALSE;
3378  else
3379  {
3380  assert(conshdlr->lastenfolpresult == SCIP_INFEASIBLE || conshdlr->lastenfolpresult == SCIP_SEPARATED);
3381  *result = SCIP_INFEASIBLE;
3382  lastinfeasible = TRUE;
3383  }
3384 
3385  /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3386  * that the new constraints are the last constraints of the useful ones
3387  */
3388  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3389  nusefulconss = nconss;
3390  firstcons = conshdlr->lastnusefulenfoconss;
3391  lpchanged = FALSE;
3392  }
3393  else
3394  {
3395  /* on a new LP solution or a new node, we want to enforce all constraints */
3396  nconss = conshdlr->nenfoconss;
3397  nusefulconss = conshdlr->nusefulenfoconss;
3398  firstcons = 0;
3399  lpchanged = TRUE;
3400  lastinfeasible = FALSE;
3401  }
3402  assert(firstcons >= 0);
3403  assert(firstcons + nconss <= conshdlr->nenfoconss);
3404  assert(nusefulconss <= nconss);
3405 
3406  /* constraint handlers without constraints should only be called once */
3407  if( nconss > 0 || (!conshdlr->needscons && lpchanged) )
3408  {
3409  SCIP_CONS** conss;
3410  SCIP_Longint oldndomchgs;
3411  SCIP_Longint oldnprobdomchgs;
3412  int oldncuts;
3413  int oldnactiveconss;
3414 
3415  SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n",
3416  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, lpchanged ? "new" : "old");
3417 
3418  /* remember the number of processed constraints on the current LP solution */
3419  conshdlr->lastenfolplpcount = stat->lpcount;
3420  conshdlr->lastenfolpdomchgcount = stat->domchgcount;
3421  conshdlr->lastenfolpnode = stat->nnodes;
3422  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3423 
3424  /* get the array of the constraints to be processed */
3425  conss = &(conshdlr->enfoconss[firstcons]);
3426 
3427  oldncuts = SCIPsepastoreGetNCuts(sepastore);
3428  oldnactiveconss = stat->nactiveconss;
3429  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3430  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3431 
3432  /* check, if we want to use eager evaluation */
3433  if( (conshdlr->eagerfreq == 0 && conshdlr->nenfolpcalls == 0)
3434  || (conshdlr->eagerfreq > 0 && conshdlr->nenfolpcalls % conshdlr->eagerfreq == 0) )
3435  nusefulconss = nconss;
3436 
3437  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3438  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3439  * external method; to avoid this, these changes will be buffered and processed after the method call
3440  */
3441  conshdlrDelayUpdates(conshdlr);
3442 
3443  /* start timing */
3444  SCIPclockStart(conshdlr->enfolptime, set);
3445 
3446  /* call external method */
3447  SCIP_CALL( conshdlr->consenfolp(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) );
3448  SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3449 
3450  /* stop timing */
3451  SCIPclockStop(conshdlr->enfolptime, set);
3452 
3453  /* perform the cached constraint updates */
3454  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3455 
3456  /* remember the result of the enforcement call */
3457  conshdlr->lastenfolpresult = *result;
3458 
3459  /* update statistics */
3460  conshdlr->nenfolpcalls++;
3461  if( *result == SCIP_CUTOFF )
3462  conshdlr->ncutoffs++;
3463  conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3464  conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3465  if( *result != SCIP_BRANCHED )
3466  {
3467  assert(tree->nchildren == 0);
3468 
3469  /* update domain reductions; therefore remove the domain
3470  * reduction counts which were generated in probing mode */
3471  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3472  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3473  }
3474  else
3475  conshdlr->nchildren += tree->nchildren;
3476 
3477  /* evaluate result */
3478  if( *result != SCIP_CUTOFF
3479  && *result != SCIP_CONSADDED
3480  && *result != SCIP_REDUCEDDOM
3481  && *result != SCIP_SEPARATED
3482  && *result != SCIP_SOLVELP
3483  && *result != SCIP_BRANCHED
3484  && *result != SCIP_INFEASIBLE
3485  && *result != SCIP_FEASIBLE )
3486  {
3487  SCIPerrorMessage("enforcing method of constraint handler <%s> for LP solutions returned invalid result <%d>\n",
3488  conshdlr->name, *result);
3489  return SCIP_INVALIDRESULT;
3490  }
3491 
3492  /* if the same LP solution was already enforced at this node, we only enforced new constraints this time;
3493  * if the enfolp call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3494  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3495  */
3496  if( lastinfeasible && *result == SCIP_FEASIBLE )
3497  *result = SCIP_INFEASIBLE;
3498  }
3499  }
3500 
3501  return SCIP_OKAY;
3502 }
3503 
3504 /** calls diving solution enforcement callback of constraint handler, if it exists */
3506  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3507  SCIP_SET* set, /**< global SCIP settings */
3508  SCIP_DIVESET* diveset, /**< diving settings to control scoring */
3509  SCIP_SOL* sol, /**< current solution of diving mode */
3510  SCIP_Bool* success, /**< pointer to store whether constraint handler successfully found a variable */
3511  SCIP_Bool* infeasible /**< pointer to store whether the current node was detected to be infeasible */
3512  )
3513 {
3514  assert(conshdlr != NULL);
3515  assert(set != NULL);
3516  assert(diveset != NULL);
3517  assert(sol != NULL);
3518  assert(success != NULL);
3519  assert(infeasible != NULL);
3520 
3521  if( conshdlr->consgetdivebdchgs != NULL )
3522  {
3523  SCIP_CALL( conshdlr->consgetdivebdchgs(set->scip, conshdlr, diveset, sol, success, infeasible) );
3524  }
3525 
3526  return SCIP_OKAY;
3527 }
3528 
3529 /** calls enforcing method of constraint handler for pseudo solution for all constraints added after last
3530  * conshdlrResetEnfo() call
3531  */
3533  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3534  BMS_BLKMEM* blkmem, /**< block memory */
3535  SCIP_SET* set, /**< global SCIP settings */
3536  SCIP_STAT* stat, /**< dynamic problem statistics */
3537  SCIP_TREE* tree, /**< branch and bound tree */
3538  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3539  SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */
3540  SCIP_Bool objinfeasible, /**< is the solution infeasible anyway due to violating lower objective bound? */
3541  SCIP_Bool forced, /**< should enforcement of pseudo solution be forced? */
3542  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3543  )
3544 {
3545  assert(conshdlr != NULL);
3546  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3547  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3548  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3549  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3550  assert(stat != NULL);
3551  assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount
3552  || conshdlr->lastenfopsnode != stat->nnodes
3553  || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3554  assert(set != NULL);
3555  assert(tree != NULL);
3556  assert(tree->nchildren == 0);
3557  assert(result != NULL);
3558 
3559  /* no enforcing of pseudo solution */
3560  if( set->cons_disableenfops && SCIPbranchcandGetNPseudoCands(branchcand) > 0 )
3561  {
3562  *result = SCIP_INFEASIBLE;
3563  return SCIP_OKAY;
3564  }
3565 
3566  *result = SCIP_FEASIBLE;
3567  if( conshdlr->consenfops != NULL )
3568  {
3569  int nconss;
3570  int nusefulconss;
3571  int firstcons;
3572  SCIP_Bool pschanged;
3573  SCIP_Bool lastinfeasible;
3574 
3575  /* check, if this pseudo solution was already enforced at this node */
3576  if( !forced && conshdlr->lastenfopsdomchgcount == stat->domchgcount
3577  && conshdlr->lastenfopsnode == stat->nnodes
3578  && conshdlr->lastenfopsresult != SCIP_CONSADDED
3579  && conshdlr->lastenfopsresult != SCIP_SOLVELP
3580  )
3581  {
3582  assert(conshdlr->lastenfopsresult != SCIP_CUTOFF);
3583  assert(conshdlr->lastenfopsresult != SCIP_BRANCHED);
3584  assert(conshdlr->lastenfopsresult != SCIP_REDUCEDDOM);
3585  assert(conshdlr->lastenfopsresult != SCIP_DIDNOTRUN || objinfeasible);
3586 
3587  /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3588  * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3589  * that an infeasibility in the last call is not lost because we only enforce new constraints
3590  */
3591  if( conshdlr->lastenfopsresult == SCIP_INFEASIBLE )
3592  {
3593  *result = SCIP_INFEASIBLE;
3594  lastinfeasible = TRUE;
3595  }
3596  else
3597  lastinfeasible = FALSE;
3598 
3599  /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3600  * that the new constraints are the last constraints of the useful ones
3601  */
3602  nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3603  nusefulconss = nconss;
3604  firstcons = conshdlr->lastnusefulenfoconss;
3605  pschanged = FALSE;
3606  }
3607  else
3608  {
3609  /* on a new pseudo solution or a new node, we want to enforce all constraints */
3610  nconss = conshdlr->nenfoconss;
3611  nusefulconss = conshdlr->nusefulenfoconss;
3612  firstcons = 0;
3613  pschanged = TRUE;
3614  lastinfeasible = FALSE;
3615  }
3616  assert(firstcons >= 0);
3617  assert(firstcons + nconss <= conshdlr->nenfoconss);
3618  assert(nusefulconss <= nconss);
3619 
3620  /* constraint handlers without constraints should only be called once */
3621  if( nconss > 0 || (!conshdlr->needscons && pschanged) )
3622  {
3623  SCIP_CONS** conss;
3624  SCIP_Longint oldndomchgs;
3625  SCIP_Longint oldnprobdomchgs;
3626 
3627  SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, objinfeasible=%u)\n",
3628  firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, pschanged ? "new" : "old", objinfeasible);
3629 
3630  /* remember the number of processed constraints on the current pseudo solution */
3631  conshdlr->lastenfopsdomchgcount = stat->domchgcount;
3632  conshdlr->lastenfopsnode = stat->nnodes;
3633  conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3634 
3635  /* get the array of the constraints to be processed */
3636  conss = &(conshdlr->enfoconss[firstcons]);
3637 
3638  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3639  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3640 
3641  /* check, if we want to use eager evaluation */
3642  if( (conshdlr->eagerfreq == 0 && conshdlr->nenfopscalls == 0)
3643  || (conshdlr->eagerfreq > 0 && conshdlr->nenfopscalls % conshdlr->eagerfreq == 0) )
3644  nusefulconss = nconss;
3645 
3646  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3647  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3648  * external method; to avoid this, these changes will be buffered and processed after the method call
3649  */
3650  conshdlrDelayUpdates(conshdlr);
3651 
3652  /* start timing */
3653  SCIPclockStart(conshdlr->enfopstime, set);
3654 
3655  /* call external method */
3656  SCIP_CALL( conshdlr->consenfops(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, objinfeasible, result) );
3657  SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3658 
3659  /* stop timing */
3660  SCIPclockStop(conshdlr->enfopstime, set);
3661 
3662  /* perform the cached constraint updates */
3663  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3664 
3665  /* update statistics */
3666  if( *result != SCIP_DIDNOTRUN )
3667  conshdlr->nenfopscalls++;
3668  else if( !objinfeasible )
3669  {
3670  SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions was skipped, even though the solution was not objective-infeasible\n",
3671  conshdlr->name);
3672  conshdlr->lastenfopsresult = *result;
3673 
3674  return SCIP_INVALIDRESULT;
3675  }
3676  /* A constraint handler might return SCIP_DIDNOTRUN and not check any constraints in case objinfeasible was
3677  * TRUE; we change the result pointer to SCIP_INFEASIBLE in this case.
3678  */
3679  else
3680  *result = SCIP_INFEASIBLE;
3681 
3682  if( *result == SCIP_CUTOFF )
3683  conshdlr->ncutoffs++;
3684 
3685  if( *result != SCIP_BRANCHED )
3686  {
3687  assert(tree->nchildren == 0);
3688 
3689  /* update domain reductions; therefore remove the domain
3690  * reduction counts which were generated in probing mode */
3691  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3692  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3693  }
3694  else
3695  conshdlr->nchildren += tree->nchildren;
3696 
3697  /* remember the result of the enforcement call */
3698  conshdlr->lastenfopsresult = *result;
3699 
3700  /* evaluate result */
3701  if( *result != SCIP_CUTOFF
3702  && *result != SCIP_CONSADDED
3703  && *result != SCIP_REDUCEDDOM
3704  && *result != SCIP_BRANCHED
3705  && *result != SCIP_SOLVELP
3706  && *result != SCIP_INFEASIBLE
3707  && *result != SCIP_FEASIBLE
3708  && *result != SCIP_DIDNOTRUN )
3709  {
3710  SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions returned invalid result <%d>\n",
3711  conshdlr->name, *result);
3712  return SCIP_INVALIDRESULT;
3713  }
3714 
3715  /* if the same pseudo solution was already enforced at this node, we only enforced new constraints this time;
3716  * if the enfops call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3717  * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3718  */
3719  if( lastinfeasible && *result == SCIP_FEASIBLE )
3720  *result = SCIP_INFEASIBLE;
3721  }
3722  }
3723 
3724  return SCIP_OKAY;
3725 }
3726 
3727 /** calls feasibility check method of constraint handler */
3729  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3730  BMS_BLKMEM* blkmem, /**< block memory */
3731  SCIP_SET* set, /**< global SCIP settings */
3732  SCIP_STAT* stat, /**< dynamic problem statistics */
3733  SCIP_SOL* sol, /**< primal CIP solution */
3734  SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
3735  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
3736  SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
3737  SCIP_Bool completely, /**< Should all violations be checked? */
3738  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3739  )
3740 {
3741  assert(conshdlr != NULL);
3742  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3743  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3744  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3745  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3746  assert(set != NULL);
3747  assert(result != NULL);
3748 
3749  *result = SCIP_FEASIBLE;
3750 
3751  if( conshdlr->conscheck != NULL && (!conshdlr->needscons || conshdlr->ncheckconss > 0) )
3752  {
3753  SCIPsetDebugMsg(set, "checking %d constraints of handler <%s>\n", conshdlr->ncheckconss, conshdlr->name);
3754 
3755  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3756  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3757  * external method; to avoid this, these changes will be buffered and processed after the method call
3758  */
3759  conshdlrDelayUpdates(conshdlr);
3760 
3761  /* start timing */
3762  SCIPclockStart(conshdlr->checktime, set);
3763 
3764  /* call external method */
3765  SCIP_CALL( conshdlr->conscheck(set->scip, conshdlr, conshdlr->checkconss, conshdlr->ncheckconss,
3766  sol, checkintegrality, checklprows, printreason, completely, result) );
3767  SCIPsetDebugMsg(set, " -> checking returned result <%d>\n", *result);
3768 
3769  /* stop timing */
3770  SCIPclockStop(conshdlr->checktime, set);
3771 
3772  /* update statistics */
3773  conshdlr->ncheckcalls++;
3774 
3775  /* perform the cached constraint updates */
3776  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3777 
3778  /* evaluate result */
3779  if( *result != SCIP_INFEASIBLE && *result != SCIP_FEASIBLE )
3780  {
3781  SCIPerrorMessage("feasibility check of constraint handler <%s> returned invalid result <%d>\n", conshdlr->name, *result);
3782  return SCIP_INVALIDRESULT;
3783  }
3784  }
3785 
3786  return SCIP_OKAY;
3787 }
3788 
3789 /** calls propagation method of constraint handler */
3791  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3792  BMS_BLKMEM* blkmem, /**< block memory */
3793  SCIP_SET* set, /**< global SCIP settings */
3794  SCIP_STAT* stat, /**< dynamic problem statistics */
3795  int depth, /**< depth of current node */
3796  SCIP_Bool fullpropagation, /**< should all constraints be propagated (or only new ones)? */
3797  SCIP_Bool execdelayed, /**< execute propagation method even if it is marked to be delayed */
3798  SCIP_Bool instrongbranching, /**< are we currently doing strong branching? */
3799  SCIP_PROPTIMING proptiming, /**< current point in the node solving process */
3800  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3801  )
3802 {
3803  assert(conshdlr != NULL);
3804  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3805  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3806  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3807  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3808  assert(stat != NULL);
3809  assert(conshdlr->lastpropdomchgcount != stat->domchgcount
3810  || (0 <= conshdlr->lastnusefulpropconss && conshdlr->lastnusefulpropconss <= conshdlr->nusefulpropconss));
3811  assert(set != NULL);
3812  assert(depth >= 0);
3813  assert(result != NULL);
3814 
3815  *result = SCIP_DIDNOTRUN;
3816 
3817  if( conshdlr->consprop != NULL
3818  && (!conshdlr->needscons || conshdlr->npropconss > 0)
3819  && ((depth == 0 && conshdlr->propfreq == 0)
3820  || (conshdlr->propfreq > 0 && depth % conshdlr->propfreq == 0)
3821  || conshdlr->propwasdelayed) )
3822  {
3823  /* check, if propagation method should be delayed */
3824  if( !conshdlr->delayprop || execdelayed )
3825  {
3826  int nconss;
3827  int nusefulconss;
3828  int nmarkedpropconss;
3829  int firstcons;
3830 
3831  /* check, if the current domains were already propagated */
3832  if( !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount && conshdlr->nmarkedpropconss == 0 )
3833  {
3834  /* all constraints that were not yet propagated on the new domains must be useful constraints, which means,
3835  * that the new constraints are the last constraints of the useful ones
3836  */
3837  nconss = conshdlr->nusefulpropconss - conshdlr->lastnusefulpropconss;
3838  nusefulconss = nconss;
3839  firstcons = conshdlr->lastnusefulpropconss;
3840  }
3841  else
3842  {
3843  /* on new domains, we want to propagate all constraints */
3844  nconss = conshdlr->npropconss;
3845  nusefulconss = conshdlr->nusefulpropconss;
3846  firstcons = 0;
3847  }
3848  assert(firstcons >= 0);
3849  assert(firstcons + nconss <= conshdlr->npropconss);
3850  assert(nusefulconss <= nconss);
3851 
3852  nmarkedpropconss = conshdlr->nmarkedpropconss;
3853 
3854  /* constraint handlers without constraints should only be called once */
3855  if( nconss > 0 || fullpropagation
3856  || (!conshdlr->needscons && conshdlr->lastpropdomchgcount != stat->domchgcount) )
3857  {
3858  SCIP_CONS** conss;
3859  SCIP_Longint oldndomchgs;
3860  SCIP_Longint oldnprobdomchgs;
3861  SCIP_Longint lastpropdomchgcount;
3862  int lastnusefulpropconss;
3863 
3864  SCIPsetDebugMsg(set, "propagating constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, %d useful)\n",
3865  firstcons, firstcons + nconss - 1, conshdlr->npropconss, conshdlr->name,
3866  !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount ? "old" : "new", nusefulconss);
3867 
3868  /* remember the number of processed constraints on the current domains */
3869  lastpropdomchgcount = stat->domchgcount;
3870  lastnusefulpropconss = conshdlr->nusefulpropconss;
3871 
3872  /* get the array of the constraints to be processed */
3873  conss = &(conshdlr->propconss[firstcons]);
3874 
3875  oldndomchgs = stat->nboundchgs + stat->nholechgs;
3876  oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3877 
3878  /* check, if we want to use eager evaluation */
3879  if( (conshdlr->eagerfreq == 0 && conshdlr->npropcalls == 0)
3880  || (conshdlr->eagerfreq > 0 && conshdlr->npropcalls % conshdlr->eagerfreq == 0) )
3881  nusefulconss = nconss;
3882 
3883  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3884  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3885  * external method; to avoid this, these changes will be buffered and processed after the method call
3886  */
3887  conshdlrDelayUpdates(conshdlr);
3888  conshdlr->duringprop = TRUE;
3889 
3890  /* start timing */
3891  if( instrongbranching )
3892  SCIPclockStart(conshdlr->sbproptime, set);
3893  else
3894  SCIPclockStart(conshdlr->proptime, set);
3895 
3896  assert(nusefulconss <= nconss);
3897  assert(nmarkedpropconss <= nconss);
3898 
3899  /* call external method */
3900  SCIP_CALL( conshdlr->consprop(set->scip, conshdlr, conss, nconss, nusefulconss, nmarkedpropconss, proptiming, result) );
3901  SCIPsetDebugMsg(set, " -> propagation returned result <%d>\n", *result);
3902 
3903  /* stop timing */
3904  if( instrongbranching )
3905  SCIPclockStop(conshdlr->sbproptime, set);
3906  else
3907  SCIPclockStop(conshdlr->proptime, set);
3908 
3909  /* perform the cached constraint updates */
3910  conshdlr->duringprop = FALSE;
3911  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3912 
3913  /* update statistics */
3914  if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
3915  {
3916  conshdlr->lastpropdomchgcount = lastpropdomchgcount;
3917  conshdlr->lastnusefulpropconss = MIN(conshdlr->nusefulpropconss, lastnusefulpropconss);
3918  conshdlr->npropcalls++;
3919  }
3920  else
3921  {
3922  assert(lastpropdomchgcount == stat->domchgcount);
3923  assert(lastnusefulpropconss == conshdlr->nusefulpropconss);
3924  }
3925  if( *result == SCIP_CUTOFF )
3926  conshdlr->ncutoffs++;
3927 
3928  /* update domain reductions; therefore remove the domain
3929  * reduction counts which were generated in probing mode */
3930  conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3931  conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3932 
3933  /* check result code of callback method */
3934  if( *result != SCIP_CUTOFF
3935  && *result != SCIP_REDUCEDDOM
3936  && *result != SCIP_DIDNOTFIND
3937  && *result != SCIP_DIDNOTRUN
3938  && *result != SCIP_DELAYED
3939  && *result != SCIP_DELAYNODE )
3940  {
3941  SCIPerrorMessage("propagation method of constraint handler <%s> returned invalid result <%d>\n",
3942  conshdlr->name, *result);
3943  return SCIP_INVALIDRESULT;
3944  }
3945  }
3946  }
3947  else
3948  {
3949  SCIPsetDebugMsg(set, "propagation method of constraint handler <%s> was delayed\n", conshdlr->name);
3950  *result = SCIP_DELAYED;
3951  }
3952 
3953  /* remember whether propagation method was delayed */
3954  conshdlr->propwasdelayed = (*result == SCIP_DELAYED);
3955  }
3956 
3957  return SCIP_OKAY;
3958 }
3959 
3960 /** calls presolving method of constraint handler */
3962  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3963  BMS_BLKMEM* blkmem, /**< block memory */
3964  SCIP_SET* set, /**< global SCIP settings */
3965  SCIP_STAT* stat, /**< dynamic problem statistics */
3966  SCIP_PRESOLTIMING timing, /**< current presolving timing */
3967  int nrounds, /**< number of presolving rounds already done */
3968  int* nfixedvars, /**< pointer to total number of variables fixed of all presolvers */
3969  int* naggrvars, /**< pointer to total number of variables aggregated of all presolvers */
3970  int* nchgvartypes, /**< pointer to total number of variable type changes of all presolvers */
3971  int* nchgbds, /**< pointer to total number of variable bounds tightened of all presolvers */
3972  int* naddholes, /**< pointer to total number of domain holes added of all presolvers */
3973  int* ndelconss, /**< pointer to total number of deleted constraints of all presolvers */
3974  int* naddconss, /**< pointer to total number of added constraints of all presolvers */
3975  int* nupgdconss, /**< pointer to total number of upgraded constraints of all presolvers */
3976  int* nchgcoefs, /**< pointer to total number of changed coefficients of all presolvers */
3977  int* nchgsides, /**< pointer to total number of changed left/right hand sides of all presolvers */
3978  SCIP_RESULT* result /**< pointer to store the result of the callback method */
3979  )
3980 {
3981  assert(conshdlr != NULL);
3982  assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3983  assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3984  assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3985  assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3986  assert(set != NULL);
3987  assert(nfixedvars != NULL);
3988  assert(naggrvars != NULL);
3989  assert(nchgvartypes != NULL);
3990  assert(nchgbds != NULL);
3991  assert(naddholes != NULL);
3992  assert(ndelconss != NULL);
3993  assert(naddconss != NULL);
3994  assert(nupgdconss != NULL);
3995  assert(nchgcoefs != NULL);
3996  assert(nchgsides != NULL);
3997  assert(result != NULL);
3998 
3999  *result = SCIP_DIDNOTRUN;
4000 
4001  if( conshdlr->conspresol != NULL
4002  && (!conshdlr->needscons || conshdlr->nactiveconss > 0)
4003  && (conshdlr->maxprerounds == -1 || conshdlr->npresolcalls < conshdlr->maxprerounds ) )
4004  {
4005  SCIPsetDebugMsg(set, "presolving %d constraints of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4006 
4007  /* check, if presolving method should be executed for the current timing */
4008  if( timing & conshdlr->presoltiming )
4009  {
4010  int nnewfixedvars;
4011  int nnewaggrvars;
4012  int nnewchgvartypes;
4013  int nnewchgbds;
4014  int nnewholes;
4015  int nnewdelconss;
4016  int nnewaddconss;
4017  int nnewupgdconss;
4018  int nnewchgcoefs;
4019  int nnewchgsides;
4020 
4021  /* calculate the number of changes since last call */
4022  nnewfixedvars = *nfixedvars - conshdlr->lastnfixedvars;
4023  nnewaggrvars = *naggrvars - conshdlr->lastnaggrvars;
4024  nnewchgvartypes = *nchgvartypes - conshdlr->lastnchgvartypes;
4025  nnewchgbds = *nchgbds - conshdlr->lastnchgbds;
4026  nnewholes = *naddholes - conshdlr->lastnaddholes;
4027  nnewdelconss = *ndelconss - conshdlr->lastndelconss;
4028  nnewaddconss = *naddconss - conshdlr->lastnaddconss;
4029  nnewupgdconss = *nupgdconss - conshdlr->lastnupgdconss;
4030  nnewchgcoefs = *nchgcoefs - conshdlr->lastnchgcoefs;
4031  nnewchgsides = *nchgsides - conshdlr->lastnchgsides;
4032 
4033  /* remember the old number of changes */
4034  conshdlr->lastnfixedvars = *nfixedvars;
4035  conshdlr->lastnaggrvars = *naggrvars;
4036  conshdlr->lastnchgvartypes = *nchgvartypes;
4037  conshdlr->lastnchgbds = *nchgbds;
4038  conshdlr->lastnaddholes = *naddholes;
4039  conshdlr->lastndelconss = *ndelconss;
4040  conshdlr->lastnaddconss = *naddconss;
4041  conshdlr->lastnupgdconss = *nupgdconss;
4042  conshdlr->lastnchgcoefs = *nchgcoefs;
4043  conshdlr->lastnchgsides = *nchgsides;
4044 
4045  /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4046  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4047  * external method; to avoid this, these changes will be buffered and processed after the method call
4048  */
4049  conshdlrDelayUpdates(conshdlr);
4050 
4051  /* start timing */
4052  SCIPclockStart(conshdlr->presoltime, set);
4053 
4054  /* call external method */
4055  SCIP_CALL( conshdlr->conspresol(set->scip, conshdlr, conshdlr->conss, conshdlr->nactiveconss, nrounds, timing,
4056  nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewholes,
4057  nnewdelconss, nnewaddconss, nnewupgdconss, nnewchgcoefs, nnewchgsides,
4058  nfixedvars, naggrvars, nchgvartypes, nchgbds, naddholes,
4059  ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) );
4060 
4061  /* stop timing */
4062  SCIPclockStop(conshdlr->presoltime, set);
4063 
4064  /* perform the cached constraint updates */
4065  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4066 
4067  /* count the new changes */
4068  conshdlr->nfixedvars += *nfixedvars - conshdlr->lastnfixedvars;
4069  conshdlr->naggrvars += *naggrvars - conshdlr->lastnaggrvars;
4070  conshdlr->nchgvartypes += *nchgvartypes - conshdlr->lastnchgvartypes;
4071  conshdlr->nchgbds += *nchgbds - conshdlr->lastnchgbds;
4072  conshdlr->naddholes += *naddholes - conshdlr->lastnaddholes;
4073  conshdlr->ndelconss += *ndelconss - conshdlr->lastndelconss;
4074  conshdlr->naddconss += *naddconss - conshdlr->lastnaddconss;
4075  conshdlr->nupgdconss += *nupgdconss - conshdlr->lastnupgdconss;
4076  conshdlr->nchgcoefs += *nchgcoefs - conshdlr->lastnchgcoefs;
4077  conshdlr->nchgsides += *nchgsides - conshdlr->lastnchgsides;
4078 
4079  /* check result code of callback method */
4080  if( *result != SCIP_CUTOFF
4081  && *result != SCIP_UNBOUNDED
4082  && *result != SCIP_SUCCESS
4083  && *result != SCIP_DIDNOTFIND
4084  && *result != SCIP_DIDNOTRUN
4085  && *result != SCIP_DELAYED )
4086  {
4087  SCIPerrorMessage("presolving method of constraint handler <%s> returned invalid result <%d>\n",
4088  conshdlr->name, *result);
4089  return SCIP_INVALIDRESULT;
4090  }
4091 
4092  /* increase the number of calls, if the presolving method tried to find reductions */
4093  if( *result != SCIP_DIDNOTRUN )
4094  ++(conshdlr->npresolcalls);
4095  }
4096 
4097  SCIPsetDebugMsg(set, "after presolving %d constraints left of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4098  }
4099 
4100  return SCIP_OKAY;
4101 }
4102 
4103 /** calls variable deletion method of constraint handler */
4105  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4106  BMS_BLKMEM* blkmem, /**< block memory */
4107  SCIP_SET* set, /**< global SCIP settings */
4108  SCIP_STAT* stat /**< dynamic problem statistics */
4109  )
4110 {
4111  assert(conshdlr != NULL);
4112  assert(set != NULL);
4113 
4114  if( conshdlr->consdelvars != NULL )
4115  {
4116  SCIPsetDebugMsg(set, "deleting variables in constraints of handler <%s>\n", conshdlr->name);
4117 
4118  /* during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4119  * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4120  * external method; to avoid this, these changes will be buffered and processed after the method call
4121  */
4122  conshdlrDelayUpdates(conshdlr);
4123 
4124  /* call external method */
4125  SCIP_CALL( conshdlr->consdelvars(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
4126 
4127  /* perform the cached constraint updates */
4128  SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4129  }
4130 
4131  return SCIP_OKAY;
4132 }
4133 
4134 /** locks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
4136  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4137  SCIP_SET* set /**< global SCIP settings */
4138  )
4139 {
4140  assert(conshdlr != NULL);
4141  assert(conshdlr->conslock != NULL);
4142  assert(!conshdlr->needscons);
4143 
4144  SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, +1, 0) );
4145 
4146  return SCIP_OKAY;
4147 }
4148 
4149 /** unlocks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
4151  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4152  SCIP_SET* set /**< global SCIP settings */
4153  )
4154 {
4155  assert(conshdlr != NULL);
4156  assert(conshdlr->conslock != NULL);
4157  assert(!conshdlr->needscons);
4158 
4159  SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, -1, 0) );
4160 
4161  return SCIP_OKAY;
4162 }
4163 
4164 /** gets name of constraint handler */
4165 const char* SCIPconshdlrGetName(
4166  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4167  )
4168 {
4169  assert(conshdlr != NULL);
4170 
4171  return conshdlr->name;
4172 }
4173 
4174 /** gets description of constraint handler */
4175 const char* SCIPconshdlrGetDesc(
4176  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4177  )
4178 {
4179  assert(conshdlr != NULL);
4180 
4181  return conshdlr->desc;
4182 }
4183 
4184 /** gets user data of constraint handler */
4186  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4187  )
4188 {
4189  assert(conshdlr != NULL);
4190 
4191  return conshdlr->conshdlrdata;
4192 }
4193 
4194 /** sets user data of constraint handler; user has to free old data in advance! */
4195 void SCIPconshdlrSetData(
4196  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4197  SCIP_CONSHDLRDATA* conshdlrdata /**< new constraint handler user data */
4198  )
4199 {
4200  assert(conshdlr != NULL);
4201 
4202  conshdlr->conshdlrdata = conshdlrdata;
4203 }
4204 
4205 /** sets all separation related callbacks of the constraint handler */
4206 void SCIPconshdlrSetSepa(
4207  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4208  SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */
4209  SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */
4210  int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */
4211  int sepapriority, /**< priority of the constraint handler for separation */
4212  SCIP_Bool delaysepa /**< should separation method be delayed, if other separators found cuts? */
4213  )
4214 {
4215  assert(conshdlr != NULL);
4216 
4217  assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
4218 
4219  conshdlr->conssepalp = conssepalp;
4220  conshdlr->conssepasol = conssepasol;
4221  conshdlr->sepafreq = sepafreq;
4222  conshdlr->sepapriority = sepapriority;
4223  conshdlr->delaysepa = delaysepa;
4224 }
4225 
4226 /** sets both the propagation callback and the propagation frequency of the constraint handler */
4227 void SCIPconshdlrSetProp(
4228  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4229  SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */
4230  int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */
4231  SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */
4232  SCIP_PROPTIMING timingmask /**< positions in the node solving loop where propagators should be executed */
4233  )
4234 {
4235  assert(conshdlr != NULL);
4236 
4237  assert(consprop != NULL || propfreq == -1);
4238 
4239  conshdlr->consprop = consprop;
4240  conshdlr->propfreq = propfreq;
4241  conshdlr->delayprop = delayprop;
4242  conshdlr->proptiming = timingmask;
4243 }
4244 
4245 /** sets copy method of both the constraint handler and each associated constraint */
4247  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4248  SCIP_DECL_CONSENFORELAX ((*consenforelax)) /**< constraint copying method */
4249  )
4250 {
4251  assert(conshdlr != NULL);
4252 
4253  conshdlr->consenforelax = consenforelax;
4254 }
4255 
4256 /** sets copy method of both the constraint handler and each associated constraint */
4257 void SCIPconshdlrSetCopy(
4258  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4259  SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
4260  SCIP_DECL_CONSCOPY ((*conscopy)) /**< constraint copying method */
4261  )
4262 {
4263  assert(conshdlr != NULL);
4264 
4265  assert(!conshdlr->needscons || (conshdlrcopy == NULL) == (conscopy == NULL));
4266 
4267  conshdlr->conshdlrcopy = conshdlrcopy;
4268  conshdlr->conscopy = conscopy;
4269 }
4270 
4271 /** sets destructor method of constraint handler */
4272 void SCIPconshdlrSetFree(
4273  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4274  SCIP_DECL_CONSFREE ((*consfree)) /**< destructor of constraint handler */
4275  )
4276 {
4277  assert(conshdlr != NULL);
4278 
4279  conshdlr->consfree = consfree;
4280 }
4281 
4282 /** sets initialization method of constraint handler */
4283 void SCIPconshdlrSetInit(
4284  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4285  SCIP_DECL_CONSINIT ((*consinit)) /**< initialize constraint handler */
4286  )
4287 {
4288  assert(conshdlr != NULL);
4289 
4290  conshdlr->consinit = consinit;
4291 }
4292 
4293 /** sets deinitialization method of constraint handler */
4294 void SCIPconshdlrSetExit(
4295  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4296  SCIP_DECL_CONSEXIT ((*consexit)) /**< deinitialize constraint handler */
4297  )
4298 {
4299  assert(conshdlr != NULL);
4300 
4301  conshdlr->consexit = consexit;
4302 }
4303 
4304 /** sets solving process initialization method of constraint handler */
4306  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4307  SCIP_DECL_CONSINITSOL((*consinitsol)) /**< solving process initialization method of constraint handler */
4308  )
4309 {
4310  assert(conshdlr != NULL);
4311 
4312  conshdlr->consinitsol = consinitsol;
4313 }
4314 
4315 /** sets solving process deinitialization method of constraint handler */
4317  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4318  SCIP_DECL_CONSEXITSOL ((*consexitsol)) /**< solving process deinitialization method of constraint handler */
4319  )
4320 {
4321  assert(conshdlr != NULL);
4322 
4323  conshdlr->consexitsol = consexitsol;
4324 }
4325 
4326 /** sets preprocessing initialization method of constraint handler */
4328  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4329  SCIP_DECL_CONSINITPRE((*consinitpre)) /**< preprocessing initialization method of constraint handler */
4330  )
4331 {
4332  assert(conshdlr != NULL);
4333 
4334  conshdlr->consinitpre = consinitpre;
4335 }
4336 
4337 /** sets preprocessing deinitialization method of constraint handler */
4339  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4340  SCIP_DECL_CONSEXITPRE((*consexitpre)) /**< preprocessing deinitialization method of constraint handler */
4341  )
4342 {
4343  assert(conshdlr != NULL);
4344 
4345  conshdlr->consexitpre = consexitpre;
4346 }
4347 
4348 /** sets presolving method of constraint handler */
4350  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4351  SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method of constraint handler */
4352  int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
4353  SCIP_PRESOLTIMING presoltiming /**< timing mask of the constraint handler's presolving method */
4354  )
4355 {
4356  assert(conshdlr != NULL);
4357 
4358  conshdlr->conspresol = conspresol;
4359  conshdlr->maxprerounds = maxprerounds;
4360 
4361  /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
4362  * error message
4363  */
4364  if( presoltiming < SCIP_PRESOLTIMING_FAST || presoltiming > SCIP_PRESOLTIMING_MAX )
4365  {
4366  SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
4367  "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", conshdlr->name);
4368 
4369  return SCIP_PARAMETERWRONGVAL;
4370  }
4371 
4372  conshdlr->presoltiming = presoltiming;
4373 
4374  return SCIP_OKAY;
4375 }
4376 
4377 /** sets method of constraint handler to free specific constraint data */
4379  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4380  SCIP_DECL_CONSDELETE ((*consdelete)) /**< free specific constraint data */
4381  )
4382 {
4383  assert(conshdlr != NULL);
4384 
4385  conshdlr->consdelete = consdelete;
4386 }
4387 
4388 /** sets method of constraint handler to transform constraint data into data belonging to the transformed problem */
4390  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4391  SCIP_DECL_CONSTRANS ((*constrans)) /**< transform constraint data into data belonging to the transformed problem */
4392  )
4393 {
4394  assert(conshdlr != NULL);
4395 
4396  conshdlr->constrans = constrans;
4397 }
4398 
4399 /** sets method of constraint handler to initialize LP with relaxations of "initial" constraints */
4401  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4402  SCIP_DECL_CONSINITLP ((*consinitlp)) /**< initialize LP with relaxations of "initial" constraints */
4403  )
4404 {
4405  assert(conshdlr != NULL);
4406 
4407  conshdlr->consinitlp = consinitlp;
4408 }
4409 
4410 /** sets propagation conflict resolving method of constraint handler */
4412  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4413  SCIP_DECL_CONSRESPROP ((*consresprop)) /**< propagation conflict resolving method */
4414  )
4415 {
4416  assert(conshdlr != NULL);
4417 
4418  conshdlr->consresprop = consresprop;
4419 }
4420 
4421 /** sets activation notification method of constraint handler */
4423  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4424  SCIP_DECL_CONSACTIVE ((*consactive)) /**< activation notification method */
4425  )
4426 {
4427  assert(conshdlr != NULL);
4428 
4429  conshdlr->consactive = consactive;
4430 }
4431 
4432 /** sets deactivation notification method of constraint handler */
4434  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4435  SCIP_DECL_CONSDEACTIVE((*consdeactive)) /**< deactivation notification method */
4436  )
4437 {
4438  assert(conshdlr != NULL);
4439 
4440  conshdlr->consdeactive = consdeactive;
4441 }
4442 
4443 /** sets enabling notification method of constraint handler */
4445  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4446  SCIP_DECL_CONSENABLE ((*consenable)) /**< enabling notification method */
4447  )
4448 {
4449  assert(conshdlr != NULL);
4450 
4451  conshdlr->consenable = consenable;
4452 }
4453 
4454 /** sets disabling notification method of constraint handler */
4456  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4457  SCIP_DECL_CONSDISABLE ((*consdisable)) /**< disabling notification method */
4458  )
4459 {
4460  assert(conshdlr != NULL);
4461 
4462  conshdlr->consdisable = consdisable;
4463 }
4464 
4465 /** sets variable deletion method of constraint handler */
4467  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4468  SCIP_DECL_CONSDELVARS ((*consdelvars)) /**< variable deletion method */
4469  )
4470 {
4471  assert(conshdlr != NULL);
4472 
4473  conshdlr->consdelvars = consdelvars;
4474 }
4475 
4476 /** sets constraint display method of constraint handler */
4478  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4479  SCIP_DECL_CONSPRINT ((*consprint)) /**< constraint display method */
4480  )
4481 {
4482  assert(conshdlr != NULL);
4483 
4484  conshdlr->consprint = consprint;
4485 }
4486 
4487 /** sets constraint parsing method of constraint handler */
4489  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4490  SCIP_DECL_CONSPARSE ((*consparse)) /**< constraint parsing method */
4491  )
4492 {
4493  assert(conshdlr != NULL);
4494 
4495  conshdlr->consparse = consparse;
4496 }
4497 
4498 /** sets constraint variable getter method of constraint handler */
4500  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4501  SCIP_DECL_CONSGETVARS ((*consgetvars)) /**< constraint variable getter method */
4502  )
4503 {
4504  assert(conshdlr != NULL);
4505 
4506  conshdlr->consgetvars = consgetvars;
4507 }
4508 
4509 /** sets constraint variable number getter method of constraint handler */
4511  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4512  SCIP_DECL_CONSGETNVARS((*consgetnvars)) /**< constraint variable number getter method */
4513  )
4514 {
4515  assert(conshdlr != NULL);
4516 
4517  conshdlr->consgetnvars = consgetnvars;
4518 }
4519 
4520 /** sets diving enforcement method of constraint handler */
4522  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4523  SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)) /**< constraint handler diving solution enforcement method */
4524  )
4525 {
4526  assert(conshdlr != NULL);
4527 
4528  conshdlr->consgetdivebdchgs = consgetdivebdchgs;
4529 }
4530 
4531 /** gets array with constraints of constraint handler; the first SCIPconshdlrGetNActiveConss() entries are the active
4532  * constraints, the last SCIPconshdlrGetNConss() - SCIPconshdlrGetNActiveConss() constraints are deactivated
4533  *
4534  * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4535  * flag is TRUE) and the current node belongs to the corresponding sub tree.
4536  */
4538  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4539  )
4540 {
4541  assert(conshdlr != NULL);
4542 
4543  return conshdlr->conss;
4544 }
4545 
4546 /** gets array with enforced constraints of constraint handler; this is local information */
4548  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4549  )
4550 {
4551  assert(conshdlr != NULL);
4552 
4553  return conshdlr->enfoconss;
4554 }
4555 
4556 /** gets array with checked constraints of constraint handler; this is local information */
4558  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4559  )
4560 {
4561  assert(conshdlr != NULL);
4562 
4563  return conshdlr->checkconss;
4564 }
4565 
4566 /** gets array with delayed update constraints
4567  *
4568  * @attention Usually, there should be no need to access this array. Use this only if you are absolutely sure what you are doing.
4569  */
4571  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4572  )
4573 {
4574  assert(conshdlr != NULL);
4575 
4576  return conshdlr->updateconss;
4577 }
4578 
4579 /** gets total number of existing transformed constraints of constraint handler */
4581  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4582  )
4583 {
4584  assert(conshdlr != NULL);
4585 
4586  return conshdlr->nconss;
4587 }
4588 
4589 /** gets number of enforced constraints of constraint handler; this is local information */
4591  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4592  )
4593 {
4594  assert(conshdlr != NULL);
4595 
4596  return conshdlr->nenfoconss;
4597 }
4598 
4599 /** gets number of checked constraints of constraint handler; this is local information */
4601  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4602  )
4603 {
4604  assert(conshdlr != NULL);
4605 
4606  return conshdlr->ncheckconss;
4607 }
4608 
4609 /** gets number of active constraints of constraint handler
4610  *
4611  * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4612  * flag is TRUE) and the current node belongs to the corresponding sub tree.
4613  */
4615  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4616  )
4617 {
4618  assert(conshdlr != NULL);
4619 
4620  return conshdlr->nactiveconss;
4621 }
4622 
4623 /** gets number of enabled constraints of constraint handler */
4625  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4626  )
4627 {
4628  assert(conshdlr != NULL);
4629 
4630  return conshdlr->nenabledconss;
4631 }
4632 
4633 /** gets number of constraints that have delayed updates */
4635  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4636  )
4637 {
4638  assert(conshdlr != NULL);
4639 
4640  return conshdlr->nupdateconss;
4641 }
4642 
4643 /** enables or disables all clocks of \p conshdlr, depending on the value of the flag */
4645  SCIP_CONSHDLR* conshdlr, /**< the constraint handler for which all clocks should be enabled or disabled */
4646  SCIP_Bool enable /**< should the clocks of the constraint handler be enabled? */
4647  )
4648 {
4649  assert(conshdlr != NULL);
4650 
4651  SCIPclockEnableOrDisable(conshdlr->setuptime, enable);
4652  SCIPclockEnableOrDisable(conshdlr->checktime, enable);
4653  SCIPclockEnableOrDisable(conshdlr->enfolptime, enable);
4654  SCIPclockEnableOrDisable(conshdlr->enfopstime, enable);
4655  SCIPclockEnableOrDisable(conshdlr->enforelaxtime, enable);
4656  SCIPclockEnableOrDisable(conshdlr->presoltime, enable);
4657  SCIPclockEnableOrDisable(conshdlr->proptime, enable);
4658  SCIPclockEnableOrDisable(conshdlr->resproptime, enable);
4659  SCIPclockEnableOrDisable(conshdlr->sbproptime, enable);
4660  SCIPclockEnableOrDisable(conshdlr->sepatime, enable);
4661 }
4662 
4663 /** gets time in seconds used for setting up this constraint handler for new stages */
4665  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4666  )
4667 {
4668  assert(conshdlr != NULL);
4669 
4670  return SCIPclockGetTime(conshdlr->setuptime);
4671 }
4672 
4673 /** gets time in seconds used for presolving in this constraint handler */
4675  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4676  )
4677 {
4678  assert(conshdlr != NULL);
4679 
4680  return SCIPclockGetTime(conshdlr->presoltime);
4681 }
4682 
4683 /** gets time in seconds used for separation in this constraint handler */
4685  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4686  )
4687 {
4688  assert(conshdlr != NULL);
4689 
4690  return SCIPclockGetTime(conshdlr->sepatime);
4691 }
4692 
4693 /** gets time in seconds used for LP enforcement in this constraint handler */
4695  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4696  )
4697 {
4698  assert(conshdlr != NULL);
4699 
4700  return SCIPclockGetTime(conshdlr->enfolptime);
4701 }
4702 
4703 /** gets time in seconds used for pseudo enforcement in this constraint handler */
4705  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4706  )
4707 {
4708  assert(conshdlr != NULL);
4709 
4710  return SCIPclockGetTime(conshdlr->enfopstime);
4711 }
4712 
4713 /** gets time in seconds used for relaxation enforcement in this constraint handler */
4715  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4716  )
4717 {
4718  assert(conshdlr != NULL);
4719 
4720  return SCIPclockGetTime(conshdlr->enforelaxtime);
4721 }
4722 
4723 /** gets time in seconds used for propagation in this constraint handler */
4725  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4726  )
4727 {
4728  assert(conshdlr != NULL);
4729 
4730  return SCIPclockGetTime(conshdlr->proptime);
4731 }
4732 
4733 /** gets time in seconds used for propagation in this constraint handler during strong branching */
4735  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4736  )
4737 {
4738  assert(conshdlr != NULL);
4739 
4740  return SCIPclockGetTime(conshdlr->sbproptime);
4741 }
4742 
4743 /** gets time in seconds used for feasibility checking in this constraint handler */
4745  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4746  )
4747 {
4748  assert(conshdlr != NULL);
4749 
4750  return SCIPclockGetTime(conshdlr->checktime);
4751 }
4752 
4753 /** gets time in seconds used for resolving propagation in this constraint handler */
4755  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4756  )
4757 {
4758  assert(conshdlr != NULL);
4759 
4760  return SCIPclockGetTime(conshdlr->resproptime);
4761 }
4762 
4763 /** gets number of calls to the constraint handler's separation method */
4765  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4766  )
4767 {
4768  assert(conshdlr != NULL);
4769 
4770  return conshdlr->nsepacalls;
4771 }
4772 
4773 /** gets number of calls to the constraint handler's LP enforcing method */
4775  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4776  )
4777 {
4778  assert(conshdlr != NULL);
4779 
4780  return conshdlr->nenfolpcalls;
4781 }
4782 
4783 /** gets number of calls to the constraint handler's pseudo enforcing method */
4785  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4786  )
4787 {
4788  assert(conshdlr != NULL);
4789 
4790  return conshdlr->nenfopscalls;
4791 }
4792 
4793 /** gets number of calls to the constraint handler's relaxation enforcing method */
4795  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4796  )
4797 {
4798  assert(conshdlr != NULL);
4799 
4800  return conshdlr->nenforelaxcalls;
4801 }
4802 
4803 /** gets number of calls to the constraint handler's propagation method */
4805  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4806  )
4807 {
4808  assert(conshdlr != NULL);
4809 
4810  return conshdlr->npropcalls;
4811 }
4812 
4813 /** gets number of calls to the constraint handler's checking method */
4815  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4816  )
4817 {
4818  assert(conshdlr != NULL);
4819 
4820  return conshdlr->ncheckcalls;
4821 }
4822 
4823 /** gets number of calls to the constraint handler's resolve propagation method */
4825  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4826  )
4827 {
4828  assert(conshdlr != NULL);
4829 
4830  return conshdlr->nrespropcalls;
4831 }
4832 
4833 /** gets total number of times, this constraint handler detected a cutoff */
4835  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4836  )
4837 {
4838  assert(conshdlr != NULL);
4839 
4840  return conshdlr->ncutoffs;
4841 }
4842 
4843 /** gets total number of cuts found by this constraint handler */
4845  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4846  )
4847 {
4848  assert(conshdlr != NULL);
4849 
4850  return conshdlr->ncutsfound;
4851 }
4852 
4853 /** gets total number of cuts found by this constraint handler applied to lp */
4855  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4856  )
4857 {
4858  assert(conshdlr != NULL);
4859 
4860  return conshdlr->ncutsapplied;
4861 }
4862 
4863 /** increase count of applied cuts */
4865  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4866  )
4867 {
4868  assert(conshdlr != NULL);
4869 
4870  ++conshdlr->ncutsapplied;
4871 }
4872 
4873 /** increase count of found cuts */
4875  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4876  )
4877 {
4878  assert(conshdlr != NULL);
4879 
4880  ++conshdlr->ncutsfound;
4881 }
4882 
4883 /** gets total number of additional constraints added by this constraint handler */
4885  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4886  )
4887 {
4888  assert(conshdlr != NULL);
4889 
4890  return conshdlr->nconssfound;
4891 }
4892 
4893 /** gets total number of domain reductions found by this constraint handler */
4895  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4896  )
4897 {
4898  assert(conshdlr != NULL);
4899 
4900  return conshdlr->ndomredsfound;
4901 }
4902 
4903 /** gets number of children created by this constraint handler */
4905  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4906  )
4907 {
4908  assert(conshdlr != NULL);
4909 
4910  return conshdlr->nchildren;
4911 }
4912 
4913 /** gets maximum number of active constraints of constraint handler existing at the same time */
4915  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4916  )
4917 {
4918  assert(conshdlr != NULL);
4919 
4920  return conshdlr->maxnactiveconss;
4921 }
4922 
4923 /** gets initial number of active constraints of constraint handler */
4925  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4926  )
4927 {
4928  assert(conshdlr != NULL);
4929 
4930  return conshdlr->startnactiveconss;
4931 }
4932 
4933 /** gets number of variables fixed in presolving method of constraint handler */
4935  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4936  )
4937 {
4938  assert(conshdlr != NULL);
4939 
4940  return conshdlr->nfixedvars;
4941 }
4942 
4943 /** gets number of variables aggregated in presolving method of constraint handler */
4945  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4946  )
4947 {
4948  assert(conshdlr != NULL);
4949 
4950  return conshdlr->naggrvars;
4951 }
4952 
4953 /** gets number of variable types changed in presolving method of constraint handler */
4955  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4956  )
4957 {
4958  assert(conshdlr != NULL);
4959 
4960  return conshdlr->nchgvartypes;
4961 }
4962 
4963 /** gets number of bounds changed in presolving method of constraint handler */
4965  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4966  )
4967 {
4968  assert(conshdlr != NULL);
4969 
4970  return conshdlr->nchgbds;
4971 }
4972 
4973 /** gets number of holes added to domains of variables in presolving method of constraint handler */
4975  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4976  )
4977 {
4978  assert(conshdlr != NULL);
4979 
4980  return conshdlr->naddholes;
4981 }
4982 
4983 /** gets number of constraints deleted in presolving method of constraint handler */
4985  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4986  )
4987 {
4988  assert(conshdlr != NULL);
4989 
4990  return conshdlr->ndelconss;
4991 }
4992 
4993 /** gets number of constraints added in presolving method of constraint handler */
4995  SCIP_CONSHDLR* conshdlr /**< constraint handler */
4996  )
4997 {
4998  assert(conshdlr != NULL);
4999 
5000  return conshdlr->naddconss;
5001 }
5002 
5003 /** gets number of constraints upgraded in presolving method of constraint handler */
5005  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5006  )
5007 {
5008  assert(conshdlr != NULL);
5009 
5010  return conshdlr->nupgdconss;
5011 }
5012 
5013 /** gets number of coefficients changed in presolving method of constraint handler */
5015  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5016  )
5017 {
5018  assert(conshdlr != NULL);
5019 
5020  return conshdlr->nchgcoefs;
5021 }
5022 
5023 /** gets number of constraint sides changed in presolving method of constraint handler */
5025  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5026  )
5027 {
5028  assert(conshdlr != NULL);
5029 
5030  return conshdlr->nchgsides;
5031 }
5032 
5033 /** gets number of times the presolving method of the constraint handler was called and tried to find reductions */
5035  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5036  )
5037 {
5038  assert(conshdlr != NULL);
5039 
5040  return conshdlr->npresolcalls;
5041 }
5042 
5043 /** gets separation priority of constraint handler */
5045  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5046  )
5047 {
5048  assert(conshdlr != NULL);
5049 
5050  return conshdlr->sepapriority;
5051 }
5052 
5053 /** gets enforcing priority of constraint handler */
5055  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5056  )
5057 {
5058  assert(conshdlr != NULL);
5059 
5060  return conshdlr->enfopriority;
5061 }
5062 
5063 /** gets checking priority of constraint handler */
5065  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5066  )
5067 {
5068  assert(conshdlr != NULL);
5069 
5070  return conshdlr->checkpriority;
5071 }
5072 
5073 /** gets separation frequency of constraint handler */
5075  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5076  )
5077 {
5078  assert(conshdlr != NULL);
5079 
5080  return conshdlr->sepafreq;
5081 }
5082 
5083 /** gets propagation frequency of constraint handler */
5085  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5086  )
5087 {
5088  assert(conshdlr != NULL);
5089 
5090  return conshdlr->propfreq;
5091 }
5092 
5093 /** gets frequency of constraint handler for eager evaluations in separation, propagation and enforcement */
5095  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5096  )
5097 {
5098  assert(conshdlr != NULL);
5099 
5100  return conshdlr->eagerfreq;
5101 }
5102 
5103 /** needs constraint handler a constraint to be called? */
5105  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5106  )
5107 {
5108  assert(conshdlr != NULL);
5109 
5110  return conshdlr->needscons;
5111 }
5112 
5113 /** does the constraint handler perform presolving? */
5115  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5116  )
5117 {
5118  assert(conshdlr != NULL);
5119 
5120  return (conshdlr->conspresol != NULL);
5121 }
5122 
5123 /** should separation method be delayed, if other separators found cuts? */
5125  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5126  )
5127 {
5128  assert(conshdlr != NULL);
5129 
5130  return conshdlr->delaysepa;
5131 }
5132 
5133 /** should propagation method be delayed, if other propagators found reductions? */
5135  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5136  )
5137 {
5138  assert(conshdlr != NULL);
5139 
5140  return conshdlr->delayprop;
5141 }
5142 
5143 /** was LP separation method delayed at the last call? */
5145  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5146  )
5147 {
5148  assert(conshdlr != NULL);
5149 
5150  return conshdlr->sepalpwasdelayed;
5151 }
5152 
5153 /** was primal solution separation method delayed at the last call? */
5155  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5156  )
5157 {
5158  assert(conshdlr != NULL);
5159 
5160  return conshdlr->sepasolwasdelayed;
5161 }
5162 
5163 /** was propagation method delayed at the last call? */
5165  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5166  )
5167 {
5168  assert(conshdlr != NULL);
5169 
5170  return conshdlr->propwasdelayed;
5171 }
5172 
5173 /** is constraint handler initialized? */
5175  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5176  )
5177 {
5178  assert(conshdlr != NULL);
5179 
5180  return conshdlr->initialized;
5181 }
5182 
5183 /** does the constraint handler have a copy function? */
5185  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5186  )
5187 {
5188  assert(conshdlr != NULL);
5189 
5190  return (conshdlr->conshdlrcopy != NULL);
5191 }
5192 
5193 /** returns the timing mask of the propagation method of the constraint handler */
5195  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5196  )
5197 {
5198  assert(conshdlr != NULL);
5199 
5200  return conshdlr->proptiming;
5201 }
5202 
5203 /** sets the timing mask of the propagation method of the constraint handler */
5205  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
5206  SCIP_PROPTIMING proptiming /**< timing mask to be set */
5207  )
5208 {
5209  assert(conshdlr != NULL);
5210 
5211  conshdlr->proptiming = proptiming;
5212 }
5213 
5214 
5215 /** returns the timing mask of the presolving method of the constraint handler */
5217  SCIP_CONSHDLR* conshdlr /**< constraint handler */
5218  )
5219 {
5220  assert(conshdlr != NULL);
5221 
5222  return conshdlr->presoltiming;
5223 }
5224 
5225 /** sets the timing mask of the presolving method of the constraint handler */
5227  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
5228  SCIP_PRESOLTIMING presoltiming /** timing mask to be set */
5229  )
5230 {
5231  assert(conshdlr != NULL);
5232 
5233  conshdlr->presoltiming = presoltiming;
5234 }
5235 
5236 
5237 /*
5238  * Constraint set change methods
5239  */
5240 
5241 /** creates empty constraint set change data */
5242 static
5244  SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change data */
5245  BMS_BLKMEM* blkmem /**< block memory */
5246  )
5247 {
5248  assert(conssetchg != NULL);
5249  assert(blkmem != NULL);
5250 
5251  SCIP_ALLOC( BMSallocBlockMemory(blkmem, conssetchg) );
5252  (*conssetchg)->addedconss = NULL;
5253  (*conssetchg)->disabledconss = NULL;
5254  (*conssetchg)->addedconsssize = 0;
5255  (*conssetchg)->naddedconss = 0;
5256  (*conssetchg)->disabledconsssize = 0;
5257  (*conssetchg)->ndisabledconss = 0;
5258 
5259  return SCIP_OKAY;
5260 }
5261 
5262 /** releases all constraints of the constraint set change data */
5263 static
5265  SCIP_CONSSETCHG* conssetchg, /**< constraint set change data */
5266  BMS_BLKMEM* blkmem, /**< block memory */
5267  SCIP_SET* set /**< global SCIP settings */
5268  )
5269 {
5270  int i;
5271 
5272  assert(conssetchg != NULL);
5273 
5274  /* release constraints */
5275  for( i = 0; i < conssetchg->naddedconss; ++i )
5276  {
5277  if( conssetchg->addedconss[i] != NULL )
5278  {
5279  SCIP_CALL( SCIPconsRelease(&conssetchg->addedconss[i], blkmem, set) );
5280  }
5281  }
5282  for( i = 0; i < conssetchg->ndisabledconss; ++i )
5283  {
5284  if( conssetchg->disabledconss[i] != NULL )
5285  {
5286  SCIP_CALL( SCIPconsRelease(&conssetchg->disabledconss[i], blkmem, set) );
5287  }
5288  }
5289 
5290  return SCIP_OKAY;
5291 }
5292 
5293 /** frees constraint set change data and releases all included constraints */
5295  SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change */
5296  BMS_BLKMEM* blkmem, /**< block memory */
5297  SCIP_SET* set /**< global SCIP settings */
5298  )
5299 {
5300  assert(conssetchg != NULL);
5301  assert(blkmem != NULL);
5302 
5303  if( *conssetchg != NULL )
5304  {
5305  /* release constraints */
5306  SCIP_CALL( conssetchgRelease(*conssetchg, blkmem, set) );
5307 
5308  /* free memory */
5309  BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->addedconss, (*conssetchg)->addedconsssize);
5310  BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->disabledconss, (*conssetchg)->disabledconsssize);
5311  BMSfreeBlockMemory(blkmem, conssetchg);
5312  }
5313 
5314  return SCIP_OKAY;
5315 }
5316 
5317 /** ensures, that addedconss array can store at least num entries */
5318 static
5320  SCIP_CONSSETCHG* conssetchg, /**< constraint set change data structure */
5321  BMS_BLKMEM* blkmem, /**< block memory */
5322  SCIP_SET* set, /**< global SCIP settings */
5323  int num /**< minimum number of entries to store */
5324  )
5325 {
5326  assert(conssetchg !=