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