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