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