1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                           */
3 /*                  This file is part of the program and library             */
4 /*         SCIP --- Solving Constraint Integer Programs                      */
5 /*                                                                           */
6 /*    Copyright (C) 2002-2021 Konrad-Zuse-Zentrum                            */
7 /*                            fuer Informationstechnik Berlin                */
8 /*                                                                           */
9 /*  SCIP is distributed under the terms of the ZIB Academic License.         */
10 /*                                                                           */
11 /*  You should have received a copy of the ZIB Academic License              */
12 /*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13 /*                                                                           */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file   cons.c
17  * @ingroup OTHER_CFILES
18  * @brief  methods for constraints and constraint handlers
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include <assert.h>
26 #include <string.h>
27 #include <ctype.h>
28 
29 #include "scip/def.h"
30 #include "scip/set.h"
31 #include "scip/stat.h"
32 #include "scip/clock.h"
33 #include "scip/var.h"
34 #include "scip/prob.h"
35 #include "scip/tree.h"
36 #include "scip/scip.h"
37 #include "scip/sepastore.h"
38 #include "scip/cons.h"
39 #include "scip/branch.h"
40 #include "scip/reopt.h"
41 #include "scip/pub_misc.h"
42 
43 #ifndef NDEBUG
44 #include "scip/struct_cons.h"
45 #endif
46 
47 
48 #define AGERESETAVG_INIT         1000.0 /**< initial value of the exponentially decaying weighted sum for ages */
49 #define AGERESETAVG_MIN          100.0  /**< minimal value to use for weighted sum of ages */
50 #define AGERESETAVG_DECAY        0.0005 /**< weight of a new addend in the exponentially decyaing sum */
51 #define AGERESETAVG_AGELIMIT     2.0    /**< in dynamic setting, a constraint is deleted if its age exceeds the
52                                          *   average reset age by this factor */
53 #define AGERESETAVG_OBSOLETEAGE  1.8    /**< in dynamic setting, a constraint is marked obsolete if its age exceeds the
54                                          *   average reset age by this factor */
55 
56 
57 /* #define CHECKCONSARRAYS */
58 
59 
60 /*
61  * dynamic memory arrays
62  */
63 
64 
65 /** resizes conss array to be able to store at least num constraints */
66 static
conshdlrEnsureConssMem(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,int num)67 SCIP_RETCODE conshdlrEnsureConssMem(
68    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
69    SCIP_SET*             set,                /**< global SCIP settings */
70    int                   num                 /**< minimal number of slots in array */
71    )
72 {
73    assert(conshdlr != NULL);
74    assert(set != NULL);
75 
76    if( num > conshdlr->consssize )
77    {
78       int newsize;
79 
80       newsize = SCIPsetCalcMemGrowSize(set, num);
81       SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->conss, newsize) );
82       conshdlr->consssize = newsize;
83    }
84    assert(num <= conshdlr->consssize);
85 
86    return SCIP_OKAY;
87 }
88 
89 /** resizes initconss array to be able to store at least num constraints */
90 static
conshdlrEnsureInitconssMem(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,int num)91 SCIP_RETCODE conshdlrEnsureInitconssMem(
92    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
93    SCIP_SET*             set,                /**< global SCIP settings */
94    int                   num                 /**< minimal number of slots in array */
95    )
96 {
97    assert(conshdlr != NULL);
98    assert(set != NULL);
99 
100    if( num > conshdlr->initconsssize )
101    {
102       int newsize;
103 
104       newsize = SCIPsetCalcMemGrowSize(set, num);
105       SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->initconss, newsize) );
106       conshdlr->initconsssize = newsize;
107    }
108    assert(num <= conshdlr->initconsssize);
109 
110    return SCIP_OKAY;
111 }
112 
113 /** resizes sepaconss array to be able to store at least num constraints */
114 static
conshdlrEnsureSepaconssMem(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,int num)115 SCIP_RETCODE conshdlrEnsureSepaconssMem(
116    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
117    SCIP_SET*             set,                /**< global SCIP settings */
118    int                   num                 /**< minimal number of slots in array */
119    )
120 {
121    assert(conshdlr != NULL);
122    assert(set != NULL);
123 
124    if( num > conshdlr->sepaconsssize )
125    {
126       int newsize;
127 
128       newsize = SCIPsetCalcMemGrowSize(set, num);
129       SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->sepaconss, newsize) );
130       conshdlr->sepaconsssize = newsize;
131    }
132    assert(num <= conshdlr->sepaconsssize);
133 
134    return SCIP_OKAY;
135 }
136 
137 /** resizes enfoconss array to be able to store at least num constraints */
138 static
conshdlrEnsureEnfoconssMem(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,int num)139 SCIP_RETCODE conshdlrEnsureEnfoconssMem(
140    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
141    SCIP_SET*             set,                /**< global SCIP settings */
142    int                   num                 /**< minimal number of slots in array */
143    )
144 {
145    assert(conshdlr != NULL);
146    assert(set != NULL);
147 
148    if( num > conshdlr->enfoconsssize )
149    {
150       int newsize;
151 
152       newsize = SCIPsetCalcMemGrowSize(set, num);
153       SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->enfoconss, newsize) );
154       conshdlr->enfoconsssize = newsize;
155    }
156    assert(num <= conshdlr->enfoconsssize);
157 
158    return SCIP_OKAY;
159 }
160 
161 /** resizes checkconss array to be able to store at least num constraints */
162 static
conshdlrEnsureCheckconssMem(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,int num)163 SCIP_RETCODE conshdlrEnsureCheckconssMem(
164    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
165    SCIP_SET*             set,                /**< global SCIP settings */
166    int                   num                 /**< minimal number of slots in array */
167    )
168 {
169    assert(conshdlr != NULL);
170    assert(set != NULL);
171 
172    if( num > conshdlr->checkconsssize )
173    {
174       int newsize;
175 
176       newsize = SCIPsetCalcMemGrowSize(set, num);
177       SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->checkconss, newsize) );
178       conshdlr->checkconsssize = newsize;
179    }
180    assert(num <= conshdlr->checkconsssize);
181 
182    return SCIP_OKAY;
183 }
184 
185 /** resizes propconss array to be able to store at least num constraints */
186 static
conshdlrEnsurePropconssMem(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,int num)187 SCIP_RETCODE conshdlrEnsurePropconssMem(
188    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
189    SCIP_SET*             set,                /**< global SCIP settings */
190    int                   num                 /**< minimal number of slots in array */
191    )
192 {
193    assert(conshdlr != NULL);
194    assert(set != NULL);
195 
196    if( num > conshdlr->propconsssize )
197    {
198       int newsize;
199 
200       newsize = SCIPsetCalcMemGrowSize(set, num);
201       SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->propconss, newsize) );
202       conshdlr->propconsssize = newsize;
203    }
204    assert(num <= conshdlr->propconsssize);
205 
206    return SCIP_OKAY;
207 }
208 
209 /** resizes updateconss array to be able to store at least num constraints */
210 static
conshdlrEnsureUpdateconssMem(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,int num)211 SCIP_RETCODE conshdlrEnsureUpdateconssMem(
212    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
213    SCIP_SET*             set,                /**< global SCIP settings */
214    int                   num                 /**< minimal number of slots in array */
215    )
216 {
217    assert(conshdlr != NULL);
218    assert(set != NULL);
219 
220    if( num > conshdlr->updateconsssize )
221    {
222       int newsize;
223 
224       newsize = SCIPsetCalcMemGrowSize(set, num);
225       SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->updateconss, newsize) );
226       conshdlr->updateconsssize = newsize;
227    }
228    assert(num <= conshdlr->updateconsssize);
229 
230    return SCIP_OKAY;
231 }
232 
233 
234 
235 
236 /*
237  * Constraint handler methods
238  */
239 
240 #define checkConssArrays(conshdlr) /**/
241 #ifndef NDEBUG
242 #ifdef CHECKCONSARRAYS
243 #undef checkConssArrays
244 /** sanity check for the constraint arrays of the constraint handler (only in debug mode) */
245 static
checkConssArrays(SCIP_CONSHDLR * conshdlr)246 void checkConssArrays(
247    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
248    )
249 {
250    int c;
251 
252    assert(conshdlr != NULL);
253    assert(0 <= conshdlr->nactiveconss && conshdlr->nactiveconss <= conshdlr->nconss);
254 
255    for( c = 0; c < conshdlr->nconss; ++c )
256    {
257       assert(conshdlr->conss[c] != NULL);
258       assert(!conshdlr->conss[c]->original);
259       assert(conshdlr->conss[c]->active == (c < conshdlr->nactiveconss));
260       assert(conshdlr->conss[c]->consspos == c);
261    }
262 
263    for( c = 0; c < conshdlr->ninitconss; ++c )
264    {
265       assert(conshdlr->initconss[c] != NULL);
266       assert(!conshdlr->initconss[c]->original);
267       assert(c < conshdlr->ninitconsskept || conshdlr->initconss[c]->active);
268       assert(conshdlr->initconss[c]->initial);
269    }
270 
271    for( c = 0; c < conshdlr->nsepaconss; ++c )
272    {
273       assert(conshdlr->sepaconss[c] != NULL);
274       assert(!conshdlr->sepaconss[c]->original);
275       assert(conshdlr->sepaconss[c]->active);
276       assert(conshdlr->sepaconss[c]->separate);
277       assert(conshdlr->sepaconss[c]->sepaenabled);
278       assert(conshdlr->sepaconss[c]->obsolete == (c >= conshdlr->nusefulsepaconss));
279    }
280 
281    for( c = 0; c < conshdlr->nenfoconss; ++c )
282    {
283       assert(conshdlr->enfoconss[c] != NULL);
284       assert(!conshdlr->enfoconss[c]->original);
285       assert(conshdlr->enfoconss[c]->active);
286       assert(conshdlr->enfoconss[c]->enforce);
287       assert(conshdlr->enfoconss[c]->obsolete == (c >= conshdlr->nusefulenfoconss));
288    }
289 
290    for( c = 0; c < conshdlr->ncheckconss; ++c )
291    {
292       assert(conshdlr->checkconss[c] != NULL);
293       assert(!conshdlr->checkconss[c]->original);
294       assert(conshdlr->checkconss[c]->active);
295       assert(conshdlr->checkconss[c]->check);
296       assert(conshdlr->checkconss[c]->obsolete == (c >= conshdlr->nusefulcheckconss));
297    }
298 
299    for( c = 0; c < conshdlr->npropconss; ++c )
300    {
301       assert(conshdlr->propconss[c] != NULL);
302       assert(!conshdlr->propconss[c]->original);
303       assert(conshdlr->propconss[c]->active);
304       assert(conshdlr->propconss[c]->propagate);
305       assert(conshdlr->propconss[c]->propenabled);
306       assert(conshdlr->propconss[c]->markpropagate == (c < conshdlr->nmarkedpropconss));
307       assert(conshdlr->propconss[c]->markpropagate || (conshdlr->propconss[c]->obsolete == (c >= conshdlr->nusefulpropconss)));
308    }
309    assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss);
310 }
311 #endif
312 #endif
313 
314 /** returns whether the constraint updates of the constraint handler are currently delayed */
315 static
conshdlrAreUpdatesDelayed(SCIP_CONSHDLR * conshdlr)316 SCIP_Bool conshdlrAreUpdatesDelayed(
317    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
318    )
319 {
320    return (conshdlr->delayupdatecount > 0);
321 }
322 
323 /** returns the exponentially decaying weighted age average for age resets */
324 static
conshdlrGetAgeresetavg(SCIP_CONSHDLR * conshdlr)325 SCIP_Real conshdlrGetAgeresetavg(
326    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
327    )
328 {
329    assert(conshdlr != NULL);
330 
331    return MAX(conshdlr->ageresetavg, AGERESETAVG_MIN);
332 }
333 
334 /** updates the exponentially decaying weighted age average for age resets after a constraint age was reset */
335 static
conshdlrUpdateAgeresetavg(SCIP_CONSHDLR * conshdlr,SCIP_Real age)336 void conshdlrUpdateAgeresetavg(
337    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
338    SCIP_Real             age                 /**< age of the constraint that is reset to zero */
339    )
340 {
341    assert(conshdlr != NULL);
342 
343    conshdlr->ageresetavg *= (1.0-AGERESETAVG_DECAY);
344    conshdlr->ageresetavg += AGERESETAVG_DECAY * age;
345 }
346 
347 /** returns whether the constraint's age exceeds the age limit */
348 static
consExceedsAgelimit(SCIP_CONS * cons,SCIP_SET * set)349 SCIP_Bool consExceedsAgelimit(
350    SCIP_CONS*            cons,               /**< constraint to check */
351    SCIP_SET*             set                 /**< global SCIP settings */
352    )
353 {
354    assert(cons != NULL);
355    assert(set != NULL);
356 
357    return (cons->dynamic
358       && ((set->cons_agelimit > 0 && cons->age > set->cons_agelimit)
359          || (set->cons_agelimit == 0 && cons->age > AGERESETAVG_AGELIMIT * conshdlrGetAgeresetavg(cons->conshdlr))));
360 }
361 
362 /** returns whether the constraint's age exceeds the obsolete age limit */
363 static
consExceedsObsoleteage(SCIP_CONS * cons,SCIP_SET * set)364 SCIP_Bool consExceedsObsoleteage(
365    SCIP_CONS*            cons,               /**< constraint to check */
366    SCIP_SET*             set                 /**< global SCIP settings */
367    )
368 {
369    assert(cons != NULL);
370    assert(set != NULL);
371 
372    return (cons->dynamic
373       && ((set->cons_obsoleteage > 0 && cons->age > set->cons_obsoleteage)
374          || (set->cons_obsoleteage == 0 && cons->age > AGERESETAVG_OBSOLETEAGE * conshdlrGetAgeresetavg(cons->conshdlr))));
375 }
376 
377 /** marks constraint to be obsolete; it will be moved to the last part of the constraint arrays, such that
378  *  it is checked, enforced, separated, and propagated after the useful constraints
379  */
380 static
conshdlrMarkConsObsolete(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)381 SCIP_RETCODE conshdlrMarkConsObsolete(
382    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
383    SCIP_CONS*            cons                /**< constraint to be marked obsolete */
384    )
385 {
386    SCIP_CONS* tmpcons;
387 
388    assert(conshdlr != NULL);
389    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
390    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
391    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
392    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
393    assert(cons != NULL);
394    assert(!cons->original);
395    assert(!cons->obsolete);
396    assert(!conshdlrAreUpdatesDelayed(conshdlr));
397 
398    cons->obsolete = TRUE;
399 
400    if( cons->active )
401    {
402       if( cons->check )
403       {
404          assert(0 <= cons->checkconsspos && cons->checkconsspos < conshdlr->nusefulcheckconss);
405 
406          /* switch the last useful (non-obsolete) check constraint with this constraint */
407          tmpcons = conshdlr->checkconss[conshdlr->nusefulcheckconss-1];
408          assert(tmpcons->checkconsspos == conshdlr->nusefulcheckconss-1);
409 
410          conshdlr->checkconss[conshdlr->nusefulcheckconss-1] = cons;
411          conshdlr->checkconss[cons->checkconsspos] = tmpcons;
412          tmpcons->checkconsspos = cons->checkconsspos;
413          cons->checkconsspos = conshdlr->nusefulcheckconss-1;
414 
415          conshdlr->nusefulcheckconss--;
416       }
417    }
418    if( cons->enabled )
419    {
420       if( cons->separate && cons->sepaenabled )
421       {
422          assert(0 <= cons->sepaconsspos && cons->sepaconsspos < conshdlr->nusefulsepaconss);
423 
424          if( cons->sepaconsspos < conshdlr->lastnusefulsepaconss )
425             conshdlr->lastnusefulsepaconss--;
426 
427          /* switch the last useful (non-obsolete) sepa constraint with this constraint */
428          tmpcons = conshdlr->sepaconss[conshdlr->nusefulsepaconss-1];
429          assert(tmpcons->sepaconsspos == conshdlr->nusefulsepaconss-1);
430 
431          conshdlr->sepaconss[conshdlr->nusefulsepaconss-1] = cons;
432          conshdlr->sepaconss[cons->sepaconsspos] = tmpcons;
433          tmpcons->sepaconsspos = cons->sepaconsspos;
434          cons->sepaconsspos = conshdlr->nusefulsepaconss-1;
435 
436          conshdlr->nusefulsepaconss--;
437       }
438       if( cons->enforce )
439       {
440          assert(0 <= cons->enfoconsspos && cons->enfoconsspos < conshdlr->nusefulenfoconss);
441 
442          if( cons->enfoconsspos < conshdlr->lastnusefulenfoconss )
443             conshdlr->lastnusefulenfoconss--;
444          else
445          {
446             /* the constraint that becomes obsolete is not yet enforced on the current solution:
447              * we have to make sure that it will be enforced the next time; this is not done, if the current
448              * solution was already enforced and only enforcement on the additional constraints is performed
449              * (because in this case, only the new useful constraints are enforced);
450              * thus, we have to reset the enforcement counters in order to enforce all constraints again, especially
451              * the now obsolete one;
452              * this case should occur almost never, because a constraint that was not enforced in the last enforcement
453              * is a newly added one, and it is very unlikely that this constraint will become obsolete before the next
454              * enforcement call;
455              * this reset is not performed for separation and propagation, because they are not vital for correctness
456              */
457             conshdlr->lastenfolplpcount = -1;
458             conshdlr->lastenfolpdomchgcount = -1;
459             conshdlr->lastenfopsdomchgcount = -1;
460             conshdlr->lastenforelaxdomchgcount = -1;
461             conshdlr->lastenforelaxrelaxcount = -1;
462             conshdlr->lastenfolpnode = -1;
463             conshdlr->lastenfopsnode = -1;
464          }
465 
466          /* switch the last useful (non-obsolete) enfo constraint with this constraint */
467          tmpcons = conshdlr->enfoconss[conshdlr->nusefulenfoconss-1];
468          assert(tmpcons->enfoconsspos == conshdlr->nusefulenfoconss-1);
469 
470          conshdlr->enfoconss[conshdlr->nusefulenfoconss-1] = cons;
471          conshdlr->enfoconss[cons->enfoconsspos] = tmpcons;
472          tmpcons->enfoconsspos = cons->enfoconsspos;
473          cons->enfoconsspos = conshdlr->nusefulenfoconss-1;
474 
475          conshdlr->nusefulenfoconss--;
476       }
477       /* in case the constraint is marked to be propagated, we do not move it in the propconss array since the first
478        * part of the array contains all marked constraints independently of their age
479        */
480       assert((!cons->markpropagate) == (cons->propconsspos < conshdlr->nmarkedpropconss));
481       if( cons->propagate && cons->propenabled && !cons->markpropagate )
482       {
483          assert(0 <= cons->propconsspos && cons->propconsspos < conshdlr->nusefulpropconss);
484 
485          if( cons->propconsspos < conshdlr->lastnusefulpropconss )
486             conshdlr->lastnusefulpropconss--;
487 
488          /* switch the last useful (non-obsolete) prop constraint with this constraint */
489          tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss-1];
490          assert(tmpcons->propconsspos == conshdlr->nusefulpropconss-1);
491 
492          conshdlr->propconss[conshdlr->nusefulpropconss-1] = cons;
493          conshdlr->propconss[cons->propconsspos] = tmpcons;
494          tmpcons->propconsspos = cons->propconsspos;
495          cons->propconsspos = conshdlr->nusefulpropconss-1;
496 
497          conshdlr->nusefulpropconss--;
498       }
499    }
500 
501    checkConssArrays(conshdlr);
502 
503    return SCIP_OKAY;
504 }
505 
506 /** marks obsolete constraint to be not obsolete anymore;
507  *  it will be moved to the first part of the constraint arrays, such that it is checked, enforced, separated,
508  *  and propagated before the obsolete constraints
509  */
510 static
conshdlrMarkConsUseful(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)511 SCIP_RETCODE conshdlrMarkConsUseful(
512    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
513    SCIP_CONS*            cons                /**< constraint to be marked obsolete */
514    )
515 {
516    SCIP_CONS* tmpcons;
517 
518    assert(conshdlr != NULL);
519    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
520    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
521    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
522    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
523    assert(cons != NULL);
524    assert(!cons->original);
525    assert(cons->obsolete);
526    assert(!conshdlrAreUpdatesDelayed(conshdlr));
527 
528    cons->obsolete = FALSE;
529 
530    if( cons->active )
531    {
532       if( cons->check )
533       {
534          assert(conshdlr->nusefulcheckconss <= cons->checkconsspos && cons->checkconsspos < conshdlr->ncheckconss);
535 
536          /* switch the first obsolete check constraint with this constraint */
537          tmpcons = conshdlr->checkconss[conshdlr->nusefulcheckconss];
538          assert(tmpcons->checkconsspos == conshdlr->nusefulcheckconss);
539 
540          conshdlr->checkconss[conshdlr->nusefulcheckconss] = cons;
541          conshdlr->checkconss[cons->checkconsspos] = tmpcons;
542          tmpcons->checkconsspos = cons->checkconsspos;
543          cons->checkconsspos = conshdlr->nusefulcheckconss;
544 
545          conshdlr->nusefulcheckconss++;
546       }
547    }
548    if( cons->enabled )
549    {
550       if( cons->separate && cons->sepaenabled )
551       {
552          assert(conshdlr->nusefulsepaconss <= cons->sepaconsspos && cons->sepaconsspos < conshdlr->nsepaconss);
553 
554          /* switch the first obsolete sepa constraint with this constraint */
555          tmpcons = conshdlr->sepaconss[conshdlr->nusefulsepaconss];
556          assert(tmpcons->sepaconsspos == conshdlr->nusefulsepaconss);
557 
558          conshdlr->sepaconss[conshdlr->nusefulsepaconss] = cons;
559          conshdlr->sepaconss[cons->sepaconsspos] = tmpcons;
560          tmpcons->sepaconsspos = cons->sepaconsspos;
561          cons->sepaconsspos = conshdlr->nusefulsepaconss;
562 
563          conshdlr->nusefulsepaconss++;
564       }
565       if( cons->enforce )
566       {
567          assert(conshdlr->nusefulenfoconss <= cons->enfoconsspos && cons->enfoconsspos < conshdlr->nenfoconss);
568 
569          /* switch the first obsolete enfo constraint with this constraint */
570          tmpcons = conshdlr->enfoconss[conshdlr->nusefulenfoconss];
571          assert(tmpcons->enfoconsspos == conshdlr->nusefulenfoconss);
572 
573          conshdlr->enfoconss[conshdlr->nusefulenfoconss] = cons;
574          conshdlr->enfoconss[cons->enfoconsspos] = tmpcons;
575          tmpcons->enfoconsspos = cons->enfoconsspos;
576          cons->enfoconsspos = conshdlr->nusefulenfoconss;
577 
578          conshdlr->nusefulenfoconss++;
579       }
580       /* in case the constraint is marked to be propagated, we do not move it in the propconss array since the first
581        * part of the array contains all marked constraints independently of their age
582        */
583       assert((!cons->markpropagate) == (cons->propconsspos < conshdlr->nmarkedpropconss));
584       if( cons->propagate && cons->propenabled && !cons->markpropagate)
585       {
586          assert(conshdlr->nusefulpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->npropconss);
587 
588          /* switch the first obsolete prop constraint with this constraint */
589          tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss];
590          assert(tmpcons->propconsspos == conshdlr->nusefulpropconss);
591 
592          conshdlr->propconss[conshdlr->nusefulpropconss] = cons;
593          conshdlr->propconss[cons->propconsspos] = tmpcons;
594          tmpcons->propconsspos = cons->propconsspos;
595          cons->propconsspos = conshdlr->nusefulpropconss;
596 
597          conshdlr->nusefulpropconss++;
598       }
599    }
600 
601    checkConssArrays(conshdlr);
602 
603    return SCIP_OKAY;
604 }
605 
606 /** marks constraint to be propagated in the next propagation round;
607  *
608  *  @note the propagation array is divided into three parts in contrast to the other constraint arrays;
609  *        the first part contains constraints which were marked to be propagated (independently of its age)
610  *        the second part contains the useful (non-obsolete) constraints which are not marked to be propagated
611  *        finally, the third part contains obsolete constraints which are not marked to be propagated
612  *
613  *  @note if a constraint gets marked for propagation we put it into the first part regardless of its age
614  */
615 static
conshdlrMarkConsPropagate(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)616 void conshdlrMarkConsPropagate(
617    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
618    SCIP_CONS*            cons                /**< constraint to be marked obsolete */
619    )
620 {
621    SCIP_CONS* tmpcons;
622 
623    assert(conshdlr != NULL);
624    assert(conshdlr->nmarkedpropconss <= conshdlr->nusefulpropconss);
625    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
626    assert(cons != NULL);
627    assert(!cons->original);
628 
629    /* it may happen that the constraint is deleted while updates are delayed: in this case we just return */
630    if( !cons->enabled )
631       return;
632 
633    if( cons->markpropagate )
634       return;
635 
636    cons->markpropagate = TRUE;
637 
638    /* propagation of the constraint is globally or locally disabled, so we do not have to move the constraint in the
639     * propconss array
640     */
641    if( !cons->propagate || !cons->propenabled )
642    {
643       assert(cons->propconsspos == -1);
644       return;
645    }
646    assert(cons->propconsspos >= conshdlr->nmarkedpropconss);
647 
648    /* if the constraint is obsolete, we need to move it first to the non-obsolete part of the array */
649    if( cons->obsolete )
650    {
651       assert(conshdlr->nusefulpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->npropconss);
652 
653       /* switch the first obsolete prop constraint with this constraint */
654       tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss];
655       assert(tmpcons->propconsspos == conshdlr->nusefulpropconss);
656 
657       conshdlr->propconss[conshdlr->nusefulpropconss] = cons;
658       conshdlr->propconss[cons->propconsspos] = tmpcons;
659       tmpcons->propconsspos = cons->propconsspos;
660       cons->propconsspos = conshdlr->nusefulpropconss;
661 
662       conshdlr->nusefulpropconss++;
663    }
664    assert(conshdlr->nmarkedpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->nusefulpropconss);
665 
666    /* switch the first useful prop constraint with this constraint */
667    tmpcons = conshdlr->propconss[conshdlr->nmarkedpropconss];
668    assert(tmpcons->propconsspos == conshdlr->nmarkedpropconss);
669 
670    conshdlr->propconss[conshdlr->nmarkedpropconss] = cons;
671    conshdlr->propconss[cons->propconsspos] = tmpcons;
672    tmpcons->propconsspos = cons->propconsspos;
673    cons->propconsspos = conshdlr->nmarkedpropconss;
674 
675    conshdlr->nmarkedpropconss++;
676    assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss);
677 
678    checkConssArrays(conshdlr);
679 }
680 
681 /** unmarks constraint to be propagated in the next propagation round;
682  *
683  *  @note the propagation array is divided into three parts in contrast to the other constraint arrays;
684  *        the first part contains constraints which were marked to be propagated (independently of its age)
685  *        the second part contains the useful (non-obsolete) constraints which are not marked to be propagated
686  *        finally, the third part contains obsolete constraints which are not marked to be propagated
687  *
688  *  @note if a constraint gets unmarked for propagation, it is put into the right part depending on its age
689  */
690 static
conshdlrUnmarkConsPropagate(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)691 void conshdlrUnmarkConsPropagate(
692    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
693    SCIP_CONS*            cons                /**< constraint to be marked obsolete */
694    )
695 {
696    SCIP_CONS* tmpcons;
697 
698    assert(conshdlr != NULL);
699    assert(conshdlr->nmarkedpropconss <= conshdlr->nusefulpropconss);
700    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
701    assert(cons != NULL);
702    assert(!cons->original);
703 
704    /* it may happen that the constraint is deleted while updates are delayed: in this case we just return */
705    if( !cons->enabled )
706       return;
707 
708    if( !cons->markpropagate )
709       return;
710 
711    cons->markpropagate = FALSE;
712 
713    /* propagation of the constraint is globally or locally disabled, so we do not have to move the constraint in the
714     * propconss array
715     */
716    if( !cons->propagate || !cons->propenabled )
717    {
718       assert(cons->propconsspos == -1);
719       return;
720    }
721    assert(cons->propconsspos >= 0);
722    assert(cons->propconsspos < conshdlr->nmarkedpropconss);
723 
724    /* first, move the constraint out of the first part to the second part of the constraint array */
725    if( cons->propconsspos < conshdlr->nmarkedpropconss - 1 )
726    {
727       conshdlr->nmarkedpropconss--;
728 
729       /* switch the last marked prop constraint with this constraint */
730       tmpcons = conshdlr->propconss[conshdlr->nmarkedpropconss];
731       assert(tmpcons->propconsspos == conshdlr->nmarkedpropconss);
732 
733       conshdlr->propconss[conshdlr->nmarkedpropconss] = cons;
734       conshdlr->propconss[cons->propconsspos] = tmpcons;
735       tmpcons->propconsspos = cons->propconsspos;
736       cons->propconsspos = conshdlr->nmarkedpropconss;
737    }
738    else if( cons->propconsspos == conshdlr->nmarkedpropconss - 1 )
739       conshdlr->nmarkedpropconss--;
740    assert(cons->propconsspos == conshdlr->nmarkedpropconss);
741 
742    /* if the constraint is obsolete, move it to the last part of the constraint array */
743    if( cons->obsolete )
744    {
745       conshdlr->nusefulpropconss--;
746 
747       /* switch the last useful prop constraint with this constraint */
748       tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss];
749       assert(tmpcons->propconsspos == conshdlr->nusefulpropconss);
750 
751       conshdlr->propconss[conshdlr->nusefulpropconss] = cons;
752       conshdlr->propconss[cons->propconsspos] = tmpcons;
753       tmpcons->propconsspos = cons->propconsspos;
754       cons->propconsspos = conshdlr->nusefulpropconss;
755    }
756 
757    checkConssArrays(conshdlr);
758 }
759 
760 
761 /** adds constraint to the conss array of constraint handler */
762 static
conshdlrAddCons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)763 SCIP_RETCODE conshdlrAddCons(
764    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
765    SCIP_SET*             set,                /**< global SCIP settings */
766    SCIP_CONS*            cons                /**< constraint to add */
767    )
768 {
769    assert(conshdlr != NULL);
770    assert(cons != NULL);
771    assert(cons->conshdlr == conshdlr);
772    assert(!cons->original);
773    assert(!cons->active);
774    assert(cons->consspos == -1);
775    assert(set != NULL);
776    assert(cons->scip == set->scip);
777 
778    /* insert the constraint as inactive constraint into the transformed constraints array */
779    SCIP_CALL( conshdlrEnsureConssMem(conshdlr, set, conshdlr->nconss+1) );
780    conshdlr->conss[conshdlr->nconss] = cons;
781    cons->consspos = conshdlr->nconss;
782    conshdlr->nconss++;
783 
784    return SCIP_OKAY;
785 }
786 
787 /** deletes constraint from the conss array of constraint handler */
788 static
conshdlrDelCons(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)789 void conshdlrDelCons(
790    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
791    SCIP_CONS*            cons                /**< constraint to remove */
792    )
793 {
794    assert(conshdlr != NULL);
795    assert(cons != NULL);
796    assert(cons->conshdlr == conshdlr);
797    assert(!cons->original);
798    assert(!cons->active);
799    assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss);
800 
801    conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nconss-1];
802    conshdlr->conss[cons->consspos]->consspos = cons->consspos;
803    conshdlr->nconss--;
804    cons->consspos = -1;
805 }
806 
807 /** adds constraint to the initconss array of constraint handler */
808 static
conshdlrAddInitcons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_STAT * stat,SCIP_CONS * cons)809 SCIP_RETCODE conshdlrAddInitcons(
810    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
811    SCIP_SET*             set,                /**< global SCIP settings */
812    SCIP_STAT*            stat,               /**< dynamic problem statistics */
813    SCIP_CONS*            cons                /**< constraint to add */
814    )
815 {
816    int insertpos;
817 
818    assert(conshdlr != NULL);
819    assert(cons != NULL);
820    assert(cons->conshdlr == conshdlr);
821    assert(!cons->original);
822    assert(cons->active);
823    assert(cons->initial);
824    assert(cons->initconsspos == -1 || cons->initconsspos < conshdlr->ninitconsskept);
825 
826    SCIP_CALL( conshdlrEnsureInitconssMem(conshdlr, set, conshdlr->ninitconss+1) );
827 
828    insertpos = conshdlr->ninitconss;
829 
830    conshdlr->initconss[insertpos] = cons;
831    conshdlr->ninitconss++;
832    stat->ninitconssadded++;
833 
834    /* if the constraint is kept, we keep the stored position at the beginning of the array */
835    if( cons->initconsspos == -1 )
836       cons->initconsspos = insertpos;
837 
838    checkConssArrays(conshdlr);
839 
840    return SCIP_OKAY;
841 }
842 
843 /** deletes constraint from the initconss array of constraint handler */
844 static
conshdlrDelInitcons(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)845 void conshdlrDelInitcons(
846    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
847    SCIP_CONS*            cons                /**< constraint to remove */
848    )
849 {
850    int delpos;
851 
852    assert(conshdlr != NULL);
853    assert(cons != NULL);
854    assert(cons->conshdlr == conshdlr);
855    assert(!cons->original);
856    assert(0 <= cons->initconsspos && cons->initconsspos < conshdlr->ninitconss);
857 
858    delpos = cons->initconsspos;
859    if( delpos < conshdlr->ninitconsskept )
860    {
861       conshdlr->ninitconsskept--;
862       conshdlr->initconss[delpos] = conshdlr->initconss[conshdlr->ninitconsskept];
863       conshdlr->initconss[delpos]->initconsspos = delpos;
864       delpos = conshdlr->ninitconsskept;
865    }
866 
867    if( delpos < conshdlr->ninitconss-1 )
868    {
869       conshdlr->initconss[delpos] = conshdlr->initconss[conshdlr->ninitconss-1];
870       conshdlr->initconss[delpos]->initconsspos = delpos;
871    }
872    conshdlr->ninitconss--;
873    cons->initconsspos = -1;
874 
875    checkConssArrays(conshdlr);
876 }
877 
878 /** adds constraint to the sepaconss array of constraint handler */
879 static
conshdlrAddSepacons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)880 SCIP_RETCODE conshdlrAddSepacons(
881    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
882    SCIP_SET*             set,                /**< global SCIP settings */
883    SCIP_CONS*            cons                /**< constraint to add */
884    )
885 {
886    int insertpos;
887 
888    assert(conshdlr != NULL);
889    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
890    assert(cons != NULL);
891    assert(cons->conshdlr == conshdlr);
892    assert(!cons->original);
893    assert(cons->active);
894    assert(cons->separate);
895    assert(cons->sepaenabled);
896    assert(cons->sepaconsspos == -1);
897    assert(set != NULL);
898    assert(cons->scip == set->scip);
899    assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringsepa);
900 
901    SCIP_CALL( conshdlrEnsureSepaconssMem(conshdlr, set, conshdlr->nsepaconss+1) );
902    insertpos = conshdlr->nsepaconss;
903    if( !cons->obsolete )
904    {
905       if( conshdlr->nusefulsepaconss < conshdlr->nsepaconss )
906       {
907          conshdlr->sepaconss[conshdlr->nsepaconss] = conshdlr->sepaconss[conshdlr->nusefulsepaconss];
908          conshdlr->sepaconss[conshdlr->nsepaconss]->sepaconsspos = conshdlr->nsepaconss;
909          insertpos = conshdlr->nusefulsepaconss;
910       }
911       conshdlr->nusefulsepaconss++;
912    }
913    conshdlr->sepaconss[insertpos] = cons;
914    cons->sepaconsspos = insertpos;
915    conshdlr->nsepaconss++;
916 
917    checkConssArrays(conshdlr);
918 
919    return SCIP_OKAY;
920 }
921 
922 /** deletes constraint from the sepaconss array of constraint handler */
923 static
conshdlrDelSepacons(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)924 void conshdlrDelSepacons(
925    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
926    SCIP_CONS*            cons                /**< constraint to remove */
927    )
928 {
929    int delpos;
930 
931    assert(conshdlr != NULL);
932    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
933    assert(cons != NULL);
934    assert(cons->conshdlr == conshdlr);
935    assert(!cons->original);
936    assert(cons->separate);
937    assert(cons->sepaenabled);
938    assert(cons->sepaconsspos != -1);
939    assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringsepa);
940 
941    delpos = cons->sepaconsspos;
942    if( !cons->obsolete )
943    {
944       assert(0 <= delpos && delpos < conshdlr->nusefulsepaconss);
945 
946       if( delpos < conshdlr->lastnusefulsepaconss )
947          conshdlr->lastnusefulsepaconss--;
948 
949       conshdlr->sepaconss[delpos] = conshdlr->sepaconss[conshdlr->nusefulsepaconss-1];
950       conshdlr->sepaconss[delpos]->sepaconsspos = delpos;
951       delpos = conshdlr->nusefulsepaconss-1;
952       conshdlr->nusefulsepaconss--;
953       assert(conshdlr->nusefulsepaconss >= 0);
954       assert(conshdlr->lastnusefulsepaconss >= 0);
955    }
956    assert(conshdlr->nusefulsepaconss <= delpos && delpos < conshdlr->nsepaconss);
957    if( delpos < conshdlr->nsepaconss-1 )
958    {
959       conshdlr->sepaconss[delpos] = conshdlr->sepaconss[conshdlr->nsepaconss-1];
960       conshdlr->sepaconss[delpos]->sepaconsspos = delpos;
961    }
962    conshdlr->nsepaconss--;
963    cons->sepaconsspos = -1;
964 
965    checkConssArrays(conshdlr);
966 }
967 
968 /** adds constraint to the enfoconss array of constraint handler */
969 static
conshdlrAddEnfocons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)970 SCIP_RETCODE conshdlrAddEnfocons(
971    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
972    SCIP_SET*             set,                /**< global SCIP settings */
973    SCIP_CONS*            cons                /**< constraint to add */
974    )
975 {
976    int insertpos;
977 
978    assert(conshdlr != NULL);
979    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
980    assert(cons != NULL);
981    assert(cons->conshdlr == conshdlr);
982    assert(!cons->original);
983    assert(cons->active);
984    assert(cons->enforce);
985    assert(cons->enfoconsspos == -1);
986    assert(set != NULL);
987    assert(cons->scip == set->scip);
988 
989    SCIP_CALL( conshdlrEnsureEnfoconssMem(conshdlr, set, conshdlr->nenfoconss+1) );
990    insertpos = conshdlr->nenfoconss;
991    if( !cons->obsolete )
992    {
993       if( conshdlr->nusefulenfoconss < conshdlr->nenfoconss )
994       {
995          conshdlr->enfoconss[conshdlr->nenfoconss] = conshdlr->enfoconss[conshdlr->nusefulenfoconss];
996          conshdlr->enfoconss[conshdlr->nenfoconss]->enfoconsspos = conshdlr->nenfoconss;
997          insertpos = conshdlr->nusefulenfoconss;
998       }
999       conshdlr->nusefulenfoconss++;
1000    }
1001    else
1002    {
1003       /* we have to make sure that even this obsolete constraint is enforced in the next enforcement call;
1004        * if the same LP or pseudo solution is enforced again, only the newly added useful constraints are
1005        * enforced; thus, we have to reset the enforcement counters and force all constraints to be
1006        * enforced again; this is not needed for separation and propagation, because they are not vital for correctness
1007        */
1008       conshdlr->lastenfolplpcount = -1;
1009       conshdlr->lastenfolpdomchgcount = -1;
1010       conshdlr->lastenfopsdomchgcount = -1;
1011       conshdlr->lastenforelaxdomchgcount = -1;
1012       conshdlr->lastenforelaxrelaxcount = -1;
1013       conshdlr->lastenfolpnode = -1;
1014       conshdlr->lastenfopsnode = -1;
1015    }
1016    conshdlr->enfoconss[insertpos] = cons;
1017    cons->enfoconsspos = insertpos;
1018    conshdlr->nenfoconss++;
1019 
1020    checkConssArrays(conshdlr);
1021 
1022    return SCIP_OKAY;
1023 }
1024 
1025 /** deletes constraint from the enfoconss array of constraint handler */
1026 static
conshdlrDelEnfocons(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)1027 void conshdlrDelEnfocons(
1028    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1029    SCIP_CONS*            cons                /**< constraint to remove */
1030    )
1031 {
1032    int delpos;
1033 
1034    assert(conshdlr != NULL);
1035    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1036    assert(cons != NULL);
1037    assert(cons->conshdlr == conshdlr);
1038    assert(!cons->original);
1039    assert(cons->enforce);
1040    assert(cons->enfoconsspos != -1);
1041 
1042    delpos = cons->enfoconsspos;
1043    if( !cons->obsolete )
1044    {
1045       assert(0 <= delpos && delpos < conshdlr->nusefulenfoconss);
1046 
1047       if( delpos < conshdlr->lastnusefulenfoconss )
1048          conshdlr->lastnusefulenfoconss--;
1049 
1050       conshdlr->enfoconss[delpos] = conshdlr->enfoconss[conshdlr->nusefulenfoconss-1];
1051       conshdlr->enfoconss[delpos]->enfoconsspos = delpos;
1052       delpos = conshdlr->nusefulenfoconss-1;
1053       conshdlr->nusefulenfoconss--;
1054 
1055       /* if the constraint that moved to the free position was a newly added constraint and not enforced in the last
1056        * enforcement, we have to make sure it will be enforced in the next run;
1057        * this check is not performed for separation and propagation, because they are not vital for correctness
1058        */
1059       if( delpos >= conshdlr->lastnusefulenfoconss )
1060          conshdlr->lastnusefulenfoconss = cons->enfoconsspos;
1061 
1062       assert(conshdlr->nusefulenfoconss >= 0);
1063       assert(conshdlr->lastnusefulenfoconss >= 0);
1064    }
1065    assert(conshdlr->nusefulenfoconss <= delpos && delpos < conshdlr->nenfoconss);
1066    if( delpos < conshdlr->nenfoconss-1 )
1067    {
1068       conshdlr->enfoconss[delpos] = conshdlr->enfoconss[conshdlr->nenfoconss-1];
1069       conshdlr->enfoconss[delpos]->enfoconsspos = delpos;
1070    }
1071    conshdlr->nenfoconss--;
1072    cons->enfoconsspos = -1;
1073 
1074    checkConssArrays(conshdlr);
1075 }
1076 
1077 /** adds constraint to the checkconss array of constraint handler */
1078 static
conshdlrAddCheckcons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)1079 SCIP_RETCODE conshdlrAddCheckcons(
1080    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1081    SCIP_SET*             set,                /**< global SCIP settings */
1082    SCIP_CONS*            cons                /**< constraint to add */
1083    )
1084 {
1085    int insertpos;
1086 
1087    assert(conshdlr != NULL);
1088    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1089    assert(cons != NULL);
1090    assert(cons->conshdlr == conshdlr);
1091    assert(!cons->original);
1092    assert(cons->active);
1093    assert(cons->check);
1094    assert(cons->checkconsspos == -1);
1095    assert(set != NULL);
1096    assert(cons->scip == set->scip);
1097 
1098    SCIP_CALL( conshdlrEnsureCheckconssMem(conshdlr, set, conshdlr->ncheckconss+1) );
1099    insertpos = conshdlr->ncheckconss;
1100    if( !cons->obsolete )
1101    {
1102       if( conshdlr->nusefulcheckconss < conshdlr->ncheckconss )
1103       {
1104          assert(conshdlr->checkconss[conshdlr->nusefulcheckconss] != NULL);
1105          conshdlr->checkconss[conshdlr->ncheckconss] = conshdlr->checkconss[conshdlr->nusefulcheckconss];
1106          conshdlr->checkconss[conshdlr->ncheckconss]->checkconsspos = conshdlr->ncheckconss;
1107          insertpos = conshdlr->nusefulcheckconss;
1108       }
1109       conshdlr->nusefulcheckconss++;
1110    }
1111    assert(0 <= insertpos && insertpos <= conshdlr->ncheckconss);
1112    conshdlr->checkconss[insertpos] = cons;
1113    cons->checkconsspos = insertpos;
1114    conshdlr->ncheckconss++;
1115 
1116    checkConssArrays(conshdlr);
1117 
1118    return SCIP_OKAY;
1119 }
1120 
1121 /** deletes constraint from the checkconss array of constraint handler */
1122 static
conshdlrDelCheckcons(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)1123 void conshdlrDelCheckcons(
1124    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1125    SCIP_CONS*            cons                /**< constraint to add */
1126    )
1127 {
1128    int delpos;
1129 
1130    assert(conshdlr != NULL);
1131    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1132    assert(cons != NULL);
1133    assert(cons->conshdlr == conshdlr);
1134    assert(!cons->original);
1135    assert(cons->active);
1136    assert(cons->check);
1137    assert(cons->checkconsspos != -1);
1138 
1139    delpos = cons->checkconsspos;
1140    if( !cons->obsolete )
1141    {
1142       assert(0 <= delpos && delpos < conshdlr->nusefulcheckconss);
1143       conshdlr->checkconss[delpos] = conshdlr->checkconss[conshdlr->nusefulcheckconss-1];
1144       conshdlr->checkconss[delpos]->checkconsspos = delpos;
1145       delpos = conshdlr->nusefulcheckconss-1;
1146       conshdlr->nusefulcheckconss--;
1147    }
1148    assert(conshdlr->nusefulcheckconss <= delpos && delpos < conshdlr->ncheckconss);
1149    if( delpos < conshdlr->ncheckconss-1 )
1150    {
1151       conshdlr->checkconss[delpos] = conshdlr->checkconss[conshdlr->ncheckconss-1];
1152       conshdlr->checkconss[delpos]->checkconsspos = delpos;
1153    }
1154    conshdlr->ncheckconss--;
1155    cons->checkconsspos = -1;
1156 
1157    checkConssArrays(conshdlr);
1158 }
1159 
1160 /** adds constraint to the propconss array of constraint handler */
1161 static
conshdlrAddPropcons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)1162 SCIP_RETCODE conshdlrAddPropcons(
1163    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1164    SCIP_SET*             set,                /**< global SCIP settings */
1165    SCIP_CONS*            cons                /**< constraint to add */
1166    )
1167 {
1168    int insertpos;
1169 
1170    assert(conshdlr != NULL);
1171    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1172    assert(cons != NULL);
1173    assert(cons->conshdlr == conshdlr);
1174    assert(!cons->original);
1175    assert(cons->active);
1176    assert(cons->enabled);
1177    assert(cons->propagate);
1178    assert(cons->propenabled);
1179    assert(cons->propconsspos == -1);
1180    assert(set != NULL);
1181    assert(cons->scip == set->scip);
1182    assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringprop);
1183 
1184    /* add constraint to the propagation array */
1185    SCIP_CALL( conshdlrEnsurePropconssMem(conshdlr, set, conshdlr->npropconss+1) );
1186    insertpos = conshdlr->npropconss;
1187    if( !cons->obsolete )
1188    {
1189       if( conshdlr->nusefulpropconss < conshdlr->npropconss )
1190       {
1191          conshdlr->propconss[conshdlr->npropconss] = conshdlr->propconss[conshdlr->nusefulpropconss];
1192          conshdlr->propconss[conshdlr->npropconss]->propconsspos = conshdlr->npropconss;
1193          insertpos = conshdlr->nusefulpropconss;
1194       }
1195       conshdlr->nusefulpropconss++;
1196    }
1197    conshdlr->propconss[insertpos] = cons;
1198    cons->propconsspos = insertpos;
1199    conshdlr->npropconss++;
1200 
1201    /* if the constraint is marked to be propagated, we have to move it to the first part of the array */
1202    if( cons->markpropagate )
1203    {
1204       /* temporarily unmark the constraint to be propagated, such that we can use the method below */
1205       cons->markpropagate = FALSE;
1206 
1207       conshdlrMarkConsPropagate(cons->conshdlr, cons);
1208       assert(cons->markpropagate);
1209    }
1210 
1211    checkConssArrays(conshdlr);
1212 
1213    return SCIP_OKAY;
1214 }
1215 
1216 /** deletes constraint from the propconss array of constraint handler */
1217 static
conshdlrDelPropcons(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)1218 void conshdlrDelPropcons(
1219    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1220    SCIP_CONS*            cons                /**< constraint to remove */
1221    )
1222 {
1223    int delpos;
1224 
1225    assert(conshdlr != NULL);
1226    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1227    assert(cons != NULL);
1228    assert(cons->conshdlr == conshdlr);
1229    assert(!cons->original);
1230    assert(cons->propagate);
1231    assert(cons->propenabled);
1232    assert(cons->propconsspos != -1);
1233    assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringprop);
1234 
1235    /* unmark constraint to be propagated; this will move the constraint to the obsolete or non-obsolete part of the
1236     * array, depending on its age
1237     */
1238    if( cons->markpropagate )
1239    {
1240       conshdlrUnmarkConsPropagate(cons->conshdlr, cons);
1241       assert(!cons->markpropagate);
1242    }
1243 
1244    /* delete constraint from the propagation array */
1245    delpos = cons->propconsspos;
1246    assert(delpos >= conshdlr->nmarkedpropconss);
1247    if( !cons->obsolete )
1248    {
1249       assert(0 <= delpos && delpos < conshdlr->nusefulpropconss);
1250 
1251       if( delpos < conshdlr->lastnusefulpropconss )
1252          conshdlr->lastnusefulpropconss--;
1253 
1254       conshdlr->propconss[delpos] = conshdlr->propconss[conshdlr->nusefulpropconss-1];
1255       conshdlr->propconss[delpos]->propconsspos = delpos;
1256       delpos = conshdlr->nusefulpropconss-1;
1257       conshdlr->nusefulpropconss--;
1258       assert(conshdlr->nusefulpropconss >= 0);
1259       assert(conshdlr->lastnusefulpropconss >= 0);
1260    }
1261    assert(conshdlr->nusefulpropconss <= delpos && delpos < conshdlr->npropconss);
1262 
1263    if( delpos < conshdlr->npropconss-1 )
1264    {
1265       conshdlr->propconss[delpos] = conshdlr->propconss[conshdlr->npropconss-1];
1266       conshdlr->propconss[delpos]->propconsspos = delpos;
1267    }
1268    conshdlr->npropconss--;
1269    cons->propconsspos = -1;
1270    assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss);
1271 
1272    checkConssArrays(conshdlr);
1273 }
1274 
1275 /** enables separation of constraint */
1276 static
conshdlrEnableConsSeparation(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)1277 SCIP_RETCODE conshdlrEnableConsSeparation(
1278    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1279    SCIP_SET*             set,                /**< global SCIP settings */
1280    SCIP_CONS*            cons                /**< constraint to add */
1281    )
1282 {
1283    assert(conshdlr != NULL);
1284    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1285    assert(cons != NULL);
1286    assert(cons->conshdlr == conshdlr);
1287    assert(!cons->sepaenabled);
1288    assert(cons->sepaconsspos == -1);
1289    assert(set != NULL);
1290    assert(cons->scip == set->scip);
1291 
1292    SCIPsetDebugMsg(set, "enable separation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1293 
1294    /* enable separation of constraint */
1295    cons->sepaenabled = TRUE;
1296 
1297    /* add constraint to the separation array */
1298    if( cons->enabled && cons->separate )
1299    {
1300       SCIP_CALL( conshdlrAddSepacons(conshdlr, set, cons) );
1301    }
1302 
1303    return SCIP_OKAY;
1304 }
1305 
1306 /** disables separation of constraint */
1307 static
conshdlrDisableConsSeparation(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)1308 SCIP_RETCODE conshdlrDisableConsSeparation(
1309    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1310    SCIP_CONS*            cons                /**< constraint to remove */
1311    )
1312 {
1313    assert(conshdlr != NULL);
1314    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1315    assert(cons != NULL);
1316    assert(cons->conshdlr == conshdlr);
1317    assert(cons->sepaenabled);
1318    assert((cons->separate && cons->enabled) == (cons->sepaconsspos != -1));
1319 
1320    SCIPdebugMessage("disable separation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1321 
1322    /* delete constraint from the separation array */
1323    if( cons->separate && cons->enabled )
1324    {
1325       conshdlrDelSepacons(conshdlr, cons);
1326    }
1327    assert(cons->sepaconsspos == -1);
1328 
1329    /* disable separation of constraint */
1330    cons->sepaenabled = FALSE;
1331 
1332    return SCIP_OKAY;
1333 }
1334 
1335 /** enables propagation of constraint */
1336 static
conshdlrEnableConsPropagation(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)1337 SCIP_RETCODE conshdlrEnableConsPropagation(
1338    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1339    SCIP_SET*             set,                /**< global SCIP settings */
1340    SCIP_CONS*            cons                /**< constraint to add */
1341    )
1342 {
1343    assert(conshdlr != NULL);
1344    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1345    assert(cons != NULL);
1346    assert(cons->conshdlr == conshdlr);
1347    assert(!cons->propenabled);
1348    assert(cons->propconsspos == -1);
1349    assert(set != NULL);
1350    assert(cons->scip == set->scip);
1351 
1352    SCIPsetDebugMsg(set, "enable propagation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1353 
1354    /* enable propagation of constraint */
1355    cons->propenabled = TRUE;
1356 
1357    /* add constraint to the propagation array */
1358    if( cons->enabled && cons->propagate )
1359    {
1360       SCIP_CALL( conshdlrAddPropcons(conshdlr, set, cons) );
1361    }
1362 
1363    return SCIP_OKAY;
1364 }
1365 
1366 /** disables propagation of constraint */
1367 static
conshdlrDisableConsPropagation(SCIP_CONSHDLR * conshdlr,SCIP_CONS * cons)1368 SCIP_RETCODE conshdlrDisableConsPropagation(
1369    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1370    SCIP_CONS*            cons                /**< constraint to remove */
1371    )
1372 {
1373    assert(conshdlr != NULL);
1374    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1375    assert(cons != NULL);
1376    assert(cons->conshdlr == conshdlr);
1377    assert(cons->propenabled);
1378    assert((cons->propagate && cons->enabled) == (cons->propconsspos != -1));
1379 
1380    SCIPdebugMessage("disable propagation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1381 
1382    /* delete constraint from the propagation array */
1383    if( cons->propagate && cons->enabled )
1384    {
1385       conshdlrDelPropcons(conshdlr, cons);
1386    }
1387    assert(cons->propconsspos == -1);
1388 
1389    /* disable propagation of constraint */
1390    cons->propenabled = FALSE;
1391 
1392    return SCIP_OKAY;
1393 }
1394 
1395 /** enables separation, enforcement, and propagation of constraint */
1396 static
conshdlrEnableCons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_STAT * stat,SCIP_CONS * cons)1397 SCIP_RETCODE conshdlrEnableCons(
1398    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1399    SCIP_SET*             set,                /**< global SCIP settings */
1400    SCIP_STAT*            stat,               /**< dynamic problem statistics */
1401    SCIP_CONS*            cons                /**< constraint to add */
1402    )
1403 {
1404    assert(conshdlr != NULL);
1405    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1406    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1407    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1408    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1409    assert(set != NULL);
1410    assert(stat != NULL);
1411    assert(cons != NULL);
1412    assert(cons->scip == set->scip);
1413    assert(cons->conshdlr == conshdlr);
1414    assert(!cons->original);
1415    assert(cons->active);
1416    assert(!cons->enabled);
1417    assert(cons->sepaconsspos == -1);
1418    assert(cons->enfoconsspos == -1);
1419    assert(cons->propconsspos == -1);
1420 
1421    SCIPsetDebugMsg(set, "enable constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1422 
1423    /* enable constraint */
1424    cons->enabled = TRUE;
1425    conshdlr->nenabledconss++;
1426    stat->nenabledconss++;
1427 
1428    /* add constraint to the separation array */
1429    if( cons->separate && cons->sepaenabled )
1430    {
1431       SCIP_CALL( conshdlrAddSepacons(conshdlr, set, cons) );
1432    }
1433 
1434    /* add constraint to the enforcement array */
1435    if( cons->enforce )
1436    {
1437       SCIP_CALL( conshdlrAddEnfocons(conshdlr, set, cons) );
1438    }
1439 
1440    /* add constraint to the propagation array */
1441    if( cons->propagate && cons->propenabled )
1442    {
1443       SCIP_CALL( conshdlrAddPropcons(conshdlr, set, cons) );
1444    }
1445 
1446    /* call constraint handler's enabling notification method */
1447    if( conshdlr->consenable != NULL )
1448    {
1449       SCIP_CALL( conshdlr->consenable(set->scip, conshdlr, cons) );
1450    }
1451 
1452    checkConssArrays(conshdlr);
1453 
1454    return SCIP_OKAY;
1455 }
1456 
1457 /** disables separation, enforcement, and propagation of constraint */
1458 static
conshdlrDisableCons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_STAT * stat,SCIP_CONS * cons)1459 SCIP_RETCODE conshdlrDisableCons(
1460    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1461    SCIP_SET*             set,                /**< global SCIP settings */
1462    SCIP_STAT*            stat,               /**< dynamic problem statistics */
1463    SCIP_CONS*            cons                /**< constraint to remove */
1464    )
1465 {
1466    assert(conshdlr != NULL);
1467    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1468    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1469    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1470    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1471    assert(set != NULL);
1472    assert(stat != NULL);
1473    assert(cons != NULL);
1474    assert(cons->scip == set->scip);
1475    assert(cons->conshdlr == conshdlr);
1476    assert(!cons->original);
1477    assert(cons->active);
1478    assert(cons->enabled);
1479    assert((cons->separate && cons->sepaenabled) == (cons->sepaconsspos != -1));
1480    assert(cons->enforce == (cons->enfoconsspos != -1));
1481    assert((cons->propagate && cons->propenabled) == (cons->propconsspos != -1));
1482 
1483    SCIPsetDebugMsg(set, "disable constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1484 
1485    /* call constraint handler's disabling notification method */
1486    if( conshdlr->consdisable != NULL )
1487    {
1488       SCIP_CALL( conshdlr->consdisable(set->scip, conshdlr, cons) );
1489    }
1490 
1491    /* delete constraint from the separation array */
1492    if( cons->separate && cons->sepaenabled )
1493    {
1494       conshdlrDelSepacons(conshdlr, cons);
1495    }
1496 
1497    /* delete constraint from the enforcement array */
1498    if( cons->enforce )
1499    {
1500       conshdlrDelEnfocons(conshdlr, cons);
1501    }
1502 
1503    /* delete constraint from the propagation array */
1504    if( cons->propagate && cons->propenabled )
1505    {
1506       conshdlrDelPropcons(conshdlr, cons);
1507    }
1508 
1509    assert(cons->sepaconsspos == -1);
1510    assert(cons->enfoconsspos == -1);
1511    assert(cons->propconsspos == -1);
1512 
1513    /* disable constraint */
1514    cons->enabled = FALSE;
1515    conshdlr->nenabledconss--;
1516    stat->nenabledconss--;
1517 
1518    checkConssArrays(conshdlr);
1519 
1520    return SCIP_OKAY;
1521 }
1522 
1523 /** activates and adds constraint to constraint handler's constraint arrays */
1524 static
conshdlrActivateCons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_STAT * stat,SCIP_CONS * cons,int depth,SCIP_Bool focusnode)1525 SCIP_RETCODE conshdlrActivateCons(
1526    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1527    SCIP_SET*             set,                /**< global SCIP settings */
1528    SCIP_STAT*            stat,               /**< dynamic problem statistics */
1529    SCIP_CONS*            cons,               /**< constraint to add */
1530    int                   depth,              /**< depth in the tree where the activation takes place, or -1 for global problem */
1531    SCIP_Bool             focusnode           /**< does the constraint activation take place at the focus node? */
1532    )
1533 {
1534    assert(conshdlr != NULL);
1535    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1536    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1537    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1538    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1539    assert(set != NULL);
1540    assert(stat != NULL);
1541    assert(cons != NULL);
1542    assert(cons->scip == set->scip);
1543    assert(cons->conshdlr == conshdlr);
1544    assert(!cons->original);
1545    assert(!cons->active);
1546    assert(!cons->enabled);
1547    assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss);
1548    assert(conshdlr->conss[cons->consspos] == cons);
1549    assert(cons->initconsspos < conshdlr->ninitconsskept);
1550    assert(cons->sepaconsspos == -1);
1551    assert(cons->enfoconsspos == -1);
1552    assert(cons->checkconsspos == -1);
1553    assert(cons->propconsspos == -1);
1554    assert(depth >= -1);
1555 
1556    SCIPsetDebugMsg(set, "activate constraint <%s> in constraint handler <%s> (depth %d, focus=%u)\n",
1557       cons->name, conshdlr->name, depth, focusnode);
1558 
1559    /* activate constraint, switch positions with first inactive constraint */
1560    cons->active = TRUE;
1561    cons->activedepth = depth;
1562    conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nactiveconss];
1563    conshdlr->conss[cons->consspos]->consspos = cons->consspos;
1564    conshdlr->conss[conshdlr->nactiveconss] = cons;
1565    cons->consspos = conshdlr->nactiveconss;
1566    conshdlr->nactiveconss++;
1567    conshdlr->maxnactiveconss = MAX(conshdlr->maxnactiveconss, conshdlr->nactiveconss);
1568    stat->nactiveconss++;
1569 
1570    /* add constraint to the check array */
1571    if( cons->check )
1572    {
1573       SCIP_CALL( conshdlrAddCheckcons(conshdlr, set, cons) );
1574    }
1575 
1576    /* add constraint to the initconss array if the constraint is initial and added to the focus node */
1577    if( cons->initial )
1578    {
1579       SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, cons) );
1580    }
1581 
1582    /* call constraint handler's activation notification method */
1583    if( conshdlr->consactive != NULL )
1584    {
1585       SCIP_CALL( conshdlr->consactive(set->scip, conshdlr, cons) );
1586    }
1587 
1588    /* enable separation, enforcement, and propagation of constraint */
1589    SCIP_CALL( conshdlrEnableCons(conshdlr, set, stat, cons) );
1590 
1591    assert(0 <= cons->consspos && cons->consspos < conshdlr->nactiveconss);
1592 
1593    checkConssArrays(conshdlr);
1594 
1595    return SCIP_OKAY;
1596 }
1597 
1598 /** deactivates and removes constraint from constraint handler's conss array */
1599 static
conshdlrDeactivateCons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_STAT * stat,SCIP_CONS * cons)1600 SCIP_RETCODE conshdlrDeactivateCons(
1601    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1602    SCIP_SET*             set,                /**< global SCIP settings */
1603    SCIP_STAT*            stat,               /**< dynamic problem statistics */
1604    SCIP_CONS*            cons                /**< constraint to remove */
1605    )
1606 {
1607    assert(conshdlr != NULL);
1608    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1609    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1610    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1611    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1612    assert(set != NULL);
1613    assert(stat != NULL);
1614    assert(cons != NULL);
1615    assert(cons->scip == set->scip);
1616    assert(cons->conshdlr == conshdlr);
1617    assert(!cons->original);
1618    assert(cons->active);
1619    assert(0 <= cons->consspos && cons->consspos < conshdlr->nactiveconss);
1620    assert(conshdlr->conss[cons->consspos] == cons);
1621    assert(cons->check == (cons->checkconsspos != -1));
1622 
1623    SCIPsetDebugMsg(set, "deactivate constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name);
1624 
1625    /* disable constraint */
1626    if( cons->enabled )
1627    {
1628       SCIP_CALL( conshdlrDisableCons(conshdlr, set, stat, cons) );
1629    }
1630    assert(!cons->enabled);
1631 
1632    /* call constraint handler's deactivation notification method */
1633    if( conshdlr->consdeactive != NULL )
1634    {
1635       SCIP_CALL( conshdlr->consdeactive(set->scip, conshdlr, cons) );
1636    }
1637 
1638    /* delete constraint from the initconss array */
1639    if( cons->initconsspos >= 0 )
1640    {
1641       conshdlrDelInitcons(conshdlr, cons);
1642    }
1643 
1644    /* delete constraint from the check array */
1645    if( cons->check )
1646    {
1647       conshdlrDelCheckcons(conshdlr, cons);
1648    }
1649 
1650    /* switch constraint with the last active constraint in the conss array */
1651    conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nactiveconss-1];
1652    conshdlr->conss[cons->consspos]->consspos = cons->consspos;
1653    conshdlr->conss[conshdlr->nactiveconss-1] = cons;
1654    cons->consspos = conshdlr->nactiveconss-1;
1655    conshdlr->nactiveconss--;
1656    cons->active = FALSE;
1657    cons->activedepth = -2;
1658    stat->nactiveconss--;
1659 
1660    assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss);
1661    assert(cons->initconsspos == -1);
1662    assert(cons->sepaconsspos == -1);
1663    assert(cons->enfoconsspos == -1);
1664    assert(cons->checkconsspos == -1);
1665    assert(cons->propconsspos == -1);
1666 
1667    checkConssArrays(conshdlr);
1668 
1669    return SCIP_OKAY;
1670 }
1671 
1672 /** processes all delayed updates of constraints:
1673  *  recently (de)activated constraints will be (de)activated;
1674  *  recently en/disabled constraints will be en/disabled;
1675  *  recent obsolete non-check constraints will be globally deleted;
1676  *  recent obsolete check constraints will be moved to the last positions in the sepa-, enfo-, check-, and prop-arrays;
1677  *  recent useful constraints will be moved to the first positions in the sepa-, enfo-, check-, and prop-arrays;
1678  *  constraints which were recently marked to be propagated are moved to the first positions in the prop-array;
1679  *  no longer used constraints will be freed and removed from the conss array
1680  */
1681 static
conshdlrProcessUpdates(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)1682 SCIP_RETCODE conshdlrProcessUpdates(
1683    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1684    BMS_BLKMEM*           blkmem,             /**< block memory */
1685    SCIP_SET*             set,                /**< global SCIP settings */
1686    SCIP_STAT*            stat                /**< dynamic problem statistics */
1687    )
1688 {
1689    SCIP_CONS* cons;
1690    int i;
1691 
1692    assert(conshdlr != NULL);
1693    assert(!conshdlrAreUpdatesDelayed(conshdlr));
1694    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
1695    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
1696    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
1697    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
1698 
1699    SCIPsetDebugMsg(set, "processing %d constraints that have to be updated in constraint handler <%s>\n",
1700       conshdlr->nupdateconss, conshdlr->name);
1701 
1702    for( i = conshdlr->nupdateconss - 1; i >= 0; --i )
1703    {
1704       cons = conshdlr->updateconss[i];
1705       assert(cons != NULL);
1706       assert(cons->conshdlr == conshdlr);
1707       assert(cons->update);
1708       assert(cons->updateinsert || cons->updateactivate || cons->updatedeactivate
1709          || cons->updateenable || cons->updatedisable
1710          || cons->updatesepaenable || cons->updatesepadisable
1711          || cons->updatepropenable || cons->updatepropdisable
1712          || cons->updateobsolete || cons->updatefree
1713          || cons->updatemarkpropagate || cons->updateunmarkpropagate);
1714 
1715       SCIPsetDebugMsg(set, " -> constraint <%s>: insert=%u, activate=%u, deactivate=%u, enable=%u, disable=%u, sepaenable=%u, sepadisable=%u, propenable=%u, propdisable=%u, obsolete=%u, free=%u (consdata=%p)\n",
1716          cons->name, cons->updateinsert, cons->updateactivate, cons->updatedeactivate,
1717          cons->updateenable, cons->updatedisable,
1718          cons->updatesepaenable, cons->updatesepadisable,
1719          cons->updatepropenable, cons->updatepropdisable,
1720          cons->updateobsolete, cons->updatefree, (void*)cons->consdata);
1721 
1722       if( cons->updateinsert )
1723       {
1724          SCIP_CALL( conshdlrAddCons(conshdlr, set, cons) );
1725          cons->updateinsert = FALSE;
1726       }
1727 
1728       if( cons->updateactivate )
1729       {
1730          assert(!cons->active);
1731          assert(!cons->updatedeactivate);
1732          assert(!cons->updateenable);
1733          assert(!cons->updatedisable);
1734          assert(!cons->updateobsolete);
1735          assert(!cons->updatefree);
1736 
1737          /* the activation depth was already stored in SCIPconsActivate() */
1738          SCIP_CALL( conshdlrActivateCons(conshdlr, set, stat, cons, cons->activedepth, cons->updateactfocus) );
1739          assert(cons->active);
1740          cons->updateactivate = FALSE;
1741       }
1742       else if( cons->updatedeactivate )
1743       {
1744          assert(cons->active);
1745 
1746          SCIP_CALL( conshdlrDeactivateCons(conshdlr, set, stat, cons) );
1747          assert(!cons->active);
1748          cons->updatedeactivate = FALSE;
1749          cons->updateenable = FALSE;
1750          cons->updatedisable = FALSE;
1751          cons->obsolete = consExceedsObsoleteage(cons, set);
1752          cons->updateobsolete = FALSE;
1753       }
1754       else if( cons->updateenable )
1755       {
1756          assert(!cons->enabled);
1757          assert(!cons->updatedisable);
1758 
1759          SCIP_CALL( conshdlrEnableCons(conshdlr, set, stat, cons) );
1760          assert(cons->enabled);
1761          cons->updateenable = FALSE;
1762       }
1763       else if( cons->updatedisable )
1764       {
1765          assert(cons->enabled);
1766 
1767          SCIP_CALL( conshdlrDisableCons(conshdlr, set, stat, cons) );
1768          assert(!cons->enabled);
1769          cons->updatedisable = FALSE;
1770       }
1771 
1772       if( cons->updatesepaenable )
1773       {
1774          assert(!cons->updatesepadisable);
1775          if( !cons->sepaenabled )
1776          {
1777             SCIP_CALL( conshdlrEnableConsSeparation(conshdlr, set, cons) );
1778             assert(cons->sepaenabled);
1779          }
1780          cons->updatesepaenable = FALSE;
1781       }
1782       else if( cons->updatesepadisable )
1783       {
1784          if( cons->sepaenabled )
1785          {
1786             SCIP_CALL( conshdlrDisableConsSeparation(conshdlr, cons) );
1787             assert(!cons->sepaenabled);
1788          }
1789          cons->updatesepadisable = FALSE;
1790       }
1791 
1792       if( cons->updatepropenable )
1793       {
1794          assert(!cons->updatepropdisable);
1795          if( !cons->propenabled )
1796          {
1797             SCIP_CALL( conshdlrEnableConsPropagation(conshdlr, set, cons) );
1798             assert(cons->propenabled);
1799          }
1800          cons->updatepropenable = FALSE;
1801       }
1802       else if( cons->updatepropdisable )
1803       {
1804          if( cons->propenabled )
1805          {
1806             SCIP_CALL( conshdlrDisableConsPropagation(conshdlr, cons) );
1807             assert(!cons->propenabled);
1808          }
1809          cons->updatepropdisable = FALSE;
1810       }
1811 
1812       if( cons->updatefree )
1813       {
1814          /* nothing to do here: the constraint is freed, when it is released from the updateconss array */
1815          assert(cons->nuses == 1); /* it only exists in the updateconss array */
1816          cons->updatefree = FALSE;
1817          cons->updateobsolete = FALSE;
1818       }
1819       else
1820       {
1821          if( cons->updateobsolete )
1822          {
1823             if( !cons->obsolete && consExceedsObsoleteage(cons, set) )
1824             {
1825                /* the constraint's status must be switched to obsolete */
1826                SCIP_CALL( conshdlrMarkConsObsolete(conshdlr, cons) );
1827             }
1828             else if( cons->obsolete && !consExceedsObsoleteage(cons, set) )
1829             {
1830                /* the constraint's status must be switched to useful */
1831                SCIP_CALL( conshdlrMarkConsUseful(conshdlr, cons) );
1832             }
1833             cons->updateobsolete = FALSE;
1834          }
1835 
1836          if( cons->updatemarkpropagate )
1837          {
1838             /* the constraint must be marked to be propagated */
1839             conshdlrMarkConsPropagate(conshdlr, cons);
1840             cons->updatemarkpropagate = FALSE;
1841          }
1842          else if( cons->updateunmarkpropagate )
1843          {
1844             /* the constraint must be unmarked to be propagated */
1845             conshdlrUnmarkConsPropagate(conshdlr, cons);
1846             cons->updateunmarkpropagate = FALSE;
1847          }
1848       }
1849 
1850       assert(!cons->updateinsert);
1851       assert(!cons->updateactivate);
1852       assert(!cons->updatedeactivate);
1853       assert(!cons->updateenable);
1854       assert(!cons->updatedisable);
1855       assert(!cons->updatesepaenable);
1856       assert(!cons->updatesepadisable);
1857       assert(!cons->updatepropenable);
1858       assert(!cons->updatepropdisable);
1859       assert(!cons->updateobsolete);
1860       assert(!cons->updatemarkpropagate);
1861       assert(!cons->updateunmarkpropagate);
1862       assert(!cons->updatefree);
1863       cons->update = FALSE;
1864 
1865       /* release the constraint */
1866       SCIP_CALL( SCIPconsRelease(&conshdlr->updateconss[i], blkmem, set) );
1867    }
1868 
1869    conshdlr->nupdateconss = 0;
1870 
1871    return SCIP_OKAY;
1872 }
1873 
1874 /** marks constraint handler to delay all constraint updates until the next conshdlrProcessUpdates() call */
1875 static
conshdlrDelayUpdates(SCIP_CONSHDLR * conshdlr)1876 void conshdlrDelayUpdates(
1877    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
1878    )
1879 {
1880    assert(conshdlr != NULL);
1881 
1882    SCIPdebugMessage("constraint updates of constraint handler <%s> will be delayed (count:%d)\n",
1883       conshdlr->name, conshdlr->delayupdatecount+1);
1884 
1885    conshdlr->delayupdatecount++;
1886 }
1887 
1888 /** marks constraint handler to perform all constraint updates immediately;
1889  *  all delayed constraint updates will be processed
1890  */
1891 static
conshdlrForceUpdates(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)1892 SCIP_RETCODE conshdlrForceUpdates(
1893    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1894    BMS_BLKMEM*           blkmem,             /**< block memory */
1895    SCIP_SET*             set,                /**< global SCIP settings */
1896    SCIP_STAT*            stat                /**< dynamic problem statistics */
1897    )
1898 {
1899    assert(conshdlr != NULL);
1900    assert(conshdlrAreUpdatesDelayed(conshdlr));
1901 
1902    SCIPsetDebugMsg(set, "constraint updates of constraint handler <%s> will be processed immediately (count:%d)\n",
1903       conshdlr->name, conshdlr->delayupdatecount);
1904    conshdlr->delayupdatecount--;
1905 
1906    /* only run the update if all delays are taken away (reference counting) */
1907    if( !conshdlrAreUpdatesDelayed(conshdlr) )
1908    {
1909       SCIP_CALL( conshdlrProcessUpdates(conshdlr, blkmem, set, stat) );
1910       assert(conshdlr->nupdateconss == 0);
1911    }
1912 
1913    return SCIP_OKAY;
1914 }
1915 
1916 /** adds constraint to constraint handler's update constraint array and captures it */
1917 static
conshdlrAddUpdateCons(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_CONS * cons)1918 SCIP_RETCODE conshdlrAddUpdateCons(
1919    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1920    SCIP_SET*             set,                /**< global SCIP settings */
1921    SCIP_CONS*            cons                /**< constraint to add */
1922    )
1923 {
1924    assert(conshdlr != NULL);
1925    assert(set != NULL);
1926    assert(cons != NULL);
1927    assert(cons->conshdlr == conshdlr);
1928 
1929    if( !cons->update )
1930    {
1931       SCIPsetDebugMsg(set, "constraint <%s> of age %g has to be updated in constraint handler <%s> (consdata=%p)\n",
1932          cons->name, cons->age, conshdlr->name, (void*)cons->consdata);
1933 
1934       /* add constraint to the updateconss array */
1935       SCIP_CALL( conshdlrEnsureUpdateconssMem(conshdlr, set, conshdlr->nupdateconss+1) );
1936       conshdlr->updateconss[conshdlr->nupdateconss] = cons;
1937       conshdlr->nupdateconss++;
1938 
1939       /* capture constraint */
1940       SCIPconsCapture(cons);
1941 
1942       cons->update = TRUE;
1943    }
1944 
1945    return SCIP_OKAY;
1946 }
1947 
1948 /** compares two constraint handlers w. r. to their separation priority */
SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompSepa)1949 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompSepa)
1950 {  /*lint --e{715}*/
1951    return ((SCIP_CONSHDLR*)elem2)->sepapriority - ((SCIP_CONSHDLR*)elem1)->sepapriority;
1952 }
1953 
1954 /** compares two constraint handlers w. r. to their enforcing priority */
SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompEnfo)1955 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompEnfo)
1956 {  /*lint --e{715}*/
1957    return ((SCIP_CONSHDLR*)elem2)->enfopriority - ((SCIP_CONSHDLR*)elem1)->enfopriority;
1958 }
1959 
1960 /** compares two constraint handlers w. r. to their feasibility check priority */
SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompCheck)1961 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompCheck)
1962 {  /*lint --e{715}*/
1963    return ((SCIP_CONSHDLR*)elem2)->checkpriority - ((SCIP_CONSHDLR*)elem1)->checkpriority;
1964 }
1965 
1966 /** copies the given constraint handler to a new scip */
SCIPconshdlrCopyInclude(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_Bool * valid)1967 SCIP_RETCODE SCIPconshdlrCopyInclude(
1968    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1969    SCIP_SET*             set,                /**< SCIP_SET of SCIP to copy to */
1970    SCIP_Bool*            valid               /**< was the copying process valid? */
1971    )
1972 {
1973    assert(conshdlr != NULL);
1974    assert(set != NULL);
1975    assert(valid != NULL);
1976    assert(set->scip != NULL);
1977 
1978    if( conshdlr->conshdlrcopy != NULL )
1979    {
1980       SCIPsetDebugMsg(set, "including constraint handler %s in subscip %p\n", SCIPconshdlrGetName(conshdlr), (void*)set->scip);
1981       SCIP_CALL( conshdlr->conshdlrcopy(set->scip, conshdlr, valid) );
1982    }
1983 
1984    return SCIP_OKAY;
1985 }
1986 
1987 /** internal method for creating a constraint handler */
1988 static
doConshdlrCreate(SCIP_CONSHDLR ** conshdlr,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,int sepapriority,int enfopriority,int checkpriority,int sepafreq,int propfreq,int eagerfreq,int maxprerounds,SCIP_Bool delaysepa,SCIP_Bool delayprop,SCIP_Bool needscons,SCIP_PROPTIMING proptiming,SCIP_PRESOLTIMING presoltiming,SCIP_DECL_CONSHDLRCOPY ((* conshdlrcopy)),SCIP_DECL_CONSFREE ((* consfree)),SCIP_DECL_CONSINIT ((* consinit)),SCIP_DECL_CONSEXIT ((* consexit)),SCIP_DECL_CONSINITPRE ((* consinitpre)),SCIP_DECL_CONSEXITPRE ((* consexitpre)),SCIP_DECL_CONSINITSOL ((* consinitsol)),SCIP_DECL_CONSEXITSOL ((* consexitsol)),SCIP_DECL_CONSDELETE ((* consdelete)),SCIP_DECL_CONSTRANS ((* constrans)),SCIP_DECL_CONSINITLP ((* consinitlp)),SCIP_DECL_CONSSEPALP ((* conssepalp)),SCIP_DECL_CONSSEPASOL ((* conssepasol)),SCIP_DECL_CONSENFOLP ((* consenfolp)),SCIP_DECL_CONSENFORELAX ((* consenforelax)),SCIP_DECL_CONSENFOPS ((* consenfops)),SCIP_DECL_CONSCHECK ((* conscheck)),SCIP_DECL_CONSPROP ((* consprop)),SCIP_DECL_CONSPRESOL ((* conspresol)),SCIP_DECL_CONSRESPROP ((* consresprop)),SCIP_DECL_CONSLOCK ((* conslock)),SCIP_DECL_CONSACTIVE ((* consactive)),SCIP_DECL_CONSDEACTIVE ((* consdeactive)),SCIP_DECL_CONSENABLE ((* consenable)),SCIP_DECL_CONSDISABLE ((* consdisable)),SCIP_DECL_CONSDELVARS ((* consdelvars)),SCIP_DECL_CONSPRINT ((* consprint)),SCIP_DECL_CONSCOPY ((* conscopy)),SCIP_DECL_CONSPARSE ((* consparse)),SCIP_DECL_CONSGETVARS ((* consgetvars)),SCIP_DECL_CONSGETNVARS ((* consgetnvars)),SCIP_DECL_CONSGETDIVEBDCHGS ((* consgetdivebdchgs)),SCIP_CONSHDLRDATA * conshdlrdata)1989 SCIP_RETCODE doConshdlrCreate(
1990    SCIP_CONSHDLR**       conshdlr,           /**< pointer to constraint handler data structure */
1991    SCIP_SET*             set,                /**< global SCIP settings */
1992    SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
1993    BMS_BLKMEM*           blkmem,             /**< block memory for parameter settings */
1994    const char*           name,               /**< name of constraint handler */
1995    const char*           desc,               /**< description of constraint handler */
1996    int                   sepapriority,       /**< priority of the constraint handler for separation */
1997    int                   enfopriority,       /**< priority of the constraint handler for constraint enforcing */
1998    int                   checkpriority,      /**< priority of the constraint handler for checking feasibility (and propagation) */
1999    int                   sepafreq,           /**< frequency for separating cuts; zero means to separate only in the root node */
2000    int                   propfreq,           /**< frequency for propagating domains; zero means only preprocessing propagation */
2001    int                   eagerfreq,          /**< frequency for using all instead of only the useful constraints in separation,
2002                                               *   propagation and enforcement, -1 for no eager evaluations, 0 for first only */
2003    int                   maxprerounds,       /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
2004    SCIP_Bool             delaysepa,          /**< should separation method be delayed, if other separators found cuts? */
2005    SCIP_Bool             delayprop,          /**< should propagation method be delayed, if other propagators found reductions? */
2006    SCIP_Bool             needscons,          /**< should the constraint handler be skipped, if no constraints are available? */
2007    SCIP_PROPTIMING       proptiming,         /**< positions in the node solving loop where propagation method of constraint handlers should be executed */
2008    SCIP_PRESOLTIMING     presoltiming,       /**< timing mask of the constraint handler's presolving method */
2009    SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),  /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
2010    SCIP_DECL_CONSFREE    ((*consfree)),      /**< destructor of constraint handler */
2011    SCIP_DECL_CONSINIT    ((*consinit)),      /**< initialize constraint handler */
2012    SCIP_DECL_CONSEXIT    ((*consexit)),      /**< deinitialize constraint handler */
2013    SCIP_DECL_CONSINITPRE ((*consinitpre)),   /**< presolving initialization method of constraint handler */
2014    SCIP_DECL_CONSEXITPRE ((*consexitpre)),   /**< presolving deinitialization method of constraint handler */
2015    SCIP_DECL_CONSINITSOL ((*consinitsol)),   /**< solving process initialization method of constraint handler */
2016    SCIP_DECL_CONSEXITSOL ((*consexitsol)),   /**< solving process deinitialization method of constraint handler */
2017    SCIP_DECL_CONSDELETE  ((*consdelete)),    /**< free specific constraint data */
2018    SCIP_DECL_CONSTRANS   ((*constrans)),     /**< transform constraint data into data belonging to the transformed problem */
2019    SCIP_DECL_CONSINITLP  ((*consinitlp)),    /**< initialize LP with relaxations of "initial" constraints */
2020    SCIP_DECL_CONSSEPALP  ((*conssepalp)),    /**< separate cutting planes for LP solution */
2021    SCIP_DECL_CONSSEPASOL ((*conssepasol)),   /**< separate cutting planes for arbitrary primal solution */
2022    SCIP_DECL_CONSENFOLP  ((*consenfolp)),    /**< enforcing constraints for LP solutions */
2023    SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */
2024    SCIP_DECL_CONSENFOPS  ((*consenfops)),    /**< enforcing constraints for pseudo solutions */
2025    SCIP_DECL_CONSCHECK   ((*conscheck)),     /**< check feasibility of primal solution */
2026    SCIP_DECL_CONSPROP    ((*consprop)),      /**< propagate variable domains */
2027    SCIP_DECL_CONSPRESOL  ((*conspresol)),    /**< presolving method */
2028    SCIP_DECL_CONSRESPROP ((*consresprop)),   /**< propagation conflict resolving method */
2029    SCIP_DECL_CONSLOCK    ((*conslock)),      /**< variable rounding lock method */
2030    SCIP_DECL_CONSACTIVE  ((*consactive)),    /**< activation notification method */
2031    SCIP_DECL_CONSDEACTIVE((*consdeactive)),  /**< deactivation notification method */
2032    SCIP_DECL_CONSENABLE  ((*consenable)),    /**< enabling notification method */
2033    SCIP_DECL_CONSDISABLE ((*consdisable)),   /**< disabling notification method */
2034    SCIP_DECL_CONSDELVARS ((*consdelvars)),   /**< variable deletion method */
2035    SCIP_DECL_CONSPRINT   ((*consprint)),     /**< constraint display method */
2036    SCIP_DECL_CONSCOPY    ((*conscopy)),      /**< constraint copying method */
2037    SCIP_DECL_CONSPARSE   ((*consparse)),     /**< constraint parsing method */
2038    SCIP_DECL_CONSGETVARS ((*consgetvars)),   /**< constraint get variables method */
2039    SCIP_DECL_CONSGETNVARS((*consgetnvars)),  /**< constraint get number of variable method */
2040    SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */
2041    SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler data */
2042    )
2043 {
2044    char paramname[SCIP_MAXSTRLEN];
2045    char paramdesc[SCIP_MAXSTRLEN];
2046 
2047    assert(conshdlr != NULL);
2048    assert(name != NULL);
2049    assert(desc != NULL);
2050    assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
2051    assert(consprop != NULL || propfreq == -1);
2052    assert(eagerfreq >= -1);
2053    assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL)));
2054 
2055    /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
2056     * error message
2057     */
2058    if( presoltiming < SCIP_PRESOLTIMING_NONE || presoltiming > SCIP_PRESOLTIMING_MAX )
2059    {
2060       SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
2061          "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", name);
2062 
2063       return SCIP_PARAMETERWRONGVAL;
2064    }
2065 
2066    /* both callbacks have to exist or not exist */
2067    assert((consgetvars != NULL) == (consgetnvars != NULL));
2068 
2069    SCIP_ALLOC( BMSallocMemory(conshdlr) );
2070    BMSclearMemory(*conshdlr);
2071 
2072    SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->name, name, strlen(name)+1) );
2073    SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->desc, desc, strlen(desc)+1) );
2074    (*conshdlr)->sepapriority = sepapriority;
2075    (*conshdlr)->enfopriority = enfopriority;
2076    (*conshdlr)->checkpriority = checkpriority;
2077    (*conshdlr)->sepafreq = sepafreq;
2078    (*conshdlr)->propfreq = propfreq;
2079    (*conshdlr)->eagerfreq = eagerfreq;
2080    (*conshdlr)->maxprerounds = maxprerounds;
2081    (*conshdlr)->conshdlrcopy = conshdlrcopy;
2082    (*conshdlr)->consfree = consfree;
2083    (*conshdlr)->consinit = consinit;
2084    (*conshdlr)->consexit = consexit;
2085    (*conshdlr)->consinitpre = consinitpre;
2086    (*conshdlr)->consexitpre = consexitpre;
2087    (*conshdlr)->consinitsol = consinitsol;
2088    (*conshdlr)->consexitsol = consexitsol;
2089    (*conshdlr)->consdelete = consdelete;
2090    (*conshdlr)->constrans = constrans;
2091    (*conshdlr)->consinitlp = consinitlp;
2092    (*conshdlr)->conssepalp = conssepalp;
2093    (*conshdlr)->conssepasol = conssepasol;
2094    (*conshdlr)->consenfolp = consenfolp;
2095    (*conshdlr)->consenforelax = consenforelax;
2096    (*conshdlr)->consenfops = consenfops;
2097    (*conshdlr)->conscheck = conscheck;
2098    (*conshdlr)->consprop = consprop;
2099    (*conshdlr)->conspresol = conspresol;
2100    (*conshdlr)->consresprop = consresprop;
2101    (*conshdlr)->conslock = conslock;
2102    (*conshdlr)->consactive = consactive;
2103    (*conshdlr)->consdeactive = consdeactive;
2104    (*conshdlr)->consenable = consenable;
2105    (*conshdlr)->consdisable = consdisable;
2106    (*conshdlr)->consprint = consprint;
2107    (*conshdlr)->consdelvars = consdelvars;
2108    (*conshdlr)->conscopy = conscopy;
2109    (*conshdlr)->consparse = consparse;
2110    (*conshdlr)->consgetvars = consgetvars;
2111    (*conshdlr)->consgetnvars = consgetnvars;
2112    (*conshdlr)->conshdlrdata = conshdlrdata;
2113    (*conshdlr)->consgetdivebdchgs = consgetdivebdchgs;
2114    (*conshdlr)->conss = NULL;
2115    (*conshdlr)->consssize = 0;
2116    (*conshdlr)->nconss = 0;
2117    (*conshdlr)->nactiveconss = 0;
2118    (*conshdlr)->maxnactiveconss = 0;
2119    (*conshdlr)->startnactiveconss = 0;
2120    (*conshdlr)->initconss = NULL;
2121    (*conshdlr)->initconsssize = 0;
2122    (*conshdlr)->ninitconss = 0;
2123    (*conshdlr)->ninitconsskept = 0;
2124    (*conshdlr)->sepaconss = NULL;
2125    (*conshdlr)->sepaconsssize = 0;
2126    (*conshdlr)->nsepaconss = 0;
2127    (*conshdlr)->nusefulsepaconss = 0;
2128    (*conshdlr)->enfoconss = NULL;
2129    (*conshdlr)->enfoconsssize = 0;
2130    (*conshdlr)->nenfoconss = 0;
2131    (*conshdlr)->nusefulenfoconss = 0;
2132    (*conshdlr)->checkconss = NULL;
2133    (*conshdlr)->checkconsssize = 0;
2134    (*conshdlr)->ncheckconss = 0;
2135    (*conshdlr)->nusefulcheckconss = 0;
2136    (*conshdlr)->propconss = NULL;
2137    (*conshdlr)->propconsssize = 0;
2138    (*conshdlr)->npropconss = 0;
2139    (*conshdlr)->nusefulpropconss = 0;
2140    (*conshdlr)->nmarkedpropconss = 0;
2141    (*conshdlr)->updateconss = NULL;
2142    (*conshdlr)->updateconsssize = 0;
2143    (*conshdlr)->nupdateconss = 0;
2144    (*conshdlr)->nenabledconss = 0;
2145    (*conshdlr)->lastnusefulpropconss = 0;
2146    (*conshdlr)->lastnusefulsepaconss = 0;
2147    (*conshdlr)->lastnusefulenfoconss = 0;
2148 
2149    (*conshdlr)->storedpropconss = NULL;
2150    (*conshdlr)->storedpropconsssize = 0;
2151    (*conshdlr)->storednmarkedpropconss = 0;
2152    (*conshdlr)->storedpropdomchgcount = 0;
2153 
2154    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
2155    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->presoltime, SCIP_CLOCKTYPE_DEFAULT) );
2156    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sepatime, SCIP_CLOCKTYPE_DEFAULT) );
2157    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfolptime, SCIP_CLOCKTYPE_DEFAULT) );
2158    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfopstime, SCIP_CLOCKTYPE_DEFAULT) );
2159    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enforelaxtime, SCIP_CLOCKTYPE_DEFAULT) );
2160    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->proptime, SCIP_CLOCKTYPE_DEFAULT) );
2161    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sbproptime, SCIP_CLOCKTYPE_DEFAULT) );
2162    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->checktime, SCIP_CLOCKTYPE_DEFAULT) );
2163    SCIP_CALL( SCIPclockCreate(&(*conshdlr)->resproptime, SCIP_CLOCKTYPE_DEFAULT) );
2164 
2165    (*conshdlr)->nsepacalls = 0;
2166    (*conshdlr)->nenfolpcalls = 0;
2167    (*conshdlr)->nenfopscalls = 0;
2168    (*conshdlr)->nenforelaxcalls = 0;
2169    (*conshdlr)->npropcalls = 0;
2170    (*conshdlr)->ncheckcalls = 0;
2171    (*conshdlr)->nrespropcalls = 0;
2172    (*conshdlr)->ncutoffs = 0;
2173    (*conshdlr)->ncutsfound = 0;
2174    (*conshdlr)->ncutsapplied = 0;
2175    (*conshdlr)->nconssfound = 0;
2176    (*conshdlr)->ndomredsfound = 0;
2177    (*conshdlr)->nchildren = 0;
2178    (*conshdlr)->lastpropdomchgcount = -1;
2179    (*conshdlr)->lastsepalpcount = -1;
2180    (*conshdlr)->lastenfolplpcount = -1;
2181    (*conshdlr)->lastenfolpdomchgcount = -1;
2182    (*conshdlr)->lastenfopsdomchgcount = -1;
2183    (*conshdlr)->lastenforelaxdomchgcount = -1;
2184    (*conshdlr)->lastenforelaxrelaxcount = -1;
2185    (*conshdlr)->lastenfolpnode = -1;
2186    (*conshdlr)->lastenfopsnode = -1;
2187    (*conshdlr)->lastenfolpresult = SCIP_DIDNOTRUN;
2188    (*conshdlr)->lastenfopsresult = SCIP_DIDNOTRUN;
2189    (*conshdlr)->lastenforelaxresult = SCIP_DIDNOTRUN;
2190    (*conshdlr)->lastnfixedvars = 0;
2191    (*conshdlr)->lastnaggrvars = 0;
2192    (*conshdlr)->lastnchgvartypes = 0;
2193    (*conshdlr)->lastnchgbds = 0;
2194    (*conshdlr)->lastnaddholes = 0;
2195    (*conshdlr)->lastndelconss = 0;
2196    (*conshdlr)->lastnaddconss = 0;
2197    (*conshdlr)->lastnupgdconss = 0;
2198    (*conshdlr)->lastnchgcoefs = 0;
2199    (*conshdlr)->lastnchgsides = 0;
2200    (*conshdlr)->nfixedvars = 0;
2201    (*conshdlr)->naggrvars = 0;
2202    (*conshdlr)->nchgvartypes = 0;
2203    (*conshdlr)->nchgbds = 0;
2204    (*conshdlr)->naddholes = 0;
2205    (*conshdlr)->ndelconss = 0;
2206    (*conshdlr)->naddconss = 0;
2207    (*conshdlr)->nupgdconss = 0;
2208    (*conshdlr)->nchgcoefs = 0;
2209    (*conshdlr)->nchgsides = 0;
2210    (*conshdlr)->npresolcalls = 0;
2211    (*conshdlr)->delayupdatecount = 0;
2212    (*conshdlr)->ageresetavg = AGERESETAVG_INIT;
2213    (*conshdlr)->needscons = needscons;
2214    (*conshdlr)->sepalpwasdelayed = FALSE;
2215    (*conshdlr)->sepasolwasdelayed = FALSE;
2216    (*conshdlr)->propwasdelayed = FALSE;
2217    (*conshdlr)->duringsepa = FALSE;
2218    (*conshdlr)->duringprop = FALSE;
2219    (*conshdlr)->initialized = FALSE;
2220 
2221    /* add parameters */
2222    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/sepafreq", name);
2223    SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2224          "frequency for separating cuts (-1: never, 0: only in root node)",
2225          &(*conshdlr)->sepafreq, FALSE, sepafreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2226 
2227    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/propfreq", name);
2228    SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2229          "frequency for propagating domains (-1: never, 0: only in root node)",
2230          &(*conshdlr)->propfreq, FALSE, propfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2231 
2232    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/proptiming", name);
2233    (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing when constraint propagation should be called (%u:BEFORELP, %u:DURINGLPLOOP, %u:AFTERLPLOOP, %u:ALWAYS)", SCIP_PROPTIMING_BEFORELP, SCIP_PROPTIMING_DURINGLPLOOP, SCIP_PROPTIMING_AFTERLPLOOP, SCIP_PROPTIMING_ALWAYS);
2234    SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
2235          (int*)(&(*conshdlr)->proptiming), TRUE, (int) proptiming, (int) SCIP_PROPTIMING_BEFORELP, (int) SCIP_PROPTIMING_ALWAYS, NULL, NULL) ); /*lint !e713*/
2236 
2237    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/eagerfreq", name);
2238    SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2239          "frequency for using all instead of only the useful constraints in separation, propagation and enforcement (-1: never, 0: only in first evaluation)",
2240          &(*conshdlr)->eagerfreq, TRUE, eagerfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
2241 
2242    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/maxprerounds", name);
2243    SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname,
2244          "maximal number of presolving rounds the constraint handler participates in (-1: no limit)",
2245          &(*conshdlr)->maxprerounds, TRUE, maxprerounds, -1, INT_MAX, NULL, NULL) );
2246 
2247    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delaysepa", name);
2248    SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
2249          "should separation method be delayed, if other separators found cuts?",
2250          &(*conshdlr)->delaysepa, TRUE, delaysepa, NULL, NULL) ); /*lint !e740*/
2251 
2252    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delayprop", name);
2253    SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname,
2254          "should propagation method be delayed, if other propagators found reductions?",
2255          &(*conshdlr)->delayprop, TRUE, delayprop, NULL, NULL) ); /*lint !e740*/
2256 
2257    (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/presoltiming", name);
2258    (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing mask of the constraint handler's presolving method (%u:FAST, %u:MEDIUM, %u:EXHAUSTIVE, %u:FINAL)",
2259       SCIP_PRESOLTIMING_FAST, SCIP_PRESOLTIMING_MEDIUM, SCIP_PRESOLTIMING_EXHAUSTIVE, SCIP_PRESOLTIMING_FINAL);
2260    SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc,
2261          (int*)&(*conshdlr)->presoltiming, TRUE, (int) presoltiming, (int) SCIP_PRESOLTIMING_FAST, (int) SCIP_PRESOLTIMING_MAX, NULL, NULL) ); /*lint !e740 !e713*/
2262 
2263    return SCIP_OKAY;
2264 }
2265 
2266 /** creates a constraint handler */
SCIPconshdlrCreate(SCIP_CONSHDLR ** conshdlr,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,BMS_BLKMEM * blkmem,const char * name,const char * desc,int sepapriority,int enfopriority,int checkpriority,int sepafreq,int propfreq,int eagerfreq,int maxprerounds,SCIP_Bool delaysepa,SCIP_Bool delayprop,SCIP_Bool needscons,SCIP_PROPTIMING proptiming,SCIP_PRESOLTIMING presoltiming,SCIP_DECL_CONSHDLRCOPY ((* conshdlrcopy)),SCIP_DECL_CONSFREE ((* consfree)),SCIP_DECL_CONSINIT ((* consinit)),SCIP_DECL_CONSEXIT ((* consexit)),SCIP_DECL_CONSINITPRE ((* consinitpre)),SCIP_DECL_CONSEXITPRE ((* consexitpre)),SCIP_DECL_CONSINITSOL ((* consinitsol)),SCIP_DECL_CONSEXITSOL ((* consexitsol)),SCIP_DECL_CONSDELETE ((* consdelete)),SCIP_DECL_CONSTRANS ((* constrans)),SCIP_DECL_CONSINITLP ((* consinitlp)),SCIP_DECL_CONSSEPALP ((* conssepalp)),SCIP_DECL_CONSSEPASOL ((* conssepasol)),SCIP_DECL_CONSENFOLP ((* consenfolp)),SCIP_DECL_CONSENFORELAX ((* consenforelax)),SCIP_DECL_CONSENFOPS ((* consenfops)),SCIP_DECL_CONSCHECK ((* conscheck)),SCIP_DECL_CONSPROP ((* consprop)),SCIP_DECL_CONSPRESOL ((* conspresol)),SCIP_DECL_CONSRESPROP ((* consresprop)),SCIP_DECL_CONSLOCK ((* conslock)),SCIP_DECL_CONSACTIVE ((* consactive)),SCIP_DECL_CONSDEACTIVE ((* consdeactive)),SCIP_DECL_CONSENABLE ((* consenable)),SCIP_DECL_CONSDISABLE ((* consdisable)),SCIP_DECL_CONSDELVARS ((* consdelvars)),SCIP_DECL_CONSPRINT ((* consprint)),SCIP_DECL_CONSCOPY ((* conscopy)),SCIP_DECL_CONSPARSE ((* consparse)),SCIP_DECL_CONSGETVARS ((* consgetvars)),SCIP_DECL_CONSGETNVARS ((* consgetnvars)),SCIP_DECL_CONSGETDIVEBDCHGS ((* consgetdivebdchgs)),SCIP_CONSHDLRDATA * conshdlrdata)2267 SCIP_RETCODE SCIPconshdlrCreate(
2268    SCIP_CONSHDLR**       conshdlr,           /**< pointer to constraint handler data structure */
2269    SCIP_SET*             set,                /**< global SCIP settings */
2270    SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
2271    BMS_BLKMEM*           blkmem,             /**< block memory for parameter settings */
2272    const char*           name,               /**< name of constraint handler */
2273    const char*           desc,               /**< description of constraint handler */
2274    int                   sepapriority,       /**< priority of the constraint handler for separation */
2275    int                   enfopriority,       /**< priority of the constraint handler for constraint enforcing */
2276    int                   checkpriority,      /**< priority of the constraint handler for checking feasibility (and propagation) */
2277    int                   sepafreq,           /**< frequency for separating cuts; zero means to separate only in the root node */
2278    int                   propfreq,           /**< frequency for propagating domains; zero means only preprocessing propagation */
2279    int                   eagerfreq,          /**< frequency for using all instead of only the useful constraints in separation,
2280                                               *   propagation and enforcement, -1 for no eager evaluations, 0 for first only */
2281    int                   maxprerounds,       /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
2282    SCIP_Bool             delaysepa,          /**< should separation method be delayed, if other separators found cuts? */
2283    SCIP_Bool             delayprop,          /**< should propagation method be delayed, if other propagators found reductions? */
2284    SCIP_Bool             needscons,          /**< should the constraint handler be skipped, if no constraints are available? */
2285    SCIP_PROPTIMING       proptiming,         /**< positions in the node solving loop where propagation method of constraint handlers should be executed */
2286    SCIP_PRESOLTIMING     presoltiming,       /**< timing mask of the constraint handler's presolving method */
2287    SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),  /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
2288    SCIP_DECL_CONSFREE    ((*consfree)),      /**< destructor of constraint handler */
2289    SCIP_DECL_CONSINIT    ((*consinit)),      /**< initialize constraint handler */
2290    SCIP_DECL_CONSEXIT    ((*consexit)),      /**< deinitialize constraint handler */
2291    SCIP_DECL_CONSINITPRE ((*consinitpre)),   /**< presolving initialization method of constraint handler */
2292    SCIP_DECL_CONSEXITPRE ((*consexitpre)),   /**< presolving deinitialization method of constraint handler */
2293    SCIP_DECL_CONSINITSOL ((*consinitsol)),   /**< solving process initialization method of constraint handler */
2294    SCIP_DECL_CONSEXITSOL ((*consexitsol)),   /**< solving process deinitialization method of constraint handler */
2295    SCIP_DECL_CONSDELETE  ((*consdelete)),    /**< free specific constraint data */
2296    SCIP_DECL_CONSTRANS   ((*constrans)),     /**< transform constraint data into data belonging to the transformed problem */
2297    SCIP_DECL_CONSINITLP  ((*consinitlp)),    /**< initialize LP with relaxations of "initial" constraints */
2298    SCIP_DECL_CONSSEPALP  ((*conssepalp)),    /**< separate cutting planes for LP solution */
2299    SCIP_DECL_CONSSEPASOL ((*conssepasol)),   /**< separate cutting planes for arbitrary primal solution */
2300    SCIP_DECL_CONSENFOLP  ((*consenfolp)),    /**< enforcing constraints for LP solutions */
2301    SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */
2302    SCIP_DECL_CONSENFOPS  ((*consenfops)),    /**< enforcing constraints for pseudo solutions */
2303    SCIP_DECL_CONSCHECK   ((*conscheck)),     /**< check feasibility of primal solution */
2304    SCIP_DECL_CONSPROP    ((*consprop)),      /**< propagate variable domains */
2305    SCIP_DECL_CONSPRESOL  ((*conspresol)),    /**< presolving method */
2306    SCIP_DECL_CONSRESPROP ((*consresprop)),   /**< propagation conflict resolving method */
2307    SCIP_DECL_CONSLOCK    ((*conslock)),      /**< variable rounding lock method */
2308    SCIP_DECL_CONSACTIVE  ((*consactive)),    /**< activation notification method */
2309    SCIP_DECL_CONSDEACTIVE((*consdeactive)),  /**< deactivation notification method */
2310    SCIP_DECL_CONSENABLE  ((*consenable)),    /**< enabling notification method */
2311    SCIP_DECL_CONSDISABLE ((*consdisable)),   /**< disabling notification method */
2312    SCIP_DECL_CONSDELVARS ((*consdelvars)),   /**< variable deletion method */
2313    SCIP_DECL_CONSPRINT   ((*consprint)),     /**< constraint display method */
2314    SCIP_DECL_CONSCOPY    ((*conscopy)),      /**< constraint copying method */
2315    SCIP_DECL_CONSPARSE   ((*consparse)),     /**< constraint parsing method */
2316    SCIP_DECL_CONSGETVARS ((*consgetvars)),   /**< constraint get variables method */
2317    SCIP_DECL_CONSGETNVARS((*consgetnvars)),  /**< constraint get number of variable method */
2318    SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */
2319    SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler data */
2320    )
2321 {
2322    assert(conshdlr != NULL);
2323    assert(name != NULL);
2324    assert(desc != NULL);
2325    assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
2326    assert(consprop != NULL || propfreq == -1);
2327    assert(eagerfreq >= -1);
2328    assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL)));
2329 
2330    SCIP_CALL_FINALLY( doConshdlrCreate(conshdlr, set, messagehdlr, blkmem, name, desc, sepapriority, enfopriority,
2331       checkpriority, sepafreq, propfreq, eagerfreq, maxprerounds, delaysepa, delayprop, needscons, proptiming,
2332       presoltiming, conshdlrcopy, consfree, consinit, consexit, consinitpre, consexitpre, consinitsol, consexitsol,
2333       consdelete, constrans, consinitlp, conssepalp, conssepasol, consenfolp, consenforelax, consenfops, conscheck,
2334       consprop, conspresol, consresprop, conslock, consactive, consdeactive, consenable, consdisable, consdelvars,
2335       consprint, conscopy, consparse, consgetvars, consgetnvars, consgetdivebdchgs, conshdlrdata),
2336       (void) SCIPconshdlrFree(conshdlr, set) );
2337 
2338    return SCIP_OKAY;
2339 } /*lint !e715*/
2340 
2341 /** calls destructor and frees memory of constraint handler */
SCIPconshdlrFree(SCIP_CONSHDLR ** conshdlr,SCIP_SET * set)2342 SCIP_RETCODE SCIPconshdlrFree(
2343    SCIP_CONSHDLR**       conshdlr,           /**< pointer to constraint handler data structure */
2344    SCIP_SET*             set                 /**< global SCIP settings */
2345    )
2346 {
2347    assert(conshdlr != NULL);
2348    if( *conshdlr == NULL )
2349       return SCIP_OKAY;
2350    assert(!(*conshdlr)->initialized);
2351    assert((*conshdlr)->nconss == 0);
2352    assert(set != NULL);
2353 
2354    /* call destructor of constraint handler */
2355    if( (*conshdlr)->consfree != NULL )
2356    {
2357       SCIP_CALL( (*conshdlr)->consfree(set->scip, *conshdlr) );
2358    }
2359 
2360    SCIPclockFree(&(*conshdlr)->resproptime);
2361    SCIPclockFree(&(*conshdlr)->checktime);
2362    SCIPclockFree(&(*conshdlr)->sbproptime);
2363    SCIPclockFree(&(*conshdlr)->proptime);
2364    SCIPclockFree(&(*conshdlr)->enforelaxtime);
2365    SCIPclockFree(&(*conshdlr)->enfopstime);
2366    SCIPclockFree(&(*conshdlr)->enfolptime);
2367    SCIPclockFree(&(*conshdlr)->sepatime);
2368    SCIPclockFree(&(*conshdlr)->presoltime);
2369    SCIPclockFree(&(*conshdlr)->setuptime);
2370 
2371    BMSfreeMemoryArrayNull(&(*conshdlr)->name);
2372    BMSfreeMemoryArrayNull(&(*conshdlr)->desc);
2373    BMSfreeMemoryArrayNull(&(*conshdlr)->conss);
2374    BMSfreeMemoryArrayNull(&(*conshdlr)->initconss);
2375    BMSfreeMemoryArrayNull(&(*conshdlr)->sepaconss);
2376    BMSfreeMemoryArrayNull(&(*conshdlr)->enfoconss);
2377    BMSfreeMemoryArrayNull(&(*conshdlr)->checkconss);
2378    BMSfreeMemoryArrayNull(&(*conshdlr)->propconss);
2379    BMSfreeMemoryArrayNull(&(*conshdlr)->updateconss);
2380    BMSfreeMemoryArrayNull(&(*conshdlr)->storedpropconss);
2381    BMSfreeMemory(conshdlr);
2382 
2383    return SCIP_OKAY;
2384 }
2385 
2386 /** calls initialization method of constraint handler */
SCIPconshdlrInit(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)2387 SCIP_RETCODE SCIPconshdlrInit(
2388    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2389    BMS_BLKMEM*           blkmem,             /**< block memory */
2390    SCIP_SET*             set,                /**< global SCIP settings */
2391    SCIP_STAT*            stat                /**< dynamic problem statistics */
2392    )
2393 {
2394    assert(conshdlr != NULL);
2395    assert(set != NULL);
2396 
2397    if( conshdlr->initialized )
2398    {
2399       SCIPerrorMessage("constraint handler <%s> already initialized\n", conshdlr->name);
2400       return SCIP_INVALIDCALL;
2401    }
2402 
2403    if( set->misc_resetstat )
2404    {
2405       SCIPclockReset(conshdlr->setuptime);
2406       SCIPclockReset(conshdlr->presoltime);
2407       SCIPclockReset(conshdlr->sepatime);
2408       SCIPclockReset(conshdlr->enfolptime);
2409       SCIPclockReset(conshdlr->enfopstime);
2410       SCIPclockReset(conshdlr->enforelaxtime);
2411       SCIPclockReset(conshdlr->proptime);
2412       SCIPclockReset(conshdlr->sbproptime);
2413       SCIPclockReset(conshdlr->checktime);
2414       SCIPclockReset(conshdlr->resproptime);
2415 
2416       conshdlr->nsepacalls = 0;
2417       conshdlr->nenfolpcalls = 0;
2418       conshdlr->nenfopscalls = 0;
2419       conshdlr->nenforelaxcalls = 0;
2420       conshdlr->npropcalls = 0;
2421       conshdlr->ncheckcalls = 0;
2422       conshdlr->nrespropcalls = 0;
2423       conshdlr->ncutoffs = 0;
2424       conshdlr->ncutsfound = 0;
2425       conshdlr->ncutsapplied = 0;
2426       conshdlr->nconssfound = 0;
2427       conshdlr->ndomredsfound = 0;
2428       conshdlr->nchildren = 0;
2429       conshdlr->lastpropdomchgcount = -1;
2430       conshdlr->lastenfolpdomchgcount = -1;
2431       conshdlr->lastenfopsdomchgcount = -1;
2432       conshdlr->lastenforelaxdomchgcount = -1;
2433       conshdlr->lastenforelaxrelaxcount = -1;
2434       conshdlr->lastenfolpnode = -1;
2435       conshdlr->lastenfopsnode = -1;
2436       conshdlr->lastenfolpresult = SCIP_DIDNOTRUN;
2437       conshdlr->lastenfopsresult = SCIP_DIDNOTRUN;
2438       conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2439       conshdlr->startnactiveconss = 0;
2440       conshdlr->lastsepalpcount = -1;
2441       conshdlr->lastenfolplpcount = -1;
2442       conshdlr->lastnusefulpropconss = 0;
2443       conshdlr->lastnusefulsepaconss = 0;
2444       conshdlr->lastnusefulenfoconss = 0;
2445       conshdlr->lastnfixedvars = 0;
2446       conshdlr->lastnaggrvars = 0;
2447       conshdlr->lastnchgvartypes = 0;
2448       conshdlr->lastnchgbds = 0;
2449       conshdlr->lastnaddholes = 0;
2450       conshdlr->lastndelconss = 0;
2451       conshdlr->lastnaddconss = 0;
2452       conshdlr->lastnupgdconss = 0;
2453       conshdlr->lastnchgcoefs = 0;
2454       conshdlr->lastnchgsides = 0;
2455       conshdlr->nfixedvars = 0;
2456       conshdlr->naggrvars = 0;
2457       conshdlr->nchgvartypes = 0;
2458       conshdlr->nchgbds = 0;
2459       conshdlr->naddholes = 0;
2460       conshdlr->ndelconss = 0;
2461       conshdlr->naddconss = 0;
2462       conshdlr->nupgdconss = 0;
2463       conshdlr->nchgcoefs = 0;
2464       conshdlr->nchgsides = 0;
2465       conshdlr->npresolcalls = 0;
2466       conshdlr->ageresetavg = AGERESETAVG_INIT;
2467       conshdlr->sepalpwasdelayed = FALSE;
2468       conshdlr->sepasolwasdelayed = FALSE;
2469       conshdlr->propwasdelayed = FALSE;
2470    }
2471 
2472    /* call initialization method of constraint handler */
2473    if( conshdlr->consinit != NULL )
2474    {
2475       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2476        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2477        * external method; to avoid this, these changes will be buffered and processed after the method call
2478        */
2479       conshdlrDelayUpdates(conshdlr);
2480 
2481       /* start timing */
2482       SCIPclockStart(conshdlr->setuptime, set);
2483 
2484       /* call external method */
2485       SCIP_CALL( conshdlr->consinit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2486 
2487       /* stop timing */
2488       SCIPclockStop(conshdlr->setuptime, set);
2489 
2490       /* perform the cached constraint updates */
2491       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2492    }
2493    conshdlr->initialized = TRUE;
2494    assert(!conshdlrAreUpdatesDelayed(conshdlr));
2495 
2496    return SCIP_OKAY;
2497 }
2498 
2499 /** calls exit method of constraint handler */
SCIPconshdlrExit(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)2500 SCIP_RETCODE SCIPconshdlrExit(
2501    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2502    BMS_BLKMEM*           blkmem,             /**< block memory */
2503    SCIP_SET*             set,                /**< global SCIP settings */
2504    SCIP_STAT*            stat                /**< dynamic problem statistics */
2505    )
2506 {
2507    assert(conshdlr != NULL);
2508    assert(set != NULL);
2509 
2510    if( !conshdlr->initialized )
2511    {
2512       SCIPerrorMessage("constraint handler <%s> not initialized\n", conshdlr->name);
2513       return SCIP_INVALIDCALL;
2514    }
2515 
2516    /* call deinitialization method of constraint handler */
2517    if( conshdlr->consexit != NULL )
2518    {
2519       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2520        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2521        * external method; to avoid this, these changes will be buffered and processed after the method call
2522        */
2523       conshdlrDelayUpdates(conshdlr);
2524 
2525       /* start timing */
2526       SCIPclockStart(conshdlr->setuptime, set);
2527 
2528       /* call external method */
2529       SCIP_CALL( conshdlr->consexit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2530 
2531       /* stop timing */
2532       SCIPclockStop(conshdlr->setuptime, set);
2533 
2534       /* perform the cached constraint updates */
2535       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2536    }
2537    conshdlr->initialized = FALSE;
2538 
2539    return SCIP_OKAY;
2540 }
2541 
2542 /** informs constraint handler that the presolving process is being started */
SCIPconshdlrInitpre(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)2543 SCIP_RETCODE SCIPconshdlrInitpre(
2544    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2545    BMS_BLKMEM*           blkmem,             /**< block memory */
2546    SCIP_SET*             set,                /**< global SCIP settings */
2547    SCIP_STAT*            stat                /**< dynamic problem statistics */
2548    )
2549 {
2550    assert(conshdlr != NULL);
2551    assert(set != NULL);
2552 
2553    /* reset conshdlr last presolved data in case of a restart */
2554    conshdlr->lastpropdomchgcount = -1;
2555    conshdlr->lastenfolpdomchgcount = -1;
2556    conshdlr->lastenfopsdomchgcount = -1;
2557    conshdlr->lastenforelaxdomchgcount = -1;
2558    conshdlr->lastenforelaxrelaxcount = -1;
2559    conshdlr->lastenfolpnode = -1;
2560    conshdlr->lastenfopsnode = -1;
2561    conshdlr->lastenfolpresult = SCIP_DIDNOTRUN;
2562    conshdlr->lastenfopsresult = SCIP_DIDNOTRUN;
2563    conshdlr->lastenforelaxresult = SCIP_DIDNOTRUN;
2564    conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2565    conshdlr->startnactiveconss = 0;
2566    conshdlr->lastsepalpcount = -1;
2567    conshdlr->lastenfolplpcount = -1;
2568    conshdlr->lastnusefulpropconss = 0;
2569    conshdlr->lastnusefulsepaconss = 0;
2570    conshdlr->lastnusefulenfoconss = 0;
2571    conshdlr->lastnfixedvars = 0;
2572    conshdlr->lastnaggrvars = 0;
2573    conshdlr->lastnchgvartypes = 0;
2574    conshdlr->lastnchgbds = 0;
2575    conshdlr->lastnaddholes = 0;
2576    conshdlr->lastndelconss = 0;
2577    conshdlr->lastnaddconss = 0;
2578    conshdlr->lastnupgdconss = 0;
2579    conshdlr->lastnchgcoefs = 0;
2580    conshdlr->lastnchgsides = 0;
2581    conshdlr->propwasdelayed = FALSE;
2582 
2583    /* call presolving initialization method of constraint handler */
2584    if( conshdlr->consinitpre != NULL )
2585    {
2586       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2587        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2588        * external method; to avoid this, these changes will be buffered and processed after the method call
2589        */
2590       conshdlrDelayUpdates(conshdlr);
2591 
2592       /* start timing */
2593       SCIPclockStart(conshdlr->setuptime, set);
2594 
2595       /* call external method */
2596       SCIP_CALL( conshdlr->consinitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2597 
2598       /* stop timing */
2599       SCIPclockStop(conshdlr->setuptime, set);
2600 
2601       /* perform the cached constraint updates */
2602       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2603    }
2604 
2605    /* after a restart the LP is empty but the initial constraints are not included in the initialconss array anymore;
2606     * we have to put them back into this array in order to obtain the correct initial root relaxation
2607     */
2608    if( stat->nruns >= 2 )
2609    {
2610       int c;
2611 
2612       for( c = 0; c < conshdlr->nconss; ++c )
2613       {
2614          /**@todo should only active constraints be added to the initconss array? at least cons->active is asserted in
2615           *       conshdlrAddInitcons(conshdlr, set, conshdlr->conss[c])
2616           */
2617          if( conshdlr->conss[c]->addarraypos >= 0 && !conshdlr->conss[c]->deleted &&
2618             conshdlr->conss[c]->initial && conshdlr->conss[c]->initconsspos == -1 )
2619          {
2620             SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->conss[c]) );
2621          }
2622       }
2623    }
2624 
2625    return SCIP_OKAY;
2626 }
2627 
2628 /** informs constraint handler that the presolving is finished */
SCIPconshdlrExitpre(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)2629 SCIP_RETCODE SCIPconshdlrExitpre(
2630    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2631    BMS_BLKMEM*           blkmem,             /**< block memory */
2632    SCIP_SET*             set,                /**< global SCIP settings */
2633    SCIP_STAT*            stat                /**< dynamic problem statistics */
2634    )
2635 {
2636    assert(conshdlr != NULL);
2637    assert(set != NULL);
2638 
2639    /* call presolving deinitialization method of constraint handler */
2640    if( conshdlr->consexitpre != NULL )
2641    {
2642       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2643        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2644        * external method; to avoid this, these changes will be buffered and processed after the method call
2645        */
2646       conshdlrDelayUpdates(conshdlr);
2647 
2648       /* start timing */
2649       SCIPclockStart(conshdlr->setuptime, set);
2650 
2651       /* call external method */
2652       SCIP_CALL( conshdlr->consexitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2653 
2654       /* stop timing */
2655       SCIPclockStop(conshdlr->setuptime, set);
2656 
2657       /* perform the cached constraint updates */
2658       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2659    }
2660 
2661    /* update statistics */
2662    conshdlr->maxnactiveconss = conshdlr->nactiveconss;
2663    conshdlr->startnactiveconss = conshdlr->nactiveconss;
2664 
2665    return SCIP_OKAY;
2666 }
2667 
2668 /** informs constraint handler that the branch and bound process is being started */
SCIPconshdlrInitsol(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)2669 SCIP_RETCODE SCIPconshdlrInitsol(
2670    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2671    BMS_BLKMEM*           blkmem,             /**< block memory */
2672    SCIP_SET*             set,                /**< global SCIP settings */
2673    SCIP_STAT*            stat                /**< dynamic problem statistics */
2674    )
2675 {
2676    assert(conshdlr != NULL);
2677    assert(set != NULL);
2678    assert(stat != NULL);
2679 
2680    conshdlr->sepalpwasdelayed = FALSE;
2681    conshdlr->sepasolwasdelayed = FALSE;
2682 
2683    /* call solving process initialization method of constraint handler */
2684    if( conshdlr->consinitsol != NULL )
2685    {
2686       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2687        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2688        * external method; to avoid this, these changes will be buffered and processed after the method call
2689        */
2690       conshdlrDelayUpdates(conshdlr);
2691 
2692       /* start timing */
2693       SCIPclockStart(conshdlr->setuptime, set);
2694 
2695       /* call external method */
2696       SCIP_CALL( conshdlr->consinitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
2697 
2698       /* stop timing */
2699       SCIPclockStop(conshdlr->setuptime, set);
2700 
2701       /* perform the cached constraint updates */
2702       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2703    }
2704 
2705    return SCIP_OKAY;
2706 }
2707 
2708 /** informs constraint handler that the branch and bound process data is being freed */
SCIPconshdlrExitsol(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_Bool restart)2709 SCIP_RETCODE SCIPconshdlrExitsol(
2710    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2711    BMS_BLKMEM*           blkmem,             /**< block memory */
2712    SCIP_SET*             set,                /**< global SCIP settings */
2713    SCIP_STAT*            stat,               /**< dynamic problem statistics */
2714    SCIP_Bool             restart             /**< was this exit solve call triggered by a restart? */
2715    )
2716 {
2717    assert(conshdlr != NULL);
2718    assert(set != NULL);
2719 
2720    /* call solving process deinitialization method of constraint handler */
2721    if( conshdlr->consexitsol != NULL )
2722    {
2723       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2724        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2725        * external method; to avoid this, these changes will be buffered and processed after the method call
2726        */
2727       conshdlrDelayUpdates(conshdlr);
2728 
2729       /* start timing */
2730       SCIPclockStart(conshdlr->setuptime, set);
2731 
2732       /* call external method */
2733       SCIP_CALL( conshdlr->consexitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss, restart) );
2734 
2735       /* stop timing */
2736       SCIPclockStop(conshdlr->setuptime, set);
2737 
2738       /* perform the cached constraint updates */
2739       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2740    }
2741 
2742    return SCIP_OKAY;
2743 }
2744 
2745 /** calls LP initialization method of constraint handler to separate all initial active constraints */
SCIPconshdlrInitLP(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_TREE * tree,SCIP_Bool initkeptconss,SCIP_Bool * cutoff)2746 SCIP_RETCODE SCIPconshdlrInitLP(
2747    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2748    BMS_BLKMEM*           blkmem,             /**< block memory */
2749    SCIP_SET*             set,                /**< global SCIP settings */
2750    SCIP_STAT*            stat,               /**< dynamic problem statistics */
2751    SCIP_TREE*            tree,               /**< branch and bound tree */
2752    SCIP_Bool             initkeptconss,      /**< Also initialize constraints which are valid at a more global node,
2753                                               *   but were not activated there? Should be FALSE for repeated calls at
2754                                               *   one node or if the current focusnode is a child of the former one */
2755    SCIP_Bool*            cutoff              /**< pointer to store whether infeasibility was detected while building the LP */
2756    )
2757 {
2758    assert(conshdlr != NULL);
2759    assert(cutoff != NULL);
2760 #ifdef MORE_DEBUG
2761    assert(stat->nnodes > 1 || conshdlr->ninitconsskept == 0 || SCIPtreeProbing(tree));
2762 #endif
2763 
2764    *cutoff = FALSE;
2765 
2766    if( conshdlr->consinitlp != NULL )
2767    {
2768       int currentdepth;
2769       int oldninitconss;
2770       int c;
2771 
2772       SCIPsetDebugMsg(set, "initializing LP with %d initial constraints of handler <%s> (ninitconss=%d, kept=%d, initkept=%u)\n",
2773          initkeptconss ? conshdlr->ninitconss : conshdlr->ninitconss - conshdlr->ninitconsskept, conshdlr->name,
2774          conshdlr->ninitconss, conshdlr->ninitconsskept, initkeptconss);
2775 
2776       /* no constraints to initialize (or only kept constraints which do not need to be initialized this time) -> return */
2777       if( conshdlr->needscons && (conshdlr->ninitconss == 0 || (!initkeptconss && conshdlr->ninitconss == conshdlr->ninitconsskept)) )
2778          return SCIP_OKAY;
2779 
2780       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2781        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2782        * external method; to avoid this, these changes will be buffered and processed after the method call
2783        */
2784       conshdlrDelayUpdates(conshdlr);
2785 
2786       oldninitconss = conshdlr->ninitconss;
2787 
2788       /* start timing */
2789       SCIPclockStart(conshdlr->sepatime, set);
2790 
2791       if( initkeptconss )
2792       {
2793          /* add all kept initial constraints which are currently active to the second part of the initconss array */
2794          /* @todo keep track of where a constraint was already initialized (e.g., in the conssetchg)? */
2795          for( c = 0; c < conshdlr->ninitconsskept; ++c )
2796          {
2797             assert(conshdlr->initconss[c]->initconsspos == c);
2798 
2799             if( SCIPconsIsActive(conshdlr->initconss[c]) )
2800             {
2801                SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->initconss[c]) );
2802             }
2803          }
2804       }
2805 
2806       /* call external method */
2807       SCIP_CALL( conshdlr->consinitlp(set->scip, conshdlr, &conshdlr->initconss[conshdlr->ninitconsskept],
2808             conshdlr->ninitconss - conshdlr->ninitconsskept, cutoff) );
2809 
2810       /* stop timing */
2811       SCIPclockStop(conshdlr->sepatime, set);
2812 
2813       /* perform the cached constraint updates */
2814       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2815 
2816       currentdepth = SCIPtreeGetCurrentDepth(tree);
2817       assert(currentdepth >= 0);
2818 
2819       /* clear the initconss array */
2820       for( c = conshdlr->ninitconsskept; c < oldninitconss; ++c )
2821       {
2822          assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) >= -1);
2823          assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) <= currentdepth);
2824 
2825          /* if the constraint was not initialized at its valid node, we keep it */
2826          if( currentdepth > 0 ? SCIPconsGetActiveDepth(conshdlr->initconss[c]) != currentdepth :
2827             SCIPconsGetActiveDepth(conshdlr->initconss[c]) > 0 )
2828          {
2829             conshdlr->initconss[conshdlr->ninitconsskept] = conshdlr->initconss[c];
2830             conshdlr->initconss[conshdlr->ninitconsskept]->initconsspos = conshdlr->ninitconsskept;
2831             ++(conshdlr->ninitconsskept);
2832          }
2833          else
2834             conshdlr->initconss[c]->initconsspos = -1;
2835       }
2836 #ifndef NDEBUG
2837       for( ; c < conshdlr->ninitconss; ++c )
2838          assert(conshdlr->initconss[c]->initconsspos < conshdlr->ninitconsskept);
2839 #endif
2840       conshdlr->ninitconss = conshdlr->ninitconsskept;
2841 
2842       if( conshdlr->ninitconss == 0 )
2843       {
2844          BMSfreeMemoryArrayNull(&conshdlr->initconss);
2845          conshdlr->initconsssize = 0;
2846       }
2847    }
2848 
2849    return SCIP_OKAY;
2850 }
2851 
2852 /** calls separator method of constraint handler to separate LP solution */
SCIPconshdlrSeparateLP(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_SEPASTORE * sepastore,int depth,SCIP_Bool execdelayed,SCIP_RESULT * result)2853 SCIP_RETCODE SCIPconshdlrSeparateLP(
2854    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2855    BMS_BLKMEM*           blkmem,             /**< block memory */
2856    SCIP_SET*             set,                /**< global SCIP settings */
2857    SCIP_STAT*            stat,               /**< dynamic problem statistics */
2858    SCIP_SEPASTORE*       sepastore,          /**< separation storage */
2859    int                   depth,              /**< depth of current node */
2860    SCIP_Bool             execdelayed,        /**< execute separation method even if it is marked to be delayed */
2861    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
2862    )
2863 {
2864    assert(conshdlr != NULL);
2865    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
2866    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
2867    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
2868    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
2869    assert(stat != NULL);
2870    assert(conshdlr->lastsepalpcount != stat->lpcount
2871       || (0 <= conshdlr->lastnusefulsepaconss && conshdlr->lastnusefulsepaconss <= conshdlr->nusefulsepaconss));
2872    assert(set != NULL);
2873    assert(result != NULL);
2874 
2875    *result = SCIP_DIDNOTRUN;
2876 
2877    if( conshdlr->conssepalp != NULL
2878       && ((depth == 0 && conshdlr->sepafreq == 0)
2879          || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0)
2880          || conshdlr->sepalpwasdelayed) )
2881    {
2882       /* check, if separation method should be delayed */
2883       if( !conshdlr->delaysepa || execdelayed )
2884       {
2885          int nconss;
2886          int nusefulconss;
2887          int firstcons;
2888 
2889          /* check, if this LP solution was already separated */
2890          if( conshdlr->lastsepalpcount == stat->lpcount )
2891          {
2892             /* all constraints that were not yet separated on the new LP solution must be useful constraints, which means,
2893              * that the new constraints are the last constraints of the useful ones
2894              */
2895             nconss = conshdlr->nusefulsepaconss - conshdlr->lastnusefulsepaconss;
2896             nusefulconss = nconss;
2897             firstcons = conshdlr->lastnusefulsepaconss;
2898          }
2899          else
2900          {
2901             /* on a new LP solution, we want to separate all constraints */
2902             nconss = conshdlr->nsepaconss;
2903             nusefulconss = conshdlr->nusefulsepaconss;
2904             firstcons = 0;
2905          }
2906          assert(firstcons >= 0);
2907          assert(firstcons + nconss <= conshdlr->nsepaconss);
2908          assert(nusefulconss <= nconss);
2909 
2910          /* constraint handlers without constraints should only be called once */
2911          if( nconss > 0 || (!conshdlr->needscons && conshdlr->lastsepalpcount != stat->lpcount) )
2912          {
2913             SCIP_CONS** conss;
2914             SCIP_Longint oldndomchgs;
2915             SCIP_Longint oldnprobdomchgs;
2916             SCIP_Longint lastsepalpcount;
2917             int oldncuts;
2918             int oldnactiveconss;
2919             int lastnusefulsepaconss;
2920 
2921             SCIPsetDebugMsg(set, "separating constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n",
2922                firstcons, firstcons + nconss - 1, conshdlr->nsepaconss, conshdlr->name,
2923                conshdlr->lastsepalpcount == stat->lpcount ? "old" : "new");
2924 
2925             /* remember the number of processed constraints on the current LP solution */
2926             lastsepalpcount = stat->lpcount;
2927             lastnusefulsepaconss = conshdlr->nusefulsepaconss;
2928 
2929             /* get the array of the constraints to be processed */
2930             conss = &(conshdlr->sepaconss[firstcons]);
2931 
2932             oldndomchgs = stat->nboundchgs + stat->nholechgs;
2933             oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
2934             oldncuts = SCIPsepastoreGetNCuts(sepastore);
2935             oldnactiveconss = stat->nactiveconss;
2936 
2937             /* check, if we want to use eager evaluation */
2938             if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0)
2939                || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) )
2940                nusefulconss = nconss;
2941 
2942             /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
2943              * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
2944              * external method; to avoid this, these changes will be buffered and processed after the method call
2945              */
2946             conshdlrDelayUpdates(conshdlr);
2947             conshdlr->duringsepa = TRUE;
2948 
2949             /* start timing */
2950             SCIPclockStart(conshdlr->sepatime, set);
2951 
2952             /* call external method */
2953             SCIP_CALL( conshdlr->conssepalp(set->scip, conshdlr, conss, nconss, nusefulconss, result) );
2954             SCIPsetDebugMsg(set, " -> separating LP returned result <%d>\n", *result);
2955 
2956             /* stop timing */
2957             SCIPclockStop(conshdlr->sepatime, set);
2958 
2959             /* perform the cached constraint updates */
2960             conshdlr->duringsepa = FALSE;
2961             SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
2962 
2963             /* update statistics */
2964             if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
2965             {
2966                conshdlr->lastsepalpcount = lastsepalpcount;
2967                conshdlr->lastnusefulsepaconss = MIN(lastnusefulsepaconss, conshdlr->nusefulsepaconss);
2968                conshdlr->nsepacalls++;
2969             }
2970             if( *result == SCIP_CUTOFF )
2971                conshdlr->ncutoffs++;
2972             conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
2973             conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
2974 
2975             /* update domain reductions; therefore remove the domain
2976              * reduction counts which were generated in probing mode */
2977             conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
2978             conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
2979 
2980             /* evaluate result */
2981             if( *result != SCIP_CUTOFF
2982                && *result != SCIP_CONSADDED
2983                && *result != SCIP_REDUCEDDOM
2984                && *result != SCIP_SEPARATED
2985                && *result != SCIP_NEWROUND
2986                && *result != SCIP_DIDNOTFIND
2987                && *result != SCIP_DIDNOTRUN
2988                && *result != SCIP_DELAYED )
2989             {
2990                SCIPerrorMessage("LP separation method of constraint handler <%s> returned invalid result <%d>\n",
2991                   conshdlr->name, *result);
2992                return SCIP_INVALIDRESULT;
2993             }
2994          }
2995       }
2996       else
2997       {
2998          SCIPsetDebugMsg(set, "LP separation method of constraint handler <%s> was delayed\n", conshdlr->name);
2999          *result = SCIP_DELAYED;
3000       }
3001 
3002       /* remember whether separation method was delayed */
3003       conshdlr->sepalpwasdelayed = (*result == SCIP_DELAYED);
3004    }
3005 
3006    return SCIP_OKAY;
3007 }
3008 
3009 /** calls separator method of constraint handler to separate given primal solution */
SCIPconshdlrSeparateSol(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_SEPASTORE * sepastore,SCIP_SOL * sol,int depth,SCIP_Bool execdelayed,SCIP_RESULT * result)3010 SCIP_RETCODE SCIPconshdlrSeparateSol(
3011    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3012    BMS_BLKMEM*           blkmem,             /**< block memory */
3013    SCIP_SET*             set,                /**< global SCIP settings */
3014    SCIP_STAT*            stat,               /**< dynamic problem statistics */
3015    SCIP_SEPASTORE*       sepastore,          /**< separation storage */
3016    SCIP_SOL*             sol,                /**< primal solution that should be separated */
3017    int                   depth,              /**< depth of current node */
3018    SCIP_Bool             execdelayed,        /**< execute separation method even if it is marked to be delayed */
3019    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
3020    )
3021 {
3022    assert(conshdlr != NULL);
3023    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3024    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3025    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3026    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3027    assert(set != NULL);
3028    assert(stat != NULL);
3029    assert(result != NULL);
3030 
3031    *result = SCIP_DIDNOTRUN;
3032 
3033    if( conshdlr->conssepasol != NULL
3034       && ((depth == 0 && conshdlr->sepafreq == 0)
3035          || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0)
3036          || conshdlr->sepasolwasdelayed) )
3037    {
3038       /* check, if separation method should be delayed */
3039       if( !conshdlr->delaysepa || execdelayed )
3040       {
3041          int nconss;
3042          int nusefulconss;
3043 
3044          /* always separate all constraints */
3045          nconss = conshdlr->nsepaconss;
3046          nusefulconss = conshdlr->nusefulsepaconss;
3047          assert(nusefulconss <= nconss);
3048 
3049          if( nconss > 0 || !conshdlr->needscons )
3050          {
3051             SCIP_CONS** conss;
3052             SCIP_Longint oldndomchgs;
3053             SCIP_Longint oldnprobdomchgs;
3054             int oldncuts;
3055             int oldnactiveconss;
3056 
3057             SCIPsetDebugMsg(set, "separating %d constraints of handler <%s> (primal solution %p)\n",
3058                nconss, conshdlr->name, (void*)sol);
3059 
3060             /* get the array of the constraints to be processed */
3061             conss = conshdlr->sepaconss;
3062 
3063             oldndomchgs = stat->nboundchgs + stat->nholechgs;
3064             oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3065             oldncuts = SCIPsepastoreGetNCuts(sepastore);
3066             oldnactiveconss = stat->nactiveconss;
3067 
3068             /* check, if we want to use eager evaluation */
3069             if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0)
3070                || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) )
3071                nusefulconss = nconss;
3072 
3073             /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3074              * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3075              * external method; to avoid this, these changes will be buffered and processed after the method call
3076              */
3077             conshdlrDelayUpdates(conshdlr);
3078             conshdlr->duringsepa = TRUE;
3079 
3080             /* start timing */
3081             SCIPclockStart(conshdlr->sepatime, set);
3082 
3083             /* call external method */
3084             SCIP_CALL( conshdlr->conssepasol(set->scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
3085             SCIPsetDebugMsg(set, " -> separating sol returned result <%d>\n", *result);
3086 
3087             /* stop timing */
3088             SCIPclockStop(conshdlr->sepatime, set);
3089 
3090             /* perform the cached constraint updates */
3091             conshdlr->duringsepa = FALSE;
3092             SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3093 
3094             /* update statistics */
3095             if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
3096                conshdlr->nsepacalls++;
3097             if( *result == SCIP_CUTOFF )
3098                conshdlr->ncutoffs++;
3099             conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3100             conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3101 
3102             /* update domain reductions; therefore remove the domain
3103              * reduction counts which were generated in probing mode */
3104             conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3105             conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3106 
3107             /* evaluate result */
3108             if( *result != SCIP_CUTOFF
3109                && *result != SCIP_CONSADDED
3110                && *result != SCIP_REDUCEDDOM
3111                && *result != SCIP_SEPARATED
3112                && *result != SCIP_NEWROUND
3113                && *result != SCIP_DIDNOTFIND
3114                && *result != SCIP_DIDNOTRUN
3115                && *result != SCIP_DELAYED )
3116             {
3117                SCIPerrorMessage("SOL separation method of constraint handler <%s> returned invalid result <%d>\n",
3118                   conshdlr->name, *result);
3119                return SCIP_INVALIDRESULT;
3120             }
3121          }
3122       }
3123       else
3124       {
3125          SCIPsetDebugMsg(set, "SOL separation method of constraint handler <%s> was delayed\n", conshdlr->name);
3126          *result = SCIP_DELAYED;
3127       }
3128 
3129       /* remember whether separation method was delayed */
3130       conshdlr->sepasolwasdelayed = (*result == SCIP_DELAYED);
3131    }
3132 
3133    return SCIP_OKAY;
3134 }
3135 
3136 /** calls enforcing method of constraint handler for a relaxation solution for all constraints added after last
3137  *  conshdlrResetEnfo() call
3138  */
SCIPconshdlrEnforceRelaxSol(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_TREE * tree,SCIP_SEPASTORE * sepastore,SCIP_SOL * relaxsol,SCIP_Bool solinfeasible,SCIP_RESULT * result)3139 SCIP_RETCODE SCIPconshdlrEnforceRelaxSol(
3140    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3141    BMS_BLKMEM*           blkmem,             /**< block memory */
3142    SCIP_SET*             set,                /**< global SCIP settings */
3143    SCIP_STAT*            stat,               /**< dynamic problem statistics */
3144    SCIP_TREE*            tree,               /**< branch and bound tree */
3145    SCIP_SEPASTORE*       sepastore,          /**< separation storage */
3146    SCIP_SOL*             relaxsol,           /**< solution to be enforced */
3147    SCIP_Bool             solinfeasible,      /**< was the solution already found out to be infeasible? */
3148    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
3149    )
3150 {
3151    int nconss;
3152    int nusefulconss;
3153    int firstcons;
3154    SCIP_Bool relaxchanged;
3155    SCIP_Bool lastinfeasible;
3156 
3157    assert(conshdlr != NULL);
3158    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3159    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3160    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3161    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3162    assert(stat != NULL);
3163    assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount
3164       || conshdlr->lastenfopsnode != stat->nnodes
3165       || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3166    assert(set != NULL);
3167    assert(tree != NULL);
3168    assert(tree->nchildren == 0);
3169    assert(relaxsol != NULL);
3170    assert(result != NULL);
3171 
3172    *result = SCIP_FEASIBLE;
3173 
3174    /* check, if this relaxation solution was already enforced at this node
3175     * the integrality constraint handler always needs to be enforced for all constraints since external branching
3176     * candidates are cleared before each resolve
3177     */
3178    if( conshdlr->lastenforelaxrelaxcount == stat->relaxcount
3179       && conshdlr->lastenforelaxdomchgcount == stat->domchgcount
3180       && conshdlr->lastenforelaxnode == stat->nnodes
3181       && conshdlr->lastenforelaxresult != SCIP_CONSADDED
3182       && conshdlr->lastenforelaxresult != SCIP_SOLVELP
3183       && ( strcmp(conshdlr->name, "integral") != 0 )
3184       )
3185    {
3186       assert(conshdlr->lastenforelaxresult != SCIP_CUTOFF);
3187       assert(conshdlr->lastenforelaxresult != SCIP_BRANCHED);
3188       assert(conshdlr->lastenforelaxresult != SCIP_REDUCEDDOM);
3189       assert(conshdlr->lastenforelaxresult != SCIP_DIDNOTRUN);
3190 
3191       /* if we already enforced the same relaxation solution at this node, we will only enforce new constraints in the
3192        * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3193        * that an infeasibility in the last call is not lost because we only enforce new constraints
3194        */
3195       if( conshdlr->lastenforelaxresult == SCIP_INFEASIBLE )
3196       {
3197          *result = SCIP_INFEASIBLE;
3198          lastinfeasible = TRUE;
3199       }
3200       else
3201          lastinfeasible = FALSE;
3202 
3203       /* all constraints that were not yet enforced on the new relaxation solution must be useful constraints, which means,
3204        * that the new constraints are the last constraints of the useful ones
3205        */
3206       nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3207       nusefulconss = nconss;
3208       firstcons = conshdlr->lastnusefulenfoconss;
3209       relaxchanged = FALSE;
3210    }
3211    else
3212    {
3213       /* on a new relaxation solution or a new node, we want to enforce all constraints */
3214       nconss = conshdlr->nenfoconss;
3215       nusefulconss = conshdlr->nusefulenfoconss;
3216       firstcons = 0;
3217       relaxchanged = TRUE;
3218       lastinfeasible = FALSE;
3219    }
3220    assert(firstcons >= 0);
3221    assert(firstcons + nconss <= conshdlr->nenfoconss);
3222    assert(nusefulconss <= nconss);
3223 
3224    /* constraint handlers without constraints should only be called once */
3225    if( nconss > 0 || (!conshdlr->needscons && relaxchanged) )
3226    {
3227       SCIP_CONS** conss;
3228       SCIP_Longint oldndomchgs;
3229       SCIP_Longint oldnprobdomchgs;
3230       int oldncuts;
3231       int oldnactiveconss;
3232 
3233       assert(conshdlr->consenforelax != NULL);
3234 
3235       SCIPdebugMessage("enforcing constraints %d to %d of %d constraints of handler <%s> (%s relaxation solution)\n",
3236          firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, relaxchanged ? "new" : "old");
3237 
3238       /* remember the number of processed constraints on the current relaxation solution */
3239       conshdlr->lastenforelaxrelaxcount = stat->relaxcount;
3240       conshdlr->lastenforelaxdomchgcount = stat->domchgcount;
3241       conshdlr->lastenforelaxnode = stat->nnodes;
3242       conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3243 
3244       /* get the array of the constraints to be processed */
3245       conss = &(conshdlr->enfoconss[firstcons]);
3246 
3247       oldncuts = SCIPsepastoreGetNCuts(sepastore);
3248       oldnactiveconss = stat->nactiveconss;
3249       oldndomchgs = stat->nboundchgs + stat->nholechgs;
3250       oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3251 
3252       /* check, if we want to use eager evaluation */
3253       if( (conshdlr->eagerfreq == 0 && conshdlr->nenforelaxcalls == 0)
3254          || (conshdlr->eagerfreq > 0 && conshdlr->nenforelaxcalls % conshdlr->eagerfreq == 0) )
3255          nusefulconss = nconss;
3256 
3257       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3258        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3259        * external method; to avoid this, these changes will be buffered and processed after the method call
3260        */
3261       conshdlrDelayUpdates(conshdlr);
3262 
3263       /* start timing */
3264       SCIPclockStart(conshdlr->enforelaxtime, set);
3265 
3266       /* call external method */
3267       SCIP_CALL( conshdlr->consenforelax(set->scip, relaxsol, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) );
3268       SCIPdebugMessage(" -> enforcing returned result <%d>\n", *result);
3269 
3270       /* stop timing */
3271       SCIPclockStop(conshdlr->enforelaxtime, set);
3272 
3273       /* perform the cached constraint updates */
3274       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3275 
3276       /* update statistics */
3277       conshdlr->nenforelaxcalls++;
3278       if( *result == SCIP_CUTOFF )
3279          conshdlr->ncutoffs++;
3280       conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3281       conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3282 
3283       if( *result != SCIP_BRANCHED )
3284       {
3285          assert(tree->nchildren == 0);
3286 
3287          /* update domain reductions; therefore remove the domain
3288           * reduction counts which were generated in probing mode */
3289          conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3290          conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3291       }
3292       else
3293          conshdlr->nchildren += tree->nchildren;
3294 
3295       /* remember the result of the enforcement call */
3296       conshdlr->lastenforelaxresult = *result;
3297 
3298       /* evaluate result */
3299       if( *result != SCIP_CUTOFF
3300          && *result != SCIP_CONSADDED
3301          && *result != SCIP_REDUCEDDOM
3302          && *result != SCIP_SEPARATED
3303          && *result != SCIP_BRANCHED
3304          && *result != SCIP_SOLVELP
3305          && *result != SCIP_INFEASIBLE
3306          && *result != SCIP_FEASIBLE )
3307       {
3308          SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation solutions returned invalid result <%d>\n",
3309             conshdlr->name, *result);
3310          return SCIP_INVALIDRESULT;
3311       }
3312 
3313       /* if the same relaxation solution was already enforced at this node, we only enforced new constraints this time;
3314        * if the enforelax call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3315        * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3316        */
3317       if( lastinfeasible && *result == SCIP_FEASIBLE )
3318          *result = SCIP_INFEASIBLE;
3319    }
3320 
3321    return SCIP_OKAY;
3322 }
3323 
3324 /** calls enforcing method of constraint handler for LP solution for all constraints added after last
3325  *  conshdlrResetEnfo() call
3326  */
SCIPconshdlrEnforceLPSol(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_TREE * tree,SCIP_SEPASTORE * sepastore,SCIP_Bool solinfeasible,SCIP_RESULT * result)3327 SCIP_RETCODE SCIPconshdlrEnforceLPSol(
3328    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3329    BMS_BLKMEM*           blkmem,             /**< block memory */
3330    SCIP_SET*             set,                /**< global SCIP settings */
3331    SCIP_STAT*            stat,               /**< dynamic problem statistics */
3332    SCIP_TREE*            tree,               /**< branch and bound tree */
3333    SCIP_SEPASTORE*       sepastore,          /**< separation storage */
3334    SCIP_Bool             solinfeasible,      /**< was the solution already found out to be infeasible? */
3335    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
3336    )
3337 {
3338    assert(conshdlr != NULL);
3339    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3340    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3341    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3342    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3343    assert(stat != NULL);
3344    assert(conshdlr->lastenfolplpcount != stat->lpcount
3345       || conshdlr->lastenfolpdomchgcount != stat->domchgcount
3346       || conshdlr->lastenfolpnode != stat->nnodes
3347       || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3348    assert(set != NULL);
3349    assert(tree != NULL);
3350    assert(tree->nchildren == 0);
3351    assert(result != NULL);
3352 
3353    *result = SCIP_FEASIBLE;
3354 
3355    if( conshdlr->consenfolp != NULL )
3356    {
3357       int nconss;
3358       int nusefulconss;
3359       int firstcons;
3360       SCIP_Bool lpchanged;
3361       SCIP_Bool lastinfeasible;
3362 
3363       /* check, if this LP solution was already enforced at this node */
3364       if( conshdlr->lastenfolplpcount == stat->lpcount
3365          && conshdlr->lastenfolpdomchgcount == stat->domchgcount
3366          && conshdlr->lastenfolpnode == stat->nnodes
3367          && conshdlr->lastenfolpresult != SCIP_CONSADDED )
3368       {
3369          assert(conshdlr->lastenfolpresult == SCIP_FEASIBLE || conshdlr->lastenfolpresult == SCIP_INFEASIBLE
3370             || conshdlr->lastenfolpresult == SCIP_SEPARATED );
3371 
3372          /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3373           * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3374           * that an infeasibility in the last call is not lost because we only enforce new constraints
3375           */
3376          if( conshdlr->lastenfolpresult == SCIP_FEASIBLE )
3377             lastinfeasible = FALSE;
3378          else
3379          {
3380             assert(conshdlr->lastenfolpresult == SCIP_INFEASIBLE || conshdlr->lastenfolpresult == SCIP_SEPARATED);
3381             *result = SCIP_INFEASIBLE;
3382             lastinfeasible = TRUE;
3383          }
3384 
3385          /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3386           * that the new constraints are the last constraints of the useful ones
3387           */
3388          nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3389          nusefulconss = nconss;
3390          firstcons = conshdlr->lastnusefulenfoconss;
3391          lpchanged = FALSE;
3392       }
3393       else
3394       {
3395          /* on a new LP solution or a new node, we want to enforce all constraints */
3396          nconss = conshdlr->nenfoconss;
3397          nusefulconss = conshdlr->nusefulenfoconss;
3398          firstcons = 0;
3399          lpchanged = TRUE;
3400          lastinfeasible = FALSE;
3401       }
3402       assert(firstcons >= 0);
3403       assert(firstcons + nconss <= conshdlr->nenfoconss);
3404       assert(nusefulconss <= nconss);
3405 
3406       /* constraint handlers without constraints should only be called once */
3407       if( nconss > 0 || (!conshdlr->needscons && lpchanged) )
3408       {
3409          SCIP_CONS** conss;
3410          SCIP_Longint oldndomchgs;
3411          SCIP_Longint oldnprobdomchgs;
3412          int oldncuts;
3413          int oldnactiveconss;
3414 
3415          SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n",
3416             firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, lpchanged ? "new" : "old");
3417 
3418          /* remember the number of processed constraints on the current LP solution */
3419          conshdlr->lastenfolplpcount = stat->lpcount;
3420          conshdlr->lastenfolpdomchgcount = stat->domchgcount;
3421          conshdlr->lastenfolpnode = stat->nnodes;
3422          conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3423 
3424          /* get the array of the constraints to be processed */
3425          conss = &(conshdlr->enfoconss[firstcons]);
3426 
3427          oldncuts = SCIPsepastoreGetNCuts(sepastore);
3428          oldnactiveconss = stat->nactiveconss;
3429          oldndomchgs = stat->nboundchgs + stat->nholechgs;
3430          oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3431 
3432          /* check, if we want to use eager evaluation */
3433          if( (conshdlr->eagerfreq == 0 && conshdlr->nenfolpcalls == 0)
3434             || (conshdlr->eagerfreq > 0 && conshdlr->nenfolpcalls % conshdlr->eagerfreq == 0) )
3435             nusefulconss = nconss;
3436 
3437          /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3438           * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3439           * external method; to avoid this, these changes will be buffered and processed after the method call
3440           */
3441          conshdlrDelayUpdates(conshdlr);
3442 
3443          /* start timing */
3444          SCIPclockStart(conshdlr->enfolptime, set);
3445 
3446          /* call external method */
3447          SCIP_CALL( conshdlr->consenfolp(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) );
3448          SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3449 
3450          /* stop timing */
3451          SCIPclockStop(conshdlr->enfolptime, set);
3452 
3453          /* perform the cached constraint updates */
3454          SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3455 
3456          /* remember the result of the enforcement call */
3457          conshdlr->lastenfolpresult = *result;
3458 
3459          /* update statistics */
3460          conshdlr->nenfolpcalls++;
3461          if( *result == SCIP_CUTOFF )
3462             conshdlr->ncutoffs++;
3463          conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/
3464          conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/
3465          if( *result != SCIP_BRANCHED )
3466          {
3467             assert(tree->nchildren == 0);
3468 
3469             /* update domain reductions; therefore remove the domain
3470              * reduction counts which were generated in probing mode */
3471             conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3472             conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3473          }
3474          else
3475             conshdlr->nchildren += tree->nchildren;
3476 
3477          /* evaluate result */
3478          if( *result != SCIP_CUTOFF
3479             && *result != SCIP_CONSADDED
3480             && *result != SCIP_REDUCEDDOM
3481             && *result != SCIP_SEPARATED
3482             && *result != SCIP_SOLVELP
3483             && *result != SCIP_BRANCHED
3484             && *result != SCIP_INFEASIBLE
3485             && *result != SCIP_FEASIBLE )
3486          {
3487             SCIPerrorMessage("enforcing method of constraint handler <%s> for LP solutions returned invalid result <%d>\n",
3488                conshdlr->name, *result);
3489             return SCIP_INVALIDRESULT;
3490          }
3491 
3492          /* if the same LP solution was already enforced at this node, we only enforced new constraints this time;
3493           * if the enfolp call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3494           * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3495           */
3496          if( lastinfeasible && *result == SCIP_FEASIBLE )
3497             *result = SCIP_INFEASIBLE;
3498       }
3499    }
3500 
3501    return SCIP_OKAY;
3502 }
3503 
3504 /** calls diving solution enforcement callback of constraint handler, if it exists */
SCIPconshdlrGetDiveBoundChanges(SCIP_CONSHDLR * conshdlr,SCIP_SET * set,SCIP_DIVESET * diveset,SCIP_SOL * sol,SCIP_Bool * success,SCIP_Bool * infeasible)3505 SCIP_RETCODE SCIPconshdlrGetDiveBoundChanges(
3506    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3507    SCIP_SET*             set,                /**< global SCIP settings */
3508    SCIP_DIVESET*         diveset,            /**< diving settings to control scoring */
3509    SCIP_SOL*             sol,                /**< current solution of diving mode */
3510    SCIP_Bool*            success,            /**< pointer to store whether constraint handler successfully found a variable */
3511    SCIP_Bool*            infeasible          /**< pointer to store whether the current node was detected to be infeasible */
3512    )
3513 {
3514    assert(conshdlr != NULL);
3515    assert(set != NULL);
3516    assert(diveset != NULL);
3517    assert(sol != NULL);
3518    assert(success != NULL);
3519    assert(infeasible != NULL);
3520 
3521    if( conshdlr->consgetdivebdchgs != NULL )
3522    {
3523       SCIP_CALL( conshdlr->consgetdivebdchgs(set->scip, conshdlr, diveset, sol, success, infeasible) );
3524    }
3525 
3526    return SCIP_OKAY;
3527 }
3528 
3529 /** calls enforcing method of constraint handler for pseudo solution for all constraints added after last
3530  *  conshdlrResetEnfo() call
3531  */
SCIPconshdlrEnforcePseudoSol(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_TREE * tree,SCIP_BRANCHCAND * branchcand,SCIP_Bool solinfeasible,SCIP_Bool objinfeasible,SCIP_Bool forced,SCIP_RESULT * result)3532 SCIP_RETCODE SCIPconshdlrEnforcePseudoSol(
3533    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3534    BMS_BLKMEM*           blkmem,             /**< block memory */
3535    SCIP_SET*             set,                /**< global SCIP settings */
3536    SCIP_STAT*            stat,               /**< dynamic problem statistics */
3537    SCIP_TREE*            tree,               /**< branch and bound tree */
3538    SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
3539    SCIP_Bool             solinfeasible,      /**< was the solution already found out to be infeasible? */
3540    SCIP_Bool             objinfeasible,      /**< is the solution infeasible anyway due to violating lower objective bound? */
3541    SCIP_Bool             forced,             /**< should enforcement of pseudo solution be forced? */
3542    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
3543    )
3544 {
3545    assert(conshdlr != NULL);
3546    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3547    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3548    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3549    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3550    assert(stat != NULL);
3551    assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount
3552       || conshdlr->lastenfopsnode != stat->nnodes
3553       || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss));
3554    assert(set != NULL);
3555    assert(tree != NULL);
3556    assert(tree->nchildren == 0);
3557    assert(result != NULL);
3558 
3559    /* no enforcing of pseudo solution */
3560    if( set->cons_disableenfops && SCIPbranchcandGetNPseudoCands(branchcand) > 0 )
3561    {
3562       *result = SCIP_INFEASIBLE;
3563       return SCIP_OKAY;
3564    }
3565 
3566    *result = SCIP_FEASIBLE;
3567    if( conshdlr->consenfops != NULL )
3568    {
3569       int nconss;
3570       int nusefulconss;
3571       int firstcons;
3572       SCIP_Bool pschanged;
3573       SCIP_Bool lastinfeasible;
3574 
3575       /* check, if this pseudo solution was already enforced at this node */
3576       if( !forced && conshdlr->lastenfopsdomchgcount == stat->domchgcount
3577          && conshdlr->lastenfopsnode == stat->nnodes
3578          && conshdlr->lastenfopsresult != SCIP_CONSADDED
3579          && conshdlr->lastenfopsresult != SCIP_SOLVELP
3580          )
3581       {
3582          assert(conshdlr->lastenfopsresult != SCIP_CUTOFF);
3583          assert(conshdlr->lastenfopsresult != SCIP_BRANCHED);
3584          assert(conshdlr->lastenfopsresult != SCIP_REDUCEDDOM);
3585          assert(conshdlr->lastenfopsresult != SCIP_DIDNOTRUN || objinfeasible);
3586 
3587          /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the
3588           * following; however, the result of the last call for the old constraint is still valid and we have to ensure
3589           * that an infeasibility in the last call is not lost because we only enforce new constraints
3590           */
3591          if( conshdlr->lastenfopsresult == SCIP_INFEASIBLE )
3592          {
3593             *result = SCIP_INFEASIBLE;
3594             lastinfeasible = TRUE;
3595          }
3596          else
3597             lastinfeasible = FALSE;
3598 
3599          /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means,
3600           * that the new constraints are the last constraints of the useful ones
3601           */
3602          nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss;
3603          nusefulconss = nconss;
3604          firstcons = conshdlr->lastnusefulenfoconss;
3605          pschanged = FALSE;
3606       }
3607       else
3608       {
3609          /* on a new pseudo solution or a new node, we want to enforce all constraints */
3610          nconss = conshdlr->nenfoconss;
3611          nusefulconss = conshdlr->nusefulenfoconss;
3612          firstcons = 0;
3613          pschanged = TRUE;
3614          lastinfeasible = FALSE;
3615       }
3616       assert(firstcons >= 0);
3617       assert(firstcons + nconss <= conshdlr->nenfoconss);
3618       assert(nusefulconss <= nconss);
3619 
3620       /* constraint handlers without constraints should only be called once */
3621       if( nconss > 0 || (!conshdlr->needscons && pschanged) )
3622       {
3623          SCIP_CONS** conss;
3624          SCIP_Longint oldndomchgs;
3625          SCIP_Longint oldnprobdomchgs;
3626 
3627          SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, objinfeasible=%u)\n",
3628             firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, pschanged ? "new" : "old", objinfeasible);
3629 
3630          /* remember the number of processed constraints on the current pseudo solution */
3631          conshdlr->lastenfopsdomchgcount = stat->domchgcount;
3632          conshdlr->lastenfopsnode = stat->nnodes;
3633          conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss;
3634 
3635          /* get the array of the constraints to be processed */
3636          conss = &(conshdlr->enfoconss[firstcons]);
3637 
3638          oldndomchgs = stat->nboundchgs + stat->nholechgs;
3639          oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3640 
3641          /* check, if we want to use eager evaluation */
3642          if( (conshdlr->eagerfreq == 0 && conshdlr->nenfopscalls == 0)
3643             || (conshdlr->eagerfreq > 0 && conshdlr->nenfopscalls % conshdlr->eagerfreq == 0) )
3644             nusefulconss = nconss;
3645 
3646          /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3647           * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3648           * external method; to avoid this, these changes will be buffered and processed after the method call
3649           */
3650          conshdlrDelayUpdates(conshdlr);
3651 
3652          /* start timing */
3653          SCIPclockStart(conshdlr->enfopstime, set);
3654 
3655          /* call external method */
3656          SCIP_CALL( conshdlr->consenfops(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, objinfeasible, result) );
3657          SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result);
3658 
3659          /* stop timing */
3660          SCIPclockStop(conshdlr->enfopstime, set);
3661 
3662          /* perform the cached constraint updates */
3663          SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3664 
3665          /* update statistics */
3666          if( *result != SCIP_DIDNOTRUN )
3667             conshdlr->nenfopscalls++;
3668          else if( !objinfeasible )
3669          {
3670             SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions was skipped, even though the solution was not objective-infeasible\n",
3671                conshdlr->name);
3672             conshdlr->lastenfopsresult = *result;
3673 
3674             return SCIP_INVALIDRESULT;
3675          }
3676          /* A constraint handler might return SCIP_DIDNOTRUN and not check any constraints in case objinfeasible was
3677           * TRUE; we change the result pointer to SCIP_INFEASIBLE in this case.
3678           */
3679          else
3680             *result = SCIP_INFEASIBLE;
3681 
3682          if( *result == SCIP_CUTOFF )
3683             conshdlr->ncutoffs++;
3684 
3685          if( *result != SCIP_BRANCHED )
3686          {
3687             assert(tree->nchildren == 0);
3688 
3689             /* update domain reductions; therefore remove the domain
3690              * reduction counts which were generated in probing mode */
3691             conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3692             conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3693          }
3694          else
3695             conshdlr->nchildren += tree->nchildren;
3696 
3697          /* remember the result of the enforcement call */
3698          conshdlr->lastenfopsresult = *result;
3699 
3700          /* evaluate result */
3701          if( *result != SCIP_CUTOFF
3702             && *result != SCIP_CONSADDED
3703             && *result != SCIP_REDUCEDDOM
3704             && *result != SCIP_BRANCHED
3705             && *result != SCIP_SOLVELP
3706             && *result != SCIP_INFEASIBLE
3707             && *result != SCIP_FEASIBLE
3708             && *result != SCIP_DIDNOTRUN )
3709          {
3710             SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions returned invalid result <%d>\n",
3711                conshdlr->name, *result);
3712             return SCIP_INVALIDRESULT;
3713          }
3714 
3715          /* if the same pseudo solution was already enforced at this node, we only enforced new constraints this time;
3716           * if the enfops call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the
3717           * last call detected infeasibility for the old constraints, we have to change the result to infeasible
3718           */
3719          if( lastinfeasible && *result == SCIP_FEASIBLE )
3720             *result = SCIP_INFEASIBLE;
3721       }
3722    }
3723 
3724    return SCIP_OKAY;
3725 }
3726 
3727 /** calls feasibility check method of constraint handler */
SCIPconshdlrCheck(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_SOL * sol,SCIP_Bool checkintegrality,SCIP_Bool checklprows,SCIP_Bool printreason,SCIP_Bool completely,SCIP_RESULT * result)3728 SCIP_RETCODE SCIPconshdlrCheck(
3729    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3730    BMS_BLKMEM*           blkmem,             /**< block memory */
3731    SCIP_SET*             set,                /**< global SCIP settings */
3732    SCIP_STAT*            stat,               /**< dynamic problem statistics */
3733    SCIP_SOL*             sol,                /**< primal CIP solution */
3734    SCIP_Bool             checkintegrality,   /**< Has integrality to be checked? */
3735    SCIP_Bool             checklprows,        /**< Do constraints represented by rows in the current LP have to be checked? */
3736    SCIP_Bool             printreason,        /**< Should the reason for the violation be printed? */
3737    SCIP_Bool             completely,         /**< Should all violations be checked? */
3738    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
3739    )
3740 {
3741    assert(conshdlr != NULL);
3742    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3743    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3744    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3745    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3746    assert(set != NULL);
3747    assert(result != NULL);
3748 
3749    *result = SCIP_FEASIBLE;
3750 
3751    if( conshdlr->conscheck != NULL && (!conshdlr->needscons || conshdlr->ncheckconss > 0) )
3752    {
3753       SCIPsetDebugMsg(set, "checking %d constraints of handler <%s>\n", conshdlr->ncheckconss, conshdlr->name);
3754 
3755       /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3756        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3757        * external method; to avoid this, these changes will be buffered and processed after the method call
3758        */
3759       conshdlrDelayUpdates(conshdlr);
3760 
3761       /* start timing */
3762       SCIPclockStart(conshdlr->checktime, set);
3763 
3764       /* call external method */
3765       SCIP_CALL( conshdlr->conscheck(set->scip, conshdlr, conshdlr->checkconss, conshdlr->ncheckconss,
3766             sol, checkintegrality, checklprows, printreason, completely, result) );
3767       SCIPsetDebugMsg(set, " -> checking returned result <%d>\n", *result);
3768 
3769       /* stop timing */
3770       SCIPclockStop(conshdlr->checktime, set);
3771 
3772       /* update statistics */
3773       conshdlr->ncheckcalls++;
3774 
3775       /* perform the cached constraint updates */
3776       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3777 
3778       /* evaluate result */
3779       if( *result != SCIP_INFEASIBLE && *result != SCIP_FEASIBLE )
3780       {
3781          SCIPerrorMessage("feasibility check of constraint handler <%s> returned invalid result <%d>\n", conshdlr->name, *result);
3782          return SCIP_INVALIDRESULT;
3783       }
3784    }
3785 
3786    return SCIP_OKAY;
3787 }
3788 
3789 /** calls propagation method of constraint handler */
SCIPconshdlrPropagate(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,int depth,SCIP_Bool fullpropagation,SCIP_Bool execdelayed,SCIP_Bool instrongbranching,SCIP_PROPTIMING proptiming,SCIP_RESULT * result)3790 SCIP_RETCODE SCIPconshdlrPropagate(
3791    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3792    BMS_BLKMEM*           blkmem,             /**< block memory */
3793    SCIP_SET*             set,                /**< global SCIP settings */
3794    SCIP_STAT*            stat,               /**< dynamic problem statistics */
3795    int                   depth,              /**< depth of current node */
3796    SCIP_Bool             fullpropagation,    /**< should all constraints be propagated (or only new ones)? */
3797    SCIP_Bool             execdelayed,        /**< execute propagation method even if it is marked to be delayed */
3798    SCIP_Bool             instrongbranching,  /**< are we currently doing strong branching? */
3799    SCIP_PROPTIMING       proptiming,         /**< current point in the node solving process */
3800    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
3801    )
3802 {
3803    assert(conshdlr != NULL);
3804    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3805    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3806    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3807    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3808    assert(stat != NULL);
3809    assert(conshdlr->lastpropdomchgcount != stat->domchgcount
3810       || (0 <= conshdlr->lastnusefulpropconss && conshdlr->lastnusefulpropconss <= conshdlr->nusefulpropconss));
3811    assert(set != NULL);
3812    assert(depth >= 0);
3813    assert(result != NULL);
3814 
3815    *result = SCIP_DIDNOTRUN;
3816 
3817    if( conshdlr->consprop != NULL
3818       && (!conshdlr->needscons || conshdlr->npropconss > 0)
3819       && ((depth == 0 && conshdlr->propfreq == 0)
3820          || (conshdlr->propfreq > 0 && depth % conshdlr->propfreq == 0)
3821          || conshdlr->propwasdelayed) )
3822    {
3823       /* check, if propagation method should be delayed */
3824       if( !conshdlr->delayprop || execdelayed )
3825       {
3826          int nconss;
3827          int nusefulconss;
3828          int nmarkedpropconss;
3829          int firstcons;
3830 
3831          /* check, if the current domains were already propagated */
3832          if( !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount && conshdlr->nmarkedpropconss == 0 )
3833          {
3834             /* all constraints that were not yet propagated on the new domains must be useful constraints, which means,
3835              * that the new constraints are the last constraints of the useful ones
3836              */
3837             nconss = conshdlr->nusefulpropconss - conshdlr->lastnusefulpropconss;
3838             nusefulconss = nconss;
3839             firstcons = conshdlr->lastnusefulpropconss;
3840          }
3841          else
3842          {
3843             /* on new domains, we want to propagate all constraints */
3844             nconss = conshdlr->npropconss;
3845             nusefulconss = conshdlr->nusefulpropconss;
3846             firstcons = 0;
3847          }
3848          assert(firstcons >= 0);
3849          assert(firstcons + nconss <= conshdlr->npropconss);
3850          assert(nusefulconss <= nconss);
3851 
3852          nmarkedpropconss = conshdlr->nmarkedpropconss;
3853 
3854          /* constraint handlers without constraints should only be called once */
3855          if( nconss > 0 || fullpropagation
3856             || (!conshdlr->needscons && conshdlr->lastpropdomchgcount != stat->domchgcount) )
3857          {
3858             SCIP_CONS** conss;
3859             SCIP_Longint oldndomchgs;
3860             SCIP_Longint oldnprobdomchgs;
3861             SCIP_Longint lastpropdomchgcount;
3862             int lastnusefulpropconss;
3863 
3864             SCIPsetDebugMsg(set, "propagating constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, %d useful)\n",
3865                firstcons, firstcons + nconss - 1, conshdlr->npropconss, conshdlr->name,
3866                !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount ? "old" : "new", nusefulconss);
3867 
3868             /* remember the number of processed constraints on the current domains */
3869             lastpropdomchgcount = stat->domchgcount;
3870             lastnusefulpropconss = conshdlr->nusefulpropconss;
3871 
3872             /* get the array of the constraints to be processed */
3873             conss = &(conshdlr->propconss[firstcons]);
3874 
3875             oldndomchgs = stat->nboundchgs + stat->nholechgs;
3876             oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs;
3877 
3878             /* check, if we want to use eager evaluation */
3879             if( (conshdlr->eagerfreq == 0 && conshdlr->npropcalls == 0)
3880                || (conshdlr->eagerfreq > 0 && conshdlr->npropcalls % conshdlr->eagerfreq == 0) )
3881                nusefulconss = nconss;
3882 
3883             /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
3884              * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
3885              * external method; to avoid this, these changes will be buffered and processed after the method call
3886              */
3887             conshdlrDelayUpdates(conshdlr);
3888             conshdlr->duringprop = TRUE;
3889 
3890             /* start timing */
3891             if( instrongbranching )
3892                SCIPclockStart(conshdlr->sbproptime, set);
3893             else
3894                SCIPclockStart(conshdlr->proptime, set);
3895 
3896             assert(nusefulconss <= nconss);
3897             assert(nmarkedpropconss <= nconss);
3898 
3899             /* call external method */
3900             SCIP_CALL( conshdlr->consprop(set->scip, conshdlr, conss, nconss, nusefulconss, nmarkedpropconss, proptiming, result) );
3901             SCIPsetDebugMsg(set, " -> propagation returned result <%d>\n", *result);
3902 
3903             /* stop timing */
3904             if( instrongbranching )
3905                SCIPclockStop(conshdlr->sbproptime, set);
3906             else
3907                SCIPclockStop(conshdlr->proptime, set);
3908 
3909             /* perform the cached constraint updates */
3910             conshdlr->duringprop = FALSE;
3911             SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
3912 
3913             /* update statistics */
3914             if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED )
3915             {
3916                conshdlr->lastpropdomchgcount = lastpropdomchgcount;
3917                conshdlr->lastnusefulpropconss = MIN(conshdlr->nusefulpropconss, lastnusefulpropconss);
3918                conshdlr->npropcalls++;
3919             }
3920             else
3921             {
3922                assert(lastpropdomchgcount == stat->domchgcount);
3923                assert(lastnusefulpropconss == conshdlr->nusefulpropconss);
3924             }
3925             if( *result == SCIP_CUTOFF )
3926                conshdlr->ncutoffs++;
3927 
3928             /* update domain reductions; therefore remove the domain
3929              * reduction counts which were generated in probing mode */
3930             conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs;
3931             conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs);
3932 
3933             /* check result code of callback method */
3934             if( *result != SCIP_CUTOFF
3935                && *result != SCIP_REDUCEDDOM
3936                && *result != SCIP_DIDNOTFIND
3937                && *result != SCIP_DIDNOTRUN
3938                && *result != SCIP_DELAYED
3939                && *result != SCIP_DELAYNODE )
3940             {
3941                SCIPerrorMessage("propagation method of constraint handler <%s> returned invalid result <%d>\n",
3942                   conshdlr->name, *result);
3943                return SCIP_INVALIDRESULT;
3944             }
3945          }
3946       }
3947       else
3948       {
3949          SCIPsetDebugMsg(set, "propagation method of constraint handler <%s> was delayed\n", conshdlr->name);
3950          *result = SCIP_DELAYED;
3951       }
3952 
3953       /* remember whether propagation method was delayed */
3954       conshdlr->propwasdelayed = (*result == SCIP_DELAYED);
3955    }
3956 
3957    return SCIP_OKAY;
3958 }
3959 
3960 /** calls presolving method of constraint handler */
SCIPconshdlrPresolve(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_PRESOLTIMING timing,int nrounds,int * nfixedvars,int * naggrvars,int * nchgvartypes,int * nchgbds,int * naddholes,int * ndelconss,int * naddconss,int * nupgdconss,int * nchgcoefs,int * nchgsides,SCIP_RESULT * result)3961 SCIP_RETCODE SCIPconshdlrPresolve(
3962    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3963    BMS_BLKMEM*           blkmem,             /**< block memory */
3964    SCIP_SET*             set,                /**< global SCIP settings */
3965    SCIP_STAT*            stat,               /**< dynamic problem statistics */
3966    SCIP_PRESOLTIMING     timing,             /**< current presolving timing */
3967    int                   nrounds,            /**< number of presolving rounds already done */
3968    int*                  nfixedvars,         /**< pointer to total number of variables fixed of all presolvers */
3969    int*                  naggrvars,          /**< pointer to total number of variables aggregated of all presolvers */
3970    int*                  nchgvartypes,       /**< pointer to total number of variable type changes of all presolvers */
3971    int*                  nchgbds,            /**< pointer to total number of variable bounds tightened of all presolvers */
3972    int*                  naddholes,          /**< pointer to total number of domain holes added of all presolvers */
3973    int*                  ndelconss,          /**< pointer to total number of deleted constraints of all presolvers */
3974    int*                  naddconss,          /**< pointer to total number of added constraints of all presolvers */
3975    int*                  nupgdconss,         /**< pointer to total number of upgraded constraints of all presolvers */
3976    int*                  nchgcoefs,          /**< pointer to total number of changed coefficients of all presolvers */
3977    int*                  nchgsides,          /**< pointer to total number of changed left/right hand sides of all presolvers */
3978    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
3979    )
3980 {
3981    assert(conshdlr != NULL);
3982    assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss);
3983    assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss);
3984    assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss);
3985    assert(conshdlr->nusefulpropconss <= conshdlr->npropconss);
3986    assert(set != NULL);
3987    assert(nfixedvars != NULL);
3988    assert(naggrvars != NULL);
3989    assert(nchgvartypes != NULL);
3990    assert(nchgbds != NULL);
3991    assert(naddholes != NULL);
3992    assert(ndelconss != NULL);
3993    assert(naddconss != NULL);
3994    assert(nupgdconss != NULL);
3995    assert(nchgcoefs != NULL);
3996    assert(nchgsides != NULL);
3997    assert(result != NULL);
3998 
3999    *result = SCIP_DIDNOTRUN;
4000 
4001    if( conshdlr->conspresol != NULL
4002       && (!conshdlr->needscons || conshdlr->nactiveconss > 0)
4003       && (conshdlr->maxprerounds == -1 || conshdlr->npresolcalls < conshdlr->maxprerounds ) )
4004    {
4005       SCIPsetDebugMsg(set, "presolving %d constraints of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4006 
4007       /* check, if presolving method should be executed for the current timing */
4008       if( timing & conshdlr->presoltiming )
4009       {
4010          int nnewfixedvars;
4011          int nnewaggrvars;
4012          int nnewchgvartypes;
4013          int nnewchgbds;
4014          int nnewholes;
4015          int nnewdelconss;
4016          int nnewaddconss;
4017          int nnewupgdconss;
4018          int nnewchgcoefs;
4019          int nnewchgsides;
4020 
4021          /* calculate the number of changes since last call */
4022          nnewfixedvars = *nfixedvars - conshdlr->lastnfixedvars;
4023          nnewaggrvars = *naggrvars - conshdlr->lastnaggrvars;
4024          nnewchgvartypes = *nchgvartypes - conshdlr->lastnchgvartypes;
4025          nnewchgbds = *nchgbds - conshdlr->lastnchgbds;
4026          nnewholes = *naddholes - conshdlr->lastnaddholes;
4027          nnewdelconss = *ndelconss - conshdlr->lastndelconss;
4028          nnewaddconss = *naddconss - conshdlr->lastnaddconss;
4029          nnewupgdconss = *nupgdconss - conshdlr->lastnupgdconss;
4030          nnewchgcoefs = *nchgcoefs - conshdlr->lastnchgcoefs;
4031          nnewchgsides = *nchgsides - conshdlr->lastnchgsides;
4032 
4033          /* remember the old number of changes */
4034          conshdlr->lastnfixedvars = *nfixedvars;
4035          conshdlr->lastnaggrvars = *naggrvars;
4036          conshdlr->lastnchgvartypes = *nchgvartypes;
4037          conshdlr->lastnchgbds = *nchgbds;
4038          conshdlr->lastnaddholes = *naddholes;
4039          conshdlr->lastndelconss = *ndelconss;
4040          conshdlr->lastnaddconss = *naddconss;
4041          conshdlr->lastnupgdconss = *nupgdconss;
4042          conshdlr->lastnchgcoefs = *nchgcoefs;
4043          conshdlr->lastnchgsides = *nchgsides;
4044 
4045          /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4046           * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4047           * external method; to avoid this, these changes will be buffered and processed after the method call
4048           */
4049          conshdlrDelayUpdates(conshdlr);
4050 
4051          /* start timing */
4052          SCIPclockStart(conshdlr->presoltime, set);
4053 
4054          /* call external method */
4055          SCIP_CALL( conshdlr->conspresol(set->scip, conshdlr, conshdlr->conss, conshdlr->nactiveconss, nrounds, timing,
4056                nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewholes,
4057                nnewdelconss, nnewaddconss, nnewupgdconss, nnewchgcoefs, nnewchgsides,
4058                nfixedvars, naggrvars, nchgvartypes, nchgbds, naddholes,
4059                ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) );
4060 
4061          /* stop timing */
4062          SCIPclockStop(conshdlr->presoltime, set);
4063 
4064          /* perform the cached constraint updates */
4065          SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4066 
4067          /* count the new changes */
4068          conshdlr->nfixedvars += *nfixedvars - conshdlr->lastnfixedvars;
4069          conshdlr->naggrvars += *naggrvars - conshdlr->lastnaggrvars;
4070          conshdlr->nchgvartypes += *nchgvartypes - conshdlr->lastnchgvartypes;
4071          conshdlr->nchgbds += *nchgbds - conshdlr->lastnchgbds;
4072          conshdlr->naddholes += *naddholes - conshdlr->lastnaddholes;
4073          conshdlr->ndelconss += *ndelconss - conshdlr->lastndelconss;
4074          conshdlr->naddconss += *naddconss - conshdlr->lastnaddconss;
4075          conshdlr->nupgdconss += *nupgdconss - conshdlr->lastnupgdconss;
4076          conshdlr->nchgcoefs += *nchgcoefs - conshdlr->lastnchgcoefs;
4077          conshdlr->nchgsides += *nchgsides - conshdlr->lastnchgsides;
4078 
4079          /* check result code of callback method */
4080          if( *result != SCIP_CUTOFF
4081             && *result != SCIP_UNBOUNDED
4082             && *result != SCIP_SUCCESS
4083             && *result != SCIP_DIDNOTFIND
4084             && *result != SCIP_DIDNOTRUN
4085             && *result != SCIP_DELAYED )
4086          {
4087             SCIPerrorMessage("presolving method of constraint handler <%s> returned invalid result <%d>\n",
4088                conshdlr->name, *result);
4089             return SCIP_INVALIDRESULT;
4090          }
4091 
4092          /* increase the number of calls, if the presolving method tried to find reductions */
4093          if( *result != SCIP_DIDNOTRUN )
4094             ++(conshdlr->npresolcalls);
4095       }
4096 
4097       SCIPsetDebugMsg(set, "after presolving %d constraints left of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name);
4098    }
4099 
4100    return SCIP_OKAY;
4101 }
4102 
4103 /** calls variable deletion method of constraint handler */
SCIPconshdlrDelVars(SCIP_CONSHDLR * conshdlr,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)4104 SCIP_RETCODE SCIPconshdlrDelVars(
4105    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4106    BMS_BLKMEM*           blkmem,             /**< block memory */
4107    SCIP_SET*             set,                /**< global SCIP settings */
4108    SCIP_STAT*            stat                /**< dynamic problem statistics */
4109    )
4110 {
4111    assert(conshdlr != NULL);
4112    assert(set != NULL);
4113 
4114    if( conshdlr->consdelvars != NULL )
4115    {
4116       SCIPsetDebugMsg(set, "deleting variables in constraints of handler <%s>\n", conshdlr->name);
4117 
4118       /* during constraint processing, constraints of this handler may be deleted, activated, deactivated,
4119        * enabled, disabled, marked obsolete or useful, which would change the conss array given to the
4120        * external method; to avoid this, these changes will be buffered and processed after the method call
4121        */
4122       conshdlrDelayUpdates(conshdlr);
4123 
4124       /* call external method */
4125       SCIP_CALL( conshdlr->consdelvars(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) );
4126 
4127       /* perform the cached constraint updates */
4128       SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) );
4129    }
4130 
4131    return SCIP_OKAY;
4132 }
4133 
4134 /** locks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
SCIPconshdlrLockVars(SCIP_CONSHDLR * conshdlr,SCIP_SET * set)4135 SCIP_RETCODE SCIPconshdlrLockVars(
4136    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4137    SCIP_SET*             set                 /**< global SCIP settings */
4138    )
4139 {
4140    assert(conshdlr != NULL);
4141    assert(conshdlr->conslock != NULL);
4142    assert(!conshdlr->needscons);
4143 
4144    SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, +1, 0) );
4145 
4146    return SCIP_OKAY;
4147 }
4148 
4149 /** unlocks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */
SCIPconshdlrUnlockVars(SCIP_CONSHDLR * conshdlr,SCIP_SET * set)4150 SCIP_RETCODE SCIPconshdlrUnlockVars(
4151    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4152    SCIP_SET*             set                 /**< global SCIP settings */
4153    )
4154 {
4155    assert(conshdlr != NULL);
4156    assert(conshdlr->conslock != NULL);
4157    assert(!conshdlr->needscons);
4158 
4159    SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, -1, 0) );
4160 
4161    return SCIP_OKAY;
4162 }
4163 
4164 /** gets name of constraint handler */
SCIPconshdlrGetName(SCIP_CONSHDLR * conshdlr)4165 const char* SCIPconshdlrGetName(
4166    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4167    )
4168 {
4169    assert(conshdlr != NULL);
4170 
4171    return conshdlr->name;
4172 }
4173 
4174 /** gets description of constraint handler */
SCIPconshdlrGetDesc(SCIP_CONSHDLR * conshdlr)4175 const char* SCIPconshdlrGetDesc(
4176    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4177    )
4178 {
4179    assert(conshdlr != NULL);
4180 
4181    return conshdlr->desc;
4182 }
4183 
4184 /** gets user data of constraint handler */
SCIPconshdlrGetData(SCIP_CONSHDLR * conshdlr)4185 SCIP_CONSHDLRDATA* SCIPconshdlrGetData(
4186    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4187    )
4188 {
4189    assert(conshdlr != NULL);
4190 
4191    return conshdlr->conshdlrdata;
4192 }
4193 
4194 /** sets user data of constraint handler; user has to free old data in advance! */
SCIPconshdlrSetData(SCIP_CONSHDLR * conshdlr,SCIP_CONSHDLRDATA * conshdlrdata)4195 void SCIPconshdlrSetData(
4196    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4197    SCIP_CONSHDLRDATA*    conshdlrdata        /**< new constraint handler user data */
4198    )
4199 {
4200    assert(conshdlr != NULL);
4201 
4202    conshdlr->conshdlrdata = conshdlrdata;
4203 }
4204 
4205 /** sets all separation related callbacks of the constraint handler */
SCIPconshdlrSetSepa(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSSEPALP ((* conssepalp)),SCIP_DECL_CONSSEPASOL ((* conssepasol)),int sepafreq,int sepapriority,SCIP_Bool delaysepa)4206 void SCIPconshdlrSetSepa(
4207    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4208    SCIP_DECL_CONSSEPALP  ((*conssepalp)),    /**< separate cutting planes for LP solution */
4209    SCIP_DECL_CONSSEPASOL ((*conssepasol)),   /**< separate cutting planes for arbitrary primal solution */
4210    int                   sepafreq,           /**< frequency for separating cuts; zero means to separate only in the root node */
4211    int                   sepapriority,       /**< priority of the constraint handler for separation */
4212    SCIP_Bool             delaysepa           /**< should separation method be delayed, if other separators found cuts? */
4213    )
4214 {
4215    assert(conshdlr != NULL);
4216 
4217    assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1);
4218 
4219    conshdlr->conssepalp = conssepalp;
4220    conshdlr->conssepasol = conssepasol;
4221    conshdlr->sepafreq = sepafreq;
4222    conshdlr->sepapriority = sepapriority;
4223    conshdlr->delaysepa = delaysepa;
4224 }
4225 
4226 /** sets both the propagation callback and the propagation frequency of the constraint handler */
SCIPconshdlrSetProp(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSPROP ((* consprop)),int propfreq,SCIP_Bool delayprop,SCIP_PROPTIMING timingmask)4227 void SCIPconshdlrSetProp(
4228    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4229    SCIP_DECL_CONSPROP    ((*consprop)),      /**< propagate variable domains */
4230    int                   propfreq,           /**< frequency for propagating domains; zero means only preprocessing propagation */
4231    SCIP_Bool             delayprop,          /**< should propagation method be delayed, if other propagators found reductions? */
4232    SCIP_PROPTIMING       timingmask          /**< positions in the node solving loop where propagators should be executed */
4233    )
4234 {
4235    assert(conshdlr != NULL);
4236 
4237    assert(consprop != NULL || propfreq == -1);
4238 
4239    conshdlr->consprop = consprop;
4240    conshdlr->propfreq = propfreq;
4241    conshdlr->delayprop = delayprop;
4242    conshdlr->proptiming = timingmask;
4243 }
4244 
4245 /** sets copy method of both the constraint handler and each associated constraint */
SCIPconshdlrSetEnforelax(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSENFORELAX ((* consenforelax)))4246 void SCIPconshdlrSetEnforelax(
4247    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4248    SCIP_DECL_CONSENFORELAX ((*consenforelax)) /**< constraint copying method */
4249    )
4250 {
4251    assert(conshdlr != NULL);
4252 
4253    conshdlr->consenforelax = consenforelax;
4254 }
4255 
4256 /** sets copy method of both the constraint handler and each associated constraint */
SCIPconshdlrSetCopy(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSHDLRCOPY ((* conshdlrcopy)),SCIP_DECL_CONSCOPY ((* conscopy)))4257 void SCIPconshdlrSetCopy(
4258    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4259    SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),  /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */
4260    SCIP_DECL_CONSCOPY    ((*conscopy))       /**< constraint copying method */
4261    )
4262 {
4263    assert(conshdlr != NULL);
4264 
4265    assert(!conshdlr->needscons || (conshdlrcopy == NULL) == (conscopy == NULL));
4266 
4267    conshdlr->conshdlrcopy = conshdlrcopy;
4268    conshdlr->conscopy = conscopy;
4269 }
4270 
4271 /** sets destructor method of constraint handler */
SCIPconshdlrSetFree(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSFREE ((* consfree)))4272 void SCIPconshdlrSetFree(
4273    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4274    SCIP_DECL_CONSFREE    ((*consfree))       /**< destructor of constraint handler */
4275    )
4276 {
4277    assert(conshdlr != NULL);
4278 
4279    conshdlr->consfree = consfree;
4280 }
4281 
4282 /** sets initialization method of constraint handler */
SCIPconshdlrSetInit(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSINIT ((* consinit)))4283 void SCIPconshdlrSetInit(
4284    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4285    SCIP_DECL_CONSINIT    ((*consinit))       /**< initialize constraint handler */
4286    )
4287 {
4288    assert(conshdlr != NULL);
4289 
4290    conshdlr->consinit = consinit;
4291 }
4292 
4293 /** sets deinitialization method of constraint handler */
SCIPconshdlrSetExit(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSEXIT ((* consexit)))4294 void SCIPconshdlrSetExit(
4295    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4296    SCIP_DECL_CONSEXIT    ((*consexit))       /**< deinitialize constraint handler */
4297    )
4298 {
4299    assert(conshdlr != NULL);
4300 
4301    conshdlr->consexit = consexit;
4302 }
4303 
4304 /** sets solving process initialization method of constraint handler */
SCIPconshdlrSetInitsol(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSINITSOL ((* consinitsol)))4305 void SCIPconshdlrSetInitsol(
4306    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4307    SCIP_DECL_CONSINITSOL((*consinitsol))     /**< solving process initialization method of constraint handler */
4308    )
4309 {
4310    assert(conshdlr != NULL);
4311 
4312    conshdlr->consinitsol = consinitsol;
4313 }
4314 
4315 /** sets solving process deinitialization method of constraint handler */
SCIPconshdlrSetExitsol(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSEXITSOL ((* consexitsol)))4316 void SCIPconshdlrSetExitsol(
4317    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4318    SCIP_DECL_CONSEXITSOL ((*consexitsol))    /**< solving process deinitialization method of constraint handler */
4319    )
4320 {
4321    assert(conshdlr != NULL);
4322 
4323    conshdlr->consexitsol = consexitsol;
4324 }
4325 
4326 /** sets preprocessing initialization method of constraint handler */
SCIPconshdlrSetInitpre(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSINITPRE ((* consinitpre)))4327 void SCIPconshdlrSetInitpre(
4328    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4329    SCIP_DECL_CONSINITPRE((*consinitpre))     /**< preprocessing initialization method of constraint handler */
4330    )
4331 {
4332    assert(conshdlr != NULL);
4333 
4334    conshdlr->consinitpre = consinitpre;
4335 }
4336 
4337 /** sets preprocessing deinitialization method of constraint handler */
SCIPconshdlrSetExitpre(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSEXITPRE ((* consexitpre)))4338 void SCIPconshdlrSetExitpre(
4339    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4340    SCIP_DECL_CONSEXITPRE((*consexitpre))     /**< preprocessing deinitialization method of constraint handler */
4341    )
4342 {
4343    assert(conshdlr != NULL);
4344 
4345    conshdlr->consexitpre = consexitpre;
4346 }
4347 
4348 /** sets presolving method of constraint handler */
SCIPconshdlrSetPresol(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSPRESOL ((* conspresol)),int maxprerounds,SCIP_PRESOLTIMING presoltiming)4349 SCIP_RETCODE SCIPconshdlrSetPresol(
4350    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4351    SCIP_DECL_CONSPRESOL  ((*conspresol)),    /**< presolving method of constraint handler */
4352    int                   maxprerounds,       /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
4353    SCIP_PRESOLTIMING     presoltiming        /**< timing mask of the constraint handler's presolving method */
4354    )
4355 {
4356    assert(conshdlr != NULL);
4357 
4358    conshdlr->conspresol = conspresol;
4359    conshdlr->maxprerounds = maxprerounds;
4360 
4361    /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate
4362     * error message
4363     */
4364    if( presoltiming < SCIP_PRESOLTIMING_FAST || presoltiming > SCIP_PRESOLTIMING_MAX )
4365    {
4366       SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate "
4367          "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", conshdlr->name);
4368 
4369       return SCIP_PARAMETERWRONGVAL;
4370    }
4371 
4372    conshdlr->presoltiming = presoltiming;
4373 
4374    return SCIP_OKAY;
4375 }
4376 
4377 /** sets method of constraint handler to free specific constraint data */
SCIPconshdlrSetDelete(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSDELETE ((* consdelete)))4378 void SCIPconshdlrSetDelete(
4379    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4380    SCIP_DECL_CONSDELETE  ((*consdelete))     /**< free specific constraint data */
4381    )
4382 {
4383    assert(conshdlr != NULL);
4384 
4385    conshdlr->consdelete = consdelete;
4386 }
4387 
4388 /** sets method of constraint handler to transform constraint data into data belonging to the transformed problem */
SCIPconshdlrSetTrans(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSTRANS ((* constrans)))4389 void SCIPconshdlrSetTrans(
4390    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4391    SCIP_DECL_CONSTRANS   ((*constrans))      /**< transform constraint data into data belonging to the transformed problem */
4392    )
4393 {
4394    assert(conshdlr != NULL);
4395 
4396    conshdlr->constrans = constrans;
4397 }
4398 
4399 /** sets method of constraint handler to initialize LP with relaxations of "initial" constraints */
SCIPconshdlrSetInitlp(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSINITLP ((* consinitlp)))4400 void SCIPconshdlrSetInitlp(
4401    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4402    SCIP_DECL_CONSINITLP  ((*consinitlp))     /**< initialize LP with relaxations of "initial" constraints */
4403    )
4404 {
4405    assert(conshdlr != NULL);
4406 
4407    conshdlr->consinitlp = consinitlp;
4408 }
4409 
4410 /** sets propagation conflict resolving method of constraint handler */
SCIPconshdlrSetResprop(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSRESPROP ((* consresprop)))4411 void SCIPconshdlrSetResprop(
4412    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4413    SCIP_DECL_CONSRESPROP ((*consresprop))    /**< propagation conflict resolving method */
4414    )
4415 {
4416    assert(conshdlr != NULL);
4417 
4418    conshdlr->consresprop = consresprop;
4419 }
4420 
4421 /** sets activation notification method of constraint handler */
SCIPconshdlrSetActive(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSACTIVE ((* consactive)))4422 void SCIPconshdlrSetActive(
4423    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4424    SCIP_DECL_CONSACTIVE  ((*consactive))     /**< activation notification method */
4425    )
4426 {
4427    assert(conshdlr != NULL);
4428 
4429    conshdlr->consactive = consactive;
4430 }
4431 
4432 /** sets deactivation notification method of constraint handler */
SCIPconshdlrSetDeactive(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSDEACTIVE ((* consdeactive)))4433 void SCIPconshdlrSetDeactive(
4434    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4435    SCIP_DECL_CONSDEACTIVE((*consdeactive))   /**< deactivation notification method */
4436    )
4437 {
4438    assert(conshdlr != NULL);
4439 
4440    conshdlr->consdeactive = consdeactive;
4441 }
4442 
4443 /** sets enabling notification method of constraint handler */
SCIPconshdlrSetEnable(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSENABLE ((* consenable)))4444 void SCIPconshdlrSetEnable(
4445    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4446    SCIP_DECL_CONSENABLE  ((*consenable))     /**< enabling notification method */
4447    )
4448 {
4449    assert(conshdlr != NULL);
4450 
4451    conshdlr->consenable = consenable;
4452 }
4453 
4454 /** sets disabling notification method of constraint handler */
SCIPconshdlrSetDisable(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSDISABLE ((* consdisable)))4455 void SCIPconshdlrSetDisable(
4456    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4457    SCIP_DECL_CONSDISABLE ((*consdisable))    /**< disabling notification method */
4458    )
4459 {
4460    assert(conshdlr != NULL);
4461 
4462    conshdlr->consdisable = consdisable;
4463 }
4464 
4465 /** sets variable deletion method of constraint handler */
SCIPconshdlrSetDelvars(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSDELVARS ((* consdelvars)))4466 void SCIPconshdlrSetDelvars(
4467    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4468    SCIP_DECL_CONSDELVARS ((*consdelvars))    /**< variable deletion method */
4469    )
4470 {
4471    assert(conshdlr != NULL);
4472 
4473    conshdlr->consdelvars = consdelvars;
4474 }
4475 
4476 /** sets constraint display method of constraint handler */
SCIPconshdlrSetPrint(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSPRINT ((* consprint)))4477 void SCIPconshdlrSetPrint(
4478    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4479    SCIP_DECL_CONSPRINT   ((*consprint))      /**< constraint display method */
4480    )
4481 {
4482    assert(conshdlr != NULL);
4483 
4484    conshdlr->consprint = consprint;
4485 }
4486 
4487 /** sets constraint parsing method of constraint handler */
SCIPconshdlrSetParse(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSPARSE ((* consparse)))4488 void SCIPconshdlrSetParse(
4489    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4490    SCIP_DECL_CONSPARSE   ((*consparse))      /**< constraint parsing method */
4491    )
4492 {
4493    assert(conshdlr != NULL);
4494 
4495    conshdlr->consparse = consparse;
4496 }
4497 
4498 /** sets constraint variable getter method of constraint handler */
SCIPconshdlrSetGetVars(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSGETVARS ((* consgetvars)))4499 void SCIPconshdlrSetGetVars(
4500    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4501    SCIP_DECL_CONSGETVARS ((*consgetvars))    /**< constraint variable getter method */
4502    )
4503 {
4504    assert(conshdlr != NULL);
4505 
4506    conshdlr->consgetvars = consgetvars;
4507 }
4508 
4509 /** sets constraint variable number getter method of constraint handler */
SCIPconshdlrSetGetNVars(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSGETNVARS ((* consgetnvars)))4510 void SCIPconshdlrSetGetNVars(
4511    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4512    SCIP_DECL_CONSGETNVARS((*consgetnvars))   /**< constraint variable number getter method */
4513    )
4514 {
4515    assert(conshdlr != NULL);
4516 
4517    conshdlr->consgetnvars = consgetnvars;
4518 }
4519 
4520 /** sets diving enforcement method of constraint handler */
SCIPconshdlrSetGetDiveBdChgs(SCIP_CONSHDLR * conshdlr,SCIP_DECL_CONSGETDIVEBDCHGS ((* consgetdivebdchgs)))4521 void SCIPconshdlrSetGetDiveBdChgs(
4522    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4523    SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)) /**< constraint handler diving solution enforcement method */
4524    )
4525 {
4526    assert(conshdlr != NULL);
4527 
4528    conshdlr->consgetdivebdchgs = consgetdivebdchgs;
4529 }
4530 
4531 /** gets array with constraints of constraint handler; the first SCIPconshdlrGetNActiveConss() entries are the active
4532  *  constraints, the last SCIPconshdlrGetNConss() - SCIPconshdlrGetNActiveConss() constraints are deactivated
4533  *
4534  *  @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4535  *        flag is TRUE) and the current node belongs to the corresponding sub tree.
4536  */
SCIPconshdlrGetConss(SCIP_CONSHDLR * conshdlr)4537 SCIP_CONS** SCIPconshdlrGetConss(
4538    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4539    )
4540 {
4541    assert(conshdlr != NULL);
4542 
4543    return conshdlr->conss;
4544 }
4545 
4546 /** gets array with enforced constraints of constraint handler; this is local information */
SCIPconshdlrGetEnfoConss(SCIP_CONSHDLR * conshdlr)4547 SCIP_CONS** SCIPconshdlrGetEnfoConss(
4548    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4549    )
4550 {
4551    assert(conshdlr != NULL);
4552 
4553    return conshdlr->enfoconss;
4554 }
4555 
4556 /** gets array with checked constraints of constraint handler; this is local information */
SCIPconshdlrGetCheckConss(SCIP_CONSHDLR * conshdlr)4557 SCIP_CONS** SCIPconshdlrGetCheckConss(
4558    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4559    )
4560 {
4561    assert(conshdlr != NULL);
4562 
4563    return conshdlr->checkconss;
4564 }
4565 
4566 /** gets array with delayed update constraints
4567  *
4568  * @attention Usually, there should be no need to access this array. Use this only if you are absolutely sure what you are doing.
4569  */
SCIPconshdlrGetUpdateConss(SCIP_CONSHDLR * conshdlr)4570 SCIP_CONS** SCIPconshdlrGetUpdateConss(
4571    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4572    )
4573 {
4574    assert(conshdlr != NULL);
4575 
4576    return conshdlr->updateconss;
4577 }
4578 
4579 /** gets total number of existing transformed constraints of constraint handler */
SCIPconshdlrGetNConss(SCIP_CONSHDLR * conshdlr)4580 int SCIPconshdlrGetNConss(
4581    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4582    )
4583 {
4584    assert(conshdlr != NULL);
4585 
4586    return conshdlr->nconss;
4587 }
4588 
4589 /** gets number of enforced constraints of constraint handler; this is local information */
SCIPconshdlrGetNEnfoConss(SCIP_CONSHDLR * conshdlr)4590 int SCIPconshdlrGetNEnfoConss(
4591    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4592    )
4593 {
4594    assert(conshdlr != NULL);
4595 
4596    return conshdlr->nenfoconss;
4597 }
4598 
4599 /** gets number of checked constraints of constraint handler; this is local information */
SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR * conshdlr)4600 int SCIPconshdlrGetNCheckConss(
4601    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4602    )
4603 {
4604    assert(conshdlr != NULL);
4605 
4606    return conshdlr->ncheckconss;
4607 }
4608 
4609 /** gets number of active constraints of constraint handler
4610  *
4611  *  @note A constraint is active if it is global and was not removed or it was added locally (in that case the local
4612  *        flag is TRUE) and the current node belongs to the corresponding sub tree.
4613  */
SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR * conshdlr)4614 int SCIPconshdlrGetNActiveConss(
4615    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4616    )
4617 {
4618    assert(conshdlr != NULL);
4619 
4620    return conshdlr->nactiveconss;
4621 }
4622 
4623 /** gets number of enabled constraints of constraint handler */
SCIPconshdlrGetNEnabledConss(SCIP_CONSHDLR * conshdlr)4624 int SCIPconshdlrGetNEnabledConss(
4625    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4626    )
4627 {
4628    assert(conshdlr != NULL);
4629 
4630    return conshdlr->nenabledconss;
4631 }
4632 
4633 /** gets number of constraints that have delayed updates */
SCIPconshdlrGetNUpdateConss(SCIP_CONSHDLR * conshdlr)4634 int SCIPconshdlrGetNUpdateConss(
4635    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4636    )
4637 {
4638    assert(conshdlr != NULL);
4639 
4640    return conshdlr->nupdateconss;
4641 }
4642 
4643 /** enables or disables all clocks of \p conshdlr, depending on the value of the flag */
SCIPconshdlrEnableOrDisableClocks(SCIP_CONSHDLR * conshdlr,SCIP_Bool enable)4644 void SCIPconshdlrEnableOrDisableClocks(
4645    SCIP_CONSHDLR*        conshdlr,           /**< the constraint handler for which all clocks should be enabled or disabled */
4646    SCIP_Bool             enable              /**< should the clocks of the constraint handler be enabled? */
4647    )
4648 {
4649    assert(conshdlr != NULL);
4650 
4651    SCIPclockEnableOrDisable(conshdlr->setuptime, enable);
4652    SCIPclockEnableOrDisable(conshdlr->checktime, enable);
4653    SCIPclockEnableOrDisable(conshdlr->enfolptime, enable);
4654    SCIPclockEnableOrDisable(conshdlr->enfopstime, enable);
4655    SCIPclockEnableOrDisable(conshdlr->enforelaxtime, enable);
4656    SCIPclockEnableOrDisable(conshdlr->presoltime, enable);
4657    SCIPclockEnableOrDisable(conshdlr->proptime, enable);
4658    SCIPclockEnableOrDisable(conshdlr->resproptime, enable);
4659    SCIPclockEnableOrDisable(conshdlr->sbproptime, enable);
4660    SCIPclockEnableOrDisable(conshdlr->sepatime, enable);
4661 }
4662 
4663 /** gets time in seconds used for setting up this constraint handler for new stages */
SCIPconshdlrGetSetupTime(SCIP_CONSHDLR * conshdlr)4664 SCIP_Real SCIPconshdlrGetSetupTime(
4665    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4666    )
4667 {
4668    assert(conshdlr != NULL);
4669 
4670    return SCIPclockGetTime(conshdlr->setuptime);
4671 }
4672 
4673 /** gets time in seconds used for presolving in this constraint handler */
SCIPconshdlrGetPresolTime(SCIP_CONSHDLR * conshdlr)4674 SCIP_Real SCIPconshdlrGetPresolTime(
4675    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4676    )
4677 {
4678    assert(conshdlr != NULL);
4679 
4680    return SCIPclockGetTime(conshdlr->presoltime);
4681 }
4682 
4683 /** gets time in seconds used for separation in this constraint handler */
SCIPconshdlrGetSepaTime(SCIP_CONSHDLR * conshdlr)4684 SCIP_Real SCIPconshdlrGetSepaTime(
4685    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4686    )
4687 {
4688    assert(conshdlr != NULL);
4689 
4690    return SCIPclockGetTime(conshdlr->sepatime);
4691 }
4692 
4693 /** gets time in seconds used for LP enforcement in this constraint handler */
SCIPconshdlrGetEnfoLPTime(SCIP_CONSHDLR * conshdlr)4694 SCIP_Real SCIPconshdlrGetEnfoLPTime(
4695    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4696    )
4697 {
4698    assert(conshdlr != NULL);
4699 
4700    return SCIPclockGetTime(conshdlr->enfolptime);
4701 }
4702 
4703 /** gets time in seconds used for pseudo enforcement in this constraint handler */
SCIPconshdlrGetEnfoPSTime(SCIP_CONSHDLR * conshdlr)4704 SCIP_Real SCIPconshdlrGetEnfoPSTime(
4705    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4706    )
4707 {
4708    assert(conshdlr != NULL);
4709 
4710    return SCIPclockGetTime(conshdlr->enfopstime);
4711 }
4712 
4713 /** gets time in seconds used for relaxation enforcement in this constraint handler */
SCIPconshdlrGetEnfoRelaxTime(SCIP_CONSHDLR * conshdlr)4714 SCIP_Real SCIPconshdlrGetEnfoRelaxTime(
4715    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4716    )
4717 {
4718    assert(conshdlr != NULL);
4719 
4720    return SCIPclockGetTime(conshdlr->enforelaxtime);
4721 }
4722 
4723 /** gets time in seconds used for propagation in this constraint handler */
SCIPconshdlrGetPropTime(SCIP_CONSHDLR * conshdlr)4724 SCIP_Real SCIPconshdlrGetPropTime(
4725    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4726    )
4727 {
4728    assert(conshdlr != NULL);
4729 
4730    return SCIPclockGetTime(conshdlr->proptime);
4731 }
4732 
4733 /** gets time in seconds used for propagation in this constraint handler during strong branching */
SCIPconshdlrGetStrongBranchPropTime(SCIP_CONSHDLR * conshdlr)4734 SCIP_Real SCIPconshdlrGetStrongBranchPropTime(
4735    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4736    )
4737 {
4738    assert(conshdlr != NULL);
4739 
4740    return SCIPclockGetTime(conshdlr->sbproptime);
4741 }
4742 
4743 /** gets time in seconds used for feasibility checking in this constraint handler */
SCIPconshdlrGetCheckTime(SCIP_CONSHDLR * conshdlr)4744 SCIP_Real SCIPconshdlrGetCheckTime(
4745    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4746    )
4747 {
4748    assert(conshdlr != NULL);
4749 
4750    return SCIPclockGetTime(conshdlr->checktime);
4751 }
4752 
4753 /** gets time in seconds used for resolving propagation in this constraint handler */
SCIPconshdlrGetRespropTime(SCIP_CONSHDLR * conshdlr)4754 SCIP_Real SCIPconshdlrGetRespropTime(
4755    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4756    )
4757 {
4758    assert(conshdlr != NULL);
4759 
4760    return SCIPclockGetTime(conshdlr->resproptime);
4761 }
4762 
4763 /** gets number of calls to the constraint handler's separation method */
SCIPconshdlrGetNSepaCalls(SCIP_CONSHDLR * conshdlr)4764 SCIP_Longint SCIPconshdlrGetNSepaCalls(
4765    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4766    )
4767 {
4768    assert(conshdlr != NULL);
4769 
4770    return conshdlr->nsepacalls;
4771 }
4772 
4773 /** gets number of calls to the constraint handler's LP enforcing method */
SCIPconshdlrGetNEnfoLPCalls(SCIP_CONSHDLR * conshdlr)4774 SCIP_Longint SCIPconshdlrGetNEnfoLPCalls(
4775    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4776    )
4777 {
4778    assert(conshdlr != NULL);
4779 
4780    return conshdlr->nenfolpcalls;
4781 }
4782 
4783 /** gets number of calls to the constraint handler's pseudo enforcing method */
SCIPconshdlrGetNEnfoPSCalls(SCIP_CONSHDLR * conshdlr)4784 SCIP_Longint SCIPconshdlrGetNEnfoPSCalls(
4785    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4786    )
4787 {
4788    assert(conshdlr != NULL);
4789 
4790    return conshdlr->nenfopscalls;
4791 }
4792 
4793 /** gets number of calls to the constraint handler's relaxation enforcing method */
SCIPconshdlrGetNEnfoRelaxCalls(SCIP_CONSHDLR * conshdlr)4794 SCIP_Longint SCIPconshdlrGetNEnfoRelaxCalls(
4795    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4796    )
4797 {
4798    assert(conshdlr != NULL);
4799 
4800    return conshdlr->nenforelaxcalls;
4801 }
4802 
4803 /** gets number of calls to the constraint handler's propagation method */
SCIPconshdlrGetNPropCalls(SCIP_CONSHDLR * conshdlr)4804 SCIP_Longint SCIPconshdlrGetNPropCalls(
4805    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4806    )
4807 {
4808    assert(conshdlr != NULL);
4809 
4810    return conshdlr->npropcalls;
4811 }
4812 
4813 /** gets number of calls to the constraint handler's checking method */
SCIPconshdlrGetNCheckCalls(SCIP_CONSHDLR * conshdlr)4814 SCIP_Longint SCIPconshdlrGetNCheckCalls(
4815    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4816    )
4817 {
4818    assert(conshdlr != NULL);
4819 
4820    return conshdlr->ncheckcalls;
4821 }
4822 
4823 /** gets number of calls to the constraint handler's resolve propagation method */
SCIPconshdlrGetNRespropCalls(SCIP_CONSHDLR * conshdlr)4824 SCIP_Longint SCIPconshdlrGetNRespropCalls(
4825    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4826    )
4827 {
4828    assert(conshdlr != NULL);
4829 
4830    return conshdlr->nrespropcalls;
4831 }
4832 
4833 /** gets total number of times, this constraint handler detected a cutoff */
SCIPconshdlrGetNCutoffs(SCIP_CONSHDLR * conshdlr)4834 SCIP_Longint SCIPconshdlrGetNCutoffs(
4835    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4836    )
4837 {
4838    assert(conshdlr != NULL);
4839 
4840    return conshdlr->ncutoffs;
4841 }
4842 
4843 /** gets total number of cuts found by this constraint handler */
SCIPconshdlrGetNCutsFound(SCIP_CONSHDLR * conshdlr)4844 SCIP_Longint SCIPconshdlrGetNCutsFound(
4845    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4846    )
4847 {
4848    assert(conshdlr != NULL);
4849 
4850    return conshdlr->ncutsfound;
4851 }
4852 
4853 /** gets total number of cuts found by this constraint handler applied to lp */
SCIPconshdlrGetNCutsApplied(SCIP_CONSHDLR * conshdlr)4854 SCIP_Longint SCIPconshdlrGetNCutsApplied(
4855    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4856    )
4857 {
4858    assert(conshdlr != NULL);
4859 
4860    return conshdlr->ncutsapplied;
4861 }
4862 
4863 /** increase count of applied cuts */
SCIPconshdlrIncNAppliedCuts(SCIP_CONSHDLR * conshdlr)4864 void SCIPconshdlrIncNAppliedCuts(
4865    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4866    )
4867 {
4868    assert(conshdlr != NULL);
4869 
4870    ++conshdlr->ncutsapplied;
4871 }
4872 
4873 /** increase count of found cuts */
SCIPconshdlrIncNCutsFound(SCIP_CONSHDLR * conshdlr)4874 void SCIPconshdlrIncNCutsFound(
4875    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4876    )
4877 {
4878    assert(conshdlr != NULL);
4879 
4880    ++conshdlr->ncutsfound;
4881 }
4882 
4883 /** gets total number of additional constraints added by this constraint handler */
SCIPconshdlrGetNConssFound(SCIP_CONSHDLR * conshdlr)4884 SCIP_Longint SCIPconshdlrGetNConssFound(
4885    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4886    )
4887 {
4888    assert(conshdlr != NULL);
4889 
4890    return conshdlr->nconssfound;
4891 }
4892 
4893 /** gets total number of domain reductions found by this constraint handler */
SCIPconshdlrGetNDomredsFound(SCIP_CONSHDLR * conshdlr)4894 SCIP_Longint SCIPconshdlrGetNDomredsFound(
4895    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4896    )
4897 {
4898    assert(conshdlr != NULL);
4899 
4900    return conshdlr->ndomredsfound;
4901 }
4902 
4903 /** gets number of children created by this constraint handler */
SCIPconshdlrGetNChildren(SCIP_CONSHDLR * conshdlr)4904 SCIP_Longint SCIPconshdlrGetNChildren(
4905    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4906    )
4907 {
4908    assert(conshdlr != NULL);
4909 
4910    return conshdlr->nchildren;
4911 }
4912 
4913 /** gets maximum number of active constraints of constraint handler existing at the same time */
SCIPconshdlrGetMaxNActiveConss(SCIP_CONSHDLR * conshdlr)4914 int SCIPconshdlrGetMaxNActiveConss(
4915    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4916    )
4917 {
4918    assert(conshdlr != NULL);
4919 
4920    return conshdlr->maxnactiveconss;
4921 }
4922 
4923 /** gets initial number of active constraints of constraint handler */
SCIPconshdlrGetStartNActiveConss(SCIP_CONSHDLR * conshdlr)4924 int SCIPconshdlrGetStartNActiveConss(
4925    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4926    )
4927 {
4928    assert(conshdlr != NULL);
4929 
4930    return conshdlr->startnactiveconss;
4931 }
4932 
4933 /** gets number of variables fixed in presolving method of constraint handler */
SCIPconshdlrGetNFixedVars(SCIP_CONSHDLR * conshdlr)4934 int SCIPconshdlrGetNFixedVars(
4935    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4936    )
4937 {
4938    assert(conshdlr != NULL);
4939 
4940    return conshdlr->nfixedvars;
4941 }
4942 
4943 /** gets number of variables aggregated in presolving method of constraint handler */
SCIPconshdlrGetNAggrVars(SCIP_CONSHDLR * conshdlr)4944 int SCIPconshdlrGetNAggrVars(
4945    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4946    )
4947 {
4948    assert(conshdlr != NULL);
4949 
4950    return conshdlr->naggrvars;
4951 }
4952 
4953 /** gets number of variable types changed in presolving method of constraint handler */
SCIPconshdlrGetNChgVarTypes(SCIP_CONSHDLR * conshdlr)4954 int SCIPconshdlrGetNChgVarTypes(
4955    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4956    )
4957 {
4958    assert(conshdlr != NULL);
4959 
4960    return conshdlr->nchgvartypes;
4961 }
4962 
4963 /** gets number of bounds changed in presolving method of constraint handler */
SCIPconshdlrGetNChgBds(SCIP_CONSHDLR * conshdlr)4964 int SCIPconshdlrGetNChgBds(
4965    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4966    )
4967 {
4968    assert(conshdlr != NULL);
4969 
4970    return conshdlr->nchgbds;
4971 }
4972 
4973 /** gets number of holes added to domains of variables in presolving method of constraint handler */
SCIPconshdlrGetNAddHoles(SCIP_CONSHDLR * conshdlr)4974 int SCIPconshdlrGetNAddHoles(
4975    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4976    )
4977 {
4978    assert(conshdlr != NULL);
4979 
4980    return conshdlr->naddholes;
4981 }
4982 
4983 /** gets number of constraints deleted in presolving method of constraint handler */
SCIPconshdlrGetNDelConss(SCIP_CONSHDLR * conshdlr)4984 int SCIPconshdlrGetNDelConss(
4985    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4986    )
4987 {
4988    assert(conshdlr != NULL);
4989 
4990    return conshdlr->ndelconss;
4991 }
4992 
4993 /** gets number of constraints added in presolving method of constraint handler */
SCIPconshdlrGetNAddConss(SCIP_CONSHDLR * conshdlr)4994 int SCIPconshdlrGetNAddConss(
4995    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
4996    )
4997 {
4998    assert(conshdlr != NULL);
4999 
5000    return conshdlr->naddconss;
5001 }
5002 
5003 /** gets number of constraints upgraded in presolving method of constraint handler */
SCIPconshdlrGetNUpgdConss(SCIP_CONSHDLR * conshdlr)5004 int SCIPconshdlrGetNUpgdConss(
5005    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5006    )
5007 {
5008    assert(conshdlr != NULL);
5009 
5010    return conshdlr->nupgdconss;
5011 }
5012 
5013 /** gets number of coefficients changed in presolving method of constraint handler */
SCIPconshdlrGetNChgCoefs(SCIP_CONSHDLR * conshdlr)5014 int SCIPconshdlrGetNChgCoefs(
5015    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5016    )
5017 {
5018    assert(conshdlr != NULL);
5019 
5020    return conshdlr->nchgcoefs;
5021 }
5022 
5023 /** gets number of constraint sides changed in presolving method of constraint handler */
SCIPconshdlrGetNChgSides(SCIP_CONSHDLR * conshdlr)5024 int SCIPconshdlrGetNChgSides(
5025    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5026    )
5027 {
5028    assert(conshdlr != NULL);
5029 
5030    return conshdlr->nchgsides;
5031 }
5032 
5033 /** gets number of times the presolving method of the constraint handler was called and tried to find reductions */
SCIPconshdlrGetNPresolCalls(SCIP_CONSHDLR * conshdlr)5034 int SCIPconshdlrGetNPresolCalls(
5035    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5036    )
5037 {
5038    assert(conshdlr != NULL);
5039 
5040    return conshdlr->npresolcalls;
5041 }
5042 
5043 /** gets separation priority of constraint handler */
SCIPconshdlrGetSepaPriority(SCIP_CONSHDLR * conshdlr)5044 int SCIPconshdlrGetSepaPriority(
5045    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5046    )
5047 {
5048    assert(conshdlr != NULL);
5049 
5050    return conshdlr->sepapriority;
5051 }
5052 
5053 /** gets enforcing priority of constraint handler */
SCIPconshdlrGetEnfoPriority(SCIP_CONSHDLR * conshdlr)5054 int SCIPconshdlrGetEnfoPriority(
5055    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5056    )
5057 {
5058    assert(conshdlr != NULL);
5059 
5060    return conshdlr->enfopriority;
5061 }
5062 
5063 /** gets checking priority of constraint handler */
SCIPconshdlrGetCheckPriority(SCIP_CONSHDLR * conshdlr)5064 int SCIPconshdlrGetCheckPriority(
5065    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5066    )
5067 {
5068    assert(conshdlr != NULL);
5069 
5070    return conshdlr->checkpriority;
5071 }
5072 
5073 /** gets separation frequency of constraint handler */
SCIPconshdlrGetSepaFreq(SCIP_CONSHDLR * conshdlr)5074 int SCIPconshdlrGetSepaFreq(
5075    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5076    )
5077 {
5078    assert(conshdlr != NULL);
5079 
5080    return conshdlr->sepafreq;
5081 }
5082 
5083 /** gets propagation frequency of constraint handler */
SCIPconshdlrGetPropFreq(SCIP_CONSHDLR * conshdlr)5084 int SCIPconshdlrGetPropFreq(
5085    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5086    )
5087 {
5088    assert(conshdlr != NULL);
5089 
5090    return conshdlr->propfreq;
5091 }
5092 
5093 /** gets frequency of constraint handler for eager evaluations in separation, propagation and enforcement */
SCIPconshdlrGetEagerFreq(SCIP_CONSHDLR * conshdlr)5094 int SCIPconshdlrGetEagerFreq(
5095    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5096    )
5097 {
5098    assert(conshdlr != NULL);
5099 
5100    return conshdlr->eagerfreq;
5101 }
5102 
5103 /** needs constraint handler a constraint to be called? */
SCIPconshdlrNeedsCons(SCIP_CONSHDLR * conshdlr)5104 SCIP_Bool SCIPconshdlrNeedsCons(
5105    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5106    )
5107 {
5108    assert(conshdlr != NULL);
5109 
5110    return conshdlr->needscons;
5111 }
5112 
5113 /** does the constraint handler perform presolving? */
SCIPconshdlrDoesPresolve(SCIP_CONSHDLR * conshdlr)5114 SCIP_Bool SCIPconshdlrDoesPresolve(
5115    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5116    )
5117 {
5118    assert(conshdlr != NULL);
5119 
5120    return (conshdlr->conspresol != NULL);
5121 }
5122 
5123 /** should separation method be delayed, if other separators found cuts? */
SCIPconshdlrIsSeparationDelayed(SCIP_CONSHDLR * conshdlr)5124 SCIP_Bool SCIPconshdlrIsSeparationDelayed(
5125    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5126    )
5127 {
5128    assert(conshdlr != NULL);
5129 
5130    return conshdlr->delaysepa;
5131 }
5132 
5133 /** should propagation method be delayed, if other propagators found reductions? */
SCIPconshdlrIsPropagationDelayed(SCIP_CONSHDLR * conshdlr)5134 SCIP_Bool SCIPconshdlrIsPropagationDelayed(
5135    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5136    )
5137 {
5138    assert(conshdlr != NULL);
5139 
5140    return conshdlr->delayprop;
5141 }
5142 
5143 /** was LP separation method delayed at the last call? */
SCIPconshdlrWasLPSeparationDelayed(SCIP_CONSHDLR * conshdlr)5144 SCIP_Bool SCIPconshdlrWasLPSeparationDelayed(
5145    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5146    )
5147 {
5148    assert(conshdlr != NULL);
5149 
5150    return conshdlr->sepalpwasdelayed;
5151 }
5152 
5153 /** was primal solution separation method delayed at the last call? */
SCIPconshdlrWasSolSeparationDelayed(SCIP_CONSHDLR * conshdlr)5154 SCIP_Bool SCIPconshdlrWasSolSeparationDelayed(
5155    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5156    )
5157 {
5158    assert(conshdlr != NULL);
5159 
5160    return conshdlr->sepasolwasdelayed;
5161 }
5162 
5163 /** was propagation method delayed at the last call? */
SCIPconshdlrWasPropagationDelayed(SCIP_CONSHDLR * conshdlr)5164 SCIP_Bool SCIPconshdlrWasPropagationDelayed(
5165    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5166    )
5167 {
5168    assert(conshdlr != NULL);
5169 
5170    return conshdlr->propwasdelayed;
5171 }
5172 
5173 /** is constraint handler initialized? */
SCIPconshdlrIsInitialized(SCIP_CONSHDLR * conshdlr)5174 SCIP_Bool SCIPconshdlrIsInitialized(
5175    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5176    )
5177 {
5178    assert(conshdlr != NULL);
5179 
5180    return conshdlr->initialized;
5181 }
5182 
5183 /** does the constraint handler have a copy function? */
SCIPconshdlrIsClonable(SCIP_CONSHDLR * conshdlr)5184 SCIP_Bool SCIPconshdlrIsClonable(
5185    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5186    )
5187 {
5188    assert(conshdlr != NULL);
5189 
5190    return (conshdlr->conshdlrcopy != NULL);
5191 }
5192 
5193 /** returns the timing mask of the propagation method of the constraint handler */
SCIPconshdlrGetPropTiming(SCIP_CONSHDLR * conshdlr)5194 SCIP_PROPTIMING SCIPconshdlrGetPropTiming(
5195    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5196    )
5197 {
5198    assert(conshdlr != NULL);
5199 
5200    return conshdlr->proptiming;
5201 }
5202 
5203 /** sets the timing mask of the propagation method of the constraint handler */
SCIPconshdlrSetPropTiming(SCIP_CONSHDLR * conshdlr,SCIP_PROPTIMING proptiming)5204 void SCIPconshdlrSetPropTiming(
5205    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
5206    SCIP_PROPTIMING       proptiming          /**< timing mask to be set */
5207    )
5208 {
5209    assert(conshdlr != NULL);
5210 
5211    conshdlr->proptiming = proptiming;
5212 }
5213 
5214 
5215 /** returns the timing mask of the presolving method of the constraint handler */
SCIPconshdlrGetPresolTiming(SCIP_CONSHDLR * conshdlr)5216 SCIP_PRESOLTIMING SCIPconshdlrGetPresolTiming(
5217    SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
5218    )
5219 {
5220    assert(conshdlr != NULL);
5221 
5222    return conshdlr->presoltiming;
5223 }
5224 
5225 /** sets the timing mask of the presolving method of the constraint handler */
SCIPconshdlrSetPresolTiming(SCIP_CONSHDLR * conshdlr,SCIP_PRESOLTIMING presoltiming)5226 void SCIPconshdlrSetPresolTiming(
5227    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
5228    SCIP_PRESOLTIMING     presoltiming        /** timing mask to be set */
5229    )
5230 {
5231    assert(conshdlr != NULL);
5232 
5233    conshdlr->presoltiming = presoltiming;
5234 }
5235 
5236 
5237 /*
5238  * Constraint set change methods
5239  */
5240 
5241 /** creates empty constraint set change data */
5242 static
conssetchgCreate(SCIP_CONSSETCHG ** conssetchg,BMS_BLKMEM * blkmem)5243 SCIP_RETCODE conssetchgCreate(
5244    SCIP_CONSSETCHG**     conssetchg,         /**< pointer to constraint set change data */
5245    BMS_BLKMEM*           blkmem              /**< block memory */
5246    )
5247 {
5248    assert(conssetchg != NULL);
5249    assert(blkmem != NULL);
5250 
5251    SCIP_ALLOC( BMSallocBlockMemory(blkmem, conssetchg) );
5252    (*conssetchg)->addedconss = NULL;
5253    (*conssetchg)->disabledconss = NULL;
5254    (*conssetchg)->addedconsssize = 0;
5255    (*conssetchg)->naddedconss = 0;
5256    (*conssetchg)->disabledconsssize = 0;
5257    (*conssetchg)->ndisabledconss = 0;
5258 
5259    return SCIP_OKAY;
5260 }
5261 
5262 /** releases all constraints of the constraint set change data */
5263 static
conssetchgRelease(SCIP_CONSSETCHG * conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set)5264 SCIP_RETCODE conssetchgRelease(
5265    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change data */
5266    BMS_BLKMEM*           blkmem,             /**< block memory */
5267    SCIP_SET*             set                 /**< global SCIP settings */
5268    )
5269 {
5270    int i;
5271 
5272    assert(conssetchg != NULL);
5273 
5274    /* release constraints */
5275    for( i = 0; i < conssetchg->naddedconss; ++i )
5276    {
5277       if( conssetchg->addedconss[i] != NULL )
5278       {
5279          SCIP_CALL( SCIPconsRelease(&conssetchg->addedconss[i], blkmem, set) );
5280       }
5281    }
5282    for( i = 0; i < conssetchg->ndisabledconss; ++i )
5283    {
5284       if( conssetchg->disabledconss[i] != NULL )
5285       {
5286          SCIP_CALL( SCIPconsRelease(&conssetchg->disabledconss[i], blkmem, set) );
5287       }
5288    }
5289 
5290    return SCIP_OKAY;
5291 }
5292 
5293 /** frees constraint set change data and releases all included constraints */
SCIPconssetchgFree(SCIP_CONSSETCHG ** conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set)5294 SCIP_RETCODE SCIPconssetchgFree(
5295    SCIP_CONSSETCHG**     conssetchg,         /**< pointer to constraint set change */
5296    BMS_BLKMEM*           blkmem,             /**< block memory */
5297    SCIP_SET*             set                 /**< global SCIP settings */
5298    )
5299 {
5300    assert(conssetchg != NULL);
5301    assert(blkmem != NULL);
5302 
5303    if( *conssetchg != NULL )
5304    {
5305       /* release constraints */
5306       SCIP_CALL( conssetchgRelease(*conssetchg, blkmem, set) );
5307 
5308       /* free memory */
5309       BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->addedconss, (*conssetchg)->addedconsssize);
5310       BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->disabledconss, (*conssetchg)->disabledconsssize);
5311       BMSfreeBlockMemory(blkmem, conssetchg);
5312    }
5313 
5314    return SCIP_OKAY;
5315 }
5316 
5317 /** ensures, that addedconss array can store at least num entries */
5318 static
conssetchgEnsureAddedconssSize(SCIP_CONSSETCHG * conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,int num)5319 SCIP_RETCODE conssetchgEnsureAddedconssSize(
5320    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change data structure */
5321    BMS_BLKMEM*           blkmem,             /**< block memory */
5322    SCIP_SET*             set,                /**< global SCIP settings */
5323    int                   num                 /**< minimum number of entries to store */
5324    )
5325 {
5326    assert(conssetchg != NULL);
5327 
5328    if( num > conssetchg->addedconsssize )
5329    {
5330       int newsize;
5331 
5332       newsize = SCIPsetCalcMemGrowSize(set, num);
5333       SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conssetchg->addedconss, conssetchg->addedconsssize, newsize) );
5334       conssetchg->addedconsssize = newsize;
5335    }
5336    assert(num <= conssetchg->addedconsssize);
5337 
5338    return SCIP_OKAY;
5339 }
5340 
5341 /** ensures, that disabledconss array can store at least num entries */
5342 static
conssetchgEnsureDisabledconssSize(SCIP_CONSSETCHG * conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,int num)5343 SCIP_RETCODE conssetchgEnsureDisabledconssSize(
5344    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change data structure */
5345    BMS_BLKMEM*           blkmem,             /**< block memory */
5346    SCIP_SET*             set,                /**< global SCIP settings */
5347    int                   num                 /**< minimum number of entries to store */
5348    )
5349 {
5350    assert(conssetchg != NULL);
5351 
5352    if( num > conssetchg->disabledconsssize )
5353    {
5354       int newsize;
5355 
5356       newsize = SCIPsetCalcMemGrowSize(set, num);
5357       SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conssetchg->disabledconss, conssetchg->disabledconsssize, newsize) );
5358       conssetchg->disabledconsssize = newsize;
5359    }
5360    assert(num <= conssetchg->disabledconsssize);
5361 
5362    return SCIP_OKAY;
5363 }
5364 
5365 /** adds constraint addition to constraint set changes, and captures constraint; activates constraint if the
5366  *  constraint set change data is currently active
5367  */
SCIPconssetchgAddAddedCons(SCIP_CONSSETCHG ** conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_CONS * cons,int depth,SCIP_Bool focusnode,SCIP_Bool active)5368 SCIP_RETCODE SCIPconssetchgAddAddedCons(
5369    SCIP_CONSSETCHG**     conssetchg,         /**< pointer to constraint set change data structure */
5370    BMS_BLKMEM*           blkmem,             /**< block memory */
5371    SCIP_SET*             set,                /**< global SCIP settings */
5372    SCIP_STAT*            stat,               /**< dynamic problem statistics */
5373    SCIP_CONS*            cons,               /**< added constraint */
5374    int                   depth,              /**< depth of constraint set change's node */
5375    SCIP_Bool             focusnode,          /**< does the constraint set change belong to the focus node? */
5376    SCIP_Bool             active              /**< is the constraint set change currently active? */
5377    )
5378 {
5379    assert(conssetchg != NULL);
5380    assert(cons != NULL);
5381 
5382    /* if constraint set change doesn't exist, create it */
5383    if( *conssetchg == NULL )
5384    {
5385       SCIP_CALL( conssetchgCreate(conssetchg, blkmem) );
5386    }
5387 
5388    /* add constraint to the addedconss array */
5389    SCIP_CALL( conssetchgEnsureAddedconssSize(*conssetchg, blkmem, set, (*conssetchg)->naddedconss+1) );
5390    (*conssetchg)->addedconss[(*conssetchg)->naddedconss] = cons;
5391    (*conssetchg)->naddedconss++;
5392 
5393    /* undelete constraint, if it was globally deleted in the past */
5394    cons->deleted = FALSE;
5395 
5396    /* capture constraint */
5397    SCIPconsCapture(cons);
5398 
5399    /* activate constraint, if node is active */
5400    if( active && !SCIPconsIsActive(cons) )
5401    {
5402       SCIP_CALL( SCIPconsActivate(cons, set, stat, depth, focusnode) );
5403       assert(SCIPconsIsActive(cons));
5404 
5405       /* remember, that this constraint set change data was responsible for the constraint's addition */
5406       cons->addconssetchg = *conssetchg;
5407       cons->addarraypos = (*conssetchg)->naddedconss-1;
5408    }
5409 
5410    return SCIP_OKAY;
5411 }
5412 
5413 /** adds constraint disabling to constraint set changes, and captures constraint */
SCIPconssetchgAddDisabledCons(SCIP_CONSSETCHG ** conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_CONS * cons)5414 SCIP_RETCODE SCIPconssetchgAddDisabledCons(
5415    SCIP_CONSSETCHG**     conssetchg,         /**< pointer to constraint set change data structure */
5416    BMS_BLKMEM*           blkmem,             /**< block memory */
5417    SCIP_SET*             set,                /**< global SCIP settings */
5418    SCIP_CONS*            cons                /**< disabled constraint */
5419    )
5420 {
5421    assert(conssetchg != NULL);
5422    assert(cons != NULL);
5423 
5424    /* if constraint set change doesn't exist, create it */
5425    if( *conssetchg == NULL )
5426    {
5427       SCIP_CALL( conssetchgCreate(conssetchg, blkmem) );
5428    }
5429 
5430    /* add constraint to the disabledconss array */
5431    SCIP_CALL( conssetchgEnsureDisabledconssSize(*conssetchg, blkmem, set, (*conssetchg)->ndisabledconss+1) );
5432    (*conssetchg)->disabledconss[(*conssetchg)->ndisabledconss] = cons;
5433    (*conssetchg)->ndisabledconss++;
5434 
5435    /* capture constraint */
5436    SCIPconsCapture(cons);
5437 
5438    return SCIP_OKAY;
5439 }
5440 
5441 /** deactivates, deletes, and releases constraint from the addedconss array of the constraint set change data */
5442 static
conssetchgDelAddedCons(SCIP_CONSSETCHG * conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,int arraypos)5443 SCIP_RETCODE conssetchgDelAddedCons(
5444    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change to delete constraint from */
5445    BMS_BLKMEM*           blkmem,             /**< block memory */
5446    SCIP_SET*             set,                /**< global SCIP settings */
5447    int                   arraypos            /**< position of constraint in disabledconss array */
5448    )
5449 {
5450    SCIP_CONS* cons;
5451 
5452    assert(conssetchg != NULL);
5453    assert(conssetchg->addedconss != NULL);
5454    assert(0 <= arraypos && arraypos < conssetchg->naddedconss);
5455 
5456    cons = conssetchg->addedconss[arraypos];
5457    assert(cons != NULL);
5458 
5459    SCIPsetDebugMsg(set, "delete added constraint <%s> at position %d from constraint set change data\n", cons->name, arraypos);
5460 
5461    /* remove the link to the constraint set change data */
5462    if( cons->addconssetchg == conssetchg )
5463    {
5464       cons->addconssetchg = NULL;
5465       cons->addarraypos = -1;
5466    }
5467 
5468    /* release constraint */
5469    SCIP_CALL( SCIPconsRelease(&conssetchg->addedconss[arraypos], blkmem, set) );
5470 
5471    /* we want to keep the order of the constraint additions: move all subsequent constraints one slot to the front */
5472    for( ; arraypos < conssetchg->naddedconss-1; ++arraypos )
5473    {
5474       conssetchg->addedconss[arraypos] = conssetchg->addedconss[arraypos+1];
5475       assert(conssetchg->addedconss[arraypos] != NULL);
5476       if( conssetchg->addedconss[arraypos]->addconssetchg == conssetchg )
5477       {
5478          assert(conssetchg->addedconss[arraypos]->addarraypos == arraypos+1);
5479          conssetchg->addedconss[arraypos]->addarraypos = arraypos;
5480       }
5481    }
5482    conssetchg->naddedconss--;
5483 
5484    return SCIP_OKAY;
5485 }
5486 
5487 /** deletes and releases deactivated constraint from the disabledconss array of the constraint set change data */
5488 static
conssetchgDelDisabledCons(SCIP_CONSSETCHG * conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,int arraypos)5489 SCIP_RETCODE conssetchgDelDisabledCons(
5490    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change to apply */
5491    BMS_BLKMEM*           blkmem,             /**< block memory */
5492    SCIP_SET*             set,                /**< global SCIP settings */
5493    int                   arraypos            /**< position of constraint in disabledconss array */
5494    )
5495 {
5496    assert(conssetchg != NULL);
5497    assert(0 <= arraypos && arraypos < conssetchg->ndisabledconss);
5498    assert(conssetchg->disabledconss[arraypos] != NULL);
5499 
5500    SCIPsetDebugMsg(set, "delete disabled constraint <%s> at position %d from constraint set change data\n",
5501       conssetchg->disabledconss[arraypos]->name, arraypos);
5502 
5503    /* release constraint */
5504    SCIP_CALL( SCIPconsRelease(&conssetchg->disabledconss[arraypos], blkmem, set) );
5505 
5506    /* we want to keep the order of the constraint disablings: move all subsequent constraints one slot to the front */
5507    for( ; arraypos < conssetchg->ndisabledconss-1; ++arraypos )
5508    {
5509       conssetchg->disabledconss[arraypos] = conssetchg->disabledconss[arraypos+1];
5510       assert(conssetchg->disabledconss[arraypos] != NULL);
5511    }
5512    conssetchg->ndisabledconss--;
5513 
5514    return SCIP_OKAY;
5515 }
5516 
5517 /** gets added constraints data for a constraint set change */
SCIPconssetchgGetAddedConsData(SCIP_CONSSETCHG * conssetchg,SCIP_CONS *** conss,int * nconss)5518 void SCIPconssetchgGetAddedConsData(
5519    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change to get data from */
5520    SCIP_CONS***          conss,              /**< reference to constraints array added in the conssetchg, or NULL */
5521    int*                  nconss              /**< reference to store the size of the constraints array, or NULL */
5522    )
5523 {
5524    assert(conssetchg != NULL);
5525    if( conss != NULL )
5526       *conss = conssetchg->addedconss;
5527    if( nconss != NULL )
5528       *nconss = conssetchg->naddedconss;
5529 }
5530 
5531 /** applies constraint set change */
SCIPconssetchgApply(SCIP_CONSSETCHG * conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,int depth,SCIP_Bool focusnode)5532 SCIP_RETCODE SCIPconssetchgApply(
5533    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change to apply */
5534    BMS_BLKMEM*           blkmem,             /**< block memory */
5535    SCIP_SET*             set,                /**< global SCIP settings */
5536    SCIP_STAT*            stat,               /**< dynamic problem statistics */
5537    int                   depth,              /**< depth of constraint set change's node */
5538    SCIP_Bool             focusnode           /**< does the constraint set change belong to the focus node? */
5539    )
5540 {
5541    SCIP_CONS* cons;
5542    int i;
5543 
5544    if( conssetchg == NULL )
5545       return SCIP_OKAY;
5546 
5547    SCIPsetDebugMsg(set, "applying constraint set changes at %p: %d constraint additions, %d constraint disablings\n",
5548       (void*)conssetchg, conssetchg->naddedconss, conssetchg->ndisabledconss);
5549 
5550    /* apply constraint additions */
5551    i = 0;
5552    while( i < conssetchg->naddedconss )
5553    {
5554       cons = conssetchg->addedconss[i];
5555       assert(cons != NULL);
5556       assert(!cons->update);
5557 
5558       /* if constraint is already active, or if constraint is globally deleted, it can be removed from addedconss array */
5559       if( cons->active || cons->deleted )
5560       {
5561          /* delete constraint from addedcons array, the empty slot is now used by the next constraint,
5562           * and naddedconss was decreased, so do not increase i
5563           */
5564          SCIP_CALL( conssetchgDelAddedCons(conssetchg, blkmem, set, i) );
5565       }
5566       else
5567       {
5568          assert(cons->addconssetchg == NULL);
5569          assert(cons->addarraypos == -1);
5570 
5571          /* activate constraint */
5572          SCIP_CALL( SCIPconsActivate(cons, set, stat, depth, focusnode) );
5573          assert(cons->active);
5574          assert(!cons->update);
5575 
5576          /* remember, that this constraint set change data was responsible for the constraint's addition */
5577          cons->addconssetchg = conssetchg;
5578          cons->addarraypos = i;
5579 
5580          ++i; /* handle the next constraint */
5581       }
5582    }
5583 
5584    /* apply constraint disablings */
5585    i = 0;
5586    while( i < conssetchg->ndisabledconss )
5587    {
5588       cons = conssetchg->disabledconss[i];
5589       assert(cons != NULL);
5590       assert(!cons->update);
5591 
5592       /* if the constraint is disabled, we can permanently remove it from the disabledconss array */
5593       if( !cons->enabled )
5594       {
5595          SCIPsetDebugMsg(set, "constraint <%s> of handler <%s> was deactivated -> remove it from disabledconss array\n",
5596             cons->name, cons->conshdlr->name);
5597 
5598          /* release and remove constraint from the disabledconss array, the empty slot is now used by the next constraint
5599           * and ndisabledconss was decreased, so do not increase i
5600           */
5601          SCIP_CALL( conssetchgDelDisabledCons(conssetchg, blkmem, set, i) );
5602       }
5603       else
5604       {
5605          assert(cons->addarraypos >= 0);
5606          assert(!cons->deleted); /* deleted constraints must not be enabled! */
5607          SCIP_CALL( SCIPconsDisable(conssetchg->disabledconss[i], set, stat) );
5608          assert(!cons->update);
5609          assert(!cons->enabled);
5610 
5611          ++i; /* handle the next constraint */
5612       }
5613    }
5614 
5615    return SCIP_OKAY;
5616 }
5617 
5618 /** undoes constraint set change */
SCIPconssetchgUndo(SCIP_CONSSETCHG * conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat)5619 SCIP_RETCODE SCIPconssetchgUndo(
5620    SCIP_CONSSETCHG*      conssetchg,         /**< constraint set change to undo */
5621    BMS_BLKMEM*           blkmem,             /**< block memory */
5622    SCIP_SET*             set,                /**< global SCIP settings */
5623    SCIP_STAT*            stat                /**< dynamic problem statistics */
5624    )
5625 {
5626    SCIP_CONS* cons;
5627    int i;
5628 
5629    if( conssetchg == NULL )
5630       return SCIP_OKAY;
5631 
5632    SCIPsetDebugMsg(set, "undoing constraint set changes at %p: %d constraint additions, %d constraint disablings\n",
5633       (void*)conssetchg, conssetchg->naddedconss, conssetchg->ndisabledconss);
5634 
5635    /* undo constraint disablings */
5636    for( i = conssetchg->ndisabledconss-1; i >= 0; --i )
5637    {
5638       cons = conssetchg->disabledconss[i];
5639       assert(cons != NULL);
5640       assert(!cons->update);
5641 
5642       /* If the constraint is inactive, we can permanently remove it from the disabledconss array. It was deactivated
5643        * in the subtree of the current node but not reactivated on the switching way back to the current node, which
5644        * means, the deactivation was more global (i.e. valid on a higher level node) than the current node and the
5645        * disabling at the current node doesn't have any effect anymore.
5646        * If the constraint is already enabled, we need not to do anything. This may happen on a path A -> B,
5647        * if the constraint is disabled at node B, and while processing the subtree of B, it is also disabled at
5648        * the more global node A. Then on the switching path back to A, the constraint is enabled at node B (which is
5649        * actually wrong, since it now should be disabled in the whole subtree of A, but we cannot know this), and
5650        * again enabled at node A (where enabling is ignored). If afterwards, a subnode of B is processed, the
5651        * switching disables the constraint in node A, and the disabling is then removed from node B.
5652        */
5653       if( !cons->active )
5654       {
5655          SCIPsetDebugMsg(set, "constraint <%s> of handler <%s> was deactivated -> remove it from disabledconss array\n",
5656             cons->name, cons->conshdlr->name);
5657 
5658          /* release and remove constraint from the disabledconss array */
5659          SCIP_CALL( conssetchgDelDisabledCons(conssetchg, blkmem, set, i) );
5660       }
5661       else if( !cons->enabled )
5662       {
5663          assert(cons->addarraypos >= 0);
5664          assert(!cons->deleted); /* deleted constraints must not be active! */
5665          SCIP_CALL( SCIPconsEnable(cons, set, stat) );
5666          assert(!cons->update);
5667          assert(!cons->active || cons->enabled);
5668       }
5669    }
5670 
5671    /* undo constraint additions */
5672    for( i = conssetchg->naddedconss-1; i >= 0; --i )
5673    {
5674       cons = conssetchg->addedconss[i];
5675       assert(cons != NULL);
5676       assert(!cons->update);
5677 
5678       /* If the constraint is already deactivated, we need not to do anything. This may happen on a path A -> B,
5679        * if the constraint is added at node B, and while processing the subtree of B, it is also added at
5680        * the more global node A. Then on the switching path back to A, the node is deactivated at node B (which is
5681        * actually wrong, since it now should be active in the whole subtree of A, but we cannot know this), and
5682        * again deactivated at node A (where deactivation is ignored). If afterwards, a subnode of B is processed, the
5683        * switching activates the constraint in node A, and the activation is then removed from node B.
5684        */
5685       if( cons->active )
5686       {
5687          assert(cons->addconssetchg == conssetchg);
5688          assert(cons->addarraypos == i);
5689 
5690          /* deactivate constraint */
5691          SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
5692 
5693          /* unlink the constraint and the constraint set change */
5694          cons->addconssetchg = NULL;
5695          cons->addarraypos = -1;
5696       }
5697       assert(!cons->active);
5698       assert(!cons->update);
5699    }
5700 
5701    return SCIP_OKAY;
5702 }
5703 
5704 /** applies constraint set change to the global problem and deletes the constraint set change data */
SCIPconssetchgMakeGlobal(SCIP_CONSSETCHG ** conssetchg,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_PROB * prob,SCIP_REOPT * reopt)5705 SCIP_RETCODE SCIPconssetchgMakeGlobal(
5706    SCIP_CONSSETCHG**     conssetchg,         /**< pointer to constraint set change data */
5707    BMS_BLKMEM*           blkmem,             /**< block memory */
5708    SCIP_SET*             set,                /**< global SCIP settings */
5709    SCIP_STAT*            stat,               /**< dynamic problem statistics */
5710    SCIP_PROB*            prob,               /**< problem data */
5711    SCIP_REOPT*           reopt               /**< reoptimization data */
5712    )
5713 {
5714    SCIP_CONS* cons;
5715    int i;
5716 
5717    assert(conssetchg != NULL);
5718 
5719    /* nothing to do on empty constraint set change data */
5720    if( *conssetchg == NULL )
5721       return SCIP_OKAY;
5722 
5723    SCIPsetDebugMsg(set, "moving constraint set changes at %p to global problem: %d constraint additions, %d constraint disablings\n",
5724       (void*)*conssetchg, (*conssetchg)->naddedconss, (*conssetchg)->ndisabledconss);
5725 
5726    /* apply constraint additions to the global problem (loop backwards, because then conssetchgDelAddedCons() is
5727     * more efficient)
5728     */
5729    for( i = (*conssetchg)->naddedconss-1; i >= 0; --i )
5730    {
5731       cons = (*conssetchg)->addedconss[i];
5732       assert(cons != NULL);
5733       assert(!cons->update);
5734 
5735       /* only move constraints that are not sticking at the current node */
5736       if( !SCIPconsIsStickingAtNode(cons) )
5737       {
5738          /* because we first have to delete the constraint, we have to capture it in order to not loose it */
5739          SCIPconsCapture(cons);
5740 
5741          /* delete constraint addition from constraint set change data */
5742          SCIP_CALL( conssetchgDelAddedCons(*conssetchg, blkmem, set, i) );
5743 
5744          /* don't move deleted constraints to the global problem */
5745          if( !cons->deleted )
5746          {
5747             SCIP_CALL( SCIPprobAddCons(prob, set, stat, cons) );
5748          }
5749 
5750          /* release constraint */
5751          SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5752       }
5753    }
5754 
5755    /* apply constraint disablings to the global problem (loop backwards, because then conssetchgDelDisabledCons() is
5756     * more efficient)
5757     */
5758    for( i = (*conssetchg)->ndisabledconss-1; i >= 0; --i )
5759    {
5760       cons = (*conssetchg)->disabledconss[i];
5761       assert(cons != NULL);
5762       assert(!cons->update);
5763 
5764       /* only delete constraints that are not sticking at the current node */
5765       if( !SCIPconsIsStickingAtNode(cons) )
5766       {
5767          /* globally delete constraint */
5768          if( !cons->deleted )
5769          {
5770             SCIP_CALL( SCIPconsDelete(cons, blkmem, set, stat, prob, reopt) );
5771          }
5772 
5773          /* release and remove constraint from the disabledconss array */
5774          SCIP_CALL( conssetchgDelDisabledCons(*conssetchg, blkmem, set, i) );
5775       }
5776    }
5777 
5778    if( (*conssetchg)->naddedconss == 0 && (*conssetchg)->ndisabledconss == 0 )
5779    {
5780       /* free empty constraint set change data */
5781       SCIP_CALL( SCIPconssetchgFree(conssetchg, blkmem, set) );
5782    }
5783 
5784    return SCIP_OKAY;
5785 }
5786 
5787 
5788 
5789 
5790 /*
5791  * Constraint methods
5792  */
5793 
5794 /** creates and captures a constraint, and inserts it into the conss array of its constraint handler
5795  *
5796  *  @warning If a constraint is marked to be checked for feasibility but not to be enforced, a LP or pseudo solution
5797  *  may be declared feasible even if it violates this particular constraint.
5798  *  This constellation should only be used, if no LP or pseudo solution can violate the constraint -- e.g. if a
5799  *  local constraint is redundant due to the variable's local bounds.
5800  */
SCIPconsCreate(SCIP_CONS ** cons,BMS_BLKMEM * blkmem,SCIP_SET * set,const char * name,SCIP_CONSHDLR * conshdlr,SCIP_CONSDATA * consdata,SCIP_Bool initial,SCIP_Bool separate,SCIP_Bool enforce,SCIP_Bool check,SCIP_Bool propagate,SCIP_Bool local,SCIP_Bool modifiable,SCIP_Bool dynamic,SCIP_Bool removable,SCIP_Bool stickingatnode,SCIP_Bool original,SCIP_Bool deleteconsdata)5801 SCIP_RETCODE SCIPconsCreate(
5802    SCIP_CONS**           cons,               /**< pointer to constraint */
5803    BMS_BLKMEM*           blkmem,             /**< block memory */
5804    SCIP_SET*             set,                /**< global SCIP settings */
5805    const char*           name,               /**< name of constraint */
5806    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler for this constraint */
5807    SCIP_CONSDATA*        consdata,           /**< data for this specific constraint */
5808    SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
5809                                               *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5810    SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
5811                                               *   Usually set to TRUE. */
5812    SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
5813                                               *   TRUE for model constraints, FALSE for additional, redundant constraints. */
5814    SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
5815                                               *   TRUE for model constraints, FALSE for additional, redundant constraints. */
5816    SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
5817                                               *   Usually set to TRUE. */
5818    SCIP_Bool             local,              /**< is constraint only valid locally?
5819                                               *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5820    SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
5821                                               *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
5822                                               *   adds coefficients to this constraint. */
5823    SCIP_Bool             dynamic,            /**< is constraint subject to aging?
5824                                               *   Usually set to FALSE. Set to TRUE for own cuts which
5825                                               *   are separated as constraints. */
5826    SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
5827                                               *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5828    SCIP_Bool             stickingatnode,     /**< should the constraint always be kept at the node where it was added, even
5829                                               *   if it may be moved to a more global node?
5830                                               *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
5831    SCIP_Bool             original,           /**< is constraint belonging to the original problem? */
5832    SCIP_Bool             deleteconsdata      /**< has the constraint data to be deleted if constraint is freed? */
5833    )
5834 {
5835    int i;
5836 
5837    assert(cons != NULL);
5838    assert(blkmem != NULL);
5839    assert(set != NULL);
5840    assert(name != NULL);
5841    assert(conshdlr != NULL);
5842    assert(!original || deleteconsdata);
5843 
5844    /* create constraint data */
5845    SCIP_ALLOC( BMSallocBlockMemory(blkmem, cons) );
5846    SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->name, name, strlen(name)+1) );
5847 #ifndef NDEBUG
5848    (*cons)->scip = set->scip;
5849 #endif
5850    (*cons)->conshdlr = conshdlr;
5851    (*cons)->consdata = consdata;
5852    (*cons)->transorigcons = NULL;
5853    (*cons)->addconssetchg = NULL;
5854    (*cons)->addarraypos = -1;
5855    (*cons)->consspos = -1;
5856    (*cons)->initconsspos = -1;
5857    (*cons)->sepaconsspos = -1;
5858    (*cons)->enfoconsspos = -1;
5859    (*cons)->checkconsspos = -1;
5860    (*cons)->propconsspos = -1;
5861    (*cons)->activedepth = -2;
5862    (*cons)->validdepth = (local ? -1 : 0);
5863    (*cons)->age = 0.0;
5864    (*cons)->nuses = 0;
5865    (*cons)->nupgradelocks = 0;
5866    (*cons)->initial = initial;
5867    (*cons)->separate = separate;
5868    (*cons)->enforce = enforce;
5869    (*cons)->check = check;
5870    (*cons)->propagate = propagate;
5871    (*cons)->sepaenabled = separate;
5872    (*cons)->propenabled = propagate;
5873    (*cons)->local = local;
5874    (*cons)->modifiable = modifiable;
5875    (*cons)->dynamic = dynamic;
5876    (*cons)->removable = removable;
5877    (*cons)->stickingatnode = stickingatnode;
5878    (*cons)->original = original;
5879    (*cons)->deleteconsdata = deleteconsdata;
5880    (*cons)->active = FALSE;
5881    (*cons)->conflict = FALSE;
5882    (*cons)->enabled = FALSE;
5883    (*cons)->obsolete = FALSE;
5884    (*cons)->markpropagate = TRUE;
5885    (*cons)->deleted = FALSE;
5886    (*cons)->update = FALSE;
5887    (*cons)->updateinsert = FALSE;
5888    (*cons)->updateactivate = FALSE;
5889    (*cons)->updatedeactivate = FALSE;
5890    (*cons)->updateenable = FALSE;
5891    (*cons)->updatedisable = FALSE;
5892    (*cons)->updatesepaenable = FALSE;
5893    (*cons)->updatesepadisable = FALSE;
5894    (*cons)->updatepropenable = FALSE;
5895    (*cons)->updatepropdisable = FALSE;
5896    (*cons)->updateobsolete = FALSE;
5897    (*cons)->updatemarkpropagate = FALSE;
5898    (*cons)->updateunmarkpropagate = FALSE;
5899    (*cons)->updatefree = FALSE;
5900    (*cons)->updateactfocus = FALSE;
5901 
5902    for( i = 0; i < NLOCKTYPES; i++ )
5903    {
5904       (*cons)->nlockspos[i] = 0;
5905       (*cons)->nlocksneg[i] = 0;
5906    }
5907 
5908    /* capture constraint */
5909    SCIPconsCapture(*cons);
5910 
5911    /* insert the constraint as inactive constraint into the transformed constraints array */
5912    if( !original )
5913    {
5914       /* check, if inserting constraint should be delayed */
5915       if( conshdlrAreUpdatesDelayed(conshdlr) )
5916       {
5917          SCIPsetDebugMsg(set, " -> delaying insertion of constraint <%s>\n", (*cons)->name);
5918          (*cons)->updateinsert = TRUE;
5919          SCIP_CALL( conshdlrAddUpdateCons((*cons)->conshdlr, set, *cons) );
5920          assert((*cons)->update);
5921          assert((*cons)->nuses == 2);
5922       }
5923       else
5924       {
5925          SCIP_CALL( conshdlrAddCons(conshdlr, set, *cons) );
5926       }
5927    }
5928 
5929    checkConssArrays(conshdlr);
5930 
5931    return SCIP_OKAY;
5932 }
5933 
5934 /** copies source constraint of source SCIP into the target constraint for the target SCIP, using the variable map for
5935  *  mapping the variables of the source SCIP to the variables of the target SCIP; if the copying process was successful
5936  *  a constraint is created and captured;
5937  *
5938  *  @warning If a constraint is marked to be checked for feasibility but not to be enforced, an LP or pseudo solution
5939  *  may be declared feasible even if it violates this particular constraint.
5940  *  This constellation should only be used, if no LP or pseudo solution can violate the constraint -- e.g. if a
5941  *  local constraint is redundant due to the variable's local bounds.
5942  */
SCIPconsCopy(SCIP_CONS ** cons,SCIP_SET * set,const char * name,SCIP * sourcescip,SCIP_CONSHDLR * sourceconshdlr,SCIP_CONS * sourcecons,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool initial,SCIP_Bool separate,SCIP_Bool enforce,SCIP_Bool check,SCIP_Bool propagate,SCIP_Bool local,SCIP_Bool modifiable,SCIP_Bool dynamic,SCIP_Bool removable,SCIP_Bool stickingatnode,SCIP_Bool global,SCIP_Bool * valid)5943 SCIP_RETCODE SCIPconsCopy(
5944    SCIP_CONS**           cons,               /**< pointer to store the created target constraint */
5945    SCIP_SET*             set,                /**< global SCIP settings of the target SCIP */
5946    const char*           name,               /**< name of constraint, or NULL if the name of the source constraint should be used */
5947    SCIP*                 sourcescip,         /**< source SCIP data structure */
5948    SCIP_CONSHDLR*        sourceconshdlr,     /**< source constraint handler for this constraint */
5949    SCIP_CONS*            sourcecons,         /**< source constraint of the source SCIP */
5950    SCIP_HASHMAP*         varmap,             /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
5951                                               *   variables of the target SCIP */
5952    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
5953                                               *   target constraints, must not be NULL! */
5954    SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP? */
5955    SCIP_Bool             separate,           /**< should the constraint be separated during LP processing? */
5956    SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing? */
5957    SCIP_Bool             check,              /**< should the constraint be checked for feasibility? */
5958    SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing? */
5959    SCIP_Bool             local,              /**< is constraint only valid locally? */
5960    SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)? */
5961    SCIP_Bool             dynamic,            /**< is constraint subject to aging? */
5962    SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup? */
5963    SCIP_Bool             stickingatnode,     /**< should the constraint always be kept at the node where it was added, even
5964                                               *   if it may be moved to a more global node? */
5965    SCIP_Bool             global,             /**< create a global or a local copy? */
5966    SCIP_Bool*            valid               /**< pointer to store whether the copying was valid or not */
5967    )
5968 {
5969    assert(cons != NULL);
5970    assert(set != NULL);
5971    assert(sourcescip != NULL);
5972    assert(sourceconshdlr != NULL);
5973    assert(sourcecons != NULL);
5974    assert(varmap != NULL);
5975    assert(consmap != NULL);
5976    assert(valid != NULL);
5977 
5978    /* if constraint handler does not support copying, success will return false. Constraints handlers have to actively set this to true. */
5979    (*valid) = FALSE;
5980 
5981    if( sourceconshdlr->conscopy != NULL )
5982    {
5983       SCIP_CALL( sourceconshdlr->conscopy(set->scip, cons, name, sourcescip, sourceconshdlr, sourcecons, varmap, consmap,
5984             initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
5985    }
5986 
5987    return SCIP_OKAY;
5988 }
5989 
5990 
5991 /** parses constraint information (in cip format) out of a string; if the parsing process was successful a constraint is
5992  *  created, captured, and inserted into the conss array of its constraint handler.
5993  *
5994  *  @warning If a constraint is marked to be checked for feasibility but not to be enforced, an LP or pseudo solution
5995  *  may be declared feasible even if it violates this particular constraint.
5996  *  This constellation should only be used, if no LP or pseudo solution can violate the constraint -- e.g. if a
5997  *  local constraint is redundant due to the variable's local bounds.
5998  */
SCIPconsParse(SCIP_CONS ** cons,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,const char * str,SCIP_Bool initial,SCIP_Bool separate,SCIP_Bool enforce,SCIP_Bool check,SCIP_Bool propagate,SCIP_Bool local,SCIP_Bool modifiable,SCIP_Bool dynamic,SCIP_Bool removable,SCIP_Bool stickingatnode,SCIP_Bool * success)5999 SCIP_RETCODE SCIPconsParse(
6000    SCIP_CONS**           cons,               /**< pointer to constraint */
6001    SCIP_SET*             set,                /**< global SCIP settings */
6002    SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler of target SCIP */
6003    const char*           str,                /**< string to parse for constraint */
6004    SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
6005                                               *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
6006    SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
6007                                               *   Usually set to TRUE. */
6008    SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
6009                                               *   TRUE for model constraints, FALSE for additional, redundant constraints. */
6010    SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
6011                                               *   TRUE for model constraints, FALSE for additional, redundant constraints. */
6012    SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
6013                                               *   Usually set to TRUE. */
6014    SCIP_Bool             local,              /**< is constraint only valid locally?
6015                                               *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
6016    SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
6017                                               *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
6018                                               *   adds coefficients to this constraint. */
6019    SCIP_Bool             dynamic,            /**< is constraint subject to aging?
6020                                               *   Usually set to FALSE. Set to TRUE for own cuts which
6021                                               *   are separated as constraints. */
6022    SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
6023                                               *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
6024    SCIP_Bool             stickingatnode,     /**< should the constraint always be kept at the node where it was added, even
6025                                               *   if it may be moved to a more global node?
6026                                               *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
6027    SCIP_Bool*            success             /**< pointer store if the paring process was successful */
6028    )
6029 {
6030    SCIP_CONSHDLR* conshdlr;
6031    char conshdlrname[SCIP_MAXSTRLEN];
6032    char consname[SCIP_MAXSTRLEN];
6033    char* endptr;
6034 
6035    assert(cons != NULL);
6036    assert(set != NULL);
6037 
6038    (*success) = FALSE;
6039 
6040    /* scan constraint handler name */
6041    assert(str != NULL);
6042    SCIPstrCopySection(str, '[', ']', conshdlrname, SCIP_MAXSTRLEN, &endptr);
6043    if ( endptr == NULL || endptr == str )
6044    {
6045       SCIPmessagePrintWarning(messagehdlr, "Syntax error: Could not find constraint handler name.\n");
6046       return SCIP_OKAY;
6047    }
6048    assert(endptr != NULL);
6049    SCIPsetDebugMsg(set, "constraint handler name <%s>\n", conshdlrname);
6050 
6051    /* scan constraint name */
6052    SCIPstrCopySection(endptr, '<', '>', consname, SCIP_MAXSTRLEN, &endptr);
6053    if ( endptr == NULL || endptr == str )
6054    {
6055       SCIPmessagePrintWarning(messagehdlr, "Syntax error: Could not find constraint name.\n");
6056       return SCIP_OKAY;
6057    }
6058    assert(endptr != NULL);
6059    SCIPsetDebugMsg(set, "constraint name <%s>\n", consname);
6060 
6061    str = endptr;
6062 
6063    /* skip white space */
6064    while ( isspace((unsigned char)* str) )
6065       ++str;
6066 
6067    /* check for colon */
6068    if( *str != ':' )
6069    {
6070       SCIPmessagePrintWarning(messagehdlr, "Syntax error: Could not find colon ':' after constraint name.\n");
6071       return SCIP_OKAY;
6072    }
6073 
6074    /* skip colon */
6075    ++str;
6076 
6077    /* skip white space */
6078    while ( isspace((unsigned char)* str) )
6079       ++str;
6080 
6081    /* check if a constraint handler with parsed name exists */
6082    conshdlr = SCIPsetFindConshdlr(set, conshdlrname);
6083 
6084    if( conshdlr == NULL )
6085    {
6086       SCIPmessagePrintWarning(messagehdlr, "constraint handler <%s> doesn't exist in SCIP data structure\n", conshdlrname);
6087    }
6088    else
6089    {
6090       assert( conshdlr != NULL );
6091       if ( conshdlr->consparse == NULL )
6092       {
6093          SCIPmessagePrintWarning(messagehdlr, "constraint handler <%s> does not support parsing constraints\n", conshdlrname);
6094       }
6095       else
6096       {
6097          SCIP_CALL( conshdlr->consparse(set->scip, conshdlr, cons, consname, str,
6098                initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) );
6099       }
6100    }
6101 
6102    return SCIP_OKAY;
6103 }
6104 
6105 /** change name of given constraint */
SCIPconsChgName(SCIP_CONS * cons,BMS_BLKMEM * blkmem,const char * name)6106 SCIP_RETCODE SCIPconsChgName(
6107    SCIP_CONS*            cons,               /**< problem constraint */
6108    BMS_BLKMEM*           blkmem,             /**< block memory buffer */
6109    const char*           name                /**< new name of constraint */
6110    )
6111 {
6112    assert(cons != NULL);
6113    assert(cons->name != NULL);
6114 
6115    /* free old constraint name */
6116    BMSfreeBlockMemoryArray(blkmem, &cons->name, strlen(cons->name)+1);
6117 
6118    /* copy new constraint name */
6119    SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &cons->name, name, strlen(name)+1) );
6120 
6121    return SCIP_OKAY;
6122 }
6123 
6124 
6125 /** frees a constraint and removes it from the conss array of its constraint handler */
SCIPconsFree(SCIP_CONS ** cons,BMS_BLKMEM * blkmem,SCIP_SET * set)6126 SCIP_RETCODE SCIPconsFree(
6127    SCIP_CONS**           cons,               /**< constraint to free */
6128    BMS_BLKMEM*           blkmem,             /**< block memory buffer */
6129    SCIP_SET*             set                 /**< global SCIP settings */
6130    )
6131 {
6132    assert(cons != NULL);
6133    assert(*cons != NULL);
6134    assert((*cons)->conshdlr != NULL);
6135    assert((*cons)->nuses == 0);
6136    assert(!(*cons)->active);
6137    assert(!(*cons)->update);
6138    assert(!(*cons)->original || (*cons)->transorigcons == NULL);
6139    assert(blkmem != NULL);
6140    assert(set != NULL);
6141    assert((*cons)->scip == set->scip);
6142 
6143    SCIPsetDebugMsg(set, "freeing constraint <%s> at conss pos %d of handler <%s>\n",
6144       (*cons)->name, (*cons)->consspos, (*cons)->conshdlr->name);
6145 
6146    /* free constraint data */
6147    if( (*cons)->conshdlr->consdelete != NULL && (*cons)->consdata != NULL && (*cons)->deleteconsdata )
6148    {
6149       SCIP_CALL( (*cons)->conshdlr->consdelete(set->scip, (*cons)->conshdlr, *cons, &(*cons)->consdata) );
6150    }
6151    else if( !(*cons)->deleteconsdata )
6152       (*cons)->consdata = NULL;
6153    assert((*cons)->consdata == NULL);
6154 
6155    /* unlink transformed and original constraint */
6156    if( (*cons)->transorigcons != NULL )
6157    {
6158       assert(!(*cons)->original);
6159       assert((*cons)->transorigcons->original);
6160       assert((*cons)->transorigcons->transorigcons == *cons);
6161 
6162       (*cons)->transorigcons->transorigcons = NULL;
6163    }
6164 
6165    /* remove constraint from the transformed constraints array */
6166    if( !(*cons)->original )
6167    {
6168       conshdlrDelCons((*cons)->conshdlr, *cons);
6169       checkConssArrays((*cons)->conshdlr);
6170    }
6171    assert((*cons)->consspos == -1);
6172 
6173    /* free constraint */
6174    BMSfreeBlockMemoryArray(blkmem, &(*cons)->name, strlen((*cons)->name)+1);
6175    BMSfreeBlockMemory(blkmem, cons);
6176 
6177    return SCIP_OKAY;
6178 }
6179 
6180 /** increases usage counter of constraint */
SCIPconsCapture(SCIP_CONS * cons)6181 void SCIPconsCapture(
6182    SCIP_CONS*            cons                /**< constraint */
6183    )
6184 {
6185    assert(cons != NULL);
6186    assert(cons->nuses >= 0);
6187 
6188    SCIPdebugMessage("capture constraint <%s> with nuses=%d, cons pointer %p\n", cons->name, cons->nuses, (void*)cons);
6189    cons->nuses++;
6190 }
6191 
6192 /** decreases usage counter of constraint, and frees memory if necessary */
SCIPconsRelease(SCIP_CONS ** cons,BMS_BLKMEM * blkmem,SCIP_SET * set)6193 SCIP_RETCODE SCIPconsRelease(
6194    SCIP_CONS**           cons,               /**< pointer to constraint */
6195    BMS_BLKMEM*           blkmem,             /**< block memory */
6196    SCIP_SET*             set                 /**< global SCIP settings */
6197    )
6198 {
6199    assert(blkmem != NULL);
6200    assert(cons != NULL);
6201    assert(*cons != NULL);
6202    assert((*cons)->conshdlr != NULL);
6203    assert((*cons)->nuses >= 1);
6204    assert(set != NULL);
6205    assert((*cons)->scip == set->scip);
6206 
6207    SCIPsetDebugMsg(set, "release constraint <%s> with nuses=%d, cons pointer %p\n", (*cons)->name, (*cons)->nuses, (void*)(*cons));
6208    (*cons)->nuses--;
6209    if( (*cons)->nuses == 0 )
6210    {
6211       assert(!(*cons)->active || (*cons)->updatedeactivate);
6212 
6213       /* check, if freeing constraint should be delayed */
6214       if( conshdlrAreUpdatesDelayed((*cons)->conshdlr) )
6215       {
6216          SCIPsetDebugMsg(set, " -> delaying freeing constraint <%s>\n", (*cons)->name);
6217          (*cons)->updatefree = TRUE;
6218          SCIP_CALL( conshdlrAddUpdateCons((*cons)->conshdlr, set, *cons) );
6219          assert((*cons)->update);
6220          assert((*cons)->nuses == 1);
6221       }
6222       else
6223       {
6224          SCIP_CALL( SCIPconsFree(cons, blkmem, set) );
6225       }
6226    }
6227    *cons = NULL;
6228 
6229    return SCIP_OKAY;
6230 }
6231 
6232 /** outputs constraint information to file stream */
SCIPconsPrint(SCIP_CONS * cons,SCIP_SET * set,SCIP_MESSAGEHDLR * messagehdlr,FILE * file)6233 SCIP_RETCODE SCIPconsPrint(
6234    SCIP_CONS*            cons,               /**< constraint to print */
6235    SCIP_SET*             set,                /**< global SCIP settings */
6236    SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
6237    FILE*                 file                /**< output file (or NULL for standard output) */
6238    )
6239 {
6240    SCIP_CONSHDLR* conshdlr;
6241 
6242    assert(cons != NULL);
6243    assert(set != NULL);
6244    assert(cons->scip == set->scip);
6245 
6246    conshdlr = cons->conshdlr;
6247    assert(conshdlr != NULL);
6248 
6249    SCIPmessageFPrintInfo(messagehdlr, file, "  [%s] <%s>: ", conshdlr->name, cons->name);
6250 
6251    if( conshdlr->consprint != NULL )
6252    {
6253       SCIP_CALL( conshdlr->consprint(set->scip, conshdlr, cons, file) );
6254    }
6255    else
6256       SCIPmessageFPrintInfo(messagehdlr, file, "constraint handler <%s> doesn't support printing constraint", conshdlr->name);
6257 
6258    return SCIP_OKAY;
6259 }
6260 
6261 /** method to collect the variables of a constraint
6262  *
6263  *  If the number of variables is greater than the available slots in the variable array, nothing happens except that
6264  *  the success point is set to FALSE. With the method SCIPconsGetNVars() it is possible to get the number of variables
6265  *  a constraint has in its scope.
6266  *
6267  *  @note The success pointer indicates if all variables were copied into the vars arrray.
6268  *
6269  *  @note It might be that a constraint handler does not support this functionality, in that case the success pointer is
6270  *        set to FALSE.
6271  */
SCIPconsGetVars(SCIP_CONS * cons,SCIP_SET * set,SCIP_VAR ** vars,int varssize,SCIP_Bool * success)6272 SCIP_RETCODE SCIPconsGetVars(
6273    SCIP_CONS*            cons,               /**< constraint to print */
6274    SCIP_SET*             set,                /**< global SCIP settings */
6275    SCIP_VAR**            vars,               /**< array to store the involved variable of the constraint */
6276    int                   varssize,           /**< available slots in vars array which is needed to check if the array is large enough */
6277    SCIP_Bool*            success             /**< pointer to store whether the variables are successfully copied */
6278    )
6279 {
6280    SCIP_CONSHDLR* conshdlr;
6281 
6282    assert(cons != NULL);
6283    assert(set != NULL);
6284    assert(cons->scip == set->scip);
6285 
6286    conshdlr = cons->conshdlr;
6287    assert(conshdlr != NULL);
6288 
6289    if( conshdlr->consgetvars != NULL )
6290    {
6291       SCIP_CALL( conshdlr->consgetvars(set->scip, conshdlr, cons, vars, varssize, success) );
6292    }
6293    else
6294    {
6295       (*success) = FALSE;
6296    }
6297 
6298    return SCIP_OKAY;
6299 }
6300 
6301 /** method to collect the number of variables of a constraint
6302  *
6303  *  @note The success pointer indicates if the contraint handler was able to return the number of variables
6304  *
6305  *  @note It might be that a constraint handler does not support this functionality, in that case the success pointer is
6306  *        set to FALSE
6307  */
SCIPconsGetNVars(SCIP_CONS * cons,SCIP_SET * set,int * nvars,SCIP_Bool * success)6308 SCIP_RETCODE SCIPconsGetNVars(
6309    SCIP_CONS*            cons,               /**< constraint to print */
6310    SCIP_SET*             set,                /**< global SCIP settings */
6311    int*                  nvars,              /**< pointer to store the number of variables */
6312    SCIP_Bool*            success             /**< pointer to store whether the constraint successfully returned the number of variables */
6313    )
6314 {
6315    SCIP_CONSHDLR* conshdlr;
6316 
6317    assert(cons != NULL);
6318    assert(set != NULL);
6319    assert(cons->scip == set->scip);
6320 
6321    conshdlr = cons->conshdlr;
6322    assert(conshdlr != NULL);
6323 
6324    if( conshdlr->consgetnvars != NULL )
6325    {
6326       SCIP_CALL( conshdlr->consgetnvars(set->scip, conshdlr, cons, nvars, success) );
6327    }
6328    else
6329    {
6330       (*nvars) = 0;
6331       (*success) = FALSE;
6332    }
6333 
6334    return SCIP_OKAY;
6335 }
6336 
6337 /** globally removes constraint from all subproblems; removes constraint from the constraint set change data of the
6338  *  node, where it was created, or from the problem, if it was a problem constraint
6339  */
SCIPconsDelete(SCIP_CONS * cons,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_PROB * prob,SCIP_REOPT * reopt)6340 SCIP_RETCODE SCIPconsDelete(
6341    SCIP_CONS*            cons,               /**< constraint to delete */
6342    BMS_BLKMEM*           blkmem,             /**< block memory */
6343    SCIP_SET*             set,                /**< global SCIP settings */
6344    SCIP_STAT*            stat,               /**< dynamic problem statistics */
6345    SCIP_PROB*            prob,               /**< problem data */
6346    SCIP_REOPT*           reopt               /**< reoptimization data */
6347    )
6348 {
6349    assert(cons != NULL);
6350    assert(cons->conshdlr != NULL);
6351    assert(!cons->active || cons->updatedeactivate || cons->addarraypos >= 0);
6352    assert(set != NULL);
6353    assert(cons->scip == set->scip);
6354 
6355    SCIPsetDebugMsg(set, "globally deleting constraint <%s> (delay updates: %d)\n",
6356       cons->name, cons->conshdlr->delayupdatecount);
6357 
6358    /* mark constraint deleted */
6359    cons->deleted = TRUE;
6360 
6361    /* deactivate constraint, if it is currently active */
6362    if( cons->active && !cons->updatedeactivate )
6363    {
6364       SCIP_CALL( SCIPconsDeactivate(cons, set, stat) );
6365    }
6366    else
6367       cons->updateactivate = FALSE;
6368 
6369    if( set->reopt_enable && !SCIPreoptConsCanBeDeleted(reopt, cons) )
6370       return SCIP_OKAY;
6371 
6372    assert(!cons->active || cons->updatedeactivate);
6373    assert(!cons->enabled || cons->updatedeactivate);
6374 
6375    /* remove formerly active constraint from the conssetchg's addedconss / prob's conss array */
6376    if( cons->addarraypos >= 0 )
6377    {
6378       if( cons->addconssetchg == NULL )
6379       {
6380          /* remove problem constraint from the problem */
6381          SCIP_CALL( SCIPprobDelCons(prob, blkmem, set, stat, cons) );
6382       }
6383       else
6384       {
6385          assert(cons->addconssetchg->addedconss != NULL);
6386          assert(0 <= cons->addarraypos && cons->addarraypos < cons->addconssetchg->naddedconss);
6387          assert(cons->addconssetchg->addedconss[cons->addarraypos] == cons);
6388 
6389          /* remove constraint from the constraint set change addedconss array */
6390          SCIP_CALL( conssetchgDelAddedCons(cons->addconssetchg, blkmem, set, cons->addarraypos) );
6391       }
6392    }
6393 
6394    return SCIP_OKAY;
6395 }
6396 
6397 /** gets and captures transformed constraint of a given original constraint; if the constraint is not yet transformed,
6398  *  a new transformed constraint for this constraint is created
6399  */
SCIPconsTransform(SCIP_CONS * origcons,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_CONS ** transcons)6400 SCIP_RETCODE SCIPconsTransform(
6401    SCIP_CONS*            origcons,           /**< original constraint */
6402    BMS_BLKMEM*           blkmem,             /**< block memory buffer */
6403    SCIP_SET*             set,                /**< global SCIP settings */
6404    SCIP_CONS**           transcons           /**< pointer to store the transformed constraint */
6405    )
6406 {
6407    assert(origcons != NULL);
6408    assert(set != NULL);
6409    assert(origcons->scip == set->scip);
6410    assert(origcons->conshdlr != NULL);
6411    assert(origcons->original);
6412    assert(transcons != NULL);
6413 
6414    /* check, if the constraint is already transformed */
6415    if( origcons->transorigcons != NULL )
6416    {
6417       *transcons = origcons->transorigcons;
6418       SCIPconsCapture(*transcons);
6419    }
6420    else
6421    {
6422       /* create transformed constraint */
6423       if( origcons->conshdlr->constrans != NULL )
6424       {
6425          /* use constraint handler's own method to transform constraint */
6426          SCIP_CALL( origcons->conshdlr->constrans(set->scip, origcons->conshdlr, origcons, transcons) );
6427       }
6428       else
6429       {
6430          /* create new constraint with a pointer copy of the constraint data */
6431          SCIP_CALL( SCIPconsCreate(transcons, blkmem, set, origcons->name, origcons->conshdlr, origcons->consdata, origcons->initial,
6432                origcons->separate, origcons->enforce, origcons->check, origcons->propagate,
6433                origcons->local, origcons->modifiable, origcons->dynamic, origcons->removable, origcons->stickingatnode,
6434                FALSE, FALSE) );
6435       }
6436 
6437       /* link original and transformed constraint */
6438       origcons->transorigcons = *transcons;
6439       (*transcons)->transorigcons = origcons;
6440 
6441       /* copy the number of upgradelocks */
6442       (*transcons)->nupgradelocks = origcons->nupgradelocks; /*lint !e732*/
6443    }
6444    assert(*transcons != NULL);
6445 
6446    return SCIP_OKAY;
6447 }
6448 
6449 /** sets the initial flag of the given constraint */
SCIPconsSetInitial(SCIP_CONS * cons,SCIP_SET * set,SCIP_STAT * stat,SCIP_Bool initial)6450 SCIP_RETCODE SCIPconsSetInitial(
6451    SCIP_CONS*            cons,               /**< constraint */
6452    SCIP_SET*             set,                /**< global SCIP settings */
6453    SCIP_STAT*            stat,               /**< dynamic problem statistics */
6454    SCIP_Bool             initial             /**< new value */
6455    )
6456 {
6457    assert(cons != NULL);
6458    assert(set != NULL);
6459    assert(cons->scip == set->scip);
6460 
6461    if( cons->initial != initial )
6462    {
6463       cons->initial = initial;
6464       if( !cons->original )
6465       {
6466          if( cons->initial )
6467          {
6468             SCIP_CALL( conshdlrAddInitcons(SCIPconsGetHdlr(cons), set, stat, cons) );
6469          }
6470          else
6471          {
6472             if( cons->initconsspos >= 0 )
6473             {
6474                conshdlrDelInitcons(SCIPconsGetHdlr(cons), cons);
6475             }
6476          }
6477       }
6478    }
6479 
6480    return SCIP_OKAY;
6481 }
6482 
6483 /** sets the separate flag of the given constraint */
SCIPconsSetSeparated(SCIP_CONS * cons,SCIP_SET * set,SCIP_Bool separate)6484 SCIP_RETCODE SCIPconsSetSeparated(
6485    SCIP_CONS*            cons,               /**< constraint */
6486    SCIP_SET*             set,                /**< global SCIP settings */
6487    SCIP_Bool             separate            /**< new value */
6488    )
6489 {
6490    assert(cons != NULL);
6491    assert(set != NULL);
6492    assert(cons->scip == set->scip);
6493 
6494    if( cons->separate != separate )
6495    {
6496       if( SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM )
6497       {
6498          cons->separate = separate;
6499       }
6500       else if( cons->enabled && cons->sepaenabled )
6501       {
6502          if( separate )
6503          {
6504             cons->separate = separate;
6505             SCIP_CALL( conshdlrAddSepacons(cons->conshdlr, set, cons) );
6506          }
6507          else
6508          {
6509             conshdlrDelSepacons(cons->conshdlr, cons);
6510             cons->separate = separate;
6511          }
6512       }
6513    }
6514 
6515    return SCIP_OKAY;
6516 }
6517 
6518 /** sets the enforce flag of the given constraint */
SCIPconsSetEnforced(SCIP_CONS * cons,SCIP_SET * set,SCIP_Bool enforce)6519 SCIP_RETCODE SCIPconsSetEnforced(
6520    SCIP_CONS*            cons,               /**< constraint */
6521    SCIP_SET*             set,                /**< global SCIP settings */
6522    SCIP_Bool             enforce             /**< new value */
6523    )
6524 {
6525    assert(cons != NULL);
6526    assert(set != NULL);
6527    assert(cons->scip == set->scip);
6528 
6529    if( cons->enforce != enforce )
6530    {
6531       if( SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM )
6532       {
6533          cons->enforce = enforce;
6534       }
6535       else if( cons->enabled )
6536       {
6537          if( enforce )
6538          {
6539             cons->enforce = enforce;
6540             SCIP_CALL( conshdlrAddEnfocons(cons->conshdlr, set, cons) );
6541          }
6542          else
6543          {
6544             conshdlrDelEnfocons(cons->conshdlr, cons);
6545             cons->enforce = enforce;
6546          }
6547       }
6548    }
6549 
6550    return SCIP_OKAY;
6551 }
6552 
6553 /** sets the check flag of the given constraint */
SCIPconsSetChecked(SCIP_CONS * cons,SCIP_SET * set,SCIP_Bool check)6554 SCIP_RETCODE SCIPconsSetChecked(
6555    SCIP_CONS*            cons,               /**< constraint */
6556    SCIP_SET*             set,                /**< global SCIP settings */
6557    SCIP_Bool             check               /**< new value */
6558    )
6559 {
6560    assert(cons != NULL);
6561    assert(set != NULL);
6562    assert(cons->scip == set->scip);
6563 
6564    if( cons->check != check )
6565    {
6566       cons->check = check;
6567 
6568       if( !cons->original )
6569       {
6570          /* if constraint is a problem constraint, update variable roundings locks */
6571          if( cons->addconssetchg == NULL && cons->addarraypos >= 0 )
6572          {
6573             if( cons->check )
6574             {
6575                SCIP_CALL( SCIPconsAddLocks(cons, set, SCIP_LOCKTYPE_MODEL, +1, 0) );
6576             }
6577             else
6578             {
6579                SCIP_CALL( SCIPconsAddLocks(cons, set, SCIP_LOCKTYPE_MODEL, -1, 0) );
6580             }
6581          }
6582 
6583          /* if constraint is active, update the checkconss array of the constraint handler */
6584          if( cons->active )
6585          {
6586             if( cons->check )
6587             {
6588                SCIP_CALL( conshdlrAddCheckcons(cons->conshdlr, set, cons) );
6589             }
6590             else
6591             {
6592                conshdlrDelCheckcons(cons->conshdlr, cons);
6593             }
6594          }
6595       }
6596    }
6597 
6598    return SCIP_OKAY;
6599 }
6600 
6601 /** sets the propagate flag of the given constraint */
SCIPconsSetPropagated(SCIP_CONS * cons,SCIP_SET * set,SCIP_Bool propagate)6602 SCIP_RETCODE SCIPconsSetPropagated(
6603    SCIP_CONS*            cons,               /**< constraint */
6604    SCIP_SET*             set,                /**< global SCIP settings */
6605    SCIP_Bool             propagate           /**< new value */
6606    )
6607 {
6608    assert(cons != NULL);
6609    assert(set != NULL);
6610    assert(cons->scip == set->scip);
6611 
6612    if( cons->propagate != propagate )
6613    {
6614       if( SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM )
6615       {
6616          cons->propagate = propagate;
6617       }
6618       else if( cons->enabled && cons->propenabled )
6619       {
6620          if( propagate )
6621          {
6622             cons->propagate = propagate;
6623             SCIP_CALL( conshdlrAddPropcons(cons->conshdlr, set, cons) );
6624          }
6625          else
6626          {
6627             conshdlrDelPropcons(cons->conshdlr, cons);
6628             cons->propagate = propagate;
6629          }
6630       }
6631    }
6632 
6633    return SCIP_OKAY;
6634 }
6635 
6636 /** sets the local flag of the given constraint */
SCIPconsSetLocal(SCIP_CONS * cons,SCIP_Bool local)6637 void SCIPconsSetLocal(
6638    SCIP_CONS*            cons,               /**< constraint */
6639    SCIP_Bool             local               /**< new value */
6640    )
6641 {
6642    assert(cons != NULL);
6643 
6644    cons->local = local;
6645    if( !local )
6646       cons->validdepth = 0;
6647 }
6648 
6649 /** sets the modifiable flag of the given constraint */
SCIPconsSetModifiable(SCIP_CONS * cons,SCIP_Bool modifiable)6650 void SCIPconsSetModifiable(
6651    SCIP_CONS*            cons,               /**< constraint */
6652    SCIP_Bool             modifiable          /**< new value */
6653    )
6654 {
6655    assert(cons != NULL);
6656 
6657    cons->modifiable = modifiable;
6658 }
6659 
6660 /** sets the dynamic flag of the given constraint */
SCIPconsSetDynamic(SCIP_CONS * cons,SCIP_Bool dynamic)6661 void SCIPconsSetDynamic(
6662    SCIP_CONS*            cons,               /**< constraint */
6663    SCIP_Bool             dynamic             /**< new value */
6664    )
6665 {
6666    assert(cons != NULL);
6667 
6668    cons->dynamic = dynamic;
6669 }
6670 
6671 /** sets the removable flag of the given constraint */
SCIPconsSetRemovable(SCIP_CONS * cons,SCIP_Bool removable)6672 void SCIPconsSetRemovable(
6673    SCIP_CONS*            cons,               /**< constraint */
6674    SCIP_Bool             removable           /**< new value */
6675    )
6676 {
6677    assert(cons != NULL);
6678 
6679    cons->removable = removable;
6680 }
6681 
6682 /** sets the stickingatnode flag of the given constraint */
SCIPconsSetStickingAtNode(SCIP_CONS * cons,SCIP_Bool stickingatnode)6683 void SCIPconsSetStickingAtNode(
6684    SCIP_CONS*            cons,               /**< constraint */
6685    SCIP_Bool             stickingatnode      /**< new value */
6686    )
6687 {
6688    assert(cons != NULL);
6689 
6690    cons->stickingatnode = stickingatnode;
6691 }
6692 
6693 /** gives the constraint a new name; ATTENTION: to old pointer is over written that might
6694  *  result in a memory leakage */
SCIPconsSetNamePointer(SCIP_CONS * cons,const char * name)6695 void SCIPconsSetNamePointer(
6696    SCIP_CONS*            cons,               /**< constraint */
6697    const char*           name                /**< new name of constraint */
6698    )
6699 {
6700    assert( cons != NULL );
6701    assert( name != NULL );
6702 
6703    cons->name = (char*)name;
6704 }
6705 
6706 /** gets associated transformed constraint of an original constraint, or NULL if no associated transformed constraint
6707  *  exists
6708  */
SCIPconsGetTransformed(SCIP_CONS * cons)6709 SCIP_CONS* SCIPconsGetTransformed(
6710    SCIP_CONS*            cons                /**< constraint */
6711    )
6712 {
6713    assert(cons->original);
6714 
6715    return cons->transorigcons;
6716 }
6717 
6718 /** activates constraint or marks constraint to be activated in next update */
SCIPconsActivate(SCIP_CONS * cons,SCIP_SET * set,SCIP_STAT * stat,int depth,SCIP_Bool focusnode)6719 SCIP_RETCODE SCIPconsActivate(
6720    SCIP_CONS*            cons,               /**< constraint */
6721    SCIP_SET*             set,                /**< global SCIP settings */
6722    SCIP_STAT*            stat,               /**< dynamic problem statistics */
6723    int                   depth,              /**< depth in the tree where the constraint activation takes place, or -1 for global problem */
6724    SCIP_Bool             focusnode           /**< does the constraint activation take place at the focus node? */
6725    )
6726 {
6727    assert(cons != NULL);
6728    assert(!cons->original);
6729    assert(!cons->active);
6730    assert(!cons->updateactivate);
6731    assert(!cons->updatedeactivate);
6732    assert(!cons->updateenable);
6733    assert(!cons->updatedisable);
6734    assert(!cons->updateobsolete);
6735    assert(!cons->updatefree);
6736    assert(cons->activedepth == -2);
6737    assert(cons->conshdlr != NULL);
6738    assert(set != NULL);
6739    assert(cons->scip == set->scip);
6740 
6741    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6742    {
6743       SCIPsetDebugMsg(set, "delayed activation of constraint <%s> in constraint handler <%s> (depth %d)\n",
6744          cons->name, cons->conshdlr->name, depth);
6745       cons->updateactivate = TRUE;
6746       cons->activedepth = depth;
6747       cons->updateactfocus = focusnode;
6748       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6749       assert(cons->update);
6750    }
6751    else
6752    {
6753       SCIP_CALL( conshdlrActivateCons(cons->conshdlr, set, stat, cons, depth, focusnode) );
6754       assert(cons->active);
6755    }
6756 
6757    return SCIP_OKAY;
6758 }
6759 
6760 /** deactivates constraint or marks constraint to be deactivated in next update */
SCIPconsDeactivate(SCIP_CONS * cons,SCIP_SET * set,SCIP_STAT * stat)6761 SCIP_RETCODE SCIPconsDeactivate(
6762    SCIP_CONS*            cons,               /**< constraint */
6763    SCIP_SET*             set,                /**< global SCIP settings */
6764    SCIP_STAT*            stat                /**< dynamic problem statistics */
6765    )
6766 {
6767    assert(cons != NULL);
6768    assert(!cons->original);
6769    assert(cons->active);
6770    assert(!cons->updateactivate);
6771    assert(!cons->updatedeactivate);
6772    assert(cons->activedepth >= -1);
6773    assert(cons->conshdlr != NULL);
6774    assert(set != NULL);
6775    assert(cons->scip == set->scip);
6776 
6777    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6778    {
6779       SCIPsetDebugMsg(set, "delayed deactivation of constraint <%s> in constraint handler <%s>\n",
6780          cons->name, cons->conshdlr->name);
6781       cons->updatedeactivate = TRUE;
6782       cons->activedepth = -2;
6783       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6784       assert(cons->update);
6785    }
6786    else
6787    {
6788       SCIP_CALL( conshdlrDeactivateCons(cons->conshdlr, set, stat, cons) );
6789       assert(!cons->active);
6790    }
6791 
6792    return SCIP_OKAY;
6793 }
6794 
6795 /** enables constraint's separation, enforcing, and propagation capabilities or marks them to be enabled in next update */
SCIPconsEnable(SCIP_CONS * cons,SCIP_SET * set,SCIP_STAT * stat)6796 SCIP_RETCODE SCIPconsEnable(
6797    SCIP_CONS*            cons,               /**< constraint */
6798    SCIP_SET*             set,                /**< global SCIP settings */
6799    SCIP_STAT*            stat                /**< dynamic problem statistics */
6800    )
6801 {
6802    assert(cons != NULL);
6803    assert(!cons->original);
6804    assert(cons->conshdlr != NULL);
6805    assert(set != NULL);
6806    assert(cons->scip == set->scip);
6807 
6808    if( !cons->active || cons->updatedeactivate || cons->updateenable || (cons->enabled && !cons->updatedisable) )
6809       return SCIP_OKAY;
6810 
6811    assert(!cons->updateactivate);
6812 
6813    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6814    {
6815       cons->updateenable = TRUE;
6816       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6817       assert(cons->update);
6818    }
6819    else
6820    {
6821       SCIP_CALL( conshdlrEnableCons(cons->conshdlr, set, stat, cons) );
6822       assert(cons->enabled);
6823    }
6824 
6825    return SCIP_OKAY;
6826 }
6827 
6828 /** disables constraint's separation, enforcing, and propagation capabilities or marks them to be disabled in next update */
SCIPconsDisable(SCIP_CONS * cons,SCIP_SET * set,SCIP_STAT * stat)6829 SCIP_RETCODE SCIPconsDisable(
6830    SCIP_CONS*            cons,               /**< constraint */
6831    SCIP_SET*             set,                /**< global SCIP settings */
6832    SCIP_STAT*            stat                /**< dynamic problem statistics */
6833    )
6834 {
6835    assert(cons != NULL);
6836    assert(!cons->original);
6837    assert(cons->conshdlr != NULL);
6838    assert(set != NULL);
6839    assert(cons->scip == set->scip);
6840 
6841    if( cons->updatedisable || (!cons->enabled && !cons->updateenable) )
6842       return SCIP_OKAY;
6843 
6844    assert(cons->active);
6845    assert(!cons->updateactivate);
6846 
6847    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6848    {
6849       cons->updatedisable = TRUE;
6850       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6851       assert(cons->update);
6852    }
6853    else
6854    {
6855       SCIP_CALL( conshdlrDisableCons(cons->conshdlr, set, stat, cons) );
6856       assert(!cons->enabled);
6857    }
6858 
6859    return SCIP_OKAY;
6860 }
6861 
6862 /** enables constraint's separation capabilities or marks them to be enabled in next update */
SCIPconsEnableSeparation(SCIP_CONS * cons,SCIP_SET * set)6863 SCIP_RETCODE SCIPconsEnableSeparation(
6864    SCIP_CONS*            cons,               /**< constraint */
6865    SCIP_SET*             set                 /**< global SCIP settings */
6866    )
6867 {
6868    assert(cons != NULL);
6869    assert(cons->conshdlr != NULL);
6870    assert(set != NULL);
6871    assert(cons->scip == set->scip);
6872 
6873    if( cons->updatesepaenable || (cons->sepaenabled && !cons->updatesepadisable) )
6874       return SCIP_OKAY;
6875 
6876    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6877    {
6878       cons->updatesepadisable = FALSE;
6879       cons->updatesepaenable = TRUE;
6880       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6881       assert(cons->update);
6882    }
6883    else
6884    {
6885       SCIP_CALL( conshdlrEnableConsSeparation(cons->conshdlr, set, cons) );
6886       assert(cons->sepaenabled);
6887    }
6888 
6889    return SCIP_OKAY;
6890 }
6891 
6892 /** disables constraint's separation capabilities or marks them to be disabled in next update */
SCIPconsDisableSeparation(SCIP_CONS * cons,SCIP_SET * set)6893 SCIP_RETCODE SCIPconsDisableSeparation(
6894    SCIP_CONS*            cons,               /**< constraint */
6895    SCIP_SET*             set                 /**< global SCIP settings */
6896    )
6897 {
6898    assert(cons != NULL);
6899    assert(cons->conshdlr != NULL);
6900 
6901    if( cons->updatesepadisable || (!cons->sepaenabled && !cons->updatesepaenable) )
6902       return SCIP_OKAY;
6903 
6904    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6905    {
6906       cons->updatesepaenable = FALSE;
6907       cons->updatesepadisable = TRUE;
6908       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6909       assert(cons->update);
6910    }
6911    else
6912    {
6913       SCIP_CALL( conshdlrDisableConsSeparation(cons->conshdlr, cons) );
6914       assert(!cons->sepaenabled);
6915    }
6916 
6917    return SCIP_OKAY;
6918 }
6919 
6920 /** enables constraint's propagation capabilities or marks them to be enabled in next update */
SCIPconsEnablePropagation(SCIP_CONS * cons,SCIP_SET * set)6921 SCIP_RETCODE SCIPconsEnablePropagation(
6922    SCIP_CONS*            cons,               /**< constraint */
6923    SCIP_SET*             set                 /**< global SCIP settings */
6924    )
6925 {
6926    assert(cons != NULL);
6927    assert(cons->conshdlr != NULL);
6928    assert(set != NULL);
6929    assert(cons->scip == set->scip);
6930 
6931    if( cons->updatepropenable || (cons->propenabled && !cons->updatepropdisable) )
6932       return SCIP_OKAY;
6933 
6934    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6935    {
6936       cons->updatepropdisable = FALSE;
6937       cons->updatepropenable = TRUE;
6938       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6939       assert(cons->update);
6940    }
6941    else
6942    {
6943       SCIP_CALL( conshdlrEnableConsPropagation(cons->conshdlr, set, cons) );
6944       assert(cons->propenabled);
6945    }
6946 
6947    return SCIP_OKAY;
6948 }
6949 
6950 /** disables constraint's propagation capabilities or marks them to be disabled in next update */
SCIPconsDisablePropagation(SCIP_CONS * cons,SCIP_SET * set)6951 SCIP_RETCODE SCIPconsDisablePropagation(
6952    SCIP_CONS*            cons,               /**< constraint */
6953    SCIP_SET*             set                 /**< global SCIP settings */
6954    )
6955 {
6956    assert(cons != NULL);
6957    assert(cons->conshdlr != NULL);
6958    assert(set != NULL);
6959    assert(cons->scip == set->scip);
6960 
6961    if( cons->updatepropdisable || (!cons->propenabled && !cons->updatepropenable) )
6962       return SCIP_OKAY;
6963 
6964    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
6965    {
6966       cons->updatepropenable = FALSE;
6967       cons->updatepropdisable = TRUE;
6968       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
6969       assert(cons->update);
6970    }
6971    else
6972    {
6973       SCIP_CALL( conshdlrDisableConsPropagation(cons->conshdlr, cons) );
6974       assert(!cons->propenabled);
6975    }
6976 
6977    return SCIP_OKAY;
6978 }
6979 
6980 /** marks the constraint to be a conflict */
SCIPconsMarkConflict(SCIP_CONS * cons)6981 void SCIPconsMarkConflict(
6982    SCIP_CONS*            cons                /**< constraint */
6983    )
6984 {
6985    assert(cons != NULL);
6986 
6987    cons->conflict = TRUE;
6988 }
6989 
6990 /** marks the constraint to be propagated (update might be delayed) */
SCIPconsMarkPropagate(SCIP_CONS * cons,SCIP_SET * set)6991 SCIP_RETCODE SCIPconsMarkPropagate(
6992    SCIP_CONS*            cons,               /**< constraint */
6993    SCIP_SET*             set                 /**< global SCIP settings */
6994    )
6995 {
6996    assert(cons != NULL);
6997    assert(cons->conshdlr != NULL);
6998    assert(set != NULL);
6999    assert(cons->scip == set->scip);
7000 
7001    if( cons->updatemarkpropagate || (cons->markpropagate && !cons->updateunmarkpropagate) )
7002          return SCIP_OKAY;
7003 
7004    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
7005    {
7006       cons->updateunmarkpropagate = FALSE;
7007       cons->updatemarkpropagate = TRUE;
7008       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
7009       assert(cons->update);
7010    }
7011    else
7012    {
7013       conshdlrMarkConsPropagate(cons->conshdlr, cons);
7014       assert(cons->markpropagate || !cons->enabled);
7015    }
7016 
7017    return SCIP_OKAY;
7018 }
7019 
7020 /** unmarks the constraint to be propagated (update might be delayed) */
SCIPconsUnmarkPropagate(SCIP_CONS * cons,SCIP_SET * set)7021 SCIP_RETCODE SCIPconsUnmarkPropagate(
7022    SCIP_CONS*            cons,               /**< constraint */
7023    SCIP_SET*             set                 /**< global SCIP settings */
7024    )
7025 {
7026    assert(cons != NULL);
7027    assert(cons->conshdlr != NULL);
7028    assert(set != NULL);
7029    assert(cons->scip == set->scip);
7030 
7031    if( cons->updateunmarkpropagate || (!cons->markpropagate && !cons->updatemarkpropagate) )
7032       return SCIP_OKAY;
7033 
7034    if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
7035    {
7036       cons->updatemarkpropagate = FALSE;
7037       cons->updateunmarkpropagate = TRUE;
7038       SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
7039       assert(cons->update);
7040    }
7041    else
7042    {
7043       conshdlrUnmarkConsPropagate(cons->conshdlr, cons);
7044       assert(!cons->markpropagate || !cons->enabled);
7045    }
7046 
7047    return SCIP_OKAY;
7048 }
7049 
7050 /** adds given value to age of constraint, but age can never become negative;
7051  *  should be called
7052  *   - in constraint separation, if no cut was found for this constraint,
7053  *   - in constraint enforcing, if constraint was feasible, and
7054  *   - in constraint propagation, if no domain reduction was deduced;
7055  *  if it's age exceeds the constraint age limit, makes constraint obsolete or marks constraint to be made obsolete
7056  *  in next update
7057  */
SCIPconsAddAge(SCIP_CONS * cons,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_PROB * prob,SCIP_Real deltaage,SCIP_REOPT * reopt)7058 SCIP_RETCODE SCIPconsAddAge(
7059    SCIP_CONS*            cons,               /**< constraint */
7060    BMS_BLKMEM*           blkmem,             /**< block memory */
7061    SCIP_SET*             set,                /**< global SCIP settings */
7062    SCIP_STAT*            stat,               /**< dynamic problem statistics */
7063    SCIP_PROB*            prob,               /**< problem data */
7064    SCIP_Real             deltaage,           /**< value to add to the constraint's age */
7065    SCIP_REOPT*           reopt               /**< reoptimization data */
7066    )
7067 {
7068    assert(cons != NULL);
7069    assert(cons->conshdlr != NULL);
7070    assert(!cons->updateactivate);
7071    assert(set != NULL);
7072    assert(cons->scip == set->scip);
7073 
7074    /* no aging in presolving */
7075    if( set->stage == SCIP_STAGE_PRESOLVING )
7076       return SCIP_OKAY;
7077 
7078    SCIPsetDebugMsg(set, "adding %g to age (%g) of constraint <%s> of handler <%s>\n",
7079       deltaage, cons->age, cons->name, cons->conshdlr->name);
7080 
7081    cons->age += deltaage;
7082    cons->age = MAX(cons->age, 0.0);
7083 
7084    if( !cons->original )
7085    {
7086       if( !cons->check && consExceedsAgelimit(cons, set) )
7087       {
7088          SCIP_CALL( SCIPconsDelete(cons, blkmem, set, stat, prob, reopt) );
7089       }
7090       else if( !cons->obsolete && consExceedsObsoleteage(cons, set) )
7091       {
7092          if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
7093          {
7094             cons->updateobsolete = TRUE;
7095             SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
7096             assert(cons->update);
7097          }
7098          else
7099          {
7100             SCIP_CALL( conshdlrMarkConsObsolete(cons->conshdlr, cons) );
7101             assert(cons->obsolete);
7102          }
7103       }
7104    }
7105 
7106    return SCIP_OKAY;
7107 }
7108 
7109 /** increases age of constraint by 1.0;
7110  *  should be called
7111  *   - in constraint separation, if no cut was found for this constraint,
7112  *   - in constraint enforcing, if constraint was feasible, and
7113  *   - in constraint propagation, if no domain reduction was deduced;
7114  *  if it's age exceeds the constraint age limit, makes constraint obsolete or marks constraint to be made obsolete
7115  *  in next update
7116  */
SCIPconsIncAge(SCIP_CONS * cons,BMS_BLKMEM * blkmem,SCIP_SET * set,SCIP_STAT * stat,SCIP_PROB * prob,SCIP_REOPT * reopt)7117 SCIP_RETCODE SCIPconsIncAge(
7118    SCIP_CONS*            cons,               /**< constraint */
7119    BMS_BLKMEM*           blkmem,             /**< block memory */
7120    SCIP_SET*             set,                /**< global SCIP settings */
7121    SCIP_STAT*            stat,               /**< dynamic problem statistics */
7122    SCIP_PROB*            prob,               /**< problem data */
7123    SCIP_REOPT*           reopt               /**< reoptimization data */
7124    )
7125 {
7126    SCIP_CALL( SCIPconsAddAge(cons, blkmem, set, stat, prob, 1.0, reopt) );
7127 
7128    return SCIP_OKAY;
7129 }
7130 
7131 /** resets age of constraint to zero;
7132  *  should be called
7133  *   - in constraint separation, if a cut was found for this constraint,
7134  *   - in constraint enforcing, if the constraint was violated, and
7135  *   - in constraint propagation, if a domain reduction was deduced;
7136  *  if it was obsolete, makes constraint useful again or marks constraint to be made useful again in next update
7137  */
SCIPconsResetAge(SCIP_CONS * cons,SCIP_SET * set)7138 SCIP_RETCODE SCIPconsResetAge(
7139    SCIP_CONS*            cons,               /**< constraint */
7140    SCIP_SET*             set                 /**< global SCIP settings */
7141    )
7142 {
7143    assert(cons != NULL);
7144    assert(cons->conshdlr != NULL);
7145    assert(!cons->updateactivate);
7146    assert(set != NULL);
7147    assert(cons->scip == set->scip);
7148 
7149    SCIPsetDebugMsg(set, "resetting age %g of constraint <%s> of handler <%s>\n", cons->age, cons->name, cons->conshdlr->name);
7150 
7151    conshdlrUpdateAgeresetavg(cons->conshdlr, cons->age);
7152    cons->age = 0.0;
7153 
7154    if( cons->obsolete )
7155    {
7156       assert(!cons->original);
7157       if( conshdlrAreUpdatesDelayed(cons->conshdlr) )
7158       {
7159          cons->updateobsolete = TRUE;
7160          SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) );
7161          assert(cons->update);
7162       }
7163       else
7164       {
7165          SCIP_CALL( conshdlrMarkConsUseful(cons->conshdlr, cons) );
7166          assert(!cons->obsolete);
7167       }
7168    }
7169 
7170    return SCIP_OKAY;
7171 }
7172 
7173 /** resolves the given conflicting bound, that was deduced by the given constraint, by putting all "reason" bounds
7174  *  leading to the deduction into the conflict queue with calls to SCIPaddConflictLb(), SCIPaddConflictUb(), SCIPaddConflictBd(),
7175  *  SCIPaddConflictRelaxedLb(), SCIPaddConflictRelaxedUb(), SCIPaddConflictRelaxedBd(), or SCIPaddConflictBinvar();
7176  *
7177  *  @note it is sufficient to explain the relaxed bound change
7178  */
SCIPconsResolvePropagation(SCIP_CONS * cons,SCIP_SET * set,SCIP_VAR * infervar,int inferinfo,SCIP_BOUNDTYPE inferboundtype,SCIP_BDCHGIDX * bdchgidx,SCIP_Real relaxedbd,SCIP_RESULT * result)7179 SCIP_RETCODE SCIPconsResolvePropagation(
7180    SCIP_CONS*            cons,               /**< constraint that deduced the assignment */
7181    SCIP_SET*             set,                /**< global SCIP settings */
7182    SCIP_VAR*             infervar,           /**< variable whose bound was deduced by the constraint */
7183    int                   inferinfo,          /**< user inference information attached to the bound change */
7184    SCIP_BOUNDTYPE        inferboundtype,     /**< bound that was deduced (lower or upper bound) */
7185    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index, representing the point of time where change took place */
7186    SCIP_Real             relaxedbd,          /**< the relaxed bound */
7187    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7188    )
7189 {
7190    SCIP_CONSHDLR* conshdlr;
7191 
7192    assert(set != NULL);
7193    assert(cons != NULL);
7194    assert((inferboundtype == SCIP_BOUNDTYPE_LOWER
7195          && SCIPgetVarLbAtIndex(set->scip, infervar, bdchgidx, TRUE) > SCIPvarGetLbGlobal(infervar))
7196       || (inferboundtype == SCIP_BOUNDTYPE_UPPER
7197          && SCIPgetVarUbAtIndex(set->scip, infervar, bdchgidx, TRUE) < SCIPvarGetUbGlobal(infervar)));
7198    assert(result != NULL);
7199    assert(cons->scip == set->scip);
7200 
7201    *result = SCIP_DIDNOTRUN;
7202 
7203    conshdlr = cons->conshdlr;
7204    assert(conshdlr != NULL);
7205 
7206    if( conshdlr->consresprop != NULL )
7207    {
7208       /* start timing */
7209       SCIPclockStart(conshdlr->resproptime, set);
7210 
7211       SCIP_CALL( conshdlr->consresprop(set->scip, conshdlr, cons, infervar, inferinfo, inferboundtype, bdchgidx,
7212             relaxedbd, result) );
7213 
7214       /* stop timing */
7215       SCIPclockStop(conshdlr->resproptime, set);
7216 
7217       /* update statistics */
7218       conshdlr->nrespropcalls++;
7219 
7220       /* check result code */
7221       if( *result != SCIP_SUCCESS && *result != SCIP_DIDNOTFIND )
7222       {
7223          SCIPerrorMessage("propagation conflict resolving method of constraint handler <%s> returned invalid result <%d>\n",
7224             conshdlr->name, *result);
7225          return SCIP_INVALIDRESULT;
7226       }
7227    }
7228    else
7229    {
7230       SCIPerrorMessage("propagation conflict resolving method of constraint handler <%s> is not implemented\n",
7231          conshdlr->name);
7232       return SCIP_PLUGINNOTFOUND;
7233    }
7234 
7235    return SCIP_OKAY;
7236 }
7237 
7238 /** adds given values to lock status of the constraint and updates the locks of the given locktype of the involved variables */
SCIPconsAddLocks(SCIP_CONS * cons,SCIP_SET * set,SCIP_LOCKTYPE locktype,int nlockspos,int nlocksneg)7239 SCIP_RETCODE SCIPconsAddLocks(
7240    SCIP_CONS*            cons,               /**< constraint */
7241    SCIP_SET*             set,                /**< global SCIP settings */
7242    SCIP_LOCKTYPE         locktype,           /**< type of variable locks */
7243    int                   nlockspos,          /**< increase in number of rounding locks for constraint */
7244    int                   nlocksneg           /**< increase in number of rounding locks for constraint's negation */
7245    )
7246 {
7247    int oldnlockspos;
7248    int oldnlocksneg;
7249    int updlockpos;
7250    int updlockneg;
7251 
7252    assert(cons != NULL);
7253    assert(cons->conshdlr != NULL);
7254    assert(cons->conshdlr->conslock != NULL);
7255    assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
7256    assert(cons->nlockspos[locktype] >= 0);
7257    assert(cons->nlocksneg[locktype] >= 0);
7258    assert(-2 <= nlockspos && nlockspos <= 2);
7259    assert(-2 <= nlocksneg && nlocksneg <= 2);
7260    assert(set != NULL);
7261    assert(cons->scip == set->scip);
7262 
7263    /* update the rounding locks */
7264    oldnlockspos = cons->nlockspos[locktype];
7265    oldnlocksneg = cons->nlocksneg[locktype];
7266    cons->nlockspos[locktype] += nlockspos;
7267    cons->nlocksneg[locktype] += nlocksneg;
7268    assert(cons->nlockspos[locktype] >= 0);
7269    assert(cons->nlocksneg[locktype] >= 0);
7270 
7271    /* check, if the constraint switched from unlocked to locked, or from locked to unlocked */
7272    updlockpos = (int)(cons->nlockspos[locktype] > 0) - (int)(oldnlockspos > 0);
7273    updlockneg = (int)(cons->nlocksneg[locktype] > 0) - (int)(oldnlocksneg > 0);
7274 
7275    /* lock the variables, if the constraint switched from unlocked to locked or from locked to unlocked */
7276    if( updlockpos != 0 || updlockneg != 0 )
7277    {
7278       SCIP_CALL( cons->conshdlr->conslock(set->scip, cons->conshdlr, cons, locktype, updlockpos, updlockneg) );
7279    }
7280 
7281    return SCIP_OKAY;
7282 }
7283 
7284 /** checks single constraint for feasibility of the given solution */
SCIPconsCheck(SCIP_CONS * cons,SCIP_SET * set,SCIP_SOL * sol,SCIP_Bool checkintegrality,SCIP_Bool checklprows,SCIP_Bool printreason,SCIP_RESULT * result)7285 SCIP_RETCODE SCIPconsCheck(
7286    SCIP_CONS*            cons,               /**< constraint to check */
7287    SCIP_SET*             set,                /**< global SCIP settings */
7288    SCIP_SOL*             sol,                /**< primal CIP solution */
7289    SCIP_Bool             checkintegrality,   /**< Has integrality to be checked? */
7290    SCIP_Bool             checklprows,        /**< Do constraints represented by rows in the current LP have to be checked? */
7291    SCIP_Bool             printreason,        /**< Should the reason for the violation be printed? */
7292    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7293    )
7294 {
7295    SCIP_CONSHDLR* conshdlr;
7296 
7297    assert(cons != NULL);
7298    assert(set != NULL);
7299    assert(cons->scip == set->scip);
7300    assert(result != NULL);
7301 
7302    conshdlr = cons->conshdlr;
7303    assert(conshdlr != NULL);
7304 
7305    /* call external method */
7306    assert(conshdlr->conscheck != NULL);
7307 
7308    SCIP_CALL( conshdlr->conscheck(set->scip, conshdlr, &cons, 1, sol, checkintegrality, checklprows, printreason,
7309          FALSE, result) );
7310    SCIPsetDebugMsg(set, " -> checking returned result <%d>\n", *result);
7311 
7312    if( *result != SCIP_INFEASIBLE && *result != SCIP_FEASIBLE )
7313    {
7314       SCIPerrorMessage("feasibility check of constraint handler <%s> on constraint <%s> returned invalid result <%d>\n",
7315          conshdlr->name, cons->name, *result);
7316       return SCIP_INVALIDRESULT;
7317    }
7318 
7319    return SCIP_OKAY;
7320 }
7321 
7322 /** enforces single constraint for a given pseudo solution */
SCIPconsEnfops(SCIP_CONS * cons,SCIP_SET * set,SCIP_Bool solinfeasible,SCIP_Bool objinfeasible,SCIP_RESULT * result)7323 SCIP_RETCODE SCIPconsEnfops(
7324    SCIP_CONS*            cons,               /**< constraint to enforce */
7325    SCIP_SET*             set,                /**< global SCIP settings */
7326    SCIP_Bool             solinfeasible,      /**< was the solution already declared infeasible by a constraint handler? */
7327    SCIP_Bool             objinfeasible,      /**< is the solution infeasible anyway due to violating lower objective bound? */
7328    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7329    )
7330 {
7331    SCIP_CONSHDLR* conshdlr;
7332 
7333    assert(cons != NULL);
7334    assert(set != NULL);
7335    assert(cons->scip == set->scip);
7336    assert(result != NULL);
7337 
7338    conshdlr = cons->conshdlr;
7339    assert(conshdlr != NULL);
7340 
7341    /* call external method */
7342    assert(conshdlr->consenfops != NULL);
7343 
7344    SCIP_CALL( conshdlr->consenfops(set->scip, conshdlr, &cons, 1, 1, solinfeasible, objinfeasible, result) );
7345    SCIPsetDebugMsg(set, " -> enfops returned result <%d>\n", *result);
7346 
7347    if( *result != SCIP_CUTOFF
7348       && *result != SCIP_CONSADDED
7349       && *result != SCIP_REDUCEDDOM
7350       && *result != SCIP_BRANCHED
7351       && *result != SCIP_SOLVELP
7352       && *result != SCIP_INFEASIBLE
7353       && *result != SCIP_FEASIBLE
7354       && *result != SCIP_DIDNOTRUN )
7355    {
7356       SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions returned invalid result <%d>\n",
7357          conshdlr->name, *result);
7358       return SCIP_INVALIDRESULT;
7359    }
7360 
7361    /* do not update statistics */
7362 
7363    return SCIP_OKAY;
7364 }
7365 
7366 /** enforces single constraint for a given LP solution */
SCIPconsEnfolp(SCIP_CONS * cons,SCIP_SET * set,SCIP_Bool solinfeasible,SCIP_RESULT * result)7367 SCIP_RETCODE SCIPconsEnfolp(
7368    SCIP_CONS*            cons,               /**< constraint to enforce */
7369    SCIP_SET*             set,                /**< global SCIP settings */
7370    SCIP_Bool             solinfeasible,      /**< was the solution already declared infeasible by a constraint handler? */
7371    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7372    )
7373 {
7374    SCIP_CONSHDLR* conshdlr;
7375 
7376    assert(cons != NULL);
7377    assert(set != NULL);
7378    assert(cons->scip == set->scip);
7379    assert(result != NULL);
7380 
7381    conshdlr = cons->conshdlr;
7382    assert(conshdlr != NULL);
7383 
7384    /* call external method */
7385    assert(conshdlr->consenfolp != NULL);
7386 
7387    SCIP_CALL( conshdlr->consenfolp(set->scip, conshdlr, &cons, 1, 1, solinfeasible, result) );
7388    SCIPsetDebugMsg(set, " -> enfolp returned result <%d>\n", *result);
7389 
7390    if( *result != SCIP_CUTOFF
7391       && *result != SCIP_CONSADDED
7392       && *result != SCIP_REDUCEDDOM
7393       && *result != SCIP_BRANCHED
7394       && *result != SCIP_SEPARATED
7395       && *result != SCIP_INFEASIBLE
7396       && *result != SCIP_FEASIBLE)
7397    {
7398       SCIPerrorMessage("enforcing method of constraint handler <%s> for LP returned invalid result <%d>\n",
7399          conshdlr->name, *result);
7400       return SCIP_INVALIDRESULT;
7401    }
7402 
7403    /* do not update statistics */
7404 
7405    return SCIP_OKAY;
7406 }
7407 
7408 /** enforces single constraint for a given relaxation solution */
SCIPconsEnforelax(SCIP_CONS * cons,SCIP_SET * set,SCIP_SOL * sol,SCIP_Bool solinfeasible,SCIP_RESULT * result)7409 SCIP_RETCODE SCIPconsEnforelax(
7410    SCIP_CONS*            cons,               /**< constraint to enforce */
7411    SCIP_SET*             set,                /**< global SCIP settings */
7412    SCIP_SOL*             sol,                /**< solution to be enforced */
7413    SCIP_Bool             solinfeasible,      /**< was the solution already declared infeasible by a constraint handler? */
7414    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7415    )
7416 {
7417    SCIP_CONSHDLR* conshdlr;
7418 
7419    assert(cons != NULL);
7420    assert(set != NULL);
7421    assert(cons->scip == set->scip);
7422    assert(sol != NULL);
7423    assert(result != NULL);
7424 
7425    conshdlr = cons->conshdlr;
7426    assert(conshdlr != NULL);
7427 
7428    /* call external method */
7429    assert(conshdlr->consenfolp != NULL);
7430 
7431    SCIP_CALL( conshdlr->consenforelax(set->scip, sol, conshdlr, &cons, 1, 1, solinfeasible, result) );
7432    SCIPdebugMessage(" -> enforelax returned result <%d>\n", *result);
7433 
7434    if( *result != SCIP_CUTOFF
7435       && *result != SCIP_CONSADDED
7436       && *result != SCIP_REDUCEDDOM
7437       && *result != SCIP_BRANCHED
7438       && *result != SCIP_SEPARATED
7439       && *result != SCIP_INFEASIBLE
7440       && *result != SCIP_FEASIBLE)
7441    {
7442       SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation returned invalid result <%d>\n",
7443          conshdlr->name, *result);
7444       return SCIP_INVALIDRESULT;
7445    }
7446 
7447    /* do not update statistics */
7448 
7449    return SCIP_OKAY;
7450 }
7451 
7452 /** calls LP initialization method for single constraint */
SCIPconsInitlp(SCIP_CONS * cons,SCIP_SET * set,SCIP_Bool * infeasible)7453 SCIP_RETCODE SCIPconsInitlp(
7454    SCIP_CONS*            cons,               /**< constraint to initialize */
7455    SCIP_SET*             set,                /**< global SCIP settings */
7456    SCIP_Bool*            infeasible          /**< pointer to store whether infeasibility was detected while building the LP */
7457    )
7458 {
7459    SCIP_CONSHDLR* conshdlr;
7460 
7461    assert(cons != NULL);
7462    assert(set != NULL);
7463    assert(infeasible != NULL);
7464    assert(cons->scip == set->scip);
7465 
7466    conshdlr = cons->conshdlr;
7467    assert(conshdlr != NULL);
7468 
7469    /* call external method */
7470    if( conshdlr->consinitlp != NULL )
7471    {
7472       SCIP_CALL( conshdlr->consinitlp(set->scip, conshdlr, &cons, 1, infeasible) );
7473    }
7474 
7475    return SCIP_OKAY;
7476 }
7477 
7478 /** calls separation method of single constraint for LP solution */
SCIPconsSepalp(SCIP_CONS * cons,SCIP_SET * set,SCIP_RESULT * result)7479 SCIP_RETCODE SCIPconsSepalp(
7480    SCIP_CONS*            cons,               /**< constraint to separate */
7481    SCIP_SET*             set,                /**< global SCIP settings */
7482    SCIP_RESULT*          result              /**< pointer to store the result of the separation call */
7483    )
7484 {
7485    SCIP_CONSHDLR* conshdlr;
7486 
7487    assert(cons != NULL);
7488    assert(set != NULL);
7489    assert(cons->scip == set->scip);
7490    assert(result != NULL);
7491 
7492    conshdlr = cons->conshdlr;
7493    assert(conshdlr != NULL);
7494 
7495    /* call external method */
7496    if( conshdlr->conssepalp != NULL )
7497    {
7498       SCIP_CALL( conshdlr->conssepalp(set->scip, conshdlr, &cons, 1, 1, result) );
7499       SCIPsetDebugMsg(set, " -> sepalp returned result <%d>\n", *result);
7500 
7501       if( *result != SCIP_CUTOFF
7502          && *result != SCIP_CONSADDED
7503          && *result != SCIP_REDUCEDDOM
7504          && *result != SCIP_SEPARATED
7505          && *result != SCIP_NEWROUND
7506          && *result != SCIP_DIDNOTFIND
7507          && *result != SCIP_DIDNOTRUN
7508          && *result != SCIP_DELAYED )
7509       {
7510          SCIPerrorMessage("separation method of constraint handler <%s> returned invalid result <%d>\n", conshdlr->name,
7511             *result);
7512          return SCIP_INVALIDRESULT;
7513       }
7514    }
7515 
7516    return SCIP_OKAY;
7517 }
7518 
7519 /** calls separation method of single constraint for given primal solution */
SCIPconsSepasol(SCIP_CONS * cons,SCIP_SET * set,SCIP_SOL * sol,SCIP_RESULT * result)7520 SCIP_RETCODE SCIPconsSepasol(
7521    SCIP_CONS*            cons,               /**< constraint to separate */
7522    SCIP_SET*             set,                /**< global SCIP settings */
7523    SCIP_SOL*             sol,                /**< primal solution that should be separated */
7524    SCIP_RESULT*          result              /**< pointer to store the result of the separation call */
7525    )
7526 {
7527    SCIP_CONSHDLR* conshdlr;
7528 
7529    assert(cons != NULL);
7530    assert(set != NULL);
7531    assert(cons->scip == set->scip);
7532    assert(sol != NULL);
7533    assert(result != NULL);
7534 
7535    conshdlr = cons->conshdlr;
7536    assert(conshdlr != NULL);
7537 
7538    /* call external method */
7539    if( conshdlr->conssepasol != NULL )
7540    {
7541       SCIP_CALL( conshdlr->conssepasol(set->scip, conshdlr, &cons, 1, 1, sol, result) );
7542       SCIPsetDebugMsg(set, " -> sepasol returned result <%d>\n", *result);
7543 
7544       if( *result != SCIP_CUTOFF
7545          && *result != SCIP_CONSADDED
7546          && *result != SCIP_REDUCEDDOM
7547          && *result != SCIP_SEPARATED
7548          && *result != SCIP_NEWROUND
7549          && *result != SCIP_DIDNOTFIND
7550          && *result != SCIP_DIDNOTRUN
7551          && *result != SCIP_DELAYED )
7552       {
7553          SCIPerrorMessage("separation method of constraint handler for arbitrary primal solution <%s> returned invalid result <%d>\n",
7554             conshdlr->name, *result);
7555          return SCIP_INVALIDRESULT;
7556       }
7557    }
7558 
7559    return SCIP_OKAY;
7560 }
7561 
7562 /** calls domain propagation method of single constraint */
SCIPconsProp(SCIP_CONS * cons,SCIP_SET * set,SCIP_PROPTIMING proptiming,SCIP_RESULT * result)7563 SCIP_RETCODE SCIPconsProp(
7564    SCIP_CONS*            cons,               /**< constraint to propagate */
7565    SCIP_SET*             set,                /**< global SCIP settings */
7566    SCIP_PROPTIMING       proptiming,         /**< current point in the node solving loop */
7567    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7568    )
7569 {
7570    SCIP_CONSHDLR* conshdlr;
7571 
7572    assert(cons != NULL);
7573    assert(set != NULL);
7574    assert(cons->scip == set->scip);
7575    assert(result != NULL);
7576 
7577    conshdlr = cons->conshdlr;
7578    assert(conshdlr != NULL);
7579 
7580    /* call external method */
7581    if( conshdlr->consprop != NULL )
7582    {
7583       SCIP_CALL( conshdlr->consprop(set->scip, conshdlr, &cons, 1, 1, 1, proptiming, result) );
7584       SCIPsetDebugMsg(set, " -> prop returned result <%d>\n", *result);
7585 
7586       if( *result != SCIP_CUTOFF
7587          && *result != SCIP_CONSADDED
7588          && *result != SCIP_REDUCEDDOM
7589          && *result != SCIP_DIDNOTFIND
7590          && *result != SCIP_DIDNOTRUN
7591          && *result != SCIP_DELAYED )
7592       {
7593          SCIPerrorMessage("propagation method of constraint handler <%s> returned invalid result <%d>\n",
7594             conshdlr->name, *result);
7595          return SCIP_INVALIDRESULT;
7596       }
7597    }
7598 
7599    return SCIP_OKAY;
7600 }
7601 
7602 /** resolves propagation conflict of single constraint */
SCIPconsResprop(SCIP_CONS * cons,SCIP_SET * set,SCIP_VAR * infervar,int inferinfo,SCIP_BOUNDTYPE boundtype,SCIP_BDCHGIDX * bdchgidx,SCIP_Real relaxedbd,SCIP_RESULT * result)7603 SCIP_RETCODE SCIPconsResprop(
7604    SCIP_CONS*            cons,               /**< constraint to resolve conflict for */
7605    SCIP_SET*             set,                /**< global SCIP settings */
7606    SCIP_VAR*             infervar,           /**< the conflict variable whose bound change has to be resolved */
7607    int                   inferinfo,          /**< the user information passed to the corresponding SCIPinferVarLbCons() or SCIPinferVarUbCons() call */
7608    SCIP_BOUNDTYPE        boundtype,          /**< the type of the changed bound (lower or upper bound) */
7609    SCIP_BDCHGIDX*        bdchgidx,           /**< the index of the bound change, representing the point of time where the change took place */
7610    SCIP_Real             relaxedbd,          /**< the relaxed bound which is sufficient to be explained */
7611    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7612    )
7613 {
7614    SCIP_CONSHDLR* conshdlr;
7615 
7616    assert(cons != NULL);
7617    assert(set != NULL);
7618    assert(cons->scip == set->scip);
7619    assert(result != NULL);
7620    assert(infervar != NULL);
7621    assert(bdchgidx != NULL);
7622 
7623    conshdlr = cons->conshdlr;
7624    assert(conshdlr != NULL);
7625 
7626    /* call external method */
7627    if( conshdlr->consresprop != NULL )
7628    {
7629       SCIP_CALL( conshdlr->consresprop(set->scip, conshdlr, cons, infervar, inferinfo, boundtype, bdchgidx, relaxedbd, result) );
7630       SCIPsetDebugMsg(set, " -> resprop returned result <%d>\n", *result);
7631 
7632       if( *result != SCIP_SUCCESS
7633          && *result != SCIP_DIDNOTFIND )
7634       {
7635          SCIPerrorMessage("propagation conflict resolving method of constraint handler <%s> returned invalid result <%d>\n",
7636             conshdlr->name, *result);
7637          return SCIP_INVALIDRESULT;
7638       }
7639    }
7640 
7641    return SCIP_OKAY;
7642 }
7643 
7644 /** presolves single constraint */
SCIPconsPresol(SCIP_CONS * cons,SCIP_SET * set,int nrounds,SCIP_PRESOLTIMING timing,int nnewfixedvars,int nnewaggrvars,int nnewchgvartypes,int nnewchgbds,int nnewholes,int nnewdelconss,int nnewaddconss,int nnewupgdconss,int nnewchgcoefs,int nnewchgsides,int * nfixedvars,int * naggrvars,int * nchgvartypes,int * nchgbds,int * naddholes,int * ndelconss,int * naddconss,int * nupgdconss,int * nchgcoefs,int * nchgsides,SCIP_RESULT * result)7645 SCIP_RETCODE SCIPconsPresol(
7646    SCIP_CONS*            cons,               /**< constraint to presolve */
7647    SCIP_SET*             set,                /**< global SCIP settings */
7648    int                   nrounds,            /**< number of presolving rounds already done */
7649    SCIP_PRESOLTIMING     timing,             /**< current presolving timing */
7650    int                   nnewfixedvars,      /**< number of variables fixed since the last call to the presolving method */
7651    int                   nnewaggrvars,       /**< number of variables aggregated since the last call to the presolving method */
7652    int                   nnewchgvartypes,    /**< number of variable type changes since the last call to the presolving method */
7653    int                   nnewchgbds,         /**< number of variable bounds tightened since the last call to the presolving method */
7654    int                   nnewholes,          /**< number of domain holes added since the last call to the presolving method */
7655    int                   nnewdelconss,       /**< number of deleted constraints since the last call to the presolving method */
7656    int                   nnewaddconss,       /**< number of added constraints since the last call to the presolving method */
7657    int                   nnewupgdconss,      /**< number of upgraded constraints since the last call to the presolving method */
7658    int                   nnewchgcoefs,       /**< number of changed coefficients since the last call to the presolving method */
7659    int                   nnewchgsides,       /**< number of changed left or right hand sides since the last call to the presolving method */
7660    int*                  nfixedvars,         /**< pointer to count total number of variables fixed of all presolvers */
7661    int*                  naggrvars,          /**< pointer to count total number of variables aggregated of all presolvers */
7662    int*                  nchgvartypes,       /**< pointer to count total number of variable type changes of all presolvers */
7663    int*                  nchgbds,            /**< pointer to count total number of variable bounds tightened of all presolvers */
7664    int*                  naddholes,          /**< pointer to count total number of domain holes added of all presolvers */
7665    int*                  ndelconss,          /**< pointer to count total number of deleted constraints of all presolvers */
7666    int*                  naddconss,          /**< pointer to count total number of added constraints of all presolvers */
7667    int*                  nupgdconss,         /**< pointer to count total number of upgraded constraints of all presolvers */
7668    int*                  nchgcoefs,          /**< pointer to count total number of changed coefficients of all presolvers */
7669    int*                  nchgsides,          /**< pointer to count total number of changed left/right hand sides of all presolvers */
7670    SCIP_RESULT*          result              /**< pointer to store the result of the callback method */
7671    )
7672 {
7673    SCIP_CONSHDLR* conshdlr;
7674 
7675    assert(cons != NULL);
7676    assert(set != NULL);
7677    assert(cons->scip == set->scip);
7678    assert(nfixedvars != NULL);
7679    assert(naggrvars != NULL);
7680    assert(nchgvartypes != NULL);
7681    assert(nchgbds != NULL);
7682    assert(naddholes != NULL);
7683    assert(ndelconss != NULL);
7684    assert(naddconss != NULL);
7685    assert(nupgdconss != NULL);
7686    assert(nchgcoefs != NULL);
7687    assert(nchgsides != NULL);
7688    assert(result != NULL);
7689 
7690    conshdlr = cons->conshdlr;
7691    assert(conshdlr != NULL);
7692 
7693    /* call external method */
7694    if( conshdlr->conspresol != NULL )
7695    {
7696       SCIP_CALL( conshdlr->conspresol(set->scip, conshdlr, &cons, 1, nrounds,  timing,
7697             nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewholes,  nnewdelconss, nnewaddconss,
7698             nnewupgdconss, nnewchgcoefs, nnewchgsides, nfixedvars, naggrvars, nchgvartypes,
7699             nchgbds, naddholes, ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) );
7700       SCIPsetDebugMsg(set, " -> presol returned result <%d>\n", *result);
7701 
7702       if( *result != SCIP_UNBOUNDED
7703          && *result != SCIP_CUTOFF
7704          && *result != SCIP_SUCCESS
7705          && *result != SCIP_DIDNOTFIND
7706          && *result != SCIP_DIDNOTRUN
7707          && *result != SCIP_DELAYED )
7708       {
7709          SCIPerrorMessage("presolving method of constraint handler <%s> returned invalid result <%d>\n",
7710             conshdlr->name, *result);
7711          return SCIP_INVALIDRESULT;
7712       }
7713    }
7714 
7715    return SCIP_OKAY;
7716 }
7717 
7718 /** calls constraint activation notification method of single constraint */
SCIPconsActive(SCIP_CONS * cons,SCIP_SET * set)7719 SCIP_RETCODE SCIPconsActive(
7720    SCIP_CONS*            cons,               /**< constraint to notify */
7721    SCIP_SET*             set                 /**< global SCIP settings */
7722    )
7723 {
7724    SCIP_CONSHDLR* conshdlr;
7725 
7726    assert(cons != NULL);
7727    assert(set != NULL);
7728    assert(cons->scip == set->scip);
7729 
7730    conshdlr = cons->conshdlr;
7731    assert(conshdlr != NULL);
7732 
7733    /* call external method */
7734    if( conshdlr->consactive != NULL )
7735    {
7736       SCIP_CALL( conshdlr->consactive(set->scip, conshdlr, cons) );
7737    }
7738 
7739    return SCIP_OKAY;
7740 }
7741 
7742 /** calls constraint deactivation notification method of single constraint */
SCIPconsDeactive(SCIP_CONS * cons,SCIP_SET * set)7743 SCIP_RETCODE SCIPconsDeactive(
7744    SCIP_CONS*            cons,               /**< constraint to notify */
7745    SCIP_SET*             set                 /**< global SCIP settings */
7746    )
7747 {
7748    SCIP_CONSHDLR* conshdlr;
7749 
7750    assert(cons != NULL);
7751    assert(set != NULL);
7752    assert(cons->scip == set->scip);
7753 
7754    conshdlr = cons->conshdlr;
7755    assert(conshdlr != NULL);
7756 
7757    /* call external method */
7758    if( conshdlr->consdeactive != NULL )
7759    {
7760       SCIP_CALL( conshdlr->consdeactive(set->scip, conshdlr, cons) );
7761    }
7762 
7763    return SCIP_OKAY;
7764 }
7765 
7766 
7767 
7768 /*
7769  * Hash functions
7770  */
7771 
7772 /** gets the key (i.e. the name) of the given constraint */
SCIP_DECL_HASHGETKEY(SCIPhashGetKeyCons)7773 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyCons)
7774 {  /*lint --e{715}*/
7775    SCIP_CONS* cons = (SCIP_CONS*)elem;
7776 
7777    assert(cons != NULL);
7778    return cons->name;
7779 }
7780 
7781 
7782 /*
7783  * method for arrays of contraint handlers
7784  */
7785 
7786 /** ensures size of storage for propagable constraints with a minimum size of num */
7787 static
ensurePropagationStorage(SCIP_SET * set,SCIP_CONSHDLR * conshdlr,int num)7788 SCIP_RETCODE ensurePropagationStorage(
7789    SCIP_SET*             set,                /**< global SCIP settings */
7790    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
7791    int                   num                 /**< minimum number of entries to store */
7792    )
7793 {
7794    assert(set != NULL);
7795    assert(conshdlr != NULL);
7796 
7797    if( num > conshdlr->storedpropconsssize )
7798    {
7799       int newsize;
7800 
7801       newsize = SCIPsetCalcMemGrowSize(set, num);
7802       SCIP_ALLOC( BMSreallocMemoryArray(&(conshdlr->storedpropconss), newsize) );
7803 
7804       conshdlr->storedpropconsssize = newsize;
7805    }
7806    assert(num <= conshdlr->storedpropconsssize);
7807 
7808    return SCIP_OKAY;
7809 }
7810 
7811 /** stores all constraints marked for propagation away when probing is started */
SCIPconshdlrsStorePropagationStatus(SCIP_SET * set,SCIP_CONSHDLR ** conshdlrs,int nconshdlrs)7812 SCIP_RETCODE SCIPconshdlrsStorePropagationStatus(
7813    SCIP_SET*             set,                /**< global SCIP settings */
7814    SCIP_CONSHDLR**       conshdlrs,          /**< all constraint handlers */
7815    int                   nconshdlrs          /**< number of contraint handlers */
7816    )
7817 {
7818    SCIP_CONSHDLR* conshdlr;
7819    int c;
7820 
7821    assert(set != NULL);
7822    assert(conshdlrs != NULL || nconshdlrs == 0);
7823 
7824    for( c = nconshdlrs - 1; c >= 0; --c )
7825    {
7826       conshdlr = conshdlrs[c]; /*lint !e613*/
7827       assert(conshdlr != NULL);
7828       assert(conshdlr->storednmarkedpropconss == 0);
7829 
7830       if( conshdlr->nmarkedpropconss > 0 )
7831       {
7832          int v;
7833 
7834          SCIP_CALL( ensurePropagationStorage(set, conshdlr, conshdlr->nmarkedpropconss) );
7835          BMScopyMemoryArray(conshdlr->storedpropconss, conshdlr->propconss, conshdlr->nmarkedpropconss);
7836 
7837          conshdlr->storednmarkedpropconss = conshdlr->nmarkedpropconss;
7838          conshdlr->storedpropdomchgcount = conshdlr->lastpropdomchgcount;
7839 
7840          for( v = conshdlr->storednmarkedpropconss - 1; v >= 0; --v )
7841          {
7842             SCIPconsCapture(conshdlr->storedpropconss[v]);
7843          }
7844          /* assert(conshdlr->nmarkedpropconss == 0); this assert does not hold if updates are delayed */
7845       }
7846    }
7847 
7848    return SCIP_OKAY;
7849 }
7850 
7851 /** reset all constraints marked for propagation when probing was finished */
SCIPconshdlrsResetPropagationStatus(SCIP_SET * set,BMS_BLKMEM * blkmem,SCIP_CONSHDLR ** conshdlrs,int nconshdlrs)7852 SCIP_RETCODE SCIPconshdlrsResetPropagationStatus(
7853    SCIP_SET*             set,                /**< global SCIP settings */
7854    BMS_BLKMEM*           blkmem,             /**< block memory */
7855    SCIP_CONSHDLR**       conshdlrs,          /**< all constraint handlers */
7856    int                   nconshdlrs          /**< number of contraint handlers */
7857    )
7858 {
7859    SCIP_CONSHDLR* conshdlr;
7860    int c;
7861 
7862    assert(set != NULL);
7863    assert(blkmem != NULL);
7864    assert(conshdlrs != NULL || nconshdlrs == 0);
7865 
7866    for( c = nconshdlrs - 1; c >= 0; --c )
7867    {
7868       conshdlr = conshdlrs[c]; /*lint !e613*/
7869       assert(conshdlr != NULL);
7870 
7871       if( conshdlr->storednmarkedpropconss > 0 )
7872       {
7873 #ifndef NDEBUG
7874          int ndisabled = 0;
7875 #endif
7876          int v;
7877 
7878          for( v = conshdlr->nmarkedpropconss - 1; v >= 0; --v )
7879          {
7880             SCIP_CALL( SCIPconsUnmarkPropagate(conshdlr->propconss[v], set) );
7881          }
7882 
7883          /* mark all previously marked constraint, which were marked before probing */
7884          for( v = 0; v < conshdlr->storednmarkedpropconss; ++v )
7885          {
7886             SCIP_CONS* cons = conshdlr->storedpropconss[v];
7887             assert(cons != NULL);
7888 
7889             if( cons->enabled && cons->propagate && cons->propenabled )
7890             {
7891                SCIP_CALL( SCIPconsMarkPropagate(cons, set) );
7892             }
7893 #ifndef NDEBUG
7894             else
7895                ++ndisabled;
7896 #endif
7897             SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
7898          } /*lint !e438*/
7899 
7900          assert(conshdlr->storednmarkedpropconss - ndisabled <= conshdlr->npropconss);
7901          assert(conshdlr->nmarkedpropconss + ndisabled >= conshdlr->storednmarkedpropconss || (conshdlrAreUpdatesDelayed(conshdlr) && conshdlr->nupdateconss + ndisabled >= conshdlr->storednmarkedpropconss));
7902 
7903          conshdlr->lastpropdomchgcount = conshdlr->storedpropdomchgcount;
7904          conshdlr->storednmarkedpropconss = 0;
7905       }
7906    }
7907 
7908    return SCIP_OKAY;
7909 }
7910 
7911 /** create linear constraint statistics */
SCIPlinConsStatsCreate(SCIP * scip,SCIP_LINCONSSTATS ** linconsstats)7912 SCIP_RETCODE SCIPlinConsStatsCreate(
7913    SCIP*                 scip,               /**< scip data structure */
7914    SCIP_LINCONSSTATS**   linconsstats        /**< pointer to linear constraint classification statistics */
7915    )
7916 {
7917    assert(linconsstats != NULL);
7918 
7919    SCIP_CALL( SCIPallocBlockMemory(scip, linconsstats) );
7920 
7921    return SCIP_OKAY;
7922 }
7923 
7924 /** free linear constraint statistics */
SCIPlinConsStatsFree(SCIP * scip,SCIP_LINCONSSTATS ** linconsstats)7925 void SCIPlinConsStatsFree(
7926    SCIP*                 scip,               /**< scip data structure */
7927    SCIP_LINCONSSTATS**   linconsstats        /**< pointer to linear constraint classification statistics */
7928    )
7929 {
7930    assert(linconsstats != NULL);
7931    assert(*linconsstats != NULL);
7932 
7933    SCIPfreeBlockMemory(scip, linconsstats);
7934 }
7935 
7936 /** resets linear constraint statistics */
SCIPlinConsStatsReset(SCIP_LINCONSSTATS * linconsstats)7937 void SCIPlinConsStatsReset(
7938    SCIP_LINCONSSTATS*    linconsstats        /**< linear constraint classification statistics */
7939    )
7940 {
7941    BMSclearMemoryArray(linconsstats->counter, SCIP_NLINCONSTYPES);
7942    linconsstats->sum = 0;
7943 }
7944 
7945 /** returns the number of occurrences of a specific type of linear constraint */
SCIPlinConsStatsGetTypeCount(SCIP_LINCONSSTATS * linconsstats,SCIP_LINCONSTYPE linconstype)7946 int SCIPlinConsStatsGetTypeCount(
7947    SCIP_LINCONSSTATS*    linconsstats,       /**< linear constraint classification statistics */
7948    SCIP_LINCONSTYPE      linconstype         /**< linear constraint type */
7949    )
7950 {
7951    assert(linconsstats != NULL);
7952    assert(0 <= (int)linconstype && (int)linconstype < SCIP_NLINCONSTYPES); /*lint !e587 !e685 !e568*/
7953    assert(linconsstats->counter != NULL);
7954 
7955    return linconsstats->counter[(int)linconstype];
7956 }
7957 
7958 /** returns the total number of classified constraints */
SCIPlinConsStatsGetSum(SCIP_LINCONSSTATS * linconsstats)7959 int SCIPlinConsStatsGetSum(
7960    SCIP_LINCONSSTATS*    linconsstats        /**< linear constraint classification statistics */
7961    )
7962 {
7963    assert(linconsstats != NULL);
7964 
7965    return linconsstats->sum;
7966 }
7967 
7968 /** increases the number of occurrences of a specific type of linear constraint */
SCIPlinConsStatsIncTypeCount(SCIP_LINCONSSTATS * linconsstats,SCIP_LINCONSTYPE linconstype,int increment)7969 void SCIPlinConsStatsIncTypeCount(
7970    SCIP_LINCONSSTATS*    linconsstats,       /**< linear constraint classification statistics */
7971    SCIP_LINCONSTYPE      linconstype,        /**< linear constraint type */
7972    int                   increment           /**< positive increment */
7973    )
7974 {
7975    assert(linconsstats != NULL);
7976    assert(increment >= 1);
7977    assert(0 <= (int)linconstype && (int)linconstype < SCIP_NLINCONSTYPES); /*lint !e587 !e685 !e568*/
7978    assert(linconsstats->counter != NULL);
7979 
7980    linconsstats->counter[(int)linconstype] += increment;
7981    linconsstats->sum += increment;
7982 }
7983 
7984 /** print linear constraint classification statistics */
SCIPprintLinConsStats(SCIP * scip,FILE * file,SCIP_LINCONSSTATS * linconsstats)7985 void SCIPprintLinConsStats(
7986    SCIP*                 scip,               /**< scip data structure */
7987    FILE*                 file,               /**< file handle or NULL to print to standard out */
7988    SCIP_LINCONSSTATS*    linconsstats        /**< linear constraint classification statistics */
7989    )
7990 {
7991    assert(scip != NULL);
7992    assert(linconsstats != NULL);
7993 
7994    /* print statistics */
7995    SCIPinfoMessage(scip, file, "\n");
7996    SCIPinfoMessage(scip, file, "%-19s : %10s\n", "Linear cons types", "count");
7997    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "total", SCIPlinConsStatsGetSum(linconsstats));
7998    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "empty",        SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_EMPTY));
7999    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "free",         SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_FREE));
8000    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "singleton",    SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON));
8001    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "aggregation",  SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_AGGREGATION));
8002    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "precedence",   SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_PRECEDENCE));
8003    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "varbound",     SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_VARBOUND));
8004    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "setpartition", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPARTITION));
8005    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "setpacking",   SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPACKING));
8006    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "setcovering",  SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SETCOVERING));
8007    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "cardinality",  SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_CARDINALITY));
8008    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "invknapsack",  SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_INVKNAPSACK));
8009    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "eqknapsack",   SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_EQKNAPSACK));
8010    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "binpacking",   SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_BINPACKING));
8011    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "knapsack",     SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_KNAPSACK));
8012    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "intknapsack",  SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_INTKNAPSACK));
8013    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "mixedbinary",  SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY));
8014    SCIPinfoMessage(scip, file, "  %-17s : %10d\n", "general",      SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL));
8015    SCIPinfoMessage(scip, file, "\n");
8016 }
8017 
8018 /*
8019  * simple functions implemented as defines
8020  */
8021 
8022 /* In debug mode, the following methods are implemented as function calls to ensure
8023  * type validity.
8024  * In optimized mode, the methods are implemented as defines to improve performance.
8025  * However, we want to have them in the library anyways, so we have to undef the defines.
8026  */
8027 
8028 #undef SCIPconsGetName
8029 #undef SCIPconsGetPos
8030 #undef SCIPconsGetHdlr
8031 #undef SCIPconsGetData
8032 #undef SCIPconsGetNUses
8033 #undef SCIPconsGetActiveDepth
8034 #undef SCIPconsGetValidDepth
8035 #undef SCIPconsIsActive
8036 #undef SCIPconsIsEnabled
8037 #undef SCIPconsIsSeparationEnabled
8038 #undef SCIPconsIsPropagationEnabled
8039 #undef SCIPconsIsDeleted
8040 #undef SCIPconsIsObsolete
8041 #undef SCIPconsIsConflict
8042 #undef SCIPconsGetAge
8043 #undef SCIPconsIsInitial
8044 #undef SCIPconsIsSeparated
8045 #undef SCIPconsIsEnforced
8046 #undef SCIPconsIsChecked
8047 #undef SCIPconsIsMarkedPropagate
8048 #undef SCIPconsIsPropagated
8049 #undef SCIPconsIsGlobal
8050 #undef SCIPconsIsLocal
8051 #undef SCIPconsIsModifiable
8052 #undef SCIPconsIsDynamic
8053 #undef SCIPconsIsRemovable
8054 #undef SCIPconsIsStickingAtNode
8055 #undef SCIPconsIsInProb
8056 #undef SCIPconsIsOriginal
8057 #undef SCIPconsIsTransformed
8058 #undef SCIPconsIsLockedPos
8059 #undef SCIPconsIsLockedNeg
8060 #undef SCIPconsIsLocked
8061 #undef SCIPconsGetNLocksPos
8062 #undef SCIPconsGetNLocksNeg
8063 #undef SCIPconsIsLockedTypePos
8064 #undef SCIPconsIsLockedTypeNeg
8065 #undef SCIPconsIsLockedType
8066 #undef SCIPconsGetNLocksTypePos
8067 #undef SCIPconsGetNLocksTypeNeg
8068 #undef SCIPconsIsAdded
8069 #undef SCIPconsGetNUpgradeLocks
8070 
8071 /** returns the name of the constraint
8072  *
8073  *  @note to change the name of a constraint, use SCIPchgConsName() from scip.h
8074  */
SCIPconsGetName(SCIP_CONS * cons)8075 const char* SCIPconsGetName(
8076    SCIP_CONS*            cons                /**< constraint */
8077    )
8078 {
8079    assert(cons != NULL);
8080 
8081    return cons->name;
8082 }
8083 
8084 /** returns the position of constraint in the corresponding handler's conss array */
SCIPconsGetPos(SCIP_CONS * cons)8085 int SCIPconsGetPos(
8086    SCIP_CONS*            cons                /**< constraint */
8087    )
8088 {
8089    assert(cons != NULL);
8090 
8091    return cons->consspos;
8092 }
8093 
8094 /** returns the constraint handler of the constraint */
SCIPconsGetHdlr(SCIP_CONS * cons)8095 SCIP_CONSHDLR* SCIPconsGetHdlr(
8096    SCIP_CONS*            cons                /**< constraint */
8097    )
8098 {
8099    assert(cons != NULL);
8100 
8101    return cons->conshdlr;
8102 }
8103 
8104 /** returns the constraint data field of the constraint */
SCIPconsGetData(SCIP_CONS * cons)8105 SCIP_CONSDATA* SCIPconsGetData(
8106    SCIP_CONS*            cons                /**< constraint */
8107    )
8108 {
8109    assert(cons != NULL);
8110 
8111    return cons->consdata;
8112 }
8113 
8114 /** gets number of times, the constraint is currently captured */
SCIPconsGetNUses(SCIP_CONS * cons)8115 int SCIPconsGetNUses(
8116    SCIP_CONS*            cons                /**< constraint */
8117    )
8118 {
8119    assert(cons != NULL);
8120 
8121    return cons->nuses;
8122 }
8123 
8124 /** for an active constraint, returns the depth in the tree at which the constraint was activated */
SCIPconsGetActiveDepth(SCIP_CONS * cons)8125 int SCIPconsGetActiveDepth(
8126    SCIP_CONS*            cons                /**< constraint */
8127    )
8128 {
8129    assert(cons != NULL);
8130    assert(SCIPconsIsActive(cons));
8131 
8132    return cons->activedepth;
8133 }
8134 
8135 /** returns TRUE iff constraint is active in the current node */
SCIPconsIsActive(SCIP_CONS * cons)8136 SCIP_Bool SCIPconsIsActive(
8137    SCIP_CONS*            cons                /**< constraint */
8138    )
8139 {
8140    assert(cons != NULL);
8141 
8142    return cons->updateactivate || (cons->active && !cons->updatedeactivate);
8143 }
8144 
8145 /** returns TRUE iff constraint is active in the current node */
SCIPconsIsUpdatedeactivate(SCIP_CONS * cons)8146 SCIP_Bool SCIPconsIsUpdatedeactivate(
8147    SCIP_CONS*            cons                /**< constraint */
8148    )
8149 {
8150    assert(cons != NULL);
8151 
8152    return cons->updatedeactivate;
8153 }
8154 
8155 /** returns the depth in the tree at which the constraint is valid; returns INT_MAX, if the constraint is local
8156  *  and currently not active
8157  */
SCIPconsGetValidDepth(SCIP_CONS * cons)8158 int SCIPconsGetValidDepth(
8159    SCIP_CONS*            cons                /**< constraint */
8160    )
8161 {
8162    assert(cons != NULL);
8163    assert(cons->validdepth == 0 || cons->local);
8164 
8165    return (!cons->local ? 0
8166       : !SCIPconsIsActive(cons) ? INT_MAX
8167       : cons->validdepth == -1 ? SCIPconsGetActiveDepth(cons)
8168       : cons->validdepth);
8169 }
8170 
8171 /** returns TRUE iff constraint is enabled in the current node */
SCIPconsIsEnabled(SCIP_CONS * cons)8172 SCIP_Bool SCIPconsIsEnabled(
8173    SCIP_CONS*            cons                /**< constraint */
8174    )
8175 {
8176    assert(cons != NULL);
8177 
8178    return cons->updateenable || (cons->enabled && !cons->updatedisable);
8179 }
8180 
8181 /** returns TRUE iff constraint's separation is enabled in the current node */
SCIPconsIsSeparationEnabled(SCIP_CONS * cons)8182 SCIP_Bool SCIPconsIsSeparationEnabled(
8183    SCIP_CONS*            cons                /**< constraint */
8184    )
8185 {
8186    assert(cons != NULL);
8187 
8188    return SCIPconsIsEnabled(cons)
8189       && (cons->updatesepaenable || (cons->sepaenabled && !cons->updatesepadisable));
8190 }
8191 
8192 /** returns TRUE iff constraint's propagation is enabled in the current node */
SCIPconsIsPropagationEnabled(SCIP_CONS * cons)8193 SCIP_Bool SCIPconsIsPropagationEnabled(
8194    SCIP_CONS*            cons                /**< constraint */
8195    )
8196 {
8197    assert(cons != NULL);
8198 
8199    return SCIPconsIsEnabled(cons)
8200       && (cons->updatepropenable || (cons->propenabled && !cons->updatepropdisable));
8201 }
8202 
8203 /** returns TRUE iff constraint is deleted or marked to be deleted */
SCIPconsIsDeleted(SCIP_CONS * cons)8204 SCIP_Bool SCIPconsIsDeleted(
8205    SCIP_CONS*            cons                /**< constraint */
8206    )
8207 {
8208    assert(cons != NULL);
8209 
8210    return cons->deleted;
8211 }
8212 
8213 /** returns TRUE iff constraint is marked obsolete */
SCIPconsIsObsolete(SCIP_CONS * cons)8214 SCIP_Bool SCIPconsIsObsolete(
8215    SCIP_CONS*            cons                /**< constraint */
8216    )
8217 {
8218    assert(cons != NULL);
8219 
8220    return cons->updateobsolete || cons->obsolete;
8221 }
8222 
8223 /** returns TRUE iff constraint is marked as a conflict */
SCIPconsIsConflict(SCIP_CONS * cons)8224 SCIP_Bool SCIPconsIsConflict(
8225    SCIP_CONS*            cons                /**< constraint */
8226    )
8227 {
8228    assert(cons != NULL);
8229 
8230    return cons->conflict;
8231 }
8232 
8233 /** gets age of constraint */
SCIPconsGetAge(SCIP_CONS * cons)8234 SCIP_Real SCIPconsGetAge(
8235    SCIP_CONS*            cons                /**< constraint */
8236    )
8237 {
8238    assert(cons != NULL);
8239 
8240    return cons->age;
8241 }
8242 
8243 /** returns TRUE iff the LP relaxation of constraint should be in the initial LP */
SCIPconsIsInitial(SCIP_CONS * cons)8244 SCIP_Bool SCIPconsIsInitial(
8245    SCIP_CONS*            cons                /**< constraint */
8246    )
8247 {
8248    assert(cons != NULL);
8249 
8250    return cons->initial;
8251 }
8252 
8253 /** returns TRUE iff constraint should be separated during LP processing */
SCIPconsIsSeparated(SCIP_CONS * cons)8254 SCIP_Bool SCIPconsIsSeparated(
8255    SCIP_CONS*            cons                /**< constraint */
8256    )
8257 {
8258    assert(cons != NULL);
8259 
8260    return cons->separate;
8261 }
8262 
8263 /** returns TRUE iff constraint should be enforced during node processing */
SCIPconsIsEnforced(SCIP_CONS * cons)8264 SCIP_Bool SCIPconsIsEnforced(
8265    SCIP_CONS*            cons                /**< constraint */
8266    )
8267 {
8268    assert(cons != NULL);
8269 
8270    return cons->enforce;
8271 }
8272 
8273 /** returns TRUE iff constraint should be checked for feasibility */
SCIPconsIsChecked(SCIP_CONS * cons)8274 SCIP_Bool SCIPconsIsChecked(
8275    SCIP_CONS*            cons                /**< constraint */
8276    )
8277 {
8278    assert(cons != NULL);
8279 
8280    return cons->check;
8281 }
8282 
8283 /** returns whether the constraint is marked for propagation */
SCIPconsIsMarkedPropagate(SCIP_CONS * cons)8284 SCIP_Bool SCIPconsIsMarkedPropagate(
8285    SCIP_CONS*            cons                /**< constraint */
8286    )
8287 {
8288    assert(cons != NULL);
8289 
8290    return (cons->updatemarkpropagate || (cons->markpropagate && !cons->updateunmarkpropagate));
8291 }
8292 
8293 /** returns TRUE iff constraint should be propagated during node processing */
SCIPconsIsPropagated(SCIP_CONS * cons)8294 SCIP_Bool SCIPconsIsPropagated(
8295    SCIP_CONS*            cons                /**< constraint */
8296    )
8297 {
8298    assert(cons != NULL);
8299 
8300    return cons->propagate;
8301 }
8302 
8303 /** returns TRUE iff constraint is globally valid */
SCIPconsIsGlobal(SCIP_CONS * cons)8304 SCIP_Bool SCIPconsIsGlobal(
8305    SCIP_CONS*            cons                /**< constraint */
8306    )
8307 {
8308    assert(cons != NULL);
8309 
8310    return !cons->local;
8311 }
8312 
8313 /** returns TRUE iff constraint is only locally valid or not added to any (sub)problem */
SCIPconsIsLocal(SCIP_CONS * cons)8314 SCIP_Bool SCIPconsIsLocal(
8315    SCIP_CONS*            cons                /**< constraint */
8316    )
8317 {
8318    assert(cons != NULL);
8319 
8320    return cons->local;
8321 }
8322 
8323 /** returns TRUE iff constraint is modifiable (subject to column generation) */
SCIPconsIsModifiable(SCIP_CONS * cons)8324 SCIP_Bool SCIPconsIsModifiable(
8325    SCIP_CONS*            cons                /**< constraint */
8326    )
8327 {
8328    assert(cons != NULL);
8329 
8330    return cons->modifiable;
8331 }
8332 
8333 /** returns TRUE iff constraint is subject to aging */
SCIPconsIsDynamic(SCIP_CONS * cons)8334 SCIP_Bool SCIPconsIsDynamic(
8335    SCIP_CONS*            cons                /**< constraint */
8336    )
8337 {
8338    assert(cons != NULL);
8339 
8340    return cons->dynamic;
8341 }
8342 
8343 /** returns TRUE iff constraint's relaxation should be removed from the LP due to aging or cleanup */
SCIPconsIsRemovable(SCIP_CONS * cons)8344 SCIP_Bool SCIPconsIsRemovable(
8345    SCIP_CONS*            cons                /**< constraint */
8346    )
8347 {
8348    assert(cons != NULL);
8349 
8350    return cons->removable;
8351 }
8352 
8353 /** returns TRUE iff constraint's relaxation should be removed from the LP due to aging or cleanup */
SCIPconsIsStickingAtNode(SCIP_CONS * cons)8354 SCIP_Bool SCIPconsIsStickingAtNode(
8355    SCIP_CONS*            cons                /**< constraint */
8356    )
8357 {
8358    assert(cons != NULL);
8359 
8360    return cons->stickingatnode;
8361 }
8362 
8363 /** returns TRUE iff constraint belongs to the global problem */
SCIPconsIsInProb(SCIP_CONS * cons)8364 SCIP_Bool SCIPconsIsInProb(
8365    SCIP_CONS*            cons                /**< constraint */
8366    )
8367 {
8368    assert(cons != NULL);
8369 
8370    return (cons->addconssetchg == NULL && cons->addarraypos >= 0);
8371 }
8372 
8373 /** returns TRUE iff constraint is belonging to original space */
SCIPconsIsOriginal(SCIP_CONS * cons)8374 SCIP_Bool SCIPconsIsOriginal(
8375    SCIP_CONS*            cons                /**< constraint */
8376    )
8377 {
8378    assert(cons != NULL);
8379 
8380    return cons->original;
8381 }
8382 
8383 /** returns TRUE iff constraint is belonging to transformed space */
SCIPconsIsTransformed(SCIP_CONS * cons)8384 SCIP_Bool SCIPconsIsTransformed(
8385    SCIP_CONS*            cons                /**< constraint */
8386    )
8387 {
8388    assert(cons != NULL);
8389 
8390    return !cons->original;
8391 }
8392 
8393 /** returns TRUE iff roundings for variables in constraint are locked */
SCIPconsIsLockedPos(SCIP_CONS * cons)8394 SCIP_Bool SCIPconsIsLockedPos(
8395    SCIP_CONS*            cons                /**< constraint */
8396    )
8397 {
8398    assert(cons != NULL);
8399 
8400    return (cons->nlockspos[SCIP_LOCKTYPE_MODEL] > 0);
8401 }
8402 
8403 /** returns TRUE iff roundings for variables in constraint's negation are locked */
SCIPconsIsLockedNeg(SCIP_CONS * cons)8404 SCIP_Bool SCIPconsIsLockedNeg(
8405    SCIP_CONS*            cons                /**< constraint */
8406    )
8407 {
8408    assert(cons != NULL);
8409 
8410    return (cons->nlocksneg[SCIP_LOCKTYPE_MODEL] > 0);
8411 }
8412 
8413 /** returns TRUE iff roundings for variables in constraint or in constraint's negation are locked */
SCIPconsIsLocked(SCIP_CONS * cons)8414 SCIP_Bool SCIPconsIsLocked(
8415    SCIP_CONS*            cons                /**< constraint */
8416    )
8417 {
8418    assert(cons != NULL);
8419 
8420    return (cons->nlockspos[SCIP_LOCKTYPE_MODEL] > 0 || cons->nlocksneg[SCIP_LOCKTYPE_MODEL] > 0);
8421 }
8422 
8423 /** get number of times the roundings for variables in constraint are locked */
SCIPconsGetNLocksPos(SCIP_CONS * cons)8424 int SCIPconsGetNLocksPos(
8425    SCIP_CONS*            cons                /**< constraint */
8426    )
8427 {
8428    assert(cons != NULL);
8429 
8430    return cons->nlockspos[SCIP_LOCKTYPE_MODEL];
8431 }
8432 
8433 /** get number of times the roundings for variables in constraint's negation are locked */
SCIPconsGetNLocksNeg(SCIP_CONS * cons)8434 int SCIPconsGetNLocksNeg(
8435    SCIP_CONS*            cons                /**< constraint */
8436    )
8437 {
8438    assert(cons != NULL);
8439 
8440    return cons->nlocksneg[SCIP_LOCKTYPE_MODEL];
8441 }
8442 
8443 /** returns TRUE iff roundings of the given locktype for variables in constraint are locked */
SCIPconsIsLockedTypePos(SCIP_CONS * cons,SCIP_LOCKTYPE locktype)8444 SCIP_Bool SCIPconsIsLockedTypePos(
8445    SCIP_CONS*            cons,               /**< constraint */
8446    SCIP_LOCKTYPE         locktype            /**< variable lock type */
8447    )
8448 {
8449    assert(cons != NULL);
8450    assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
8451 
8452    return (cons->nlockspos[locktype] > 0);
8453 }
8454 
8455 /** returns TRUE iff roundings of the given locktype for variables in constraint are locked */
SCIPconsIsLockedTypeNeg(SCIP_CONS * cons,SCIP_LOCKTYPE locktype)8456 SCIP_Bool SCIPconsIsLockedTypeNeg(
8457    SCIP_CONS*            cons,               /**< constraint */
8458    SCIP_LOCKTYPE         locktype            /**< variable lock type */
8459    )
8460 {
8461    assert(cons != NULL);
8462    assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
8463 
8464    return (cons->nlocksneg[locktype] > 0);
8465 }
8466 
8467 /** returns TRUE iff roundings of given locktype for variables in constraint or in constraint's negation are locked */
SCIPconsIsLockedType(SCIP_CONS * cons,SCIP_LOCKTYPE locktype)8468 SCIP_Bool SCIPconsIsLockedType(
8469    SCIP_CONS*            cons,               /**< constraint */
8470    SCIP_LOCKTYPE         locktype            /**< variable lock type */
8471    )
8472 {
8473    assert(cons != NULL);
8474    assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
8475 
8476    return (cons->nlockspos[locktype] > 0 || cons->nlocksneg[locktype] > 0);
8477 }
8478 
8479 /** get number of times the roundings of given locktype for variables in constraint are locked */
SCIPconsGetNLocksTypePos(SCIP_CONS * cons,SCIP_LOCKTYPE locktype)8480 int SCIPconsGetNLocksTypePos(
8481    SCIP_CONS*            cons,               /**< constraint */
8482    SCIP_LOCKTYPE         locktype            /**< variable lock type */
8483    )
8484 {
8485    assert(cons != NULL);
8486    assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
8487 
8488    return cons->nlockspos[locktype];
8489 }
8490 
8491 /** get number of times the roundings of given locktype for variables in constraint's negation are locked */
SCIPconsGetNLocksTypeNeg(SCIP_CONS * cons,SCIP_LOCKTYPE locktype)8492 int SCIPconsGetNLocksTypeNeg(
8493    SCIP_CONS*            cons,               /**< constraint */
8494    SCIP_LOCKTYPE         locktype            /**< variable lock type */
8495    )
8496 {
8497    assert(cons != NULL);
8498    assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/
8499 
8500    return cons->nlocksneg[locktype];
8501 }
8502 
8503 /** returns if the constraint was already added to a SCIP instance */
SCIPconsIsAdded(SCIP_CONS * cons)8504 SCIP_Bool SCIPconsIsAdded(
8505    SCIP_CONS*            cons                /**< constraint */
8506    )
8507 {
8508    assert(cons != NULL);
8509 
8510    return (cons->addarraypos >= 0);
8511 }
8512 
8513 /** adds locks to (dis-)allow upgrading of constraint */
SCIPconsAddUpgradeLocks(SCIP_CONS * cons,int nlocks)8514 void SCIPconsAddUpgradeLocks(
8515    SCIP_CONS*            cons,               /**< constraint to add locks */
8516    int                   nlocks              /**< number of locks to add */
8517    )
8518 {
8519    assert(cons != NULL);
8520 
8521    assert(cons->nupgradelocks < (1 << 28) - nlocks); /*lint !e574*/
8522    cons->nupgradelocks += (unsigned int) nlocks;
8523 }
8524 
8525 /** gets number of locks against upgrading the constraint, 0 means this constraint can be upgraded */
SCIPconsGetNUpgradeLocks(SCIP_CONS * cons)8526 int SCIPconsGetNUpgradeLocks(
8527    SCIP_CONS*            cons                /**< constraint */
8528    )
8529 {
8530    assert(cons != NULL);
8531 
8532    return (int) cons->nupgradelocks;
8533 }
8534