Scippy

SCIP

Solving Constraint Integer Programs

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