Scippy

SCIP

Solving Constraint Integer Programs

cons_bounddisjunction.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-2025 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_bounddisjunction.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief constraint handler for bound disjunction constraints \f$(x_1 \{\leq,\geq\} b_1) \vee \ldots \vee (x_n \{\leq,\geq\} b_n)\f$
28 * @author Tobias Achterberg
29 * @author Marc Pfetsch
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
36#include "scip/cons_linear.h"
37#include "scip/cons_logicor.h"
38#include "scip/cons_setppc.h"
39#include "scip/expr_pow.h"
40#include "scip/expr_var.h"
41#include "scip/pub_conflict.h"
42#include "scip/pub_cons.h"
43#include "scip/pub_event.h"
44#include "scip/pub_lp.h"
45#include "scip/pub_message.h"
46#include "scip/pub_misc.h"
47#include "scip/pub_var.h"
48#include "scip/scip_branch.h"
49#include "scip/scip_conflict.h"
50#include "scip/scip_cons.h"
51#include "scip/scip_copy.h"
52#include "scip/scip_event.h"
53#include "scip/scip_expr.h"
54#include "scip/scip_general.h"
55#include "scip/scip_mem.h"
56#include "scip/scip_message.h"
57#include "scip/scip_nlp.h"
58#include "scip/scip_numerics.h"
59#include "scip/scip_param.h"
60#include "scip/scip_prob.h"
61#include "scip/scip_probing.h"
62#include "scip/scip_sol.h"
64#include "scip/scip_tree.h"
65#include "scip/scip_var.h"
66#include "scip/symmetry_graph.h"
68#include <string.h>
69
70/**@name Constraint handler properties
71 *
72 * @{
73 */
74#define CONSHDLR_NAME "bounddisjunction"
75#define CONSHDLR_DESC "bound disjunction constraints"
76#define CONSHDLR_ENFOPRIORITY -3000000 /**< priority of the constraint handler for constraint enforcing */
77#define CONSHDLR_CHECKPRIORITY -3000000 /**< priority of the constraint handler for checking feasibility */
78#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
79#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
80 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
81#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
82#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
83#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
84
85#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
86#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
87
88/**@} */
89
90/**@name Event handler properties
91 *
92 * @{
93 */
94
95#define EVENTHDLR_NAME "bounddisjunction"
96#define EVENTHDLR_DESC "event handler for bound disjunction constraints"
97
98/**@} */
99
100/**@name Conflict handler properties
101 *
102 * @{
103 */
104
105#define CONFLICTHDLR_NAME "bounddisjunction"
106#define CONFLICTHDLR_DESC "conflict handler creating bound disjunction constraints"
107#define CONFLICTHDLR_PRIORITY -3000000
108
109/**@} */
110
111/**@name Default parameter values
112 *
113 * @{
114 */
115
116#define DEFAULT_CONTINUOUSFRAC 0.4 /**< maximal percantage of continuous variables within a conflict */
117
118/**@} */
119
120/**@name Age increase defines
121 *
122 * @{
123 */
124
125/* @todo make this a parameter setting */
126#if 1 /* @todo test which AGEINCREASE formula is better! */
127#define AGEINCREASE(n) (1.0 + 0.2*n)
128#else
129#define AGEINCREASE(n) (0.1*n)
130#endif
131
132/**@} */
133
134
135/**@name Comparison for two values
136 *
137 * @{
138 */
139
140#ifdef SCIP_DISABLED_CODE /* These only work if one also passes integral values in case of integral variables. This is not always the case and not even asserted. */
141/** use defines for numeric compare methods to be slightly faster for integral values */
142#define isFeasLT(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val2) - (val1) > 0.5 : SCIPisFeasLT(scip, val1, val2))
143#define isFeasLE(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val2) - (val1) > -0.5 : SCIPisFeasLE(scip, val1, val2))
144#define isFeasGT(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val1) - (val2) > 0.5 : SCIPisFeasGT(scip, val1, val2))
145#define isFeasGE(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val1) - (val2) > -0.5 : SCIPisFeasGE(scip, val1, val2))
146#else
147#define isFeasLT(scip, var, val1, val2) SCIPisFeasLT(scip, val1, val2)
148#define isFeasLE(scip, var, val1, val2) SCIPisFeasLE(scip, val1, val2)
149#define isFeasGT(scip, var, val1, val2) SCIPisFeasGT(scip, val1, val2)
150#define isFeasGE(scip, var, val1, val2) SCIPisFeasGE(scip, val1, val2)
151#endif
152/**@} */
153
154
155/** constraint handler data */
156struct SCIP_ConshdlrData
157{
158 SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
159};
160
161/** bound disjunction constraint data */
162struct SCIP_ConsData
163{
164 SCIP_VAR** vars; /**< variables of the literals in the constraint */
165 SCIP_BOUNDTYPE* boundtypes; /**< types of bounds of the literals (lower or upper bounds) */
166 SCIP_Real* bounds; /**< bounds of the literals */
167 int varssize; /**< size of vars, boundtypes, and bounds arrays */
168 int nvars; /**< number of variables in the constraint */
169 int watchedvar1; /**< position of the first watched variable */
170 int watchedvar2; /**< position of the second watched variable */
171 int filterpos1; /**< event filter position of first watched variable */
172 int filterpos2; /**< event filter position of second watched variable */
173};
174
175/**@name Local methods
176 *
177 * @{
178 */
179
180/** adds rounding locks for the given variable in the given bound disjunction constraint */
181static
183 SCIP* scip, /**< SCIP data structure */
184 SCIP_CONS* cons, /**< bound disjunction constraint */
185 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
186 int pos /**< position of the variable in the constraint */
187 )
188{
189 assert(consdata != NULL);
190 assert(0 <= pos && pos < consdata->nvars);
191
192 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
193 {
194 SCIP_CALL( SCIPlockVarCons(scip, consdata->vars[pos], cons, TRUE, FALSE) );
195 }
196 else
197 {
198 SCIP_CALL( SCIPlockVarCons(scip, consdata->vars[pos], cons, FALSE, TRUE) );
199 }
200
201 return SCIP_OKAY;
202}
203
204/** removes rounding locks for the given variable in the given bound disjunction constraint */
205static
207 SCIP* scip, /**< SCIP data structure */
208 SCIP_CONS* cons, /**< bound disjunction constraint */
209 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
210 int pos /**< position of the variable in the constraint */
211 )
212{
213 assert(consdata != NULL);
214 assert(0 <= pos && pos < consdata->nvars);
215
216 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
217 {
218 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vars[pos], cons, TRUE, FALSE) );
219 }
220 else
221 {
222 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vars[pos], cons, FALSE, TRUE) );
223 }
224
225 return SCIP_OKAY;
226}
227
228/** catches the events on a single variable of the bound disjunction constraint */
229static
231 SCIP* scip, /**< SCIP data structure */
232 SCIP_CONS* cons, /**< bound disjunction constraint */
233 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
234 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
235 int pos, /**< position of the variable in the constraint */
236 int* filterpos /**< pointer to store position of event filter entry, or NULL */
237 )
238{
239 assert(consdata != NULL);
240 assert(0 <= pos && pos < consdata->nvars);
241
242 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
243 {
245 eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
246 }
247 else
248 {
250 eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
251 }
252
253 return SCIP_OKAY;
254}
255
256/** drops the events on a single variable of the bound disjunction constraint */
257static
259 SCIP* scip, /**< SCIP data structure */
260 SCIP_CONS* cons, /**< bound disjunction constraint */
261 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
262 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
263 int pos, /**< position of the variable in the constraint */
264 int filterpos /**< position of event filter entry returned by SCIPcatchVarEvent(), or -1 */
265 )
266{
267 assert(consdata != NULL);
268 assert(0 <= pos && pos < consdata->nvars);
269
270 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
271 {
273 eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
274 }
275 else
276 {
278 eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
279 }
280
281 return SCIP_OKAY;
282}
283
284/** creates constraint handler data for bound disjunction constraint handler */
285static
287 SCIP* scip, /**< SCIP data structure */
288 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
289 SCIP_EVENTHDLR* eventhdlr /**< event handler */
290 )
291{
292 assert(scip != NULL);
293 assert(conshdlrdata != NULL);
294 assert(eventhdlr != NULL);
295
296 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
297
298 /* set event handler for catching events on watched variables */
299 (*conshdlrdata)->eventhdlr = eventhdlr;
300
301 return SCIP_OKAY;
302}
303
304/** frees constraint handler data for bound disjunction constraint handler */
305static
307 SCIP* scip, /**< SCIP data structure */
308 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
309 )
310{
311 assert(conshdlrdata != NULL);
312 assert(*conshdlrdata != NULL);
313
314 SCIPfreeBlockMemory(scip, conshdlrdata);
315}
316
317/** creates a bound disjunction constraint data object */
318static
320 SCIP* scip, /**< SCIP data structure */
321 SCIP_CONSDATA** consdata, /**< pointer to store the bound disjunction constraint data */
322 int nvars, /**< number of variables in the constraint */
323 SCIP_VAR** vars, /**< variables of the literals in the constraint */
324 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
325 SCIP_Real* bounds /**< bounds of the literals */
326 )
327{
328 assert(consdata != NULL);
329 assert(nvars == 0 || vars != NULL);
330 assert(nvars == 0 || boundtypes != NULL);
331 assert(nvars == 0 || bounds != NULL);
332
333 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
334
335 if( nvars > 0 )
336 {
338 {
339 int k;
340 int v;
341#ifndef NDEBUG
342 int nviolations = 0;
343#endif
344 SCIP_Bool redundant;
345 SCIP_VAR** varsbuffer;
346 SCIP_BOUNDTYPE* boundtypesbuffer;
347 SCIP_Real* boundsbuffer;
348
349 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
350 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypesbuffer, nvars) );
351 SCIP_CALL( SCIPallocBufferArray(scip, &boundsbuffer, nvars) );
352
353 k = 0;
354 redundant = FALSE;
355 /* loop over variables, compare fixed ones against its bound disjunction */
356 for( v = 0; v < nvars && !redundant; ++v )
357 {
358 SCIP_VAR* var = vars[v];
359 SCIP_BOUNDTYPE boundtype = boundtypes[v];
360 SCIP_Real bound = bounds[v];
361
362 /* is the variable fixed? */
364 {
365 if( (boundtype == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPvarGetLbLocal(var), bound))
366 || (boundtype == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPvarGetUbLocal(var), bound)) )
367 {
368 /* save this feasible assignment at the first position */
369 varsbuffer[0] = var;
370 boundtypesbuffer[0] = boundtype;
371 boundsbuffer[0] = bound;
372 k = 1;
373 redundant = TRUE;
374 }
375#ifndef NDEBUG
376 else
377 ++nviolations;
378#endif
379 }
380 else
381 {
382 /* append unfixed variable to buffer */
383 varsbuffer[k] = var;
384 boundtypesbuffer[k] = boundtype;
385 boundsbuffer[k] = bound;
386 ++k;
387 }
388 }
389
390 /* duplicate a single, infeasible assignment, wlog the first one */
391 if( k == 0 )
392 {
393 assert(nviolations == nvars);
394 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, 1) );
395 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypes, 1) );
396 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, bounds, 1) );
397 (*consdata)->varssize = 1;
398 (*consdata)->nvars = 1;
399 }
400 else
401 {
402 /* if the bound disjunction is already trivially satisfied, we keep only a single feasible assignment */
403 assert(!redundant || k == 1);
404
405 /* we only copy the buffered variables required to represent the constraint */
406 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
407 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypesbuffer, k) );
408 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, boundsbuffer, k) );
409 (*consdata)->varssize = k;
410 (*consdata)->nvars = k;
411 }
412
413 /* free buffer storage */
414 SCIPfreeBufferArray(scip, &boundsbuffer);
415 SCIPfreeBufferArray(scip, &boundtypesbuffer);
416 SCIPfreeBufferArray(scip, &varsbuffer);
417 }
418 else
419 {
420 /* without problem compression, the entire vars array is copied */
421 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
422 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypes, nvars) );
423 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, bounds, nvars) );
424 (*consdata)->varssize = nvars;
425 (*consdata)->nvars = nvars;
426 }
427 }
428 else
429 {
430 (*consdata)->vars = NULL;
431 (*consdata)->boundtypes = NULL;
432 (*consdata)->bounds = NULL;
433 (*consdata)->varssize = 0;
434 (*consdata)->nvars = 0;
435 }
436 (*consdata)->watchedvar1 = -1;
437 (*consdata)->watchedvar2 = -1;
438 (*consdata)->filterpos1 = -1;
439 (*consdata)->filterpos2 = -1;
440
441 /* get transformed variables, if we are in the transformed problem */
443 {
444 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
445 }
446
447 return SCIP_OKAY;
448}
449
450/** creates a bound disjunction constraint data object with possibly redundant literals */
451static
453 SCIP* scip, /**< SCIP data structure */
454 SCIP_CONSDATA** consdata, /**< pointer to store the bound disjunction constraint data */
455 int nvars, /**< number of variables in the constraint */
456 SCIP_VAR** vars, /**< variables of the literals in the constraint */
457 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
458 SCIP_Real* bounds /**< bounds of the literals */
459 )
460{
461 assert(consdata != NULL);
462 assert(nvars == 0 || vars != NULL);
463 assert(nvars == 0 || boundtypes != NULL);
464 assert(nvars == 0 || bounds != NULL);
465
466 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
467
468 if( nvars > 0 )
469 {
470 SCIP_BOUNDTYPE* boundtypesbuffer;
471 SCIP_Real* boundsbuffer;
472 SCIP_VAR** varsbuffer;
473 SCIP_VAR* var;
474 int nvarsbuffer = 0;
475 int nviolated = 0;
476 int v = 0;
477
478 SCIP_CALL( SCIPduplicateBufferArray(scip, &varsbuffer, vars, nvars) );
479 SCIP_CALL( SCIPduplicateBufferArray(scip, &boundtypesbuffer, boundtypes, nvars) );
480 SCIP_CALL( SCIPduplicateBufferArray(scip, &boundsbuffer, bounds, nvars) );
481
482 /* sort variables according to index; this allows us to check for redundancy easily below because duplicate
483 * variables must now appear consecutively */
484 SCIPsortPtrRealInt((void**)varsbuffer, boundsbuffer, (int*) boundtypesbuffer, SCIPvarComp, nvars);
485
486 /* filter out redundant literals */
487 while( v < nvars )
488 {
489 int lowerindex;
490 int upperindex;
491
492 var = varsbuffer[v];
493
494 /* compress fixed variables */
496 {
497 /* if the literal is feasible for the fixed variable, then the whole constraint is feasible, so we reduce
498 * it to only this literal
499 */
500 if( ( boundtypesbuffer[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPvarGetLbLocal(var), boundsbuffer[v]) )
501 || ( boundtypesbuffer[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPvarGetUbLocal(var), boundsbuffer[v]) ) )
502 {
503 /* save this feasible assignment at the first position */
504 varsbuffer[0] = var;
505 boundtypesbuffer[0] = boundtypesbuffer[v];
506 boundsbuffer[0] = boundsbuffer[v];
507 nvarsbuffer = 1;
508 break;
509 }
510 else
511 {
512 /* otherwise the literal is violated - we skip the literal */
513 ++nviolated;
514 ++v;
515 continue;
516 }
517 }
518
519 /* initialize bound indices */
520 if( boundtypesbuffer[v] == SCIP_BOUNDTYPE_LOWER )
521 {
522 lowerindex = v;
523 upperindex = -1;
524 }
525 else
526 {
527 assert(boundtypesbuffer[v] == SCIP_BOUNDTYPE_UPPER);
528
529 lowerindex = -1;
530 upperindex = v;
531 }
532
533 ++v;
534
535 /* check subsequent variables with the same variable for redundancy */
536 while( v < nvars && varsbuffer[v] == var )
537 {
538 if( boundtypesbuffer[v] == SCIP_BOUNDTYPE_LOWER )
539 {
540 /* keep the weaker lower bound */
541 if( lowerindex == -1 || boundsbuffer[lowerindex] > boundsbuffer[v] )
542 lowerindex = v;
543 }
544 else
545 {
546 assert(boundtypesbuffer[v] == SCIP_BOUNDTYPE_UPPER);
547
548 /* keep the weaker upper bound */
549 if( upperindex == -1 || boundsbuffer[upperindex] < boundsbuffer[v] )
550 upperindex = v;
551 }
552
553 ++v;
554 }
555
556 /* keep bound sequence */
557 if( upperindex != -1 && lowerindex > upperindex )
558 SCIPswapInts(&lowerindex, &upperindex);
559
560 /* keep first bound */
561 if( lowerindex != -1 )
562 {
563 assert(nvarsbuffer != upperindex);
564
565 varsbuffer[nvarsbuffer] = varsbuffer[lowerindex];
566 boundtypesbuffer[nvarsbuffer] = boundtypesbuffer[lowerindex];
567 boundsbuffer[nvarsbuffer] = boundsbuffer[lowerindex];
568 ++nvarsbuffer;
569 }
570
571 /* keep second bound */
572 if( upperindex != -1 )
573 {
574 varsbuffer[nvarsbuffer] = varsbuffer[upperindex];
575 boundtypesbuffer[nvarsbuffer] = boundtypesbuffer[upperindex];
576 boundsbuffer[nvarsbuffer] = boundsbuffer[upperindex];
577 ++nvarsbuffer;
578 }
579 }
580 assert(nvarsbuffer > 0 || SCIPisConsCompressionEnabled(scip)); /* no variables can only happen if compression is enabled */
581
582#ifndef NDEBUG
583 /* if there are no variables left, this is because all literals are infeasible */
584 if( nvarsbuffer == 0 )
585 {
586 for( v = 0; v < nvars; v++ )
587 {
588 var = vars[v];
589 assert( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) );
590 assert( (boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, SCIPvarGetLbLocal(var), bounds[v]))
591 || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, SCIPvarGetUbLocal(var), bounds[v])) );
592 }
593 }
594 else
595 {
596 /* check that the literals are not redundant */
597 for( v = 0; v < nvarsbuffer; v++ )
598 {
599 int v2;
600 assert(varsbuffer[v] != NULL);
601 for( v2 = v+1; v2 < nvarsbuffer; v2++ )
602 assert(varsbuffer[v] != varsbuffer[v2] || boundtypesbuffer[v] != boundtypesbuffer[v2]);
603 }
604 }
605#endif
606
607 /* if all literals are infeasible, we keep the first */
608 if( SCIPisConsCompressionEnabled(scip) && nviolated > 0 && nvarsbuffer == 0 )
609 nvarsbuffer = 1;
610
611 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, nvarsbuffer) );
612 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypesbuffer, nvarsbuffer) );
613 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, boundsbuffer, nvarsbuffer) );
614 (*consdata)->varssize = nvarsbuffer;
615 (*consdata)->nvars = nvarsbuffer;
616
617 /* free buffer storage */
618 SCIPfreeBufferArray(scip, &boundsbuffer);
619 SCIPfreeBufferArray(scip, &boundtypesbuffer);
620 SCIPfreeBufferArray(scip, &varsbuffer);
621 }
622 else
623 {
624 (*consdata)->vars = NULL;
625 (*consdata)->boundtypes = NULL;
626 (*consdata)->bounds = NULL;
627 (*consdata)->varssize = 0;
628 (*consdata)->nvars = 0;
629 }
630 (*consdata)->watchedvar1 = -1;
631 (*consdata)->watchedvar2 = -1;
632 (*consdata)->filterpos1 = -1;
633 (*consdata)->filterpos2 = -1;
634
635 /* get transformed variables, if we are in the transformed problem */
637 {
638 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
639 }
640
641 return SCIP_OKAY;
642}
643
644/** frees a bound disjunction constraint data */
645static
647 SCIP* scip, /**< SCIP data structure */
648 SCIP_CONSDATA** consdata /**< pointer to the bound disjunction constraint */
649 )
650{
651 assert(consdata != NULL);
652 assert(*consdata != NULL);
653
654 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
655 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->boundtypes, (*consdata)->varssize);
656 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->bounds, (*consdata)->varssize);
657 SCIPfreeBlockMemory(scip, consdata);
658}
659
660/** prints bound disjunction constraint to file stream */
661static
663 SCIP* scip, /**< SCIP data structure */
664 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
665 FILE* file, /**< output file (or NULL for standard output) */
666 SCIP_Bool endline /**< should an endline be set? */
667 )
668{
669 int v;
670
671 assert(consdata != NULL);
672
673 /* print coefficients */
674 SCIPinfoMessage(scip, file, "bounddisjunction(");
675 for( v = 0; v < consdata->nvars; ++v )
676 {
677 assert(consdata->vars[v] != NULL);
678 if( v > 0 )
679 SCIPinfoMessage(scip, file, ", ");
680 SCIPinfoMessage(scip, file, "<%s> %s %.15g", SCIPvarGetName(consdata->vars[v]),
681 consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", consdata->bounds[v]);
682 }
683 SCIPinfoMessage(scip, file, ")");
684
685 if( endline )
686 SCIPinfoMessage(scip, file, "\n");
687}
688
689/** stores the given variable numbers as watched variables, and updates the event processing */
690static
692 SCIP* scip, /**< SCIP data structure */
693 SCIP_CONS* cons, /**< bound disjunction constraint */
694 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
695 int watchedvar1, /**< new first watched variable */
696 int watchedvar2 /**< new second watched variable */
697 )
698{
699 SCIP_CONSDATA* consdata;
700
701 consdata = SCIPconsGetData(cons);
702 assert(consdata != NULL);
703 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
704 assert(watchedvar1 != -1 || watchedvar2 == -1);
705 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
706 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
707
708 /* don't watch variables for non active constraints */
709 if( !SCIPconsIsActive(cons) )
710 return SCIP_OKAY;
711
712 /* if one watched variable is equal to the old other watched variable, just switch positions */
713 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
714 {
715 int tmp;
716
717 tmp = consdata->watchedvar1;
718 consdata->watchedvar1 = consdata->watchedvar2;
719 consdata->watchedvar2 = tmp;
720 tmp = consdata->filterpos1;
721 consdata->filterpos1 = consdata->filterpos2;
722 consdata->filterpos2 = tmp;
723 }
724 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
725 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
726
727 /* drop events on old watched variables */
728 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
729 {
730 assert(consdata->filterpos1 != -1);
731 SCIP_CALL( dropEvents(scip, cons, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
732 consdata->watchedvar1 = -1;
733 }
734 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
735 {
736 assert(consdata->filterpos2 != -1);
737 SCIP_CALL( dropEvents(scip, cons, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
738 consdata->watchedvar2 = -1;
739 }
740
741 /* catch events on new watched variables */
742 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
743 {
744 SCIP_CALL( catchEvents(scip, cons, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
745 }
746 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
747 {
748 SCIP_CALL( catchEvents(scip, cons, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
749 }
750
751 /* set the new watched variables */
752 consdata->watchedvar1 = watchedvar1;
753 consdata->watchedvar2 = watchedvar2;
754
755 return SCIP_OKAY;
756}
757
758/** check whether two intervals overlap */
759static
761 SCIP* scip,
762 SCIP_VAR* var,
763 SCIP_BOUNDTYPE boundtype1,
764 SCIP_Real bound1,
765 SCIP_BOUNDTYPE boundtype2,
766 SCIP_Real bound2
767 )
768{
769 SCIP_Bool overlapping = FALSE;
770
771 if( boundtype1 == SCIP_BOUNDTYPE_LOWER )
772 {
773 assert(boundtype2 == SCIP_BOUNDTYPE_UPPER);
774
775 if( SCIPisLE(scip, bound1 - bound2, (SCIP_Real)SCIPvarIsIntegral(var)) )
776 overlapping = TRUE;
777 }
778 else
779 {
780 assert(boundtype2 == SCIP_BOUNDTYPE_LOWER);
781
782 if( SCIPisLE(scip, bound2 - bound1, (SCIP_Real)SCIPvarIsIntegral(var)) )
783 overlapping = TRUE;
784 }
785
786 return overlapping;
787}
788
789/** deletes coefficient at given position from bound disjunction constraint data */
790static
792 SCIP* scip, /**< SCIP data structure */
793 SCIP_CONS* cons, /**< bound disjunction constraint */
794 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
795 int pos /**< position of coefficient to delete */
796 )
797{
798 SCIP_CONSDATA* consdata;
799
800 assert(eventhdlr != NULL);
801
802 consdata = SCIPconsGetData(cons);
803 assert(consdata != NULL);
804 assert(0 <= pos && pos < consdata->nvars);
805 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
806
807 /* remove the rounding locks of variable */
808 SCIP_CALL( unlockRounding(scip, cons, consdata, pos) );
809
810 if( SCIPconsIsTransformed(cons) )
811 {
812 /* if the position is watched, stop watching the position */
813 if( consdata->watchedvar1 == pos )
814 {
815 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar2, -1) );
816 }
817 if( consdata->watchedvar2 == pos )
818 {
819 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, -1) );
820 }
821 }
822 assert(pos != consdata->watchedvar1);
823 assert(pos != consdata->watchedvar2);
824
825 /* move the last variable to the free slot */
826 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
827 consdata->boundtypes[pos] = consdata->boundtypes[consdata->nvars-1];
828 consdata->bounds[pos] = consdata->bounds[consdata->nvars-1];
829 consdata->nvars--;
830
831 /* if the last variable (that moved) was watched, update the watched position */
832 if( consdata->watchedvar1 == consdata->nvars )
833 consdata->watchedvar1 = pos;
834 if( consdata->watchedvar2 == consdata->nvars )
835 consdata->watchedvar2 = pos;
836
838
839 return SCIP_OKAY;
840}
841
842/** adds literal to bound disjunction constraint data */
843static
845 SCIP* scip, /**< SCIP data structure */
846 SCIP_CONS* cons, /**< bound disjunction constraint */
847 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
848 SCIP_VAR* var, /**< variable in literal */
849 SCIP_BOUNDTYPE boundtype, /**< boundtype of literal */
850 SCIP_Real bound, /**< bound of literal */
851 SCIP_Bool* redundant /**< flag to indicate whether constraint has been bound redundant */
852 )
853{
854 SCIP_CONSDATA* consdata;
855 int samebndidx;
856 int v;
857
858 assert(eventhdlr != NULL);
859
860 consdata = SCIPconsGetData(cons);
861 assert(consdata != NULL);
862 assert(var != NULL);
863 assert(!SCIPisInfinity(scip, REALABS(bound)));
864 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
865
866 /* ensure enough memory in consdata arrays */
867 if( consdata->varssize == consdata->nvars )
868 {
869 int newsize;
870
871 newsize = SCIPcalcMemGrowSize(scip, consdata->nvars + 1);
872 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
873 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->boundtypes, consdata->varssize, newsize) );
874 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->bounds, consdata->varssize, newsize) );
875 consdata->varssize = newsize;
876 }
877 assert(consdata->varssize > consdata->nvars);
878
879 /* remember the position of the literal in the constraint that has the same bound type on the same variable
880 *
881 * example: (x >= 5) or (x <= 2) and literal (x >= 2) should be added.
882 * if we see (x >= 5) first, we cannot stop immediately because only in combination with the second literal
883 * we see that the constraint is redundant.
884 */
885 samebndidx = -1;
886
887 for( v = 0; v < consdata->nvars; v++ )
888 {
889 /* check if the variable is already part of the constraint */
890 if( consdata->vars[v] == var )
891 {
892 if( consdata->boundtypes[v] == boundtype )
893 samebndidx = v;
894 else if( isOverlapping(scip, var, consdata->boundtypes[v], consdata->bounds[v], boundtype, bound) )
895 {
896 *redundant = TRUE;
897 return SCIP_OKAY;
898 }
899 }
900 }
901
902 /* the combination of variable and boundtype is already part of the constraint; check whether the clause
903 * can be relaxed
904 */
905 if( samebndidx > -1 )
906 {
907 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLT(scip, bound, consdata->bounds[samebndidx]))
908 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisGT(scip, bound, consdata->bounds[samebndidx])) )
909 {
910 SCIPdebugMsg(scip, "relax clause of <%s>: (<%s> %s %.15g) -> (<%s> %s %.15g)\n", SCIPconsGetName(cons),
911 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", consdata->bounds[samebndidx],
912 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
913 consdata->bounds[samebndidx] = bound;
914 }
915 }
916 else
917 {
918 /* add the variable to the end of the array */
919 consdata->vars[consdata->nvars] = var;
920 consdata->boundtypes[consdata->nvars] = boundtype;
921 consdata->bounds[consdata->nvars] = bound;
922 consdata->nvars++;
923
924 if( SCIPconsIsTransformed(cons) )
925 {
926 /* add rounding lock of variable */
927 SCIP_CALL( lockRounding(scip, cons, consdata, consdata->nvars-1) );
928
929 /* if less than 2 variables are watched, add the new one to the watched variables */
930 if( consdata->watchedvar1 == -1 )
931 {
932 assert(consdata->watchedvar2 == -1);
933 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->nvars-1, -1) );
934 }
935 else if( consdata->watchedvar2 == -1 )
936 {
937 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, consdata->nvars-1) );
938 }
939 }
940 }
941
943
944 return SCIP_OKAY;
945}
946
947/** deletes all variables with global bounds violating the literal, checks for global bounds satisfying the literal */
948static
950 SCIP* scip, /**< SCIP data structure */
951 SCIP_CONS* cons, /**< bound disjunction constraint */
952 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
953 SCIP_Bool* redundant /**< returns whether a variable fixed to one exists in the constraint */
954 )
955{
956 SCIP_CONSDATA* consdata;
957 int v;
958 SCIP_Real bnd;
959
960 assert(eventhdlr != NULL);
961 assert(redundant != NULL);
962
963 consdata = SCIPconsGetData(cons);
964 assert(consdata != NULL);
965 assert(consdata->nvars == 0 || consdata->vars != NULL);
966
967 *redundant = FALSE;
968 v = 0;
969 while( v < consdata->nvars )
970 {
971 SCIP_VAR* var;
972
973 var = consdata->vars[v];
974
975 if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
976 {
977 bnd = SCIPcomputeVarLbGlobal(scip, var);
978 if( isFeasGE(scip, var, bnd, consdata->bounds[v]) )
979 {
980 *redundant = TRUE;
981 return SCIP_OKAY;
982 }
983 else
984 {
985 bnd = SCIPcomputeVarUbGlobal(scip, var);
986 if( isFeasLT(scip, var, bnd, consdata->bounds[v]) )
987 {
988 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
989 }
990 else
991 ++v;
992 }
993 }
994 else
995 {
996 assert(consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
997 bnd = SCIPcomputeVarUbGlobal(scip, var);
998 if( isFeasLE(scip, var, bnd, consdata->bounds[v]) )
999 {
1000 *redundant = TRUE;
1001 return SCIP_OKAY;
1002 }
1003 else
1004 {
1005 bnd = SCIPcomputeVarLbGlobal(scip, var);
1006 if( isFeasGT(scip, var, bnd, consdata->bounds[v]) )
1007 {
1008 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1009 }
1010 else
1011 ++v;
1012 }
1013 }
1014 }
1015
1016 SCIPdebugMsg(scip, "after global bounds: ");
1017 SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
1018
1019 return SCIP_OKAY;
1020}
1021
1022/** returns whether literal at the given position is satisfied in the local bounds */
1023static
1025 SCIP* scip, /**< SCIP data structure */
1026 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
1027 int pos /**< position of the literal */
1028 )
1029{
1030 SCIP_Real bnd;
1031
1032 assert(consdata != NULL);
1033 assert(0 <= pos && pos < consdata->nvars);
1034
1035 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
1036 {
1037 bnd = SCIPcomputeVarLbLocal(scip, consdata->vars[pos]);
1038 return isFeasGE(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1039 }
1040 else
1041 {
1042 bnd = SCIPcomputeVarUbLocal(scip, consdata->vars[pos]);
1043 return isFeasLE(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1044 }
1045}
1046
1047/** returns whether literal at the given position is violated in the local bounds */
1048static
1050 SCIP* scip, /**< SCIP data structure */
1051 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
1052 int pos /**< position of the literal */
1053 )
1054{
1055 SCIP_Real bnd;
1056
1057 assert(consdata != NULL);
1058 assert(0 <= pos && pos < consdata->nvars);
1059
1060 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
1061 {
1062 bnd = SCIPcomputeVarUbLocal(scip, consdata->vars[pos]);
1063 return isFeasLT(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1064 }
1065 else
1066 {
1067 bnd = SCIPcomputeVarLbLocal(scip, consdata->vars[pos]);
1068 return isFeasGT(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1069 }
1070}
1071
1072/** replace variables by their representative active (or multi-aggregated) variables */
1073static
1075 SCIP* scip, /**< SCIP data structure */
1076 SCIP_CONS* cons, /**< bound disjunction constraint */
1077 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
1078 SCIP_Bool* redundant /**< flag to indicate whether constraint has been bound redundant */
1079 )
1080{
1081 SCIP_CONSDATA* consdata;
1082 SCIP_VAR* var;
1083 SCIP_BOUNDTYPE boundtype;
1085 int v;
1086
1087 assert(scip != NULL);
1088 assert(cons != NULL);
1089 assert(eventhdlr != NULL);
1090
1091 consdata = SCIPconsGetData(cons);
1092 assert(consdata != NULL);
1093
1094 v = 0;
1095 while( v < consdata->nvars )
1096 {
1097#ifndef NDEBUG
1098 SCIP_VAR* oldvar;
1099#endif
1100 var = consdata->vars[v];
1101 assert(var != NULL);
1102
1103#ifndef NDEBUG
1104 oldvar = var;
1105#endif
1106
1108 {
1109 /* check whether the literal is satisfied and the constraint is thus redundant */
1110 if( isLiteralSatisfied(scip, consdata, v) )
1111 {
1112 *redundant = TRUE;
1113 break;
1114 }
1115 if( isLiteralViolated(scip, consdata, v) )
1116 {
1117 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1118 continue;
1119 }
1120
1121 ++v;
1122
1123 continue;
1124 }
1125
1126 /* get active/fixed/multiaggr equivalent of v'th literal */
1127 bound = consdata->bounds[v];
1128 boundtype = consdata->boundtypes[v];
1129 SCIP_CALL( SCIPvarGetProbvarBound(&var, &bound, &boundtype) );
1130 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED || oldvar != var);
1131
1132 SCIPdebugMsg(scip, "in <%s>, replace <%s>[%g,%g] %c= %g by <%s>[%g,%g] %c= %g\n", SCIPconsGetName(cons),
1133 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbGlobal(consdata->vars[v]), SCIPvarGetUbGlobal(consdata->vars[v]), (consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? '>' : '<'), consdata->bounds[v],
1134 SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), (boundtype == SCIP_BOUNDTYPE_LOWER ? '>' : '<'), bound);
1135
1136 /* if literal is satisfied, then constraint is redundant and we can stop */
1137 if( (boundtype == SCIP_BOUNDTYPE_LOWER && isFeasLE(scip, var, bound, SCIPvarGetLbGlobal(var))) || /*lint !e666*/
1138 (boundtype == SCIP_BOUNDTYPE_UPPER && isFeasGE(scip, var, bound, SCIPvarGetUbGlobal(var))) ) /*lint !e666*/
1139 {
1140 *redundant = TRUE;
1141 break;
1142 }
1143
1144 /* if literal is not fixed, replace it */
1146 {
1147 /* add new literal */
1148 SCIP_CALL( addCoef(scip, cons, eventhdlr, var, boundtype, bound, redundant) );
1149 }
1150
1151 /* remove old literal */
1152 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1153 }
1154
1155 return SCIP_OKAY;
1156}
1157
1158/** try to upgrade the bounddisjunction constraint
1159 *
1160 * if only binary variables are left, we can upgrade a bounddisjunction to a logicor constraint(, if only two variables
1161 * are left, this logicor constraint can be formulated as set-packing constraint as well)
1162 *
1163 * e.g.: bounddisjunction( x1 >= 1, x2 <= 0; x3 >= 1; x4 <= 0 ) => x1 + ~x2 + x3 + ~x4 >= 1
1164 */
1165static
1167 SCIP* scip, /**< SCIP data structure */
1168 SCIP_CONS* cons, /**< bound disjunction constraint that detected the conflict */
1169 int* ndelconss, /**< pointer to store the number of delete constraint */
1170 int* naddconss /**< pointer to store the number of added constraint */
1171 )
1172{
1173 SCIP_CONSDATA* consdata;
1174 SCIP_VAR** newvars;
1175 SCIP_Bool allbinary;
1176 int nvars;
1177 int v;
1178
1179 assert(scip != NULL);
1180 assert(cons != NULL);
1181 assert(ndelconss != NULL);
1182 assert(naddconss != NULL);
1183 assert(naddconss != NULL);
1184 assert(!SCIPconsIsModifiable(cons));
1185
1186 consdata = SCIPconsGetData(cons);
1187 assert(consdata != NULL);
1188
1189 nvars = consdata->nvars;
1190 assert(nvars >= 2);
1191 assert(consdata->vars != NULL);
1192
1193 allbinary = TRUE;
1194
1195 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars) );
1196
1197 for( v = nvars - 1; v >= 0; --v )
1198 {
1199 if( !SCIPvarIsBinary(consdata->vars[v]) )
1200 {
1201 allbinary = FALSE;
1202 break;
1203 }
1204 else
1205 {
1206 if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1207 {
1208 assert(SCIPisFeasGT(scip, consdata->bounds[v], 0.0));
1209
1210 if( nvars == 2 )
1211 {
1212 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &(newvars[v])) );
1213 }
1214 else
1215 newvars[v] = consdata->vars[v];
1216 }
1217 else
1218 {
1219 assert(consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
1220 assert(SCIPisFeasLT(scip, consdata->bounds[v], 1.0));
1221
1222 if( nvars > 2 )
1223 {
1224 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &(newvars[v])) );
1225 }
1226 else
1227 newvars[v] = consdata->vars[v];
1228 }
1229 }
1230 }
1231
1232 if( allbinary )
1233 {
1234 SCIP_CONS* newcons;
1235
1236 if( nvars == 2 )
1237 {
1238 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), nvars, newvars,
1243 }
1244 else
1245 {
1246 SCIP_CALL( SCIPcreateConsLogicor(scip, &newcons, SCIPconsGetName(cons), nvars, newvars,
1251 }
1252
1253 /* add the upgraded constraint to the problem */
1254 SCIPdebugMsg(scip, "upgrading constraint <%s> to the following %s constraint\n", SCIPconsGetName(cons), (nvars == 2 ? "setppc" : "logicor"));
1255 SCIPdebugPrintCons(scip, newcons, NULL);
1256 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
1257 ++(*naddconss);
1258
1259 /* remove the underlying constraint from the problem */
1260 SCIP_CALL( SCIPdelCons(scip, cons) );
1261 ++(*ndelconss);
1262 }
1263
1264 SCIPfreeBufferArray(scip, &newvars);
1265
1266 return SCIP_OKAY;
1267}
1268
1269/** analyzes conflicting assignment on given constraint, and adds conflict constraint to problem */
1270static
1272 SCIP* scip, /**< SCIP data structure */
1273 SCIP_CONS* cons /**< bound disjunction constraint that detected the conflict */
1274 )
1275{
1276 SCIP_CONSDATA* consdata;
1277 int v;
1278
1279 /* conflict analysis can only be applied in solving stage and if it is turned on */
1281 return SCIP_OKAY;
1282
1283 consdata = SCIPconsGetData(cons);
1284 assert(consdata != NULL);
1285
1286 /* initialize conflict analysis, and add all bounds of infeasible constraint to conflict candidate queue */
1288
1289 for( v = 0; v < consdata->nvars; ++v )
1290 {
1291 /* the opposite bound is in conflict with this literal */
1292 SCIP_CALL( SCIPaddConflictBd(scip, consdata->vars[v], SCIPboundtypeOpposite(consdata->boundtypes[v]), NULL) );
1293 }
1294
1295 /* analyze the conflict */
1297
1298 return SCIP_OKAY;
1299}
1300
1301/** disables or deletes the given constraint, depending on the current depth */
1302static
1304 SCIP* scip, /**< SCIP data structure */
1305 SCIP_CONS* cons /**< bound disjunction constraint to be disabled */
1306 )
1307{
1308 assert(SCIPconsGetValidDepth(cons) <= SCIPgetDepth(scip));
1309
1311 {
1312 SCIP_CALL( SCIPdelCons(scip, cons) );
1313 }
1314 else
1315 {
1316 SCIP_CALL( SCIPdisableCons(scip, cons) );
1317 }
1318
1319 return SCIP_OKAY;
1320}
1321
1322/** checks constraint for violation only looking at the watched variables, applies bound changes if possible */
1323static
1325 SCIP* scip, /**< SCIP data structure */
1326 SCIP_CONS* cons, /**< bound disjunction constraint to be processed */
1327 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1328 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1329 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint is infeasible in current bounds */
1330 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1331 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1332 )
1333{
1334 SCIP_CONSDATA* consdata;
1335 SCIP_VAR** vars;
1336 SCIP_BOUNDTYPE* boundtypes;
1337 SCIP_Real* bounds;
1338 SCIP_Longint nbranchings1;
1339 SCIP_Longint nbranchings2;
1340 int nvars;
1341 int watchedvar1;
1342 int watchedvar2;
1343
1344 assert(cons != NULL);
1345 assert(SCIPconsGetHdlr(cons) != NULL);
1346 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1347 assert(cutoff != NULL);
1348 assert(reduceddom != NULL);
1349 assert(mustcheck != NULL);
1350
1351 consdata = SCIPconsGetData(cons);
1352 assert(consdata != NULL);
1353 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
1354
1355 /* init bools */
1356 *cutoff = FALSE;
1357 *infeasible = FALSE;
1358 *reduceddom = FALSE;
1359 *mustcheck = FALSE;
1360
1361 SCIPdebugMsg(scip, "processing watched variables of constraint <%s>\n", SCIPconsGetName(cons));
1362
1363 nvars = consdata->nvars;
1364 vars = consdata->vars;
1365 boundtypes = consdata->boundtypes;
1366 bounds = consdata->bounds;
1367 assert(nvars == 0 || vars != NULL);
1368 assert(nvars == 0 || boundtypes != NULL);
1369 assert(nvars == 0 || bounds != NULL);
1370
1371 /* check watched variables if they are satisfying the literal */
1372 if( consdata->watchedvar1 >= 0 && isLiteralSatisfied(scip, consdata, consdata->watchedvar1) )
1373 {
1374 /* the literal is satisfied, making the constraint redundant */
1375 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar1 satisfied)\n", SCIPconsGetName(cons));
1376 SCIP_CALL( disableCons(scip, cons) );
1377 return SCIP_OKAY;
1378 }
1379 if( consdata->watchedvar2 >= 0 && isLiteralSatisfied(scip, consdata, consdata->watchedvar2) )
1380 {
1381 /* the literal is satisfied, making the constraint redundant */
1382 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar2 satisfied)\n", SCIPconsGetName(cons));
1383 SCIP_CALL( disableCons(scip, cons) );
1384 return SCIP_OKAY;
1385 }
1386
1387 /* check if watched variables are still undecided */
1388 watchedvar1 = -1;
1389 watchedvar2 = -1;
1390 nbranchings1 = SCIP_LONGINT_MAX;
1391 nbranchings2 = SCIP_LONGINT_MAX;
1392 if( consdata->watchedvar1 >= 0 && !isLiteralViolated(scip, consdata, consdata->watchedvar1) )
1393 {
1394 watchedvar1 = consdata->watchedvar1;
1395 nbranchings1 = -1; /* prefer keeping the watched variable */
1396 }
1397 if( consdata->watchedvar2 >= 0 && !isLiteralViolated(scip, consdata, consdata->watchedvar2) )
1398 {
1399 if( watchedvar1 == -1 )
1400 {
1401 watchedvar1 = consdata->watchedvar2;
1402 nbranchings1 = -1; /* prefer keeping the watched variable */
1403 }
1404 else
1405 {
1406 watchedvar2 = consdata->watchedvar2;
1407 nbranchings2 = -1; /* prefer keeping the watched variable */
1408 }
1409 }
1410 assert(watchedvar1 >= 0 || watchedvar2 == -1);
1411 assert(nbranchings1 <= nbranchings2);
1412 assert(watchedvar1 != -1 || nbranchings1 == SCIP_LONGINT_MAX);
1413 assert(watchedvar2 != -1 || nbranchings2 == SCIP_LONGINT_MAX);
1414
1415 /* search for new watched variables */
1416 if( watchedvar2 == -1 )
1417 {
1418 int v;
1419
1420 for( v = 0; v < nvars; ++v )
1421 {
1422 SCIP_Longint nbranchings;
1423
1424 /* don't process the watched variables again */
1425 if( v == consdata->watchedvar1 || v == consdata->watchedvar2 )
1426 continue;
1427
1428 /* check, if the literal is violated */
1429 if( isLiteralViolated(scip, consdata, v) )
1430 continue;
1431
1432 /* check, if the literal is satisfied */
1433 if( isLiteralSatisfied(scip, consdata, v) )
1434 {
1435 assert(v != consdata->watchedvar1);
1436 assert(v != consdata->watchedvar2);
1437
1438 /* the literal is satisfied, making the constraint redundant;
1439 * make sure, the feasible variable is watched and disable the constraint
1440 */
1441 SCIPdebugMsg(scip, " -> disabling constraint <%s> (variable <%s> fixed to 1.0)\n",
1442 SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
1443 if( consdata->watchedvar1 != -1 )
1444 {
1445 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, v) );
1446 }
1447 else
1448 {
1449 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, v, consdata->watchedvar2) );
1450 }
1451 SCIP_CALL( disableCons(scip, cons) );
1452 return SCIP_OKAY;
1453 }
1454
1455 /* the literal is still undecided and can be used as watched variable */
1456 nbranchings = SCIPvarGetNBranchingsCurrentRun(vars[v],
1458 if( nbranchings < nbranchings2 )
1459 {
1460 if( nbranchings < nbranchings1 )
1461 {
1462 watchedvar2 = watchedvar1;
1463 nbranchings2 = nbranchings1;
1464 watchedvar1 = v;
1465 nbranchings1 = nbranchings;
1466 }
1467 else
1468 {
1469 watchedvar2 = v;
1470 nbranchings2 = nbranchings;
1471 }
1472 }
1473 }
1474 }
1475 assert(nbranchings1 <= nbranchings2);
1476 assert(watchedvar1 >= 0 || watchedvar2 == -1);
1477
1478 if( watchedvar1 == -1 )
1479 {
1480 /* there is no undecided literal left -> the constraint is infeasible
1481 * - a modifiable constraint is infeasible
1482 * - an unmodifiable constraint is infeasible and the node can be cut off
1483 */
1484 assert(watchedvar2 == -1);
1485
1486 SCIPdebugMsg(scip, " -> constraint <%s> is infeasible\n", SCIPconsGetName(cons));
1487 *infeasible = TRUE;
1488
1490 if( !SCIPconsIsModifiable(cons) )
1491 {
1492 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1493 SCIP_CALL( analyzeConflict(scip, cons) );
1494
1495 /* mark the node to be cut off */
1496 *cutoff = TRUE;
1497 }
1498 }
1499 else if( watchedvar2 == -1 )
1500 {
1501 /* there is only one undecided literal:
1502 * - a modifiable constraint must be checked manually
1503 * - we cannot change bounds of multi-aggregated variables and have to check manually
1504 * - an unmodifiable constraint is feasible and can be disabled after the remaining literal is satisfied
1505 */
1506 assert(0 <= watchedvar1 && watchedvar1 < nvars);
1507 assert(!isLiteralViolated(scip, consdata, watchedvar1));
1508 assert(!isLiteralSatisfied(scip, consdata, watchedvar1));
1509 if( SCIPconsIsModifiable(cons)
1511 *mustcheck = TRUE;
1512 else
1513 {
1514 SCIP_Bool infbdchg;
1515
1516#ifndef NDEBUG
1517 int v;
1518
1519 /* check whether all other literals are violated */
1520 for (v = 0; v < nvars; ++v)
1521 {
1522 if ( v != watchedvar1 )
1523 {
1524 assert( isLiteralViolated(scip, consdata, v) );
1525 }
1526 }
1527#endif
1528
1529 /* satisfy remaining literal and disable constraint; make sure, the fixed-to-one variable is watched */
1530 SCIPdebugMsg(scip, " -> single-literal constraint <%s> (change bound <%s> %s %g) at depth %d\n",
1531 SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]),
1532 boundtypes[watchedvar1] == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bounds[watchedvar1], SCIPgetDepth(scip));
1533
1534 if( boundtypes[watchedvar1] == SCIP_BOUNDTYPE_LOWER )
1535 {
1536 SCIP_CALL( SCIPinferVarLbCons(scip, vars[watchedvar1], bounds[watchedvar1], cons, watchedvar1, TRUE,
1537 &infbdchg, NULL) );
1538 }
1539 else
1540 {
1541 SCIP_CALL( SCIPinferVarUbCons(scip, vars[watchedvar1], bounds[watchedvar1], cons, watchedvar1, TRUE,
1542 &infbdchg, NULL) );
1543 }
1544 assert(!infbdchg);
1546 if( watchedvar1 != consdata->watchedvar1 ) /* keep one of the watched variables */
1547 {
1548 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, consdata->watchedvar1) );
1549 }
1550 SCIP_CALL( disableCons(scip, cons) );
1551 *reduceddom = TRUE;
1552 }
1553 }
1554 else
1555 {
1556 SCIPdebugMsg(scip, " -> new watched variables <%s> and <%s> of constraint <%s> are still undecided\n",
1557 SCIPvarGetName(vars[watchedvar1]), SCIPvarGetName(vars[watchedvar2]), SCIPconsGetName(cons));
1558
1559 /* switch to the new watched variables */
1560 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, watchedvar2) );
1561
1562 /* there are at least two undecided variables -> the constraint must be checked manually */
1563 *mustcheck = TRUE;
1564
1565 /* disable propagation of constraint until the corresponding bound of a watched variable changed */
1567
1568 /* increase aging counter */
1569 SCIP_CALL( SCIPaddConsAge(scip, cons, AGEINCREASE(consdata->nvars)) );
1570 }
1571
1572 return SCIP_OKAY;
1573}
1574
1575/** checks constraint for violation, returns TRUE iff constraint is violated */
1576static
1578 SCIP* scip, /**< SCIP data structure */
1579 SCIP_CONS* cons, /**< bound disjunction constraint to be checked */
1580 SCIP_SOL* sol /**< primal CIP solution */
1581 )
1582{
1583 SCIP_CONSDATA* consdata;
1584 SCIP_VAR** vars;
1585 SCIP_BOUNDTYPE* boundtypes;
1586 SCIP_Real* bounds;
1587 SCIP_Real solval;
1588 SCIP_Real viol;
1589 SCIP_Real absviol;
1590 int violpos;
1591 int nvars;
1592 int v;
1593
1594 consdata = SCIPconsGetData(cons);
1595 assert(consdata != NULL);
1596
1597 nvars = consdata->nvars;
1598 vars = consdata->vars;
1599 boundtypes = consdata->boundtypes;
1600 bounds = consdata->bounds;
1601 assert(nvars == 0 || vars != NULL);
1602 assert(nvars == 0 || boundtypes != NULL);
1603 assert(nvars == 0 || bounds != NULL);
1604
1605 /* check the given solution */
1606 absviol = SCIP_REAL_MAX;
1607 violpos = -1;
1608 for( v = 0; v < nvars; ++v )
1609 {
1610 solval = SCIPgetSolVal(scip, sol, vars[v]);
1611
1612 /* update absolute violation if needed */
1613 viol = (boundtypes[v] == SCIP_BOUNDTYPE_LOWER) ? bounds[v] - solval : solval - bounds[v];
1614 if( viol < absviol )
1615 {
1616 absviol = viol;
1617 violpos = v;
1618 }
1619
1620 if( (boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, vars[v], solval, bounds[v]))
1621 || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, vars[v], solval, bounds[v])) )
1622 {
1623 return FALSE;
1624 }
1625 }
1626 /* update constraint violation in solution */
1627 if( sol != NULL )
1628 {
1629 SCIP_Real relviol;
1630
1631 assert(0 == nvars || -1 != violpos);
1632
1633 if( 0 == nvars )
1634 relviol = SCIP_REAL_MAX;
1635 else
1636 relviol = SCIPrelDiff(SCIPgetSolVal(scip, sol, vars[violpos]), bounds[violpos]);
1637
1638 SCIPupdateSolConsViolation(scip, sol, absviol, relviol);
1639 }
1640 return TRUE;
1641}
1642
1643/* registers variables of a constraint as branching candidates
1644 * indicates whether an n-ary branch is necessary to enforce this constraint,
1645 * because all active literals are w.r.t. continuous variables which bound (in the literal) is at the variable's bound
1646 */
1647static
1649 SCIP* scip, /**< SCIP data structure */
1650 SCIP_CONS* cons, /**< bound disjunction constraint which variables should be registered for branching */
1651 SCIP_SOL* sol, /**< solution (NULL for LP solution) */
1652 SCIP_Bool* cutoff, /**< pointer to store whether the constraint cannot be made feasible by branching */
1653 SCIP_Bool* neednarybranch /**< pointer to store TRUE, if n-ary branching is necessary to enforce this constraint */
1654 )
1655{
1656 SCIP_CONSDATA* consdata;
1657 SCIP_VAR** vars;
1658 SCIP_BOUNDTYPE* boundtypes;
1659 SCIP_Real* bounds;
1660 SCIP_Real violation;
1661 SCIP_Real varlb;
1662 SCIP_Real varub;
1663 int nvars;
1664 int v;
1665
1666 assert(cons != NULL);
1667 assert(SCIPconsGetHdlr(cons) != NULL);
1668 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1669 assert(cutoff != NULL);
1670 assert(neednarybranch != NULL);
1671
1672 consdata = SCIPconsGetData(cons);
1673 assert(consdata != NULL);
1674 nvars = consdata->nvars;
1675 vars = consdata->vars;
1676 boundtypes = consdata->boundtypes;
1677 bounds = consdata->bounds;
1678 assert(nvars == 0 || vars != NULL);
1679 assert(nvars == 0 || boundtypes != NULL);
1680 assert(nvars == 0 || bounds != NULL);
1681
1682 *cutoff = TRUE;
1683 *neednarybranch = TRUE;
1684
1685 for( v = 0; v < nvars; ++v )
1686 {
1687 SCIP_VAR* var;
1688
1689 var = vars[v];
1690 assert(var != NULL);
1691
1692 /* constraint should be violated, so all bounds in the constraint have to be violated */
1693 assert( !(boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPisFeasGE(scip, SCIPgetSolVal(scip, sol, var), bounds[v])) &&
1694 !(boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPisFeasLE(scip, SCIPgetSolVal(scip, sol, var), bounds[v])) );
1695
1696 varlb = SCIPcomputeVarLbLocal(scip, var);
1697 varub = SCIPcomputeVarUbLocal(scip, var);
1698
1699 /* if literal is x >= varlb, but upper bound on x is < varlb, then this literal can never be satisfied,
1700 * thus there is no use for branching
1701 */
1702 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, varub, bounds[v]) )
1703 continue;
1704
1705 /* if literal is x <= varub, but lower bound on x is > varub, then this literal can never be satisfied,
1706 * thus there is no use for branching
1707 */
1708 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, varlb, bounds[v]) )
1709 continue;
1710
1711 /* if literal is always satisfied, then no need to branch on it may happen if propagation is disabled for some
1712 * reason and due to numerics current solution does not satisfy literal, but variable bounds do
1713 */
1714 if( isLiteralSatisfied(scip, consdata, v) )
1715 continue;
1716
1717 violation = SCIPgetSolVal(scip, sol, var) - bounds[v];
1718
1719 /* if variable is continuous, then we cannot branch on one of the variable bounds */
1720 if( SCIPvarIsIntegral(vars[v]) ||
1721 ((SCIPisInfinity(scip, -varlb) || !SCIPisFeasEQ(scip, bounds[v], varlb)) &&
1722 (SCIPisInfinity(scip, varub) || !SCIPisFeasEQ(scip, bounds[v], varub))) )
1723 {
1724 SCIP_CALL( SCIPaddExternBranchCand(scip, var, REALABS(violation), bounds[v]) );
1725 *neednarybranch = FALSE;
1726 }
1727 *cutoff = FALSE;
1728 }
1729
1730 return SCIP_OKAY;
1731}
1732
1733/** enforces the pseudo or LP solution on the given constraint */
1734static
1736 SCIP* scip, /**< SCIP data structure */
1737 SCIP_CONS* cons, /**< bound disjunction constraint to be separated */
1738 SCIP_SOL* sol, /**< solution which should be enforced (NULL for LP solution) */
1739 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1740 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1741 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
1742 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1743 SCIP_Bool* registeredbrcand /**< pointer to store TRUE, if branching variable candidates were registered or was already true */
1744 )
1745{
1746 SCIP_Bool mustcheck;
1747 SCIP_Bool neednarybranch;
1748
1749 assert(cons != NULL);
1750 assert(SCIPconsGetHdlr(cons) != NULL);
1751 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1752 assert(cutoff != NULL);
1753 assert(infeasible != NULL);
1754 assert(reduceddom != NULL);
1755 assert(registeredbrcand != NULL);
1756
1757 SCIPdebugMsg(scip, "enforce bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
1758
1759 /* update and check the watched variables, if they were changed since last processing */
1761 {
1762 SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, infeasible, reduceddom, &mustcheck) );
1763 }
1764 else
1765 mustcheck = TRUE;
1766
1767 if( mustcheck )
1768 {
1769 if( isConsViolated(scip, cons, sol) )
1770 {
1771 /* constraint was infeasible -> reset age */
1773 *infeasible = TRUE;
1774
1775 /* register branching candidates */
1776 SCIP_CALL( registerBranchingCandidates(scip, cons, sol, cutoff, &neednarybranch) );
1777
1778 if( !neednarybranch )
1779 *registeredbrcand = TRUE;
1780 }
1781 }
1782
1783 return SCIP_OKAY;
1784}
1785
1786/** enforces a constraint by creating an n-ary branch consisting of a set of child nodes, each enforcing one literal
1787 */
1788static
1790 SCIP* scip, /**< SCIP data structure */
1791 SCIP_CONS* cons, /**< bound disjunction constraint to branch on */
1792 SCIP_SOL* sol /**< solution which should be enforced (NULL for LP solution) */
1793 )
1794{
1795 SCIP_CONSDATA* consdata;
1796 SCIP_VAR** vars;
1797 SCIP_BOUNDTYPE* boundtypes;
1798 SCIP_Real* bounds;
1799 SCIP_Real varlb;
1800 SCIP_Real varub;
1801 int nvars;
1802 int v;
1803
1804 SCIP_Real priority;
1805 SCIP_Real estimate;
1806 SCIP_NODE* node;
1807
1808 assert(cons != NULL);
1809 assert(SCIPconsGetHdlr(cons) != NULL);
1810 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1811
1812 consdata = SCIPconsGetData(cons);
1813 assert(consdata != NULL);
1814 nvars = consdata->nvars;
1815 vars = consdata->vars;
1816 boundtypes = consdata->boundtypes;
1817 bounds = consdata->bounds;
1818 assert(nvars == 0 || vars != NULL);
1819 assert(nvars == 0 || boundtypes != NULL);
1820 assert(nvars == 0 || bounds != NULL);
1821
1822 for( v = 0; v < nvars; ++v )
1823 {
1824 SCIP_VAR* var;
1825
1826 var = vars[v];
1827 assert(var != NULL);
1828
1829 /* constraint should be violated, so all bounds in the constraint have to be violated */
1830 assert( !(boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPgetSolVal(scip, sol, var), bounds[v])) && /*lint !e666*/
1831 !(boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPgetSolVal(scip, sol, var), bounds[v])) ); /*lint !e666*/
1832
1833 varlb = SCIPcomputeVarLbLocal(scip, var);
1834 varub = SCIPcomputeVarUbLocal(scip, var);
1835
1836 /* if literal is x >= varlb, but upper bound on x is < varlb, then this literal can never be satisfied,
1837 * thus there is no use in creating an extra child for it
1838 */
1839 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, varub, bounds[v]) )
1840 continue;
1841 /* if literal is x <= varub, but lower bound on x is > varub, then this literal can never be satisfied,
1842 * thus there is no use in creating an extra child for it
1843 */
1844 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, varlb, bounds[v]) )
1845 continue;
1846 /* if literal is always satisfied, then no need to branch on it */
1847 if( isLiteralSatisfied(scip, consdata, v) )
1848 continue;
1849
1850 /* create a child that enforces the current literal */
1851 priority = SCIPcalcNodeselPriority(scip, var, boundtypes[v] == SCIP_BOUNDTYPE_LOWER ?
1853 estimate = SCIPcalcChildEstimate (scip, var, bounds[v]);
1854
1855 SCIPdebugMsg(scip, " -> creating child to enforce: <%s> %c= %g (priority: %g, estimate: %g)\n",
1856 SCIPvarGetName(vars[v]), boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? '>' : '<', bounds[v], priority, estimate);
1857
1858 SCIP_CALL( SCIPcreateChild(scip, &node, priority, estimate) );
1859
1860 /* enforce current literal */
1862 {
1863 SCIP_CONS* brcons;
1864 SCIP_Real one;
1865
1866 one = 1.0;
1867
1868 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1869 {
1870 SCIP_CALL( SCIPcreateConsLinear(scip, &brcons, "bounddisjbranch", 1, &var, &one, bounds[v], SCIPinfinity(scip),
1874 SCIPconsIsStickingAtNode(cons)) );
1875 }
1876 else
1877 {
1878 SCIP_CALL( SCIPcreateConsLinear(scip, &brcons, "bounddisjbranch", 1, &var, &one, -SCIPinfinity(scip), bounds[v],
1882 SCIPconsIsStickingAtNode(cons)) );
1883 }
1884 SCIP_CALL( SCIPaddConsNode(scip, node, brcons, NULL) );
1885 SCIP_CALL( SCIPreleaseCons(scip, &brcons) );
1886 }
1887 else
1888 {
1889 assert(SCIPvarIsActive(var));
1890 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1891 {
1892 SCIP_CALL( SCIPchgVarLbNode(scip, node, var, bounds[v]) );
1893 }
1894 else
1895 {
1896 SCIP_CALL( SCIPchgVarUbNode(scip, node, var, bounds[v]) );
1897 }
1898 }
1899
1900 /* delete bound disjunction constraint from child node */
1901 SCIP_CALL( SCIPdelConsNode(scip, node, cons) );
1902 }
1903
1904 return SCIP_OKAY;
1905}
1906
1907/** helper function to enforce constraints */
1908static
1910 SCIP* scip, /**< SCIP data structure */
1911 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1912 SCIP_CONS** conss, /**< constraints to process */
1913 int nconss, /**< number of constraints */
1914 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
1915 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
1916 )
1917{
1918 SCIP_CONSHDLRDATA* conshdlrdata;
1919 SCIP_Bool cutoff;
1920 SCIP_Bool infeasible;
1921 SCIP_Bool reduceddom;
1922 SCIP_Bool registeredbrcand;
1923 SCIP_Bool infeasiblecons;
1924 int c;
1925 int nnarybranchconsvars;
1926 SCIP_CONS* narybranchcons; /* constraint that is a candidate for an n-ary branch */
1927
1928 assert(conshdlr != NULL);
1929 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1930 assert(nconss == 0 || conss != NULL);
1931 assert(result != NULL);
1932
1933 SCIPdebugMsg(scip, "Enforcing %d bound disjunction constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
1934
1935 *result = SCIP_FEASIBLE;
1936
1937 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1938 assert(conshdlrdata != NULL);
1939
1940 cutoff = FALSE;
1941 infeasible = FALSE;
1942 reduceddom = FALSE;
1943 registeredbrcand = FALSE;
1944 narybranchcons = NULL;
1945 nnarybranchconsvars = INT_MAX;
1946
1947 /* check all bound disjunction constraints for feasibility */
1948 for( c = 0; c < nconss && !cutoff && !reduceddom; ++c )
1949 {
1950 infeasiblecons = FALSE;
1951 SCIP_CALL( enforceCurrentSol(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &infeasiblecons, &reduceddom,
1952 &registeredbrcand) );
1953 infeasible |= infeasiblecons;
1954 if( infeasiblecons && !registeredbrcand )
1955 {
1956 /* if cons. c has less literals than the previous candidate for an n-ary branch, then keep cons. c as candidate for n-ary branch */
1957 if( narybranchcons == NULL || SCIPconsGetData(conss[c])->nvars < nnarybranchconsvars )
1958 {
1959 narybranchcons = conss[c];
1960 nnarybranchconsvars = SCIPconsGetData(narybranchcons)->nvars;
1961 assert(nnarybranchconsvars > 0);
1962 }
1963 }
1964 }
1965
1966 if( cutoff )
1967 *result = SCIP_CUTOFF;
1968 else if( reduceddom )
1969 *result = SCIP_REDUCEDDOM;
1970 else if( infeasible )
1971 {
1972 if( registeredbrcand )
1973 {
1974 *result = SCIP_INFEASIBLE;
1975 }
1976 else
1977 {
1978 SCIP_CALL( createNAryBranch(scip, narybranchcons, sol) );
1979 *result = SCIP_BRANCHED;
1980 }
1981 }
1982
1983 return SCIP_OKAY;
1984}
1985
1986/** adds symmetry information of constraint to a symmetry detection graph */
1987static
1989 SCIP* scip, /**< SCIP pointer */
1990 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
1991 SCIP_CONS* cons, /**< constraint */
1992 SYM_GRAPH* graph, /**< symmetry detection graph */
1993 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
1994 )
1995{
1996 SCIP_CONSDATA* consdata;
1997 SCIP_VAR** vars;
1998 SCIP_Real* vals;
1999 SCIP_Real constant;
2001 int consnodeidx;
2002 int opnodeidx;
2003 int nodeidx;
2004 int nconsvars;
2005 int nlocvars;
2006 int nvars;
2007 int i;
2008
2009 assert(scip != NULL);
2010 assert(cons != NULL);
2011 assert(graph != NULL);
2012 assert(success != NULL);
2013
2014 *success = TRUE;
2015
2016 consdata = SCIPconsGetData(cons);
2017 assert(consdata != NULL);
2018
2019 /* add node initializing constraint (with artificial rhs) */
2020 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
2021
2022 /* create nodes and edges for each literal in the bounddisjunction */
2023 nvars = SCIPgetNVars(scip);
2024 nconsvars = consdata->nvars;
2025
2026 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
2027 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
2028
2029 for( i = 0; i < nconsvars; ++i )
2030 {
2031 /* add node and edge for bound expression of literal */
2032 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_BDDISJ, &opnodeidx) ); /*lint !e641*/
2033 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, opnodeidx, FALSE, 0.0) );
2034
2035 /* get active variables */
2036 vars[0] = consdata->vars[i];
2037 vals[0] = consdata->boundtypes[i] == SCIP_BOUNDTYPE_UPPER ? 1.0 : -1.0;
2038 nlocvars = 1;
2039 constant = 0.0;
2040
2041 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant,
2043
2044 /* add node and edge for bound on literal (bound adapted by constant) */
2045 bound = consdata->boundtypes[i] == SCIP_BOUNDTYPE_UPPER ? consdata->bounds[i] : -consdata->bounds[i];
2046 bound -= constant;
2047
2048 SCIP_CALL( SCIPaddSymgraphValnode(scip, graph, bound, &nodeidx) );
2049 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, FALSE, 0.0) );
2050
2051 /* check whether variable is (multi-)aggregated */
2052 nodeidx = opnodeidx;
2053 if( nlocvars > 1 )
2054 {
2055 /* encode aggregation by a sum-expression and connect it to bdexpr node */
2056 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &nodeidx) ); /*lint !e641*/
2057 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, FALSE, 0.0) );
2058 }
2059
2060 /* add nodes and edges for variables in aggregation (ignore constant, has been treated above) */
2061 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, nlocvars, 0.0) );
2062 }
2063
2064 SCIPfreeBufferArray(scip, &vals);
2065 SCIPfreeBufferArray(scip, &vars);
2066
2067 return SCIP_OKAY;
2068}
2069
2070/**@} */
2071
2072/**@name Callback methods of constraint handler
2073 *
2074 * @{
2075 */
2076
2077/** copy method for constraint handler plugins (called when SCIP copies plugins) */
2078static
2079SCIP_DECL_CONSHDLRCOPY(conshdlrCopyBounddisjunction)
2080{ /*lint --e{715}*/
2081 assert(scip != NULL);
2082 assert(conshdlr != NULL);
2083 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2084
2085 /* call inclusion method of constraint handler */
2087
2088 *valid = TRUE;
2089
2090 return SCIP_OKAY;
2091}
2092
2093/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
2094static
2095SCIP_DECL_CONSFREE(consFreeBounddisjunction)
2096{ /*lint --e{715}*/
2097 SCIP_CONSHDLRDATA* conshdlrdata;
2098
2099 assert(conshdlr != NULL);
2100 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2101 assert(scip != NULL);
2102
2103 /* free constraint handler data */
2104 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2105 assert(conshdlrdata != NULL);
2106
2107 conshdlrdataFree(scip, &conshdlrdata);
2108
2109 SCIPconshdlrSetData(conshdlr, NULL);
2110
2111 return SCIP_OKAY;
2112}
2113
2114
2115/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
2116static
2117SCIP_DECL_CONSEXITPRE(consExitpreBounddisjunction)
2118{ /*lint --e{715}*/
2119 SCIP_CONSHDLRDATA* conshdlrdata;
2120 SCIP_CONS* cons;
2121 SCIP_Bool redundant;
2122 int c;
2123
2124 assert(conshdlr != NULL);
2125 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2126 assert(scip != NULL);
2127
2128 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2129 assert(conshdlrdata != NULL);
2130
2131 /* fast processing of constraints, apply global bounds and remove fixed variables */
2132 for( c = 0; c < nconss; ++c )
2133 {
2134 cons = conss[c];
2135 assert(cons != NULL);
2136
2137 SCIPdebugMsg(scip, "exit-presolving bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2138
2139 if( SCIPconsIsDeleted(cons) )
2140 continue;
2141
2142 /* remove all literals that are violated in global bounds, check redundancy due to global bounds */
2143 SCIP_CALL( applyGlobalBounds(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2144
2145 if( !redundant )
2146 {
2147 /* replace variables by their representative active (or multi-aggregated) variables */
2148 SCIP_CALL( removeFixedVariables(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2149 }
2150
2151 if( redundant && SCIPconsIsAdded(cons) )
2152 {
2153 SCIPdebugMsg(scip, "bound disjunction constraint <%s> is redundant\n", SCIPconsGetName(cons));
2154 SCIP_CALL( SCIPdelCons(scip, cons) );
2155 }
2156 }
2157
2158 return SCIP_OKAY;
2159}
2160
2161/** solving process initialization method of constraint handler */
2162static
2163SCIP_DECL_CONSINITSOL(consInitsolBounddisjunction)
2164{ /*lint --e{715}*/
2165 /* add nlrow representation to NLP, if NLP had been constructed and disjunction is simple enough */
2167 {
2168 SCIP_CONSDATA* consdata;
2169 SCIP_NLROW* nlrow;
2170 SCIP_EXPR* expr;
2171 SCIP_EXPR* exprvar;
2172 SCIP_Real lincoef;
2173 SCIP_Real a, b;
2174 int c;
2175
2176 for( c = 0; c < nconss; ++c )
2177 {
2178 /* skip deactivated or redundant constraints */
2179 if( !SCIPconsIsActive(conss[c]) || !SCIPconsIsChecked(conss[c]) )
2180 return SCIP_OKAY;
2181
2182 assert(!SCIPconsIsLocal(conss[c])); /* we are at the root node (or short before) */
2183
2184 consdata = SCIPconsGetData(conss[c]);
2185 assert(consdata != NULL);
2186
2187 /* look for a bounddisjunction of the form
2188 * x <= a or x >= b with a < b
2189 * only one of the inequalities can be strictly satisfied, so we can reformulate as
2190 * (x-a)*(b-x) <= 0
2191 * this should be sufficient to get bounddisjunction constraints that represent semi-continuous variables into the NLP
2192 */
2193
2194 if( consdata->nvars != 2 )
2195 continue;
2196
2197 if( consdata->vars[0] != consdata->vars[1] )
2198 continue;
2199
2200 if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_UPPER && consdata->boundtypes[1] == SCIP_BOUNDTYPE_LOWER )
2201 {
2202 a = consdata->bounds[0];
2203 b = consdata->bounds[1];
2204 }
2205 else if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER && consdata->boundtypes[1] == SCIP_BOUNDTYPE_UPPER )
2206 {
2207 a = consdata->bounds[1];
2208 b = consdata->bounds[0];
2209 }
2210 else
2211 {
2212 continue;
2213 }
2214
2215 if( a >= b )
2216 continue;
2217
2218 SCIP_CALL( SCIPcreateExprVar(scip, &exprvar, consdata->vars[0], NULL, NULL) );
2219 SCIP_CALL( SCIPcreateExprPow(scip, &expr, exprvar, 2.0, NULL, NULL) );
2220
2221 /* add xb-xx-ab+ax <= 0 as -ab <= -(a+b)x + x^2 */
2222 lincoef = -a - b;
2223 SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[c]),
2224 0.0, 1, consdata->vars, &lincoef, expr, -a*b, SCIPinfinity(scip), SCIP_EXPRCURV_CONVEX) );
2225
2226 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
2227 SCIP_CALL( SCIPreleaseExpr(scip, &exprvar) );
2228
2229 SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
2230 SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
2231 }
2232 }
2233
2234 return SCIP_OKAY;
2235}
2236
2237/** frees specific constraint data */
2238static
2239SCIP_DECL_CONSDELETE(consDeleteBounddisjunction)
2240{ /*lint --e{715}*/
2241 assert(conshdlr != NULL);
2242 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2243 assert(consdata != NULL);
2244 assert(*consdata != NULL);
2245
2246 /* free LP row and bound disjunction constraint */
2247 consdataFree(scip, consdata);
2248
2249 return SCIP_OKAY;
2250}
2251
2252
2253/** transforms constraint data into data belonging to the transformed problem */
2254static
2255SCIP_DECL_CONSTRANS(consTransBounddisjunction)
2256{ /*lint --e{715}*/
2257 SCIP_CONSDATA* sourcedata;
2258 SCIP_CONSDATA* targetdata;
2259
2260 /*debugMsg(scip, "Trans method of bound disjunction constraints\n");*/
2261
2262 assert(conshdlr != NULL);
2263 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2265 assert(sourcecons != NULL);
2266 assert(targetcons != NULL);
2267
2268 sourcedata = SCIPconsGetData(sourcecons);
2269 assert(sourcedata != NULL);
2270
2271 /* create constraint data for target constraint */
2272 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars,
2273 sourcedata->boundtypes, sourcedata->bounds) );
2274
2275 /* create target constraint */
2276 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
2277 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
2278 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
2279 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
2280 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
2281
2282 return SCIP_OKAY;
2283}
2284
2285
2286/** constraint enforcing method of constraint handler for LP solutions */
2287static
2288SCIP_DECL_CONSENFOLP(consEnfolpBounddisjunction)
2289{ /*lint --e{715}*/
2290 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, NULL, result) );
2291
2292 return SCIP_OKAY;
2293}
2294
2295
2296/** constraint enforcing method of constraint handler for relaxation solutions */
2297static
2298SCIP_DECL_CONSENFORELAX(consEnforelaxBounddisjunction)
2299{ /*lint --e{715}*/
2300 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, sol, result) );
2301
2302 return SCIP_OKAY;
2303}
2304
2305
2306/** constraint enforcing method of constraint handler for pseudo solutions */
2307static
2308SCIP_DECL_CONSENFOPS(consEnfopsBounddisjunction)
2309{ /*lint --e{715}*/
2310 SCIP_CONSHDLRDATA* conshdlrdata;
2311 SCIP_Bool cutoff;
2312 SCIP_Bool infeasible;
2313 SCIP_Bool reduceddom;
2314 SCIP_Bool registeredbrcand;
2315 int c;
2316 SCIP_CONS* narybranchcons; /* constraint that is a candidate for an n-ary branch */
2317
2318 assert(conshdlr != NULL);
2319 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2320 assert(nconss == 0 || conss != NULL);
2321 assert(result != NULL);
2322
2323 SCIPdebugMsg(scip, "pseudo enforcing %d bound disjunction constraints\n", nconss);
2324
2325 *result = SCIP_FEASIBLE;
2326
2327 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2328 assert(conshdlrdata != NULL);
2329
2330 cutoff = FALSE;
2331 infeasible = FALSE;
2332 reduceddom = FALSE;
2333 registeredbrcand = FALSE;
2334 narybranchcons = NULL;
2335
2336 /* check all bound disjunction constraints for feasibility */
2337 for( c = 0; c < nconss && !cutoff && !reduceddom; ++c )
2338 {
2339 SCIP_CALL( enforceCurrentSol(scip, conss[c], NULL, conshdlrdata->eventhdlr, &cutoff, &infeasible, &reduceddom,
2340 &registeredbrcand) );
2341 if( infeasible && !registeredbrcand )
2342 {
2343 /* if cons. c has less literals than the previous candidate for an n-ary branch, then keep cons. c as candidate for n-ary branch */
2344 if( !narybranchcons || SCIPconsGetData(conss[c])->nvars < SCIPconsGetData(narybranchcons)->nvars )
2345 narybranchcons = conss[c];
2346 }
2347 }
2348
2349 if( cutoff )
2350 *result = SCIP_CUTOFF;
2351 else if( reduceddom )
2352 *result = SCIP_REDUCEDDOM;
2353 else if( infeasible )
2354 {
2355 if( registeredbrcand )
2356 {
2357 *result = SCIP_INFEASIBLE;
2358 }
2359 else
2360 {
2361 SCIP_CALL( createNAryBranch(scip, narybranchcons, NULL) );
2362 *result = SCIP_BRANCHED;
2363 }
2364 }
2365
2366 return SCIP_OKAY;
2367}
2368
2369
2370/** feasibility check method of constraint handler for integral solutions */
2371static
2372SCIP_DECL_CONSCHECK(consCheckBounddisjunction)
2373{ /*lint --e{715}*/
2374 SCIP_CONS* cons;
2375 SCIP_CONSDATA* consdata;
2376 int c;
2377
2378 assert(conshdlr != NULL);
2379 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2380 assert(nconss == 0 || conss != NULL);
2381 assert(result != NULL);
2382
2383 *result = SCIP_FEASIBLE;
2384
2385 /* check all bound disjunction constraints for feasibility */
2386 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
2387 {
2388 cons = conss[c];
2389 consdata = SCIPconsGetData(cons);
2390 assert(consdata != NULL);
2391
2392 if( isConsViolated(scip, cons, sol) )
2393 {
2394 if( printreason )
2395 {
2396 int v;
2397
2398 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
2399 SCIPinfoMessage(scip, NULL, ";\nviolation: ");
2400 for( v = 0; v < consdata->nvars; ++v )
2401 {
2402 assert(consdata->vars[v] != NULL);
2403 if( v > 0 )
2404 SCIPinfoMessage(scip, NULL, ", ");
2405 SCIPinfoMessage(scip, NULL, "<%s> = %.15g",
2406 SCIPvarGetName(consdata->vars[v]), SCIPgetSolVal(scip, sol, consdata->vars[v]));
2407 }
2408 SCIPinfoMessage(scip, NULL, ")\n");
2409 }
2410
2411 /* constraint is violated */
2412 *result = SCIP_INFEASIBLE;
2413 }
2414 }
2415
2416 return SCIP_OKAY;
2417}
2418
2419
2420/** domain propagation method of constraint handler */
2421static
2422SCIP_DECL_CONSPROP(consPropBounddisjunction)
2423{ /*lint --e{715}*/
2424 SCIP_CONSHDLRDATA* conshdlrdata;
2425 SCIP_Bool cutoff;
2426 SCIP_Bool infeasible;
2427 SCIP_Bool reduceddom;
2428 SCIP_Bool mustcheck;
2429 SCIP_Bool consreduceddom;
2430 int c;
2431
2432 assert(conshdlr != NULL);
2433 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2434 assert(nconss == 0 || conss != NULL);
2435 assert(result != NULL);
2436
2437 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2438 assert(conshdlrdata != NULL);
2439
2440 cutoff = FALSE;
2441 infeasible = FALSE;
2442 reduceddom = FALSE;
2443
2444 /* propagate all useful bound disjunction constraints */
2445 for( c = 0; c < nusefulconss && !cutoff; ++c )
2446 {
2447 SCIP_CALL( processWatchedVars(scip, conss[c], conshdlrdata->eventhdlr,
2448 &cutoff, &infeasible, &consreduceddom, &mustcheck) );
2449 reduceddom = reduceddom || consreduceddom;
2450 }
2451
2452 /* return the correct result */
2453 if( cutoff )
2454 *result = SCIP_CUTOFF;
2455 else if( reduceddom )
2456 *result = SCIP_REDUCEDDOM;
2457 else
2458 *result = SCIP_DIDNOTFIND;
2459
2460 return SCIP_OKAY; /*lint !e438*/
2461}
2462
2463
2464/** presolving method of constraint handler */
2465static
2466SCIP_DECL_CONSPRESOL(consPresolBounddisjunction)
2467{ /*lint --e{715}*/
2468 SCIP_CONSHDLRDATA* conshdlrdata;
2469 SCIP_CONS* cons;
2470 SCIP_CONSDATA* consdata;
2471 SCIP_Bool infeasible;
2472 SCIP_Bool redundant;
2473 SCIP_Bool tightened;
2474 int c;
2475
2476 assert(conshdlr != NULL);
2477 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2478 assert(scip != NULL);
2479 assert(result != NULL);
2480
2481 *result = SCIP_DIDNOTFIND;
2482
2483 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2484 assert(conshdlrdata != NULL);
2485
2486 /* process constraints */
2487 for( c = 0; c < nconss && *result != SCIP_CUTOFF && !SCIPisStopped(scip); ++c )
2488 {
2489 cons = conss[c];
2490 assert(cons != NULL);
2491 consdata = SCIPconsGetData(cons);
2492 assert(consdata != NULL);
2493
2494 SCIPdebugMsg(scip, "presolving bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2495
2496 /* force presolving the constraint in the initial round */
2497 if( nrounds == 0 )
2498 {
2500 }
2501
2502 /* remove all literals that are violated in global bounds, check redundancy due to global bounds */
2503 SCIP_CALL( applyGlobalBounds(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2504
2505 if( !redundant )
2506 {
2507 /* replace variables by their representative active (or multi-aggregated) variables */
2508 SCIP_CALL( removeFixedVariables(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2509 }
2510
2511 /**@todo find pairs of negated variables in constraint: constraint is redundant */
2512 /**@todo find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
2513
2514 if( redundant )
2515 {
2516 SCIPdebugMsg(scip, "bound disjunction constraint <%s> is redundant\n", SCIPconsGetName(cons));
2517 SCIP_CALL( SCIPdelCons(scip, cons) );
2518 (*ndelconss)++;
2519 *result = SCIP_SUCCESS;
2520 continue;
2521 }
2522 else if( !SCIPconsIsModifiable(cons) )
2523 {
2524 /* if unmodifiable constraint has no variables, it is infeasible,
2525 * if unmodifiable constraint has only one variable, the literal can be satisfied and the constraint deleted
2526 */
2527 if( consdata->nvars == 0 )
2528 {
2529 SCIPdebugMsg(scip, "bound disjunction constraint <%s> is infeasible\n", SCIPconsGetName(cons));
2530 *result = SCIP_CUTOFF;
2531 return SCIP_OKAY;
2532 }
2533
2534 if( SCIPconsGetNUpgradeLocks(cons) >= 1 )
2535 continue;
2536
2537 if( consdata->nvars == 1 )
2538 {
2539 SCIPdebugMsg(scip, "bound disjunction constraint <%s> has only one undecided literal\n",
2540 SCIPconsGetName(cons));
2541
2542 assert(consdata->vars != NULL);
2543 assert(!isLiteralSatisfied(scip, consdata, 0));
2544 assert(!isLiteralViolated(scip, consdata, 0));
2545
2546 if( SCIPvarIsActive(consdata->vars[0]) )
2547 {
2548 if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER )
2549 {
2550 SCIP_CALL( SCIPtightenVarLb(scip, consdata->vars[0], consdata->bounds[0], TRUE, &infeasible, &tightened) );
2551 }
2552 else
2553 {
2554 SCIP_CALL( SCIPtightenVarUb(scip, consdata->vars[0], consdata->bounds[0], TRUE, &infeasible, &tightened) );
2555 }
2556 if( infeasible )
2557 {
2558 SCIPdebugMsg(scip, " -> infeasible fixing\n");
2559 *result = SCIP_CUTOFF;
2560 return SCIP_OKAY;
2561 }
2562 assert(tightened);
2563 (*nchgbds)++;
2564 }
2565 else
2566 {
2567 /* upgrade to a linear constraint, if vars[0] is multi-aggregated */
2568 SCIP_CONS* lincons;
2569 SCIP_Real one;
2570
2571 assert(SCIPvarGetStatus(consdata->vars[0]) == SCIP_VARSTATUS_MULTAGGR);
2572
2573 one = 1.0;
2574 if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER )
2575 {
2577 1, &consdata->vars[0], &one, consdata->bounds[0], SCIPinfinity(scip),
2581 SCIPconsIsStickingAtNode(cons)) );
2582 }
2583 else
2584 {
2586 1, &consdata->vars[0], &one, -SCIPinfinity(scip), consdata->bounds[0],
2590 SCIPconsIsStickingAtNode(cons)) );
2591 }
2592
2593 /* add the upgraded constraint to the problem */
2594 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &lincons) );
2595 ++(*nupgdconss);
2596 }
2597
2598 SCIP_CALL( SCIPdelCons(scip, cons) );
2599 (*ndelconss)++;
2600 *result = SCIP_SUCCESS;
2601 continue;
2602 }
2603 else
2604 {
2605 /* try to upgrade the bounddisjunction constraint */
2606 SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
2607 }
2608 }
2609 }
2610
2611 /**@todo preprocess pairs of bound disjunction constraints */
2612
2613 return SCIP_OKAY;
2614}
2615
2616
2617/** propagation conflict resolving method of constraint handler */
2618static
2619SCIP_DECL_CONSRESPROP(consRespropBounddisjunction)
2620{ /*lint --e{715}*/
2621 SCIP_CONSDATA* consdata;
2622 SCIP_VAR** vars;
2623 SCIP_BOUNDTYPE* boundtypes;
2624#ifndef NDEBUG
2625 SCIP_Real* bounds;
2626#endif
2627 int v;
2628
2629 assert(conshdlr != NULL);
2630 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2631 assert(cons != NULL);
2632 assert(infervar != NULL);
2633 assert(result != NULL);
2634
2635 consdata = SCIPconsGetData(cons);
2636 assert(consdata != NULL);
2637 assert(consdata->vars != NULL);
2638 assert(consdata->nvars > 0);
2639 assert(0 <= inferinfo && inferinfo < consdata->nvars);
2640 assert(consdata->vars[inferinfo] == infervar);
2641
2642 vars = consdata->vars;
2643 boundtypes = consdata->boundtypes;
2644#ifndef NDEBUG
2645 bounds = consdata->bounds;
2646 assert(bounds != NULL);
2647#endif
2648 assert(boundtypes != NULL);
2649
2650 SCIPdebugMsg(scip, "conflict resolving method of bound disjunction constraint handler\n");
2651
2652 /* the only deductions are bounds tightened to a literal's bound on bound disjunction constraints where all other
2653 * literals are violated
2654 */
2655 assert((boundtypes[inferinfo] == SCIP_BOUNDTYPE_LOWER
2656 && SCIPisFeasGE(scip, SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE), bounds[inferinfo]))
2657 || (boundtypes[inferinfo] == SCIP_BOUNDTYPE_UPPER
2658 && SCIPisFeasLE(scip, SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE), bounds[inferinfo])));
2659
2660 for( v = 0; v < consdata->nvars; ++v )
2661 {
2662 if( v != inferinfo )
2663 {
2664 assert(consdata->vars[v] != infervar || consdata->boundtypes[v] != consdata->boundtypes[inferinfo]);
2665
2666 /* the reason literal must have been violated
2667 * we do not check for multi-aggregated variables, since SCIPgetVarXbAtIndex is not implemented for them */
2668 /* Use a weaker comparison to SCIPgetVarXbAtIndex here (i.e., SCIPisXT instead of SCIPisFeasXT),
2669 * because SCIPgetVarXbAtIndex might differ from the local bound at time bdchgidx by epsilon. */
2670 assert(SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_MULTAGGR
2671 || (boundtypes[v] == SCIP_BOUNDTYPE_LOWER
2672 && SCIPisLT(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, TRUE), bounds[v]))
2673 || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER
2674 && SCIPisGT(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, TRUE), bounds[v])));
2675 SCIP_CALL( SCIPaddConflictBd(scip, vars[v], SCIPboundtypeOpposite(boundtypes[v]), bdchgidx) );
2676 }
2677 }
2678
2679 *result = SCIP_SUCCESS;
2680
2681 return SCIP_OKAY;
2682}
2683
2684
2685/** variable rounding lock method of constraint handler */
2686static
2687SCIP_DECL_CONSLOCK(consLockBounddisjunction)
2688{ /*lint --e{715}*/
2689 SCIP_CONSDATA* consdata;
2690 int i;
2691
2692 consdata = SCIPconsGetData(cons);
2693 assert(consdata != NULL);
2694
2695 /* lock every single coefficient */
2696 for( i = 0; i < consdata->nvars; ++i )
2697 {
2698 if( consdata->boundtypes[i] == SCIP_BOUNDTYPE_LOWER )
2699 {
2700 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
2701 }
2702 else
2703 {
2704 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
2705 }
2706 }
2707
2708 return SCIP_OKAY;
2709}
2710
2711
2712/** constraint activation notification method of constraint handler */
2713static
2714SCIP_DECL_CONSACTIVE(consActiveBounddisjunction)
2715{ /*lint --e{715}*/
2716 SCIP_CONSHDLRDATA* conshdlrdata;
2717 SCIP_CONSDATA* consdata;
2718
2719 assert(conshdlr != NULL);
2720 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2721 assert(cons != NULL);
2722 assert(SCIPconsIsTransformed(cons));
2723
2724 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2725 assert(conshdlrdata != NULL);
2726 consdata = SCIPconsGetData(cons);
2727 assert(consdata != NULL);
2728 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
2729
2730 SCIPdebugMsg(scip, "activating information for bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2731 SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
2732
2733 /* catch events on watched variables */
2734 if( consdata->watchedvar1 != -1 )
2735 {
2736 SCIP_CALL( catchEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar1,
2737 &consdata->filterpos1) );
2738 }
2739 if( consdata->watchedvar2 != -1 )
2740 {
2741 SCIP_CALL( catchEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar2,
2742 &consdata->filterpos2) );
2743 }
2744
2745 return SCIP_OKAY;
2746}
2747
2748
2749/** constraint deactivation notification method of constraint handler */
2750static
2751SCIP_DECL_CONSDEACTIVE(consDeactiveBounddisjunction)
2752{ /*lint --e{715}*/
2753 SCIP_CONSHDLRDATA* conshdlrdata;
2754 SCIP_CONSDATA* consdata;
2755
2756 assert(conshdlr != NULL);
2757 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2758 assert(cons != NULL);
2759 assert(SCIPconsIsTransformed(cons));
2760
2761 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2762 assert(conshdlrdata != NULL);
2763 consdata = SCIPconsGetData(cons);
2764 assert(consdata != NULL);
2765 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
2766
2767 SCIPdebugMsg(scip, "deactivating information for bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2768 SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
2769
2770 /* drop events on watched variables */
2771 if( consdata->watchedvar1 != -1 )
2772 {
2773 assert(consdata->filterpos1 != -1);
2774 SCIP_CALL( dropEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
2775 consdata->watchedvar1 = -1;
2776 }
2777 if( consdata->watchedvar2 != -1 )
2778 {
2779 assert(consdata->filterpos2 != -1);
2780 SCIP_CALL( dropEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
2781 consdata->watchedvar2 = -1;
2782 }
2783
2784 return SCIP_OKAY;
2785}
2786
2787
2788/** constraint display method of constraint handler */
2789static
2790SCIP_DECL_CONSPRINT(consPrintBounddisjunction)
2791{ /*lint --e{715}*/
2792 assert( scip != NULL );
2793 assert( conshdlr != NULL );
2794 assert( cons != NULL );
2795
2796 consdataPrint(scip, SCIPconsGetData(cons), file, FALSE);
2797
2798 return SCIP_OKAY;
2799}
2800
2801/** constraint copying method of constraint handler */
2802static
2803SCIP_DECL_CONSCOPY(consCopyBounddisjunction)
2804{ /*lint --e{715}*/
2805 SCIP_VAR** sourcevars;
2806 SCIP_VAR** targetvars;
2807 SCIP_BOUNDTYPE* boundtypes;
2808 SCIP_Real* bounds;
2809 int nvars;
2810 int v;
2811
2812 assert(valid != NULL);
2813
2814 *valid = TRUE;
2815
2816 /* get source data */
2817 sourcevars = SCIPgetVarsBounddisjunction(sourcescip, sourcecons);
2818 nvars = SCIPgetNVarsBounddisjunction(sourcescip, sourcecons);
2819 boundtypes = SCIPgetBoundtypesBounddisjunction(sourcescip, sourcecons);
2820 bounds = SCIPgetBoundsBounddisjunction(sourcescip, sourcecons);
2821
2822 SCIP_CALL( SCIPallocBufferArray(scip, &targetvars, nvars) );
2823
2824 /* map source variables to active variables of the target SCIP */
2825 for( v = 0; v < nvars && *valid; ++v )
2826 {
2827 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &targetvars[v], varmap, consmap, global, valid) );
2828 assert(!(*valid) || targetvars[v] != NULL);
2829 }
2830
2831 /* only create the target constraint, if all variables could be copied */
2832 if( *valid )
2833 {
2834 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name ? name : SCIPconsGetName(sourcecons), nvars, targetvars, boundtypes,
2835 bounds, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2836 }
2837
2838 SCIPfreeBufferArray(scip, &targetvars);
2839
2840 return SCIP_OKAY;
2841}
2842
2843/** constraint parsing method of constraint handler */
2844static
2845SCIP_DECL_CONSPARSE(consParseBounddisjunction)
2846{ /*lint --e{715}*/
2847 SCIP_BOUNDTYPE* boundtypes;
2848 SCIP_Real* bounds;
2849 SCIP_VAR** vars;
2850 char* endptr;
2851 int varssize;
2852 int nvars;
2853
2854 assert( success != NULL );
2855 *success = TRUE;
2856
2857 SCIPdebugMsg(scip, "parse <%s> as bounddisjunction constraint\n", str);
2858
2859 /* skip white space */
2860 SCIP_CALL( SCIPskipSpace((char**)&str) );
2861
2862 /* check for string "bounddisjunction" */
2863 if( strncmp(str, "bounddisjunction(", 16) != 0 )
2864 {
2865 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "error during parsing: expected \"bounddisjunction(\" in <%s>.\n", str);
2866 *success = FALSE;
2867 return SCIP_OKAY;
2868 }
2869
2870 /* skip "bounddisjunction(" */
2871 str += 17;
2872
2873 varssize = 100;
2874 nvars = 0;
2875
2876 /* allocate buffer array for variables */
2877 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
2878 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, varssize) );
2879 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, varssize) );
2880
2881 /* parse string until ")" */
2882 while( *str != ')' )
2883 {
2884 SCIP_VAR* var;
2885
2886 /* parse variable name */
2887 SCIP_CALL( SCIPparseVarName(scip, str, &var, &endptr) );
2888
2889 if( var == NULL )
2890 {
2891 endptr = strchr(endptr, ')');
2892
2893 if( endptr == NULL )
2894 {
2895 *success = FALSE;
2896 goto TERMINATE;
2897 }
2898
2899 break;
2900 }
2901
2902 str = endptr;
2903
2904 /* skip white space */
2905 SCIP_CALL( SCIPskipSpace((char**)&str) );
2906
2907 /* parse bound type */
2908 switch( *str )
2909 {
2910 case '<':
2911 boundtypes[nvars] = SCIP_BOUNDTYPE_UPPER;
2912 break;
2913 case '>':
2914 boundtypes[nvars] = SCIP_BOUNDTYPE_LOWER;
2915 break;
2916 default:
2917 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "variable with name <%s> does not exist\n", SCIPvarGetName(var));
2918 *success = FALSE;
2919 goto TERMINATE;
2920 }
2921
2922 ++str;
2923 if( *str != '=' )
2924 {
2925 SCIPdebugMsg(scip, "expected '=': %s\n", str);
2926 *success = FALSE;
2927 goto TERMINATE;
2928 }
2929
2930 /* skip '=' */
2931 ++str;
2932
2933 /* parse bound value */
2934 if( !SCIPparseReal(scip, str, &bounds[nvars], &endptr) )
2935 {
2936 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error during parsing of the weight: %s\n", str);
2937 *success = FALSE;
2938 goto TERMINATE;
2939 }
2940
2941 str = endptr;
2942
2943 /* set variable */
2944 vars[nvars++] = var;
2945
2946 /* check if the size of the variable array was big enough */
2947 if( nvars > varssize )
2948 {
2949 /* reallocate memory */
2950 varssize *= 2;
2951 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
2952 SCIP_CALL( SCIPreallocBufferArray(scip, &boundtypes, varssize) );
2953 SCIP_CALL( SCIPreallocBufferArray(scip, &bounds, varssize) );
2954 }
2955
2956 /* skip white space */
2957 SCIP_CALL( SCIPskipSpace((char**)&str) );
2958
2959 /* skip ',' */
2960 if( *str == ',' )
2961 ++str;
2962 }
2963
2964 /* add bounddisjunction */
2965 if( *success && nvars > 0 )
2966 {
2967 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name, nvars, vars, boundtypes, bounds,
2968 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2969 }
2970
2971 TERMINATE:
2972 /* free variable buffer */
2973 SCIPfreeBufferArray(scip, &bounds);
2974 SCIPfreeBufferArray(scip, &boundtypes);
2975 SCIPfreeBufferArray(scip, &vars);
2976
2977 return SCIP_OKAY;
2978}
2979
2980/** constraint method of constraint handler which returns the variables (if possible) */
2981static
2982SCIP_DECL_CONSGETVARS(consGetVarsBounddisjunction)
2983{ /*lint --e{715}*/
2984 SCIP_CONSDATA* consdata;
2985
2986 assert(cons != NULL);
2987
2988 consdata = SCIPconsGetData(cons);
2989 assert(consdata != NULL);
2990
2991 if( varssize < consdata->nvars )
2992 (*success) = FALSE;
2993 else
2994 {
2995 assert(vars != NULL);
2996
2997 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
2998 (*success) = TRUE;
2999 }
3000
3001 return SCIP_OKAY;
3002}
3003
3004/** constraint method of constraint handler which returns the number of variables (if possible) */
3005static
3006SCIP_DECL_CONSGETNVARS(consGetNVarsBounddisjunction)
3007{ /*lint --e{715}*/
3008 SCIP_CONSDATA* consdata;
3009
3010 assert(cons != NULL);
3011
3012 consdata = SCIPconsGetData(cons);
3013 assert(consdata != NULL);
3014
3015 (*nvars) = consdata->nvars;
3016 (*success) = TRUE;
3017
3018 return SCIP_OKAY;
3019}
3020
3021/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
3022static
3023SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphBounddisjunction)
3024{ /*lint --e{715}*/
3025 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
3026
3027 return SCIP_OKAY;
3028}
3029
3030/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
3031static
3032SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphBounddisjunction)
3033{ /*lint --e{715}*/
3034 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
3035
3036 return SCIP_OKAY;
3037}
3038
3039/**@} */
3040
3041/**@name Callback methods of event handler
3042 *
3043 * @{
3044 */
3045
3046static
3047SCIP_DECL_EVENTEXEC(eventExecBounddisjunction)
3048{ /*lint --e{715}*/
3049 assert(eventhdlr != NULL);
3050 assert(eventdata != NULL);
3051 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
3052 assert(event != NULL);
3053
3054 /*SCIPdebugMsg(scip, "exec method of event handler for bound disjunction constraints\n");*/
3055
3056 assert(SCIPconsGetData((SCIP_CONS*)eventdata) != NULL);
3057 assert(SCIPconsIsActive((SCIP_CONS*)eventdata) || SCIPconsIsUpdatedeactivate((SCIP_CONS*)eventdata));
3058
3059 if( (SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDRELAXED) != 0 )
3060 {
3061 SCIP_CALL( SCIPenableCons(scip, (SCIP_CONS*)eventdata) );
3062 }
3063 else
3064 assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0);
3065
3067
3068 return SCIP_OKAY;
3069}
3070
3071/**@} */
3072
3073/**@name Callback methods of conflict handler
3074 *
3075 * @{
3076 */
3077
3078/** conflict handler data struct */
3079struct SCIP_ConflicthdlrData
3080{
3081 SCIP_Real continuousfrac; /**< maximal percantage of continuous variables within a conflict */
3082};
3083
3084/** conflict processing method of conflict handler (called when conflict was found) */
3085static
3086SCIP_DECL_CONFLICTEXEC(conflictExecBounddisjunction)
3087{ /*lint --e{715}*/
3088 SCIP_VAR** vars;
3089 SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3090 SCIP_BOUNDTYPE* boundtypes;
3091 SCIP_Real* bounds;
3092 SCIP_CONS* cons;
3093 char consname[SCIP_MAXSTRLEN];
3094 int nliterals;
3095 int ncontinuous;
3096 int i;
3097
3098 assert(conflicthdlr != NULL);
3099 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
3100 assert(bdchginfos != NULL || nbdchginfos == 0);
3101 assert(result != NULL);
3102
3103 /* don't process already resolved conflicts */
3104 if( resolved )
3105 {
3106 *result = SCIP_DIDNOTRUN;
3107 return SCIP_OKAY;
3108 }
3109
3110 conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
3111 assert(conflicthdlrdata != NULL);
3112
3113 *result = SCIP_DIDNOTFIND;
3114 ncontinuous = 0;
3115
3116 /* create array of variables, boundtypes, and bound values in conflict constraint */
3117 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
3118 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nbdchginfos) );
3119 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nbdchginfos) );
3120
3121 nliterals = 0;
3122
3123 for( i = 0; i < nbdchginfos; ++i )
3124 {
3125 SCIP_VAR* var;
3127 SCIP_BOUNDTYPE boundtype;
3128 int j;
3129
3130 assert(bdchginfos != NULL);
3131
3132 var = SCIPbdchginfoGetVar(bdchginfos[i]);
3133 assert(var != NULL);
3134
3135 boundtype = SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[i]));
3136 bound = relaxedbds[i];
3137
3138 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
3139 if( SCIPvarIsIntegral(var) )
3140 bound += (boundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
3141
3142 /* check whether we have seen the variable before */
3143 for( j = nliterals-1; j >= 0; --j )
3144 {
3145 if( vars[j] != var )
3146 continue;
3147
3148 /* check whether both literals contribute with the same bound type */
3149 if( boundtypes[j] == boundtype )
3150 {
3151 /* check whether the lower bound can be relaxed */
3152 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLT(scip, bound, bounds[j]) )
3153 {
3154 SCIPdebugMsg(scip, "relax lower bound of variable <%s> from %g to %g in bounddisjunction conflict\n",
3155 SCIPvarGetName(var), bounds[j], bound);
3156 bounds[j] = bound;
3157 }
3158 /* check whether the upper bound can be relaxed */
3159 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisGT(scip, bound, bounds[j]) )
3160 {
3161 SCIPdebugMsg(scip, "relax upper bound of variable <%s> from %g to %g in bounddisjunction conflict\n",
3162 SCIPvarGetName(var), bounds[j], bound);
3163 bounds[j] = bound;
3164 }
3165
3166 continue;
3167 }
3168 /* check whether the bounds are overlapping */
3169 else if( isOverlapping(scip, var, boundtype, bound, boundtypes[j], bounds[j]) )
3170 {
3171 /* the conflict is redundant -> discard the conflict constraint */
3172 SCIPdebugMsg(scip, "redundant bounddisjunction conflict due to overlapping\n");
3173 goto DISCARDCONFLICT;
3174 }
3175 }
3176
3177 vars[nliterals] = var;
3178 boundtypes[nliterals] = boundtype;
3179 bounds[nliterals] = bound;
3180
3181 /* check if the relaxed bound is really a relaxed bound */
3182 assert(SCIPbdchginfoGetBoundtype(bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER || SCIPisGE(scip, relaxedbds[i], SCIPbdchginfoGetNewbound(bdchginfos[i])));
3183 assert(SCIPbdchginfoGetBoundtype(bdchginfos[i]) == SCIP_BOUNDTYPE_UPPER || SCIPisLE(scip, relaxedbds[i], SCIPbdchginfoGetNewbound(bdchginfos[i])));
3184
3185 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
3186 if( !SCIPvarIsIntegral(vars[nliterals]) )
3187 {
3188 if( (boundtypes[i] == SCIP_BOUNDTYPE_LOWER && SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), bounds[nliterals]))
3189 || (boundtypes[i] == SCIP_BOUNDTYPE_UPPER && SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), bounds[nliterals])) )
3190 {
3191 /* the literal is satisfied in global bounds (may happen due to weak "negation" of continuous variables)
3192 * -> discard the conflict constraint
3193 */
3194 SCIPdebugMsg(scip, "redundant bounddisjunction conflict due to globally fulfilled literal\n");
3195 goto DISCARDCONFLICT;
3196 }
3197 else
3198 ncontinuous++;
3199 }
3200
3201 nliterals++;
3202 }
3203
3204 /* create a constraint out of the conflict set */
3205 if( i == nbdchginfos && ncontinuous < conflicthdlrdata->continuousfrac * nbdchginfos + 0.5 )
3206 {
3208 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, consname, nliterals, vars, boundtypes, bounds,
3209 FALSE, FALSE, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
3210
3211 /* add conflict to SCIP */
3212 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
3213 SCIPdebugMsg(scip, "added conflict\n");
3214 *result = SCIP_CONSADDED;
3215 }
3216
3217 DISCARDCONFLICT:
3218 /* free temporary memory */
3219 SCIPfreeBufferArray(scip, &bounds);
3220 SCIPfreeBufferArray(scip, &boundtypes);
3221 SCIPfreeBufferArray(scip, &vars);
3222
3223 return SCIP_OKAY;
3224}
3225
3226/** free method of conflict handler */
3227static
3228SCIP_DECL_CONFLICTFREE(conflictFreeBounddisjunction)
3229{
3230 SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3231
3232 assert(conflicthdlr != NULL);
3233
3234 /* get conflict handler data */
3235 conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
3236 assert(conflicthdlrdata != NULL);
3237
3238 /* free conflict handler structure */
3239 SCIPfreeBlockMemory(scip, &conflicthdlrdata);
3240
3241 return SCIP_OKAY;
3242}
3243
3244/**@} */
3245
3246/** creates the handler for bound disjunction constraints and includes it in SCIP */
3248 SCIP* scip /**< SCIP data structure */
3249 )
3250{
3251 SCIP_CONSHDLRDATA* conshdlrdata;
3252 SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3253 SCIP_CONFLICTHDLR* conflicthdlr;
3254 SCIP_CONSHDLR* conshdlr;
3255 SCIP_EVENTHDLR* eventhdlr;
3256
3257 /* create event handler for events on watched variables */
3259 eventExecBounddisjunction, NULL) );
3260
3261 /* allocate memory for conflict handler data */
3262 SCIP_CALL( SCIPallocBlockMemory(scip, &conflicthdlrdata) );
3263
3264 /* create conflict handler parameter */
3266 "conflict/" CONSHDLR_NAME "/continuousfrac", "maximal percantage of continuous variables within a conflict",
3267 &conflicthdlrdata->continuousfrac, FALSE, DEFAULT_CONTINUOUSFRAC, 0.0, 1.0, NULL, NULL) );
3268
3269 /* create conflict handler for bound disjunction constraints */
3271 conflictExecBounddisjunction, conflicthdlrdata) );
3272
3273 SCIP_CALL( SCIPsetConflicthdlrFree(scip, conflicthdlr, conflictFreeBounddisjunction) );
3274
3275 /* create constraint handler data */
3276 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
3277
3278 /* include constraint handler */
3281 consEnfolpBounddisjunction, consEnfopsBounddisjunction, consCheckBounddisjunction, consLockBounddisjunction,
3282 conshdlrdata) );
3283
3284 assert(conshdlr != NULL);
3285
3286 /* set non-fundamental callbacks via specific setter functions */
3287 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveBounddisjunction) );
3288 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyBounddisjunction, consCopyBounddisjunction) );
3289 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveBounddisjunction) );
3290 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteBounddisjunction) );
3291 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreBounddisjunction) );
3292 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolBounddisjunction) );
3293 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeBounddisjunction) );
3294 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsBounddisjunction) );
3295 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsBounddisjunction) );
3296 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseBounddisjunction) );
3297 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolBounddisjunction, CONSHDLR_MAXPREROUNDS,
3299 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintBounddisjunction) );
3300 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropBounddisjunction, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
3302 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropBounddisjunction) );
3303 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransBounddisjunction) );
3304 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxBounddisjunction) );
3305 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphBounddisjunction) );
3306 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphBounddisjunction) );
3307
3308 return SCIP_OKAY;
3309}
3310
3311
3312/** creates and captures a bound disjunction constraint
3313 *
3314 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3315 */
3317 SCIP* scip, /**< SCIP data structure */
3318 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3319 const char* name, /**< name of constraint */
3320 int nvars, /**< number of variables in the constraint */
3321 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3322 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3323 SCIP_Real* bounds, /**< bounds of the literals */
3324 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3325 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3326 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3327 * Usually set to TRUE. */
3328 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3329 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3330 SCIP_Bool check, /**< should the constraint be checked for feasibility?
3331 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3332 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3333 * Usually set to TRUE. */
3334 SCIP_Bool local, /**< is constraint only valid locally?
3335 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3336 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3337 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3338 * adds coefficients to this constraint. */
3339 SCIP_Bool dynamic, /**< is constraint subject to aging?
3340 * Usually set to FALSE. Set to TRUE for own cuts which
3341 * are separated as constraints. */
3342 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3343 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3344 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3345 * if it may be moved to a more global node?
3346 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3347 )
3348{
3349 SCIP_CONSHDLR* conshdlr;
3350 SCIP_CONSDATA* consdata;
3351
3352 assert(scip != NULL);
3353
3354 /* find the bounddisjunction constraint handler */
3355 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3356 if( conshdlr == NULL )
3357 {
3358 SCIPerrorMessage("bound disjunction constraint handler not found\n");
3359 return SCIP_PLUGINNOTFOUND;
3360 }
3361
3362#ifndef NDEBUG
3363 {
3364 int v1;
3365 /* ensure that the given data neither contains overlapping nor redundant literals */
3366 for( v1 = 0; v1 < nvars; v1++ )
3367 {
3368 int v2;
3369
3370 /* check that the bounds are sensible, i.e., not nan or inf */
3371 assert( SCIPisFinite(bounds[v1]) );
3372
3373 for( v2 = v1+1; v2 < nvars; v2++ )
3374 {
3375 assert(vars[v1] != vars[v2] || (SCIPboundtypeOpposite(boundtypes[v1]) == boundtypes[v2]
3376 && !isOverlapping(scip, vars[v1], boundtypes[v1], bounds[v1], boundtypes[v2], bounds[v2])));
3377 }
3378 }
3379 }
3380#endif
3381
3382 /* create the constraint specific data */
3383 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, boundtypes, bounds) );
3384
3385 /* create constraint */
3386 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3387 local, modifiable, dynamic, removable, stickingatnode) );
3388
3389 return SCIP_OKAY;
3390}
3391
3392/** creates and captures a bound disjunction constraint
3393 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3394 * method SCIPcreateConsBounddisjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
3395 *
3396 * @see SCIPcreateConsBounddisjunction() for information about the basic constraint flag configuration
3397 *
3398 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3399 */
3401 SCIP* scip, /**< SCIP data structure */
3402 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3403 const char* name, /**< name of constraint */
3404 int nvars, /**< number of variables in the constraint */
3405 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3406 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3407 SCIP_Real* bounds /**< bounds of the literals */
3408 )
3409{
3410 assert(scip != NULL);
3411
3412 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name, nvars, vars, boundtypes, bounds,
3414
3415 return SCIP_OKAY;
3416}
3417
3418/** creates and captures a bound disjunction constraint with possibly redundant literals
3419 *
3420 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3421 */
3423 SCIP* scip, /**< SCIP data structure */
3424 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3425 const char* name, /**< name of constraint */
3426 int nvars, /**< number of variables in the constraint */
3427 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3428 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3429 SCIP_Real* bounds, /**< bounds of the literals */
3430 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3431 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3432 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3433 * Usually set to TRUE. */
3434 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3435 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3436 SCIP_Bool check, /**< should the constraint be checked for feasibility?
3437 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3438 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3439 * Usually set to TRUE. */
3440 SCIP_Bool local, /**< is constraint only valid locally?
3441 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3442 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3443 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3444 * adds coefficients to this constraint. */
3445 SCIP_Bool dynamic, /**< is constraint subject to aging?
3446 * Usually set to FALSE. Set to TRUE for own cuts which
3447 * are separated as constraints. */
3448 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3449 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3450 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3451 * if it may be moved to a more global node?
3452 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3453 )
3454{
3455 SCIP_CONSHDLR* conshdlr;
3456 SCIP_CONSDATA* consdata;
3457
3458 assert(scip != NULL);
3459
3460 /* find the bounddisjunction constraint handler */
3461 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3462 if( conshdlr == NULL )
3463 {
3464 SCIPerrorMessage("bound disjunction constraint handler not found\n");
3465 return SCIP_PLUGINNOTFOUND;
3466 }
3467
3468 /* create the constraint specific data */
3469 SCIP_CALL( consdataCreateRedundant(scip, &consdata, nvars, vars, boundtypes, bounds) );
3470
3471 /* create constraint */
3472 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3473 local, modifiable, dynamic, removable, stickingatnode) );
3474
3475 return SCIP_OKAY;
3476}
3477
3478/** creates and captures a bound disjunction constraint with possibly redundant literals
3479 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3480 * method SCIPcreateConsBounddisjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
3481 *
3482 * @see SCIPcreateConsBounddisjunction() for information about the basic constraint flag configuration
3483 *
3484 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3485 */
3487 SCIP* scip, /**< SCIP data structure */
3488 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3489 const char* name, /**< name of constraint */
3490 int nvars, /**< number of variables in the constraint */
3491 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3492 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3493 SCIP_Real* bounds /**< bounds of the literals */
3494 )
3495{
3496 assert(scip != NULL);
3497
3498 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, cons, name, nvars, vars, boundtypes, bounds,
3500
3501 return SCIP_OKAY;
3502}
3503
3504/** gets number of variables in bound disjunction constraint */ /*lint -e{715}*/
3506 SCIP* scip, /**< SCIP data structure */
3507 SCIP_CONS* cons /**< constraint data */
3508 )
3509{
3510 SCIP_CONSDATA* consdata;
3511
3512 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3513 {
3514 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3515 SCIPABORT();
3516 return 0; /*lint !e527*/
3517 }
3518
3519 consdata = SCIPconsGetData(cons);
3520 assert(consdata != NULL);
3521
3522 return consdata->nvars;
3523}
3524
3525/** gets array of variables in bound disjunction constraint */ /*lint -e{715}*/
3527 SCIP* scip, /**< SCIP data structure */
3528 SCIP_CONS* cons /**< constraint data */
3529 )
3530{
3531 SCIP_CONSDATA* consdata;
3532
3533 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3534 {
3535 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3536 SCIPABORT();
3537 return NULL; /*lint !e527*/
3538 }
3539
3540 consdata = SCIPconsGetData(cons);
3541 assert(consdata != NULL);
3542
3543 return consdata->vars;
3544}
3545
3546/** gets array of bound types in bound disjunction constraint */ /*lint -e{715}*/
3548 SCIP* scip, /**< SCIP data structure */
3549 SCIP_CONS* cons /**< constraint data */
3550 )
3551{
3552 SCIP_CONSDATA* consdata;
3553
3554 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3555 {
3556 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3557 SCIPABORT();
3558 return NULL; /*lint !e527*/
3559 }
3560
3561 consdata = SCIPconsGetData(cons);
3562 assert(consdata != NULL);
3563
3564 return consdata->boundtypes;
3565}
3566
3567/** gets array of bounds in bound disjunction constraint */ /*lint -e{715}*/
3569 SCIP* scip, /**< SCIP data structure */
3570 SCIP_CONS* cons /**< constraint data */
3571 )
3572{
3573 SCIP_CONSDATA* consdata;
3574
3575 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3576 {
3577 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3578 SCIPABORT();
3579 return NULL; /*lint !e527*/
3580 }
3581
3582 consdata = SCIPconsGetData(cons);
3583 assert(consdata != NULL);
3584
3585 return consdata->bounds;
3586}
static long bound
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
#define isFeasGE(scip, var, val1, val2)
static SCIP_RETCODE applyGlobalBounds(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *redundant)
static SCIP_Bool isConsViolated(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
static SCIP_DECL_CONSCOPY(consCopyBounddisjunction)
#define AGEINCREASE(n)
#define CONSHDLR_NEEDSCONS
static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphBounddisjunction)
#define CONFLICTHDLR_PRIORITY
#define isFeasLT(scip, var, val1, val2)
#define CONFLICTHDLR_NAME
static SCIP_RETCODE removeFixedVariables(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *redundant)
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
#define CONSHDLR_CHECKPRIORITY
static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphBounddisjunction)
#define CONSHDLR_DESC
static SCIP_DECL_CONSDEACTIVE(consDeactiveBounddisjunction)
static SCIP_DECL_CONSLOCK(consLockBounddisjunction)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE upgradeCons(SCIP *scip, SCIP_CONS *cons, int *ndelconss, int *naddconss)
static SCIP_DECL_CONSGETVARS(consGetVarsBounddisjunction)
#define CONSHDLR_PROP_TIMING
static SCIP_DECL_EVENTEXEC(eventExecBounddisjunction)
#define CONFLICTHDLR_DESC
static SCIP_DECL_CONSENFOPS(consEnfopsBounddisjunction)
static SCIP_DECL_CONSRESPROP(consRespropBounddisjunction)
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
static SCIP_DECL_CONFLICTEXEC(conflictExecBounddisjunction)
static SCIP_RETCODE enforceCurrentSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *reduceddom, SCIP_Bool *registeredbrcand)
#define CONSHDLR_MAXPREROUNDS
#define isFeasLE(scip, var, val1, val2)
static SCIP_DECL_CONSPROP(consPropBounddisjunction)
static SCIP_DECL_CONSEXITPRE(consExitpreBounddisjunction)
static SCIP_DECL_CONSCHECK(consCheckBounddisjunction)
static SCIP_DECL_CONSPARSE(consParseBounddisjunction)
static void consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file, SCIP_Bool endline)
#define DEFAULT_CONTINUOUSFRAC
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
static SCIP_Bool isLiteralViolated(SCIP *scip, SCIP_CONSDATA *consdata, int pos)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, int pos)
static SCIP_DECL_CONSENFOLP(consEnfolpBounddisjunction)
static SCIP_RETCODE switchWatchedvars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
static SCIP_RETCODE dropEvents(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int filterpos)
#define isFeasGT(scip, var, val1, val2)
static SCIP_Bool isLiteralSatisfied(SCIP *scip, SCIP_CONSDATA *consdata, int pos)
static void consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static SCIP_DECL_CONSINITSOL(consInitsolBounddisjunction)
static SCIP_RETCODE consdataCreateRedundant(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
#define CONSHDLR_PROPFREQ
static SCIP_DECL_CONSTRANS(consTransBounddisjunction)
static SCIP_DECL_CONSFREE(consFreeBounddisjunction)
static SCIP_RETCODE createNAryBranch(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
static SCIP_DECL_CONSPRESOL(consPresolBounddisjunction)
#define CONSHDLR_PRESOLTIMING
static SCIP_DECL_CONSDELETE(consDeleteBounddisjunction)
static SCIP_RETCODE catchEvents(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
#define CONSHDLR_EAGERFREQ
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, int pos)
static SCIP_DECL_CONSPRINT(consPrintBounddisjunction)
#define EVENTHDLR_DESC
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE registerBranchingCandidates(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff, SCIP_Bool *neednarybranch)
#define CONSHDLR_ENFOPRIORITY
static SCIP_DECL_CONSENFORELAX(consEnforelaxBounddisjunction)
static SCIP_RETCODE processWatchedVars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *reduceddom, SCIP_Bool *mustcheck)
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_RESULT *result)
#define CONSHDLR_NAME
static SCIP_DECL_CONFLICTFREE(conflictFreeBounddisjunction)
#define EVENTHDLR_NAME
static SCIP_RETCODE disableCons(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real bound, SCIP_Bool *redundant)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyBounddisjunction)
static SCIP_DECL_CONSGETNVARS(consGetNVarsBounddisjunction)
#define CONSHDLR_DELAYPROP
static SCIP_DECL_CONSACTIVE(consActiveBounddisjunction)
static SCIP_Bool isOverlapping(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype1, SCIP_Real bound1, SCIP_BOUNDTYPE boundtype2, SCIP_Real bound2)
constraint handler for bound disjunction constraints
Constraint handler for linear constraints in their most general form, .
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
Constraint handler for the set partitioning / packing / covering constraints .
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define SCIPABORT()
Definition: def.h:327
#define REALABS(x)
Definition: def.h:182
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
power and signed power expression handlers
variable expression handler
SCIP_Real * SCIPgetBoundsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
int SCIPgetNVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBounddisjunctionRedundant(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_BOUNDTYPE * SCIPgetBoundtypesBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:9460
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsBasicBounddisjunctionRedundant(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
SCIP_VAR ** SCIPgetVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeConshdlrBounddisjunction(SCIP *scip)
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:662
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:713
SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_var.c:398
SCIP_RETCODE SCIPcreateExprPow(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_pow.c:3185
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:647
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
Definition: scip_prob.c:3368
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:2246
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3420
SCIP_RETCODE SCIPdelConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons)
Definition: scip_prob.c:4017
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3901
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3806
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11162
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:139
void SCIPswapInts(int *value1, int *value2)
Definition: misc.c:10485
SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
Definition: scip_branch.c:928
SCIP_RETCODE SCIPaddExternBranchCand(SCIP *scip, SCIP_VAR *var, SCIP_Real score, SCIP_Real solval)
Definition: scip_branch.c:673
SCIP_Real SCIPcalcChildEstimate(SCIP *scip, SCIP_VAR *var, SCIP_Real targetvalue)
Definition: scip_branch.c:955
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip_branch.c:1025
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:17597
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_CONFLICTHDLRDATA * SCIPconflicthdlrGetData(SCIP_CONFLICTHDLR *conflicthdlr)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_RETCODE SCIPaddConflictBd(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
SCIP_RETCODE SCIPsetConflicthdlrFree(SCIP *scip, SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTFREE((*conflictfree)))
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:808
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4346
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:281
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:181
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:693
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
Definition: scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:323
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
Definition: scip_cons.c:924
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:444
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4336
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:670
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8419
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8648
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1837
SCIP_Bool SCIPconsIsPropagationEnabled(SCIP_CONS *cons)
Definition: cons.c:8507
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8558
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8841
SCIP_RETCODE SCIPenableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1951
int SCIPconsGetValidDepth(SCIP_CONS *cons)
Definition: cons.c:8472
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8588
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8518
SCIP_Bool SCIPconsIsUpdatedeactivate(SCIP_CONS *cons)
Definition: cons.c:8460
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8698
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8578
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8450
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip_cons.c:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8608
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8628
SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1871
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1812
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8638
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:8818
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8668
SCIP_RETCODE SCIPdisableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1981
SCIP_RETCODE SCIPaddConsAge(SCIP *scip, SCIP_CONS *cons, SCIP_Real deltaage)
Definition: scip_cons.c:1755
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8568
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8658
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:413
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1443
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1058
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip_nlp.c:954
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:453
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1765
int SCIPgetNRuns(SCIP *scip)
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6401
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:17801
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:5210
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:2119
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:23430
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:7069
SCIP_RETCODE SCIPchgVarUbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:6088
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:17550
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6651
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip_var.c:728
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:5118
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:5296
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2872
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24929
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_Real SCIPcomputeVarLbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8375
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:2166
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8417
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6964
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2736
SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:6044
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:21796
SCIP_Real SCIPcomputeVarUbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8396
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24949
SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8462
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:24919
void SCIPsortPtrRealInt(void **ptrarray, SCIP_Real *realarray, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10816
SCIP_RETCODE SCIPaddSymgraphEdge(SCIP *scip, SYM_GRAPH *graph, int first, int second, SCIP_Bool hasval, SCIP_Real val)
SCIP_RETCODE SCIPaddSymgraphOpnode(SCIP *scip, SYM_GRAPH *graph, int op, int *nodeidx)
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPaddSymgraphValnode(SCIP *scip, SYM_GRAPH *graph, SCIP_Real val, int *nodeidx)
SCIP_RETCODE SCIPaddSymgraphConsnode(SCIP *scip, SYM_GRAPH *graph, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, int *nodeidx)
SCIP_RETCODE SCIPaddSymgraphVarAggregation(SCIP *scip, SYM_GRAPH *graph, int rootidx, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real constant)
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
public data structures and miscellaneous methods
#define SCIPisFinite(x)
Definition: pub_misc.h:82
public methods for problem variables
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for event handler plugins and event handlers
public functions to work with algebraic expressions
general public methods
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
Definition: sepa_flower.c:1221
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:62
struct SCIP_ConflicthdlrData SCIP_CONFLICTHDLRDATA
Definition: type_conflict.h:50
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:179
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:78
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:126
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:125
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:80
@ SCIP_EXPRCURV_CONVEX
Definition: type_expr.h:63
@ SCIP_BRANCHDIR_DOWNWARDS
Definition: type_history.h:43
@ SCIP_BRANCHDIR_UPWARDS
Definition: type_history.h:44
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
@ SCIP_VERBLEVEL_MINIMAL
Definition: type_message.h:59
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_FEASIBLE
Definition: type_result.h:45
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_CONSADDED
Definition: type_result.h:52
@ SCIP_BRANCHED
Definition: type_result.h:54
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_INFEASIBLE
Definition: type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition: type_set.h:46
enum SYM_Symtype SYM_SYMTYPE
Definition: type_symmetry.h:64
@ SYM_CONSOPTYPE_BDDISJ
Definition: type_symmetry.h:80
@ SYM_CONSOPTYPE_SUM
Definition: type_symmetry.h:83
@ SYM_SYMTYPE_SIGNPERM
Definition: type_symmetry.h:62
@ SYM_SYMTYPE_PERM
Definition: type_symmetry.h:61
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:54
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56