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-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file cons_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;
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 for( v = 0; v < nvars; ++v )
488 {
489 int w;
490
491 /* if we should compress fixed variables */
492 if( SCIPisConsCompressionEnabled(scip) && varsbuffer[v] != NULL )
493 {
494 var = varsbuffer[v];
495
496 /* if the variable is fixed */
498 {
499 /* If the literal is feasible for the fixed variable, then the whole constraint is feasible. In this
500 * case, we reduce the constraint to only this literal. */
501 if( (boundtypesbuffer[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPvarGetLbLocal(var), boundsbuffer[v]))
502 || (boundtypesbuffer[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPvarGetUbLocal(var), boundsbuffer[v])) )
503 {
504 /* save this feasible assignment at the first position */
505 varsbuffer[0] = var;
506 boundtypesbuffer[0] = boundtypesbuffer[v];
507 boundsbuffer[0] = boundsbuffer[v];
508 nvarsbuffer = 1;
509 break;
510 }
511 else
512 {
513 /* otherwise the literal is violated - we skip the literal */
514 ++nviolated;
515 continue;
516 }
517 }
518 }
519
520 /* check subsequent variables with the same variable for redundancy */
521 for( w = v + 1; w < nvars && varsbuffer[v] == varsbuffer[w]; ++w )
522 {
523 if( boundtypesbuffer[v] == boundtypesbuffer[w] )
524 {
525 if( boundtypesbuffer[v] == SCIP_BOUNDTYPE_LOWER )
526 {
527 /* check whether current bound is as strong */
528 if( SCIPisLE(scip, boundsbuffer[v], boundsbuffer[w]) )
529 varsbuffer[v] = NULL; /* skip current bound */
530 else
531 varsbuffer[w] = NULL; /* remove later bound */
532 }
533 else
534 {
535 assert(boundtypesbuffer[v] == SCIP_BOUNDTYPE_UPPER);
536
537 /* check whether current bound is as strong */
538 if( SCIPisGE(scip, boundsbuffer[v], boundsbuffer[w]) )
539 varsbuffer[v] = NULL; /* skip current bound */
540 else
541 varsbuffer[w] = NULL; /* remove later bound */
542 }
543 }
544 }
545
546 /* keep current bound if it is not redundant (possibly redundant variable w is treated later) */
547 if( varsbuffer[v] != NULL )
548 {
549 /* switch last and current bound */
550 varsbuffer[nvarsbuffer] = varsbuffer[v];
551 boundtypesbuffer[nvarsbuffer] = boundtypesbuffer[v];
552 boundsbuffer[nvarsbuffer] = boundsbuffer[v];
553 ++nvarsbuffer;
554 }
555 }
556 assert( nvarsbuffer > 0 || SCIPisConsCompressionEnabled(scip) ); /* no variables can only happen if compression is enabled */
557
558#ifndef NDEBUG
559 /* if there are no variables left, this is because all literals are infeasible */
560 if( nvarsbuffer == 0 )
561 {
562 for( v = 0; v < nvars; v++ )
563 {
564 var = vars[v];
565 assert( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) );
566 assert( (boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, SCIPvarGetLbLocal(var), bounds[v]))
567 || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, SCIPvarGetUbLocal(var), bounds[v])) );
568 }
569 }
570 else
571 {
572 /* check that the literals are not redundant */
573 for( v = 0; v < nvarsbuffer; v++ )
574 {
575 int v2;
576 assert(varsbuffer[v] != NULL);
577 for( v2 = v+1; v2 < nvarsbuffer; v2++ )
578 assert(varsbuffer[v] != varsbuffer[v2] || boundtypesbuffer[v] != boundtypesbuffer[v2]);
579 }
580 }
581#endif
582
583 /* if all literals are infeasible, we keep the first */
584 if( SCIPisConsCompressionEnabled(scip) && nviolated > 0 && nvarsbuffer == 0 )
585 nvarsbuffer = 1;
586
587 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, nvarsbuffer) );
588 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypesbuffer, nvarsbuffer) );
589 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, boundsbuffer, nvarsbuffer) );
590 (*consdata)->varssize = nvarsbuffer;
591 (*consdata)->nvars = nvarsbuffer;
592
593 /* free buffer storage */
594 SCIPfreeBufferArray(scip, &boundsbuffer);
595 SCIPfreeBufferArray(scip, &boundtypesbuffer);
596 SCIPfreeBufferArray(scip, &varsbuffer);
597 }
598 else
599 {
600 (*consdata)->vars = NULL;
601 (*consdata)->boundtypes = NULL;
602 (*consdata)->bounds = NULL;
603 (*consdata)->varssize = 0;
604 (*consdata)->nvars = 0;
605 }
606 (*consdata)->watchedvar1 = -1;
607 (*consdata)->watchedvar2 = -1;
608 (*consdata)->filterpos1 = -1;
609 (*consdata)->filterpos2 = -1;
610
611 /* get transformed variables, if we are in the transformed problem */
613 {
614 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
615 }
616
617 return SCIP_OKAY;
618}
619
620/** frees a bound disjunction constraint data */
621static
623 SCIP* scip, /**< SCIP data structure */
624 SCIP_CONSDATA** consdata /**< pointer to the bound disjunction constraint */
625 )
626{
627 assert(consdata != NULL);
628 assert(*consdata != NULL);
629
630 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
631 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->boundtypes, (*consdata)->varssize);
632 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->bounds, (*consdata)->varssize);
633 SCIPfreeBlockMemory(scip, consdata);
634}
635
636/** prints bound disjunction constraint to file stream */
637static
639 SCIP* scip, /**< SCIP data structure */
640 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
641 FILE* file, /**< output file (or NULL for standard output) */
642 SCIP_Bool endline /**< should an endline be set? */
643 )
644{
645 int v;
646
647 assert(consdata != NULL);
648
649 /* print coefficients */
650 SCIPinfoMessage(scip, file, "bounddisjunction(");
651 for( v = 0; v < consdata->nvars; ++v )
652 {
653 assert(consdata->vars[v] != NULL);
654 if( v > 0 )
655 SCIPinfoMessage(scip, file, ", ");
656 SCIPinfoMessage(scip, file, "<%s> %s %.15g", SCIPvarGetName(consdata->vars[v]),
657 consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", consdata->bounds[v]);
658 }
659 SCIPinfoMessage(scip, file, ")");
660
661 if( endline )
662 SCIPinfoMessage(scip, file, "\n");
663}
664
665/** stores the given variable numbers as watched variables, and updates the event processing */
666static
668 SCIP* scip, /**< SCIP data structure */
669 SCIP_CONS* cons, /**< bound disjunction constraint */
670 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
671 int watchedvar1, /**< new first watched variable */
672 int watchedvar2 /**< new second watched variable */
673 )
674{
675 SCIP_CONSDATA* consdata;
676
677 consdata = SCIPconsGetData(cons);
678 assert(consdata != NULL);
679 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
680 assert(watchedvar1 != -1 || watchedvar2 == -1);
681 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
682 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
683
684 /* don't watch variables for non active constraints */
685 if( !SCIPconsIsActive(cons) )
686 return SCIP_OKAY;
687
688 /* if one watched variable is equal to the old other watched variable, just switch positions */
689 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
690 {
691 int tmp;
692
693 tmp = consdata->watchedvar1;
694 consdata->watchedvar1 = consdata->watchedvar2;
695 consdata->watchedvar2 = tmp;
696 tmp = consdata->filterpos1;
697 consdata->filterpos1 = consdata->filterpos2;
698 consdata->filterpos2 = tmp;
699 }
700 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
701 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
702
703 /* drop events on old watched variables */
704 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
705 {
706 assert(consdata->filterpos1 != -1);
707 SCIP_CALL( dropEvents(scip, cons, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
708 consdata->watchedvar1 = -1;
709 }
710 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
711 {
712 assert(consdata->filterpos2 != -1);
713 SCIP_CALL( dropEvents(scip, cons, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
714 consdata->watchedvar2 = -1;
715 }
716
717 /* catch events on new watched variables */
718 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
719 {
720 SCIP_CALL( catchEvents(scip, cons, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
721 }
722 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
723 {
724 SCIP_CALL( catchEvents(scip, cons, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
725 }
726
727 /* set the new watched variables */
728 consdata->watchedvar1 = watchedvar1;
729 consdata->watchedvar2 = watchedvar2;
730
731 return SCIP_OKAY;
732}
733
734/** check whether two intervals overlap */
735static
737 SCIP* scip,
738 SCIP_VAR* var,
739 SCIP_BOUNDTYPE boundtype1,
740 SCIP_Real bound1,
741 SCIP_BOUNDTYPE boundtype2,
742 SCIP_Real bound2
743 )
744{
745 SCIP_Bool overlapping = FALSE;
746
747 if( boundtype1 == SCIP_BOUNDTYPE_LOWER )
748 {
749 assert(boundtype2 == SCIP_BOUNDTYPE_UPPER);
750
751 if( SCIPisLE(scip, bound1 - bound2, (SCIP_Real)SCIPvarIsIntegral(var)) )
752 overlapping = TRUE;
753 }
754 else
755 {
756 assert(boundtype2 == SCIP_BOUNDTYPE_LOWER);
757
758 if( SCIPisLE(scip, bound2 - bound1, (SCIP_Real)SCIPvarIsIntegral(var)) )
759 overlapping = TRUE;
760 }
761
762 return overlapping;
763}
764
765/** deletes coefficient at given position from bound disjunction constraint data */
766static
768 SCIP* scip, /**< SCIP data structure */
769 SCIP_CONS* cons, /**< bound disjunction constraint */
770 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
771 int pos /**< position of coefficient to delete */
772 )
773{
774 SCIP_CONSDATA* consdata;
775
776 assert(eventhdlr != NULL);
777
778 consdata = SCIPconsGetData(cons);
779 assert(consdata != NULL);
780 assert(0 <= pos && pos < consdata->nvars);
781 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
782
783 /* remove the rounding locks of variable */
784 SCIP_CALL( unlockRounding(scip, cons, consdata, pos) );
785
786 if( SCIPconsIsTransformed(cons) )
787 {
788 /* if the position is watched, stop watching the position */
789 if( consdata->watchedvar1 == pos )
790 {
791 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar2, -1) );
792 }
793 if( consdata->watchedvar2 == pos )
794 {
795 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, -1) );
796 }
797 }
798 assert(pos != consdata->watchedvar1);
799 assert(pos != consdata->watchedvar2);
800
801 /* move the last variable to the free slot */
802 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
803 consdata->boundtypes[pos] = consdata->boundtypes[consdata->nvars-1];
804 consdata->bounds[pos] = consdata->bounds[consdata->nvars-1];
805 consdata->nvars--;
806
807 /* if the last variable (that moved) was watched, update the watched position */
808 if( consdata->watchedvar1 == consdata->nvars )
809 consdata->watchedvar1 = pos;
810 if( consdata->watchedvar2 == consdata->nvars )
811 consdata->watchedvar2 = pos;
812
814
815 return SCIP_OKAY;
816}
817
818/** adds literal to bound disjunction constraint data */
819static
821 SCIP* scip, /**< SCIP data structure */
822 SCIP_CONS* cons, /**< bound disjunction constraint */
823 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
824 SCIP_VAR* var, /**< variable in literal */
825 SCIP_BOUNDTYPE boundtype, /**< boundtype of literal */
826 SCIP_Real bound, /**< bound of literal */
827 SCIP_Bool* redundant /**< flag to indicate whether constraint has been bound redundant */
828 )
829{
830 SCIP_CONSDATA* consdata;
831 int samebndidx;
832 int v;
833
834 assert(eventhdlr != NULL);
835
836 consdata = SCIPconsGetData(cons);
837 assert(consdata != NULL);
838 assert(var != NULL);
839 assert(!SCIPisInfinity(scip, REALABS(bound)));
840 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
841
842 /* ensure enough memory in consdata arrays */
843 if( consdata->varssize == consdata->nvars )
844 {
845 int newsize;
846
847 newsize = SCIPcalcMemGrowSize(scip, consdata->nvars + 1);
848 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
849 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->boundtypes, consdata->varssize, newsize) );
850 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->bounds, consdata->varssize, newsize) );
851 consdata->varssize = newsize;
852 }
853 assert(consdata->varssize > consdata->nvars);
854
855 /* remember the position of the literal in the constraint that has the same bound type on the same variable
856 *
857 * example: (x >= 5) or (x <= 2) and literal (x >= 2) should be added.
858 * if we see (x >= 5) first, we cannot stop immediately because only in combination with the second literal
859 * we see that the constraint is redundant.
860 */
861 samebndidx = -1;
862
863 for( v = 0; v < consdata->nvars; v++ )
864 {
865 /* check if the variable is already part of the constraint */
866 if( consdata->vars[v] == var )
867 {
868 if( consdata->boundtypes[v] == boundtype )
869 samebndidx = v;
870 else if( isOverlapping(scip, var, consdata->boundtypes[v], consdata->bounds[v], boundtype, bound) )
871 {
872 *redundant = TRUE;
873 return SCIP_OKAY;
874 }
875 }
876 }
877
878 /* the combination of variable and boundtype is already part of the constraint; check whether the clause
879 * can be relaxed
880 */
881 if( samebndidx > -1 )
882 {
883 if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLT(scip, bound, consdata->bounds[samebndidx]))
884 || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisGT(scip, bound, consdata->bounds[samebndidx])) )
885 {
886 SCIPdebugMsg(scip, "relax clause of <%s>: (<%s> %s %.15g) -> (<%s> %s %.15g)\n", SCIPconsGetName(cons),
887 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", consdata->bounds[samebndidx],
888 SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
889 consdata->bounds[samebndidx] = bound;
890 }
891 }
892 else
893 {
894 /* add the variable to the end of the array */
895 consdata->vars[consdata->nvars] = var;
896 consdata->boundtypes[consdata->nvars] = boundtype;
897 consdata->bounds[consdata->nvars] = bound;
898 consdata->nvars++;
899
900 if( SCIPconsIsTransformed(cons) )
901 {
902 /* add rounding lock of variable */
903 SCIP_CALL( lockRounding(scip, cons, consdata, consdata->nvars-1) );
904
905 /* if less than 2 variables are watched, add the new one to the watched variables */
906 if( consdata->watchedvar1 == -1 )
907 {
908 assert(consdata->watchedvar2 == -1);
909 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->nvars-1, -1) );
910 }
911 else if( consdata->watchedvar2 == -1 )
912 {
913 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, consdata->nvars-1) );
914 }
915 }
916 }
917
919
920 return SCIP_OKAY;
921}
922
923/** deletes all variables with global bounds violating the literal, checks for global bounds satisfying the literal */
924static
926 SCIP* scip, /**< SCIP data structure */
927 SCIP_CONS* cons, /**< bound disjunction constraint */
928 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
929 SCIP_Bool* redundant /**< returns whether a variable fixed to one exists in the constraint */
930 )
931{
932 SCIP_CONSDATA* consdata;
933 int v;
934 SCIP_Real bnd;
935
936 assert(eventhdlr != NULL);
937 assert(redundant != NULL);
938
939 consdata = SCIPconsGetData(cons);
940 assert(consdata != NULL);
941 assert(consdata->nvars == 0 || consdata->vars != NULL);
942
943 *redundant = FALSE;
944 v = 0;
945 while( v < consdata->nvars )
946 {
947 SCIP_VAR* var;
948
949 var = consdata->vars[v];
950
951 if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
952 {
953 bnd = SCIPcomputeVarLbGlobal(scip, var);
954 if( isFeasGE(scip, var, bnd, consdata->bounds[v]) )
955 {
956 *redundant = TRUE;
957 return SCIP_OKAY;
958 }
959 else
960 {
961 bnd = SCIPcomputeVarUbGlobal(scip, var);
962 if( isFeasLT(scip, var, bnd, consdata->bounds[v]) )
963 {
964 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
965 }
966 else
967 ++v;
968 }
969 }
970 else
971 {
972 assert(consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
973 bnd = SCIPcomputeVarUbGlobal(scip, var);
974 if( isFeasLE(scip, var, bnd, consdata->bounds[v]) )
975 {
976 *redundant = TRUE;
977 return SCIP_OKAY;
978 }
979 else
980 {
981 bnd = SCIPcomputeVarLbGlobal(scip, var);
982 if( isFeasGT(scip, var, bnd, consdata->bounds[v]) )
983 {
984 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
985 }
986 else
987 ++v;
988 }
989 }
990 }
991
992 SCIPdebugMsg(scip, "after global bounds: ");
993 SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
994
995 return SCIP_OKAY;
996}
997
998/** returns whether literal at the given position is satisfied in the local bounds */
999static
1001 SCIP* scip, /**< SCIP data structure */
1002 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
1003 int pos /**< position of the literal */
1004 )
1005{
1006 SCIP_Real bnd;
1007
1008 assert(consdata != NULL);
1009 assert(0 <= pos && pos < consdata->nvars);
1010
1011 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
1012 {
1013 bnd = SCIPcomputeVarLbLocal(scip, consdata->vars[pos]);
1014 return isFeasGE(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1015 }
1016 else
1017 {
1018 bnd = SCIPcomputeVarUbLocal(scip, consdata->vars[pos]);
1019 return isFeasLE(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1020 }
1021}
1022
1023/** returns whether literal at the given position is violated in the local bounds */
1024static
1026 SCIP* scip, /**< SCIP data structure */
1027 SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
1028 int pos /**< position of the literal */
1029 )
1030{
1031 SCIP_Real bnd;
1032
1033 assert(consdata != NULL);
1034 assert(0 <= pos && pos < consdata->nvars);
1035
1036 if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
1037 {
1038 bnd = SCIPcomputeVarUbLocal(scip, consdata->vars[pos]);
1039 return isFeasLT(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1040 }
1041 else
1042 {
1043 bnd = SCIPcomputeVarLbLocal(scip, consdata->vars[pos]);
1044 return isFeasGT(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1045 }
1046}
1047
1048/** replace variables by their representative active (or multi-aggregated) variables */
1049static
1051 SCIP* scip, /**< SCIP data structure */
1052 SCIP_CONS* cons, /**< bound disjunction constraint */
1053 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
1054 SCIP_Bool* redundant /**< flag to indicate whether constraint has been bound redundant */
1055 )
1056{
1057 SCIP_CONSDATA* consdata;
1058 SCIP_VAR* var;
1059 SCIP_BOUNDTYPE boundtype;
1061 int v;
1062
1063 assert(scip != NULL);
1064 assert(cons != NULL);
1065 assert(eventhdlr != NULL);
1066
1067 consdata = SCIPconsGetData(cons);
1068 assert(consdata != NULL);
1069
1070 v = 0;
1071 while( v < consdata->nvars )
1072 {
1073#ifndef NDEBUG
1074 SCIP_VAR* oldvar;
1075#endif
1076 var = consdata->vars[v];
1077 assert(var != NULL);
1078
1079#ifndef NDEBUG
1080 oldvar = var;
1081#endif
1082
1084 {
1085 /* check whether the literal is satisfied and the constraint is thus redundant */
1086 if( isLiteralSatisfied(scip, consdata, v) )
1087 {
1088 *redundant = TRUE;
1089 break;
1090 }
1091 if( isLiteralViolated(scip, consdata, v) )
1092 {
1093 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1094 continue;
1095 }
1096
1097 ++v;
1098
1099 continue;
1100 }
1101
1102 /* get active/fixed/multiaggr equivalent of v'th literal */
1103 bound = consdata->bounds[v];
1104 boundtype = consdata->boundtypes[v];
1105 SCIP_CALL( SCIPvarGetProbvarBound(&var, &bound, &boundtype) );
1106 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED || oldvar != var);
1107
1108 SCIPdebugMsg(scip, "in <%s>, replace <%s>[%g,%g] %c= %g by <%s>[%g,%g] %c= %g\n", SCIPconsGetName(cons),
1109 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbGlobal(consdata->vars[v]), SCIPvarGetUbGlobal(consdata->vars[v]), (consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? '>' : '<'), consdata->bounds[v],
1110 SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), (boundtype == SCIP_BOUNDTYPE_LOWER ? '>' : '<'), bound);
1111
1112 /* if literal is satisfied, then constraint is redundant and we can stop */
1113 if( (boundtype == SCIP_BOUNDTYPE_LOWER && isFeasLE(scip, var, bound, SCIPvarGetLbGlobal(var))) || /*lint !e666*/
1114 (boundtype == SCIP_BOUNDTYPE_UPPER && isFeasGE(scip, var, bound, SCIPvarGetUbGlobal(var))) ) /*lint !e666*/
1115 {
1116 *redundant = TRUE;
1117 break;
1118 }
1119
1120 /* if literal is not fixed, replace it */
1122 {
1123 /* add new literal */
1124 SCIP_CALL( addCoef(scip, cons, eventhdlr, var, boundtype, bound, redundant) );
1125 }
1126
1127 /* remove old literal */
1128 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1129 }
1130
1131 return SCIP_OKAY;
1132}
1133
1134/** try to upgrade the bounddisjunction constraint
1135 *
1136 * if only binary variables are left, we can upgrade a bounddisjunction to a logicor constraint(, if only two variables
1137 * are left, this logicor constraint can be formulated as set-packing constraint as well)
1138 *
1139 * e.g.: bounddisjunction( x1 >= 1, x2 <= 0; x3 >= 1; x4 <= 0 ) => x1 + ~x2 + x3 + ~x4 >= 1
1140 */
1141static
1143 SCIP* scip, /**< SCIP data structure */
1144 SCIP_CONS* cons, /**< bound disjunction constraint that detected the conflict */
1145 int* ndelconss, /**< pointer to store the number of delete constraint */
1146 int* naddconss /**< pointer to store the number of added constraint */
1147 )
1148{
1149 SCIP_CONSDATA* consdata;
1150 SCIP_VAR** newvars;
1151 SCIP_Bool allbinary;
1152 int nvars;
1153 int v;
1154
1155 assert(scip != NULL);
1156 assert(cons != NULL);
1157 assert(ndelconss != NULL);
1158 assert(naddconss != NULL);
1159 assert(naddconss != NULL);
1160 assert(!SCIPconsIsModifiable(cons));
1161
1162 consdata = SCIPconsGetData(cons);
1163 assert(consdata != NULL);
1164
1165 nvars = consdata->nvars;
1166 assert(nvars >= 2);
1167 assert(consdata->vars != NULL);
1168
1169 allbinary = TRUE;
1170
1171 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars) );
1172
1173 for( v = nvars - 1; v >= 0; --v )
1174 {
1175 if( !SCIPvarIsBinary(consdata->vars[v]) )
1176 {
1177 allbinary = FALSE;
1178 break;
1179 }
1180 else
1181 {
1182 if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1183 {
1184 assert(SCIPisFeasGT(scip, consdata->bounds[v], 0.0));
1185
1186 if( nvars == 2 )
1187 {
1188 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &(newvars[v])) );
1189 }
1190 else
1191 newvars[v] = consdata->vars[v];
1192 }
1193 else
1194 {
1195 assert(consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
1196 assert(SCIPisFeasLT(scip, consdata->bounds[v], 1.0));
1197
1198 if( nvars > 2 )
1199 {
1200 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &(newvars[v])) );
1201 }
1202 else
1203 newvars[v] = consdata->vars[v];
1204 }
1205 }
1206 }
1207
1208 if( allbinary )
1209 {
1210 SCIP_CONS* newcons;
1211
1212 if( nvars == 2 )
1213 {
1214 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), nvars, newvars,
1219 }
1220 else
1221 {
1222 SCIP_CALL( SCIPcreateConsLogicor(scip, &newcons, SCIPconsGetName(cons), nvars, newvars,
1227 }
1228
1229 SCIPdebugMsg(scip, "updated constraint <%s> to the following %s constraint\n", SCIPconsGetName(cons), (nvars == 2 ? "setppc" : "logicor"));
1230 SCIPdebugPrintCons(scip, newcons, NULL);
1231 SCIP_CALL( SCIPaddCons(scip, newcons) );
1232 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1233 ++(*naddconss);
1234
1235 SCIP_CALL( SCIPdelCons(scip, cons) );
1236 ++(*ndelconss);
1237 }
1238
1239 SCIPfreeBufferArray(scip, &newvars);
1240
1241 return SCIP_OKAY;
1242}
1243
1244/** analyzes conflicting assignment on given constraint, and adds conflict constraint to problem */
1245static
1247 SCIP* scip, /**< SCIP data structure */
1248 SCIP_CONS* cons /**< bound disjunction constraint that detected the conflict */
1249 )
1250{
1251 SCIP_CONSDATA* consdata;
1252 int v;
1253
1254 /* conflict analysis can only be applied in solving stage and if it is turned on */
1256 return SCIP_OKAY;
1257
1258 consdata = SCIPconsGetData(cons);
1259 assert(consdata != NULL);
1260
1261 /* initialize conflict analysis, and add all bounds of infeasible constraint to conflict candidate queue */
1263
1264 for( v = 0; v < consdata->nvars; ++v )
1265 {
1266 /* the opposite bound is in conflict with this literal */
1267 SCIP_CALL( SCIPaddConflictBd(scip, consdata->vars[v], SCIPboundtypeOpposite(consdata->boundtypes[v]), NULL) );
1268 }
1269
1270 /* analyze the conflict */
1272
1273 return SCIP_OKAY;
1274}
1275
1276/** disables or deletes the given constraint, depending on the current depth */
1277static
1279 SCIP* scip, /**< SCIP data structure */
1280 SCIP_CONS* cons /**< bound disjunction constraint to be disabled */
1281 )
1282{
1283 assert(SCIPconsGetValidDepth(cons) <= SCIPgetDepth(scip));
1284
1286 {
1287 SCIP_CALL( SCIPdelCons(scip, cons) );
1288 }
1289 else
1290 {
1291 SCIP_CALL( SCIPdisableCons(scip, cons) );
1292 }
1293
1294 return SCIP_OKAY;
1295}
1296
1297/** checks constraint for violation only looking at the watched variables, applies bound changes if possible */
1298static
1300 SCIP* scip, /**< SCIP data structure */
1301 SCIP_CONS* cons, /**< bound disjunction constraint to be processed */
1302 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1303 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1304 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint is infeasible in current bounds */
1305 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1306 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1307 )
1308{
1309 SCIP_CONSDATA* consdata;
1310 SCIP_VAR** vars;
1311 SCIP_BOUNDTYPE* boundtypes;
1312 SCIP_Real* bounds;
1313 SCIP_Longint nbranchings1;
1314 SCIP_Longint nbranchings2;
1315 int nvars;
1316 int watchedvar1;
1317 int watchedvar2;
1318
1319 assert(cons != NULL);
1320 assert(SCIPconsGetHdlr(cons) != NULL);
1321 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1322 assert(cutoff != NULL);
1323 assert(reduceddom != NULL);
1324 assert(mustcheck != NULL);
1325
1326 consdata = SCIPconsGetData(cons);
1327 assert(consdata != NULL);
1328 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
1329
1330 /* init bools */
1331 *cutoff = FALSE;
1332 *infeasible = FALSE;
1333 *reduceddom = FALSE;
1334 *mustcheck = FALSE;
1335
1336 SCIPdebugMsg(scip, "processing watched variables of constraint <%s>\n", SCIPconsGetName(cons));
1337
1338 nvars = consdata->nvars;
1339 vars = consdata->vars;
1340 boundtypes = consdata->boundtypes;
1341 bounds = consdata->bounds;
1342 assert(nvars == 0 || vars != NULL);
1343 assert(nvars == 0 || boundtypes != NULL);
1344 assert(nvars == 0 || bounds != NULL);
1345
1346 /* check watched variables if they are satisfying the literal */
1347 if( consdata->watchedvar1 >= 0 && isLiteralSatisfied(scip, consdata, consdata->watchedvar1) )
1348 {
1349 /* the literal is satisfied, making the constraint redundant */
1350 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar1 satisfied)\n", SCIPconsGetName(cons));
1351 SCIP_CALL( disableCons(scip, cons) );
1352 return SCIP_OKAY;
1353 }
1354 if( consdata->watchedvar2 >= 0 && isLiteralSatisfied(scip, consdata, consdata->watchedvar2) )
1355 {
1356 /* the literal is satisfied, making the constraint redundant */
1357 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar2 satisfied)\n", SCIPconsGetName(cons));
1358 SCIP_CALL( disableCons(scip, cons) );
1359 return SCIP_OKAY;
1360 }
1361
1362 /* check if watched variables are still undecided */
1363 watchedvar1 = -1;
1364 watchedvar2 = -1;
1365 nbranchings1 = SCIP_LONGINT_MAX;
1366 nbranchings2 = SCIP_LONGINT_MAX;
1367 if( consdata->watchedvar1 >= 0 && !isLiteralViolated(scip, consdata, consdata->watchedvar1) )
1368 {
1369 watchedvar1 = consdata->watchedvar1;
1370 nbranchings1 = -1; /* prefer keeping the watched variable */
1371 }
1372 if( consdata->watchedvar2 >= 0 && !isLiteralViolated(scip, consdata, consdata->watchedvar2) )
1373 {
1374 if( watchedvar1 == -1 )
1375 {
1376 watchedvar1 = consdata->watchedvar2;
1377 nbranchings1 = -1; /* prefer keeping the watched variable */
1378 }
1379 else
1380 {
1381 watchedvar2 = consdata->watchedvar2;
1382 nbranchings2 = -1; /* prefer keeping the watched variable */
1383 }
1384 }
1385 assert(watchedvar1 >= 0 || watchedvar2 == -1);
1386 assert(nbranchings1 <= nbranchings2);
1387 assert(watchedvar1 != -1 || nbranchings1 == SCIP_LONGINT_MAX);
1388 assert(watchedvar2 != -1 || nbranchings2 == SCIP_LONGINT_MAX);
1389
1390 /* search for new watched variables */
1391 if( watchedvar2 == -1 )
1392 {
1393 int v;
1394
1395 for( v = 0; v < nvars; ++v )
1396 {
1397 SCIP_Longint nbranchings;
1398
1399 /* don't process the watched variables again */
1400 if( v == consdata->watchedvar1 || v == consdata->watchedvar2 )
1401 continue;
1402
1403 /* check, if the literal is violated */
1404 if( isLiteralViolated(scip, consdata, v) )
1405 continue;
1406
1407 /* check, if the literal is satisfied */
1408 if( isLiteralSatisfied(scip, consdata, v) )
1409 {
1410 assert(v != consdata->watchedvar1);
1411 assert(v != consdata->watchedvar2);
1412
1413 /* the literal is satisfied, making the constraint redundant;
1414 * make sure, the feasible variable is watched and disable the constraint
1415 */
1416 SCIPdebugMsg(scip, " -> disabling constraint <%s> (variable <%s> fixed to 1.0)\n",
1417 SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
1418 if( consdata->watchedvar1 != -1 )
1419 {
1420 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, v) );
1421 }
1422 else
1423 {
1424 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, v, consdata->watchedvar2) );
1425 }
1426 SCIP_CALL( disableCons(scip, cons) );
1427 return SCIP_OKAY;
1428 }
1429
1430 /* the literal is still undecided and can be used as watched variable */
1431 nbranchings = SCIPvarGetNBranchingsCurrentRun(vars[v],
1433 if( nbranchings < nbranchings2 )
1434 {
1435 if( nbranchings < nbranchings1 )
1436 {
1437 watchedvar2 = watchedvar1;
1438 nbranchings2 = nbranchings1;
1439 watchedvar1 = v;
1440 nbranchings1 = nbranchings;
1441 }
1442 else
1443 {
1444 watchedvar2 = v;
1445 nbranchings2 = nbranchings;
1446 }
1447 }
1448 }
1449 }
1450 assert(nbranchings1 <= nbranchings2);
1451 assert(watchedvar1 >= 0 || watchedvar2 == -1);
1452
1453 if( watchedvar1 == -1 )
1454 {
1455 /* there is no undecided literal left -> the constraint is infeasible
1456 * - a modifiable constraint is infeasible
1457 * - an unmodifiable constraint is infeasible and the node can be cut off
1458 */
1459 assert(watchedvar2 == -1);
1460
1461 SCIPdebugMsg(scip, " -> constraint <%s> is infeasible\n", SCIPconsGetName(cons));
1462 *infeasible = TRUE;
1463
1465 if( !SCIPconsIsModifiable(cons) )
1466 {
1467 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1468 SCIP_CALL( analyzeConflict(scip, cons) );
1469
1470 /* mark the node to be cut off */
1471 *cutoff = TRUE;
1472 }
1473 }
1474 else if( watchedvar2 == -1 )
1475 {
1476 /* there is only one undecided literal:
1477 * - a modifiable constraint must be checked manually
1478 * - we cannot change bounds of multi-aggregated variables and have to check manually
1479 * - an unmodifiable constraint is feasible and can be disabled after the remaining literal is satisfied
1480 */
1481 assert(0 <= watchedvar1 && watchedvar1 < nvars);
1482 assert(!isLiteralViolated(scip, consdata, watchedvar1));
1483 assert(!isLiteralSatisfied(scip, consdata, watchedvar1));
1484 if( SCIPconsIsModifiable(cons)
1486 *mustcheck = TRUE;
1487 else
1488 {
1489 SCIP_Bool infbdchg;
1490
1491#ifndef NDEBUG
1492 int v;
1493
1494 /* check whether all other literals are violated */
1495 for (v = 0; v < nvars; ++v)
1496 {
1497 if ( v != watchedvar1 )
1498 {
1499 assert( isLiteralViolated(scip, consdata, v) );
1500 }
1501 }
1502#endif
1503
1504 /* satisfy remaining literal and disable constraint; make sure, the fixed-to-one variable is watched */
1505 SCIPdebugMsg(scip, " -> single-literal constraint <%s> (change bound <%s> %s %g) at depth %d\n",
1506 SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]),
1507 boundtypes[watchedvar1] == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bounds[watchedvar1], SCIPgetDepth(scip));
1508
1509 if( boundtypes[watchedvar1] == SCIP_BOUNDTYPE_LOWER )
1510 {
1511 SCIP_CALL( SCIPinferVarLbCons(scip, vars[watchedvar1], bounds[watchedvar1], cons, watchedvar1, TRUE,
1512 &infbdchg, NULL) );
1513 }
1514 else
1515 {
1516 SCIP_CALL( SCIPinferVarUbCons(scip, vars[watchedvar1], bounds[watchedvar1], cons, watchedvar1, TRUE,
1517 &infbdchg, NULL) );
1518 }
1519 assert(!infbdchg);
1521 if( watchedvar1 != consdata->watchedvar1 ) /* keep one of the watched variables */
1522 {
1523 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, consdata->watchedvar1) );
1524 }
1525 SCIP_CALL( disableCons(scip, cons) );
1526 *reduceddom = TRUE;
1527 }
1528 }
1529 else
1530 {
1531 SCIPdebugMsg(scip, " -> new watched variables <%s> and <%s> of constraint <%s> are still undecided\n",
1532 SCIPvarGetName(vars[watchedvar1]), SCIPvarGetName(vars[watchedvar2]), SCIPconsGetName(cons));
1533
1534 /* switch to the new watched variables */
1535 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, watchedvar2) );
1536
1537 /* there are at least two undecided variables -> the constraint must be checked manually */
1538 *mustcheck = TRUE;
1539
1540 /* disable propagation of constraint until the corresponding bound of a watched variable changed */
1542
1543 /* increase aging counter */
1544 SCIP_CALL( SCIPaddConsAge(scip, cons, AGEINCREASE(consdata->nvars)) );
1545 }
1546
1547 return SCIP_OKAY;
1548}
1549
1550/** checks constraint for violation, returns TRUE iff constraint is violated */
1551static
1553 SCIP* scip, /**< SCIP data structure */
1554 SCIP_CONS* cons, /**< bound disjunction constraint to be checked */
1555 SCIP_SOL* sol /**< primal CIP solution */
1556 )
1557{
1558 SCIP_CONSDATA* consdata;
1559 SCIP_VAR** vars;
1560 SCIP_BOUNDTYPE* boundtypes;
1561 SCIP_Real* bounds;
1562 SCIP_Real solval;
1563 SCIP_Real viol;
1564 SCIP_Real absviol;
1565 int violpos;
1566 int nvars;
1567 int v;
1568
1569 consdata = SCIPconsGetData(cons);
1570 assert(consdata != NULL);
1571
1572 nvars = consdata->nvars;
1573 vars = consdata->vars;
1574 boundtypes = consdata->boundtypes;
1575 bounds = consdata->bounds;
1576 assert(nvars == 0 || vars != NULL);
1577 assert(nvars == 0 || boundtypes != NULL);
1578 assert(nvars == 0 || bounds != NULL);
1579
1580 /* check the given solution */
1581 absviol = SCIP_REAL_MAX;
1582 violpos = -1;
1583 for( v = 0; v < nvars; ++v )
1584 {
1585 solval = SCIPgetSolVal(scip, sol, vars[v]);
1586
1587 /* update absolute violation if needed */
1588 viol = (boundtypes[v] == SCIP_BOUNDTYPE_LOWER) ? bounds[v] - solval : solval - bounds[v];
1589 if( viol < absviol )
1590 {
1591 absviol = viol;
1592 violpos = v;
1593 }
1594
1595 if( (boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, vars[v], solval, bounds[v]))
1596 || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, vars[v], solval, bounds[v])) )
1597 {
1598 return FALSE;
1599 }
1600 }
1601 /* update constraint violation in solution */
1602 if( sol != NULL )
1603 {
1604 SCIP_Real relviol;
1605
1606 assert(0 == nvars || -1 != violpos);
1607
1608 if( 0 == nvars )
1609 relviol = SCIP_REAL_MAX;
1610 else
1611 relviol = SCIPrelDiff(SCIPgetSolVal(scip, sol, vars[violpos]), bounds[violpos]);
1612
1613 SCIPupdateSolConsViolation(scip, sol, absviol, relviol);
1614 }
1615 return TRUE;
1616}
1617
1618/* registers variables of a constraint as branching candidates
1619 * indicates whether an n-ary branch is necessary to enforce this constraint,
1620 * because all active literals are w.r.t. continuous variables which bound (in the literal) is at the variable's bound
1621 */
1622static
1624 SCIP* scip, /**< SCIP data structure */
1625 SCIP_CONS* cons, /**< bound disjunction constraint which variables should be registered for branching */
1626 SCIP_SOL* sol, /**< solution (NULL for LP solution) */
1627 SCIP_Bool* cutoff, /**< pointer to store whether the constraint cannot be made feasible by branching */
1628 SCIP_Bool* neednarybranch /**< pointer to store TRUE, if n-ary branching is necessary to enforce this constraint */
1629 )
1630{
1631 SCIP_CONSDATA* consdata;
1632 SCIP_VAR** vars;
1633 SCIP_BOUNDTYPE* boundtypes;
1634 SCIP_Real* bounds;
1635 SCIP_Real violation;
1636 SCIP_Real varlb;
1637 SCIP_Real varub;
1638 int nvars;
1639 int v;
1640
1641 assert(cons != NULL);
1642 assert(SCIPconsGetHdlr(cons) != NULL);
1643 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1644 assert(cutoff != NULL);
1645 assert(neednarybranch != NULL);
1646
1647 consdata = SCIPconsGetData(cons);
1648 assert(consdata != NULL);
1649 nvars = consdata->nvars;
1650 vars = consdata->vars;
1651 boundtypes = consdata->boundtypes;
1652 bounds = consdata->bounds;
1653 assert(nvars == 0 || vars != NULL);
1654 assert(nvars == 0 || boundtypes != NULL);
1655 assert(nvars == 0 || bounds != NULL);
1656
1657 *cutoff = TRUE;
1658 *neednarybranch = TRUE;
1659
1660 for( v = 0; v < nvars; ++v )
1661 {
1662 SCIP_VAR* var;
1663
1664 var = vars[v];
1665 assert(var != NULL);
1666
1667 /* constraint should be violated, so all bounds in the constraint have to be violated */
1668 assert( !(boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPisFeasGE(scip, SCIPgetSolVal(scip, sol, var), bounds[v])) &&
1669 !(boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPisFeasLE(scip, SCIPgetSolVal(scip, sol, var), bounds[v])) );
1670
1671 varlb = SCIPcomputeVarLbLocal(scip, var);
1672 varub = SCIPcomputeVarUbLocal(scip, var);
1673
1674 /* if literal is x >= varlb, but upper bound on x is < varlb, then this literal can never be satisfied,
1675 * thus there is no use for branching
1676 */
1677 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, varub, bounds[v]) )
1678 continue;
1679
1680 /* if literal is x <= varub, but lower bound on x is > varub, then this literal can never be satisfied,
1681 * thus there is no use for branching
1682 */
1683 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, varlb, bounds[v]) )
1684 continue;
1685
1686 /* if literal is always satisfied, then no need to branch on it may happen if propagation is disabled for some
1687 * reason and due to numerics current solution does not satisfy literal, but variable bounds do
1688 */
1689 if( isLiteralSatisfied(scip, consdata, v) )
1690 continue;
1691
1692 violation = SCIPgetSolVal(scip, sol, var) - bounds[v];
1693
1694 /* if variable is continuous, then we cannot branch on one of the variable bounds */
1695 if( SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS ||
1696 ((SCIPisInfinity(scip, -varlb) || !SCIPisFeasEQ(scip, bounds[v], varlb)) &&
1697 (SCIPisInfinity(scip, varub) || !SCIPisFeasEQ(scip, bounds[v], varub))) )
1698 {
1699 SCIP_CALL( SCIPaddExternBranchCand(scip, var, REALABS(violation), bounds[v]) );
1700 *neednarybranch = FALSE;
1701 }
1702 *cutoff = FALSE;
1703 }
1704
1705 return SCIP_OKAY;
1706}
1707
1708/** enforces the pseudo or LP solution on the given constraint */
1709static
1711 SCIP* scip, /**< SCIP data structure */
1712 SCIP_CONS* cons, /**< bound disjunction constraint to be separated */
1713 SCIP_SOL* sol, /**< solution which should be enforced (NULL for LP solution) */
1714 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1715 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1716 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
1717 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1718 SCIP_Bool* registeredbrcand /**< pointer to store TRUE, if branching variable candidates were registered or was already true */
1719 )
1720{
1721 SCIP_Bool mustcheck;
1722 SCIP_Bool neednarybranch;
1723
1724 assert(cons != NULL);
1725 assert(SCIPconsGetHdlr(cons) != NULL);
1726 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1727 assert(cutoff != NULL);
1728 assert(infeasible != NULL);
1729 assert(reduceddom != NULL);
1730 assert(registeredbrcand != NULL);
1731
1732 SCIPdebugMsg(scip, "enforce bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
1733
1734 /* update and check the watched variables, if they were changed since last processing */
1736 {
1737 SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, infeasible, reduceddom, &mustcheck) );
1738 }
1739 else
1740 mustcheck = TRUE;
1741
1742 if( mustcheck )
1743 {
1744 if( isConsViolated(scip, cons, sol) )
1745 {
1746 /* constraint was infeasible -> reset age */
1748 *infeasible = TRUE;
1749
1750 /* register branching candidates */
1751 SCIP_CALL( registerBranchingCandidates(scip, cons, sol, cutoff, &neednarybranch) );
1752
1753 if( !neednarybranch )
1754 *registeredbrcand = TRUE;
1755 }
1756 }
1757
1758 return SCIP_OKAY;
1759}
1760
1761/** enforces a constraint by creating an n-ary branch consisting of a set of child nodes, each enforcing one literal
1762 */
1763static
1765 SCIP* scip, /**< SCIP data structure */
1766 SCIP_CONS* cons, /**< bound disjunction constraint to branch on */
1767 SCIP_SOL* sol /**< solution which should be enforced (NULL for LP solution) */
1768 )
1769{
1770 SCIP_CONSDATA* consdata;
1771 SCIP_VAR** vars;
1772 SCIP_BOUNDTYPE* boundtypes;
1773 SCIP_Real* bounds;
1774 SCIP_Real varlb;
1775 SCIP_Real varub;
1776 int nvars;
1777 int v;
1778
1779 SCIP_Real priority;
1780 SCIP_Real estimate;
1781 SCIP_NODE* node;
1782
1783 assert(cons != NULL);
1784 assert(SCIPconsGetHdlr(cons) != NULL);
1785 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1786
1787 consdata = SCIPconsGetData(cons);
1788 assert(consdata != NULL);
1789 nvars = consdata->nvars;
1790 vars = consdata->vars;
1791 boundtypes = consdata->boundtypes;
1792 bounds = consdata->bounds;
1793 assert(nvars == 0 || vars != NULL);
1794 assert(nvars == 0 || boundtypes != NULL);
1795 assert(nvars == 0 || bounds != NULL);
1796
1797 for( v = 0; v < nvars; ++v )
1798 {
1799 SCIP_VAR* var;
1800
1801 var = vars[v];
1802 assert(var != NULL);
1803
1804 /* constraint should be violated, so all bounds in the constraint have to be violated */
1805 assert( !(boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPgetSolVal(scip, sol, var), bounds[v])) && /*lint !e666*/
1806 !(boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPgetSolVal(scip, sol, var), bounds[v])) ); /*lint !e666*/
1807
1808 varlb = SCIPcomputeVarLbLocal(scip, var);
1809 varub = SCIPcomputeVarUbLocal(scip, var);
1810
1811 /* if literal is x >= varlb, but upper bound on x is < varlb, then this literal can never be satisfied,
1812 * thus there is no use in creating an extra child for it
1813 */
1814 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, varub, bounds[v]) )
1815 continue;
1816 /* if literal is x <= varub, but lower bound on x is > varub, then this literal can never be satisfied,
1817 * thus there is no use in creating an extra child for it
1818 */
1819 if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, varlb, bounds[v]) )
1820 continue;
1821 /* if literal is always satisfied, then no need to branch on it */
1822 if( isLiteralSatisfied(scip, consdata, v) )
1823 continue;
1824
1825 /* create a child that enforces the current literal */
1826 priority = SCIPcalcNodeselPriority(scip, var, boundtypes[v] == SCIP_BOUNDTYPE_LOWER ?
1828 estimate = SCIPcalcChildEstimate (scip, var, bounds[v]);
1829
1830 SCIPdebugMsg(scip, " -> creating child to enforce: <%s> %c= %g (priority: %g, estimate: %g)\n",
1831 SCIPvarGetName(vars[v]), boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? '>' : '<', bounds[v], priority, estimate);
1832
1833 SCIP_CALL( SCIPcreateChild(scip, &node, priority, estimate) );
1834
1835 /* enforce current literal */
1837 {
1838 SCIP_CONS* brcons;
1839 SCIP_Real one;
1840
1841 one = 1.0;
1842
1843 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1844 {
1845 SCIP_CALL( SCIPcreateConsLinear(scip, &brcons, "bounddisjbranch", 1, &var, &one, bounds[v], SCIPinfinity(scip),
1849 SCIPconsIsStickingAtNode(cons)) );
1850 }
1851 else
1852 {
1853 SCIP_CALL( SCIPcreateConsLinear(scip, &brcons, "bounddisjbranch", 1, &var, &one, -SCIPinfinity(scip), bounds[v],
1857 SCIPconsIsStickingAtNode(cons)) );
1858 }
1859 SCIP_CALL( SCIPaddConsNode(scip, node, brcons, NULL) );
1860 SCIP_CALL( SCIPreleaseCons(scip, &brcons) );
1861 }
1862 else
1863 {
1864 assert(SCIPvarIsActive(var));
1865 if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1866 {
1867 SCIP_CALL( SCIPchgVarLbNode(scip, node, var, bounds[v]) );
1868 }
1869 else
1870 {
1871 SCIP_CALL( SCIPchgVarUbNode(scip, node, var, bounds[v]) );
1872 }
1873 }
1874
1875 /* delete bound disjunction constraint from child node */
1876 SCIP_CALL( SCIPdelConsNode(scip, node, cons) );
1877 }
1878
1879 return SCIP_OKAY;
1880}
1881
1882/** helper function to enforce constraints */
1883static
1885 SCIP* scip, /**< SCIP data structure */
1886 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1887 SCIP_CONS** conss, /**< constraints to process */
1888 int nconss, /**< number of constraints */
1889 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
1890 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
1891 )
1892{
1893 SCIP_CONSHDLRDATA* conshdlrdata;
1894 SCIP_Bool cutoff;
1895 SCIP_Bool infeasible;
1896 SCIP_Bool reduceddom;
1897 SCIP_Bool registeredbrcand;
1898 SCIP_Bool infeasiblecons;
1899 int c;
1900 int nnarybranchconsvars;
1901 SCIP_CONS* narybranchcons; /* constraint that is a candidate for an n-ary branch */
1902
1903 assert(conshdlr != NULL);
1904 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1905 assert(nconss == 0 || conss != NULL);
1906 assert(result != NULL);
1907
1908 SCIPdebugMsg(scip, "Enforcing %d bound disjunction constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
1909
1910 *result = SCIP_FEASIBLE;
1911
1912 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1913 assert(conshdlrdata != NULL);
1914
1915 cutoff = FALSE;
1916 infeasible = FALSE;
1917 reduceddom = FALSE;
1918 registeredbrcand = FALSE;
1919 narybranchcons = NULL;
1920 nnarybranchconsvars = INT_MAX;
1921
1922 /* check all bound disjunction constraints for feasibility */
1923 for( c = 0; c < nconss && !cutoff && !reduceddom; ++c )
1924 {
1925 infeasiblecons = FALSE;
1926 SCIP_CALL( enforceCurrentSol(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &infeasiblecons, &reduceddom,
1927 &registeredbrcand) );
1928 infeasible |= infeasiblecons;
1929 if( infeasiblecons && !registeredbrcand )
1930 {
1931 /* 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 */
1932 if( narybranchcons == NULL || SCIPconsGetData(conss[c])->nvars < nnarybranchconsvars )
1933 {
1934 narybranchcons = conss[c];
1935 nnarybranchconsvars = SCIPconsGetData(narybranchcons)->nvars;
1936 assert(nnarybranchconsvars > 0);
1937 }
1938 }
1939 }
1940
1941 if( cutoff )
1942 *result = SCIP_CUTOFF;
1943 else if( reduceddom )
1944 *result = SCIP_REDUCEDDOM;
1945 else if( infeasible )
1946 {
1947 if( registeredbrcand )
1948 {
1949 *result = SCIP_INFEASIBLE;
1950 }
1951 else
1952 {
1953 SCIP_CALL( createNAryBranch(scip, narybranchcons, sol) );
1954 *result = SCIP_BRANCHED;
1955 }
1956 }
1957
1958 return SCIP_OKAY;
1959}
1960
1961/** adds symmetry information of constraint to a symmetry detection graph */
1962static
1964 SCIP* scip, /**< SCIP pointer */
1965 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
1966 SCIP_CONS* cons, /**< constraint */
1967 SYM_GRAPH* graph, /**< symmetry detection graph */
1968 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
1969 )
1970{
1971 SCIP_CONSDATA* consdata;
1972 SCIP_VAR** vars;
1973 SCIP_Real* vals;
1974 SCIP_Real constant;
1975 SCIP_Real bound = 0.0;
1976 int consnodeidx;
1977 int opnodeidx;
1978 int nodeidx;
1979 int nconsvars;
1980 int nlocvars;
1981 int nvars;
1982 int i;
1983
1984 assert(scip != NULL);
1985 assert(cons != NULL);
1986 assert(graph != NULL);
1987 assert(success != NULL);
1988
1989 *success = TRUE;
1990
1991 consdata = SCIPconsGetData(cons);
1992 assert(consdata != NULL);
1993
1994 /* add node initializing constraint (with artificial rhs) */
1995 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
1996
1997 /* create nodes and edges for each literal in the bounddisjunction */
1998 nvars = SCIPgetNVars(scip);
1999 nconsvars = consdata->nvars;
2000
2001 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
2002 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
2003
2004 for( i = 0; i < nconsvars; ++i )
2005 {
2006 /* add node and edge for bound expression of literal */
2007 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_BDDISJ, &opnodeidx) ); /*lint !e641*/
2008 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, opnodeidx, FALSE, 0.0) );
2009
2010 /* get active variables */
2011 vars[0] = consdata->vars[i];
2012 vals[0] = consdata->boundtypes[i] == SCIP_BOUNDTYPE_UPPER ? 1.0 : -1.0;
2013 nlocvars = 1;
2014 constant = 0.0;
2015
2016 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant,
2018
2019 /* add node and edge for bound on literal (bound adapted by constant) */
2020 bound = consdata->boundtypes[i] == SCIP_BOUNDTYPE_UPPER ? consdata->bounds[i] : -consdata->bounds[i];
2021 bound -= constant;
2022
2023 SCIP_CALL( SCIPaddSymgraphValnode(scip, graph, bound, &nodeidx) );
2024 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, FALSE, 0.0) );
2025
2026 /* check whether variable is (multi-)aggregated */
2027 nodeidx = opnodeidx;
2028 if( nlocvars > 1 )
2029 {
2030 /* encode aggregation by a sum-expression and connect it to bdexpr node */
2031 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &nodeidx) ); /*lint !e641*/
2032 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, opnodeidx, nodeidx, FALSE, 0.0) );
2033 }
2034
2035 /* add nodes and edges for variables in aggregation (ignore constant, has been treated above) */
2036 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, nodeidx, vars, vals, nlocvars, 0.0) );
2037 }
2038
2039 SCIPfreeBufferArray(scip, &vals);
2040 SCIPfreeBufferArray(scip, &vars);
2041
2042 return SCIP_OKAY;
2043}
2044
2045/**@} */
2046
2047/**@name Callback methods of constraint handler
2048 *
2049 * @{
2050 */
2051
2052/** copy method for constraint handler plugins (called when SCIP copies plugins) */
2053static
2054SCIP_DECL_CONSHDLRCOPY(conshdlrCopyBounddisjunction)
2055{ /*lint --e{715}*/
2056 assert(scip != NULL);
2057 assert(conshdlr != NULL);
2058 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2059
2060 /* call inclusion method of constraint handler */
2062
2063 *valid = TRUE;
2064
2065 return SCIP_OKAY;
2066}
2067
2068/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
2069static
2070SCIP_DECL_CONSFREE(consFreeBounddisjunction)
2071{ /*lint --e{715}*/
2072 SCIP_CONSHDLRDATA* conshdlrdata;
2073
2074 assert(conshdlr != NULL);
2075 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2076 assert(scip != NULL);
2077
2078 /* free constraint handler data */
2079 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2080 assert(conshdlrdata != NULL);
2081
2082 conshdlrdataFree(scip, &conshdlrdata);
2083
2084 SCIPconshdlrSetData(conshdlr, NULL);
2085
2086 return SCIP_OKAY;
2087}
2088
2089
2090/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
2091static
2092SCIP_DECL_CONSEXITPRE(consExitpreBounddisjunction)
2093{ /*lint --e{715}*/
2094 SCIP_CONSHDLRDATA* conshdlrdata;
2095 SCIP_CONS* cons;
2096 SCIP_Bool redundant;
2097 int c;
2098
2099 assert(conshdlr != NULL);
2100 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2101 assert(scip != NULL);
2102
2103 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2104 assert(conshdlrdata != NULL);
2105
2106 /* fast processing of constraints, apply global bounds and remove fixed variables */
2107 for( c = 0; c < nconss; ++c )
2108 {
2109 cons = conss[c];
2110 assert(cons != NULL);
2111
2112 SCIPdebugMsg(scip, "exit-presolving bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2113
2114 if( SCIPconsIsDeleted(cons) )
2115 continue;
2116
2117 /* remove all literals that are violated in global bounds, check redundancy due to global bounds */
2118 SCIP_CALL( applyGlobalBounds(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2119
2120 if( !redundant )
2121 {
2122 /* replace variables by their representative active (or multi-aggregated) variables */
2123 SCIP_CALL( removeFixedVariables(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2124 }
2125
2126 if( redundant && SCIPconsIsAdded(cons) )
2127 {
2128 SCIPdebugMsg(scip, "bound disjunction constraint <%s> is redundant\n", SCIPconsGetName(cons));
2129 SCIP_CALL( SCIPdelCons(scip, cons) );
2130 }
2131 }
2132
2133 return SCIP_OKAY;
2134}
2135
2136/** solving process initialization method of constraint handler */
2137static
2138SCIP_DECL_CONSINITSOL(consInitsolBounddisjunction)
2139{ /*lint --e{715}*/
2140 /* add nlrow representation to NLP, if NLP had been constructed and disjunction is simple enough */
2142 {
2143 SCIP_CONSDATA* consdata;
2144 SCIP_NLROW* nlrow;
2145 SCIP_EXPR* expr;
2146 SCIP_EXPR* exprvar;
2147 SCIP_Real lincoef;
2148 SCIP_Real a, b;
2149 int c;
2150
2151 for( c = 0; c < nconss; ++c )
2152 {
2153 /* skip deactivated or redundant constraints */
2154 if( !SCIPconsIsActive(conss[c]) || !SCIPconsIsChecked(conss[c]) )
2155 return SCIP_OKAY;
2156
2157 assert(!SCIPconsIsLocal(conss[c])); /* we are at the root node (or short before) */
2158
2159 consdata = SCIPconsGetData(conss[c]);
2160 assert(consdata != NULL);
2161
2162 /* look for a bounddisjunction of the form
2163 * x <= a or x >= b with a < b
2164 * only one of the inequalities can be strictly satisfied, so we can reformulate as
2165 * (x-a)*(b-x) <= 0
2166 * this should be sufficient to get bounddisjunction constraints that represent semi-continuous variables into the NLP
2167 */
2168
2169 if( consdata->nvars != 2 )
2170 continue;
2171
2172 if( consdata->vars[0] != consdata->vars[1] )
2173 continue;
2174
2175 if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_UPPER && consdata->boundtypes[1] == SCIP_BOUNDTYPE_LOWER )
2176 {
2177 a = consdata->bounds[0];
2178 b = consdata->bounds[1];
2179 }
2180 else if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER && consdata->boundtypes[1] == SCIP_BOUNDTYPE_UPPER )
2181 {
2182 a = consdata->bounds[1];
2183 b = consdata->bounds[0];
2184 }
2185 else
2186 {
2187 continue;
2188 }
2189
2190 if( a >= b )
2191 continue;
2192
2193 SCIP_CALL( SCIPcreateExprVar(scip, &exprvar, consdata->vars[0], NULL, NULL) );
2194 SCIP_CALL( SCIPcreateExprPow(scip, &expr, exprvar, 2.0, NULL, NULL) );
2195
2196 /* add xb-xx-ab+ax <= 0 as -ab <= -(a+b)x + x^2 */
2197 lincoef = -a - b;
2198 SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[c]),
2199 0.0, 1, consdata->vars, &lincoef, expr, -a*b, SCIPinfinity(scip), SCIP_EXPRCURV_CONVEX) );
2200
2201 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
2202 SCIP_CALL( SCIPreleaseExpr(scip, &exprvar) );
2203
2204 SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
2205 SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
2206 }
2207 }
2208
2209 return SCIP_OKAY;
2210}
2211
2212/** frees specific constraint data */
2213static
2214SCIP_DECL_CONSDELETE(consDeleteBounddisjunction)
2215{ /*lint --e{715}*/
2216 assert(conshdlr != NULL);
2217 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2218 assert(consdata != NULL);
2219 assert(*consdata != NULL);
2220
2221 /* free LP row and bound disjunction constraint */
2222 consdataFree(scip, consdata);
2223
2224 return SCIP_OKAY;
2225}
2226
2227
2228/** transforms constraint data into data belonging to the transformed problem */
2229static
2230SCIP_DECL_CONSTRANS(consTransBounddisjunction)
2231{ /*lint --e{715}*/
2232 SCIP_CONSDATA* sourcedata;
2233 SCIP_CONSDATA* targetdata;
2234
2235 /*debugMsg(scip, "Trans method of bound disjunction constraints\n");*/
2236
2237 assert(conshdlr != NULL);
2238 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2240 assert(sourcecons != NULL);
2241 assert(targetcons != NULL);
2242
2243 sourcedata = SCIPconsGetData(sourcecons);
2244 assert(sourcedata != NULL);
2245
2246 /* create constraint data for target constraint */
2247 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars,
2248 sourcedata->boundtypes, sourcedata->bounds) );
2249
2250 /* create target constraint */
2251 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
2252 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
2253 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
2254 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
2255 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
2256
2257 return SCIP_OKAY;
2258}
2259
2260
2261/** constraint enforcing method of constraint handler for LP solutions */
2262static
2263SCIP_DECL_CONSENFOLP(consEnfolpBounddisjunction)
2264{ /*lint --e{715}*/
2265 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, NULL, result) );
2266
2267 return SCIP_OKAY;
2268}
2269
2270
2271/** constraint enforcing method of constraint handler for relaxation solutions */
2272static
2273SCIP_DECL_CONSENFORELAX(consEnforelaxBounddisjunction)
2274{ /*lint --e{715}*/
2275 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, sol, result) );
2276
2277 return SCIP_OKAY;
2278}
2279
2280
2281/** constraint enforcing method of constraint handler for pseudo solutions */
2282static
2283SCIP_DECL_CONSENFOPS(consEnfopsBounddisjunction)
2284{ /*lint --e{715}*/
2285 SCIP_CONSHDLRDATA* conshdlrdata;
2286 SCIP_Bool cutoff;
2287 SCIP_Bool infeasible;
2288 SCIP_Bool reduceddom;
2289 SCIP_Bool registeredbrcand;
2290 int c;
2291 SCIP_CONS* narybranchcons; /* constraint that is a candidate for an n-ary branch */
2292
2293 assert(conshdlr != NULL);
2294 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2295 assert(nconss == 0 || conss != NULL);
2296 assert(result != NULL);
2297
2298 SCIPdebugMsg(scip, "pseudo enforcing %d bound disjunction constraints\n", nconss);
2299
2300 *result = SCIP_FEASIBLE;
2301
2302 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2303 assert(conshdlrdata != NULL);
2304
2305 cutoff = FALSE;
2306 infeasible = FALSE;
2307 reduceddom = FALSE;
2308 registeredbrcand = FALSE;
2309 narybranchcons = NULL;
2310
2311 /* check all bound disjunction constraints for feasibility */
2312 for( c = 0; c < nconss && !cutoff && !reduceddom; ++c )
2313 {
2314 SCIP_CALL( enforceCurrentSol(scip, conss[c], NULL, conshdlrdata->eventhdlr, &cutoff, &infeasible, &reduceddom,
2315 &registeredbrcand) );
2316 if( infeasible && !registeredbrcand )
2317 {
2318 /* 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 */
2319 if( !narybranchcons || SCIPconsGetData(conss[c])->nvars < SCIPconsGetData(narybranchcons)->nvars )
2320 narybranchcons = conss[c];
2321 }
2322 }
2323
2324 if( cutoff )
2325 *result = SCIP_CUTOFF;
2326 else if( reduceddom )
2327 *result = SCIP_REDUCEDDOM;
2328 else if( infeasible )
2329 {
2330 if( registeredbrcand )
2331 {
2332 *result = SCIP_INFEASIBLE;
2333 }
2334 else
2335 {
2336 SCIP_CALL( createNAryBranch(scip, narybranchcons, NULL) );
2337 *result = SCIP_BRANCHED;
2338 }
2339 }
2340
2341 return SCIP_OKAY;
2342}
2343
2344
2345/** feasibility check method of constraint handler for integral solutions */
2346static
2347SCIP_DECL_CONSCHECK(consCheckBounddisjunction)
2348{ /*lint --e{715}*/
2349 SCIP_CONS* cons;
2350 SCIP_CONSDATA* consdata;
2351 int c;
2352
2353 assert(conshdlr != NULL);
2354 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2355 assert(nconss == 0 || conss != NULL);
2356 assert(result != NULL);
2357
2358 *result = SCIP_FEASIBLE;
2359
2360 /* check all bound disjunction constraints for feasibility */
2361 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
2362 {
2363 cons = conss[c];
2364 consdata = SCIPconsGetData(cons);
2365 assert(consdata != NULL);
2366
2367 if( isConsViolated(scip, cons, sol) )
2368 {
2369 if( printreason )
2370 {
2371 int v;
2372
2373 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
2374 SCIPinfoMessage(scip, NULL, ";\nviolation: ");
2375 for( v = 0; v < consdata->nvars; ++v )
2376 {
2377 assert(consdata->vars[v] != NULL);
2378 if( v > 0 )
2379 SCIPinfoMessage(scip, NULL, ", ");
2380 SCIPinfoMessage(scip, NULL, "<%s> = %.15g",
2381 SCIPvarGetName(consdata->vars[v]), SCIPgetSolVal(scip, sol, consdata->vars[v]));
2382 }
2383 SCIPinfoMessage(scip, NULL, ")\n");
2384 }
2385
2386 /* constraint is violated */
2387 *result = SCIP_INFEASIBLE;
2388 }
2389 }
2390
2391 return SCIP_OKAY;
2392}
2393
2394
2395/** domain propagation method of constraint handler */
2396static
2397SCIP_DECL_CONSPROP(consPropBounddisjunction)
2398{ /*lint --e{715}*/
2399 SCIP_CONSHDLRDATA* conshdlrdata;
2400 SCIP_Bool cutoff;
2401 SCIP_Bool infeasible;
2402 SCIP_Bool reduceddom;
2403 SCIP_Bool mustcheck;
2404 SCIP_Bool consreduceddom;
2405 int c;
2406
2407 assert(conshdlr != NULL);
2408 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2409 assert(nconss == 0 || conss != NULL);
2410 assert(result != NULL);
2411
2412 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2413 assert(conshdlrdata != NULL);
2414
2415 cutoff = FALSE;
2416 infeasible = FALSE;
2417 reduceddom = FALSE;
2418
2419 /* propagate all useful bound disjunction constraints */
2420 for( c = 0; c < nusefulconss && !cutoff; ++c )
2421 {
2422 SCIP_CALL( processWatchedVars(scip, conss[c], conshdlrdata->eventhdlr,
2423 &cutoff, &infeasible, &consreduceddom, &mustcheck) );
2424 reduceddom = reduceddom || consreduceddom;
2425 }
2426
2427 /* return the correct result */
2428 if( cutoff )
2429 *result = SCIP_CUTOFF;
2430 else if( reduceddom )
2431 *result = SCIP_REDUCEDDOM;
2432 else
2433 *result = SCIP_DIDNOTFIND;
2434
2435 return SCIP_OKAY; /*lint !e438*/
2436}
2437
2438
2439/** presolving method of constraint handler */
2440static
2441SCIP_DECL_CONSPRESOL(consPresolBounddisjunction)
2442{ /*lint --e{715}*/
2443 SCIP_CONSHDLRDATA* conshdlrdata;
2444 SCIP_CONS* cons;
2445 SCIP_CONSDATA* consdata;
2446 SCIP_Bool infeasible;
2447 SCIP_Bool redundant;
2448 SCIP_Bool tightened;
2449 int c;
2450
2451 assert(conshdlr != NULL);
2452 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2453 assert(scip != NULL);
2454 assert(result != NULL);
2455
2456 *result = SCIP_DIDNOTFIND;
2457
2458 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2459 assert(conshdlrdata != NULL);
2460
2461 /* process constraints */
2462 for( c = 0; c < nconss && *result != SCIP_CUTOFF && !SCIPisStopped(scip); ++c )
2463 {
2464 cons = conss[c];
2465 assert(cons != NULL);
2466 consdata = SCIPconsGetData(cons);
2467 assert(consdata != NULL);
2468
2469 SCIPdebugMsg(scip, "presolving bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2470
2471 /* force presolving the constraint in the initial round */
2472 if( nrounds == 0 )
2473 {
2475 }
2476
2477 /* remove all literals that are violated in global bounds, check redundancy due to global bounds */
2478 SCIP_CALL( applyGlobalBounds(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2479
2480 if( !redundant )
2481 {
2482 /* replace variables by their representative active (or multi-aggregated) variables */
2483 SCIP_CALL( removeFixedVariables(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2484 }
2485
2486 /**@todo find pairs of negated variables in constraint: constraint is redundant */
2487 /**@todo find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
2488
2489 if( redundant )
2490 {
2491 SCIPdebugMsg(scip, "bound disjunction constraint <%s> is redundant\n", SCIPconsGetName(cons));
2492 SCIP_CALL( SCIPdelCons(scip, cons) );
2493 (*ndelconss)++;
2494 *result = SCIP_SUCCESS;
2495 continue;
2496 }
2497 else if( !SCIPconsIsModifiable(cons) )
2498 {
2499 /* if unmodifiable constraint has no variables, it is infeasible,
2500 * if unmodifiable constraint has only one variable, the literal can be satisfied and the constraint deleted
2501 */
2502 if( consdata->nvars == 0 )
2503 {
2504 SCIPdebugMsg(scip, "bound disjunction constraint <%s> is infeasible\n", SCIPconsGetName(cons));
2505 *result = SCIP_CUTOFF;
2506 return SCIP_OKAY;
2507 }
2508 else if( consdata->nvars == 1 )
2509 {
2510 SCIPdebugMsg(scip, "bound disjunction constraint <%s> has only one undecided literal\n",
2511 SCIPconsGetName(cons));
2512
2513 assert(consdata->vars != NULL);
2514 assert(!isLiteralSatisfied(scip, consdata, 0));
2515 assert(!isLiteralViolated(scip, consdata, 0));
2516
2517 if( SCIPvarIsActive(consdata->vars[0]) )
2518 {
2519 if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER )
2520 {
2521 SCIP_CALL( SCIPtightenVarLb(scip, consdata->vars[0], consdata->bounds[0], TRUE, &infeasible, &tightened) );
2522 }
2523 else
2524 {
2525 SCIP_CALL( SCIPtightenVarUb(scip, consdata->vars[0], consdata->bounds[0], TRUE, &infeasible, &tightened) );
2526 }
2527 if( infeasible )
2528 {
2529 SCIPdebugMsg(scip, " -> infeasible fixing\n");
2530 *result = SCIP_CUTOFF;
2531 return SCIP_OKAY;
2532 }
2533 assert(tightened);
2534 (*nchgbds)++;
2535 }
2536 else
2537 {
2538 /* upgrade to a linear constraint, if vars[0] is multi-aggregated */
2539 SCIP_CONS* lincons;
2540 SCIP_Real one;
2541
2542 assert(SCIPvarGetStatus(consdata->vars[0]) == SCIP_VARSTATUS_MULTAGGR);
2543
2544 one = 1.0;
2545 if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER )
2546 {
2548 1, &consdata->vars[0], &one, consdata->bounds[0], SCIPinfinity(scip),
2552 SCIPconsIsStickingAtNode(cons)) );
2553 }
2554 else
2555 {
2557 1, &consdata->vars[0], &one, -SCIPinfinity(scip), consdata->bounds[0],
2561 SCIPconsIsStickingAtNode(cons)) );
2562 }
2563 SCIP_CALL( SCIPaddCons(scip, lincons) );
2564 SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2565 (*nupgdconss)++;
2566 }
2567
2568 SCIP_CALL( SCIPdelCons(scip, cons) );
2569 (*ndelconss)++;
2570 *result = SCIP_SUCCESS;
2571 continue;
2572 }
2573 else
2574 {
2575 /* try to upgrade the bounddisjunction constraint */
2576 SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
2577 }
2578 }
2579 }
2580
2581 /**@todo preprocess pairs of bound disjunction constraints */
2582
2583 return SCIP_OKAY;
2584}
2585
2586
2587/** propagation conflict resolving method of constraint handler */
2588static
2589SCIP_DECL_CONSRESPROP(consRespropBounddisjunction)
2590{ /*lint --e{715}*/
2591 SCIP_CONSDATA* consdata;
2592 SCIP_VAR** vars;
2593 SCIP_BOUNDTYPE* boundtypes;
2594#ifndef NDEBUG
2595 SCIP_Real* bounds;
2596#endif
2597 int v;
2598
2599 assert(conshdlr != NULL);
2600 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2601 assert(cons != NULL);
2602 assert(infervar != NULL);
2603 assert(result != NULL);
2604
2605 consdata = SCIPconsGetData(cons);
2606 assert(consdata != NULL);
2607 assert(consdata->vars != NULL);
2608 assert(consdata->nvars > 0);
2609 assert(0 <= inferinfo && inferinfo < consdata->nvars);
2610 assert(consdata->vars[inferinfo] == infervar);
2611
2612 vars = consdata->vars;
2613 boundtypes = consdata->boundtypes;
2614#ifndef NDEBUG
2615 bounds = consdata->bounds;
2616 assert(bounds != NULL);
2617#endif
2618 assert(boundtypes != NULL);
2619
2620 SCIPdebugMsg(scip, "conflict resolving method of bound disjunction constraint handler\n");
2621
2622 /* the only deductions are bounds tightened to a literal's bound on bound disjunction constraints where all other
2623 * literals are violated
2624 */
2625 assert((boundtypes[inferinfo] == SCIP_BOUNDTYPE_LOWER
2626 && SCIPisFeasGE(scip, SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE), bounds[inferinfo]))
2627 || (boundtypes[inferinfo] == SCIP_BOUNDTYPE_UPPER
2628 && SCIPisFeasLE(scip, SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE), bounds[inferinfo])));
2629
2630 for( v = 0; v < consdata->nvars; ++v )
2631 {
2632 if( v != inferinfo )
2633 {
2634 assert(consdata->vars[v] != infervar || consdata->boundtypes[v] != consdata->boundtypes[inferinfo]);
2635
2636 /* the reason literal must have been violated
2637 * we do not check for multi-aggregated variables, since SCIPvarGetXbAtIndex is not implemented for them */
2638 /* Use a weaker comparison to SCIPvarGetXbAtIndex here (i.e., SCIPisXT instead of SCIPisFeasXT),
2639 * because SCIPvarGetXbAtIndex might differ from the local bound at time bdchgidx by epsilon. */
2640 assert(SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_MULTAGGR
2641 || (boundtypes[v] == SCIP_BOUNDTYPE_LOWER
2642 && SCIPisLT(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, TRUE), bounds[v]))
2643 || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER
2644 && SCIPisGT(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, TRUE), bounds[v])));
2645 SCIP_CALL( SCIPaddConflictBd(scip, vars[v], SCIPboundtypeOpposite(boundtypes[v]), bdchgidx) );
2646 }
2647 }
2648
2649 *result = SCIP_SUCCESS;
2650
2651 return SCIP_OKAY;
2652}
2653
2654
2655/** variable rounding lock method of constraint handler */
2656static
2657SCIP_DECL_CONSLOCK(consLockBounddisjunction)
2658{ /*lint --e{715}*/
2659 SCIP_CONSDATA* consdata;
2660 int i;
2661
2662 consdata = SCIPconsGetData(cons);
2663 assert(consdata != NULL);
2664
2665 /* lock every single coefficient */
2666 for( i = 0; i < consdata->nvars; ++i )
2667 {
2668 if( consdata->boundtypes[i] == SCIP_BOUNDTYPE_LOWER )
2669 {
2670 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
2671 }
2672 else
2673 {
2674 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
2675 }
2676 }
2677
2678 return SCIP_OKAY;
2679}
2680
2681
2682/** constraint activation notification method of constraint handler */
2683static
2684SCIP_DECL_CONSACTIVE(consActiveBounddisjunction)
2685{ /*lint --e{715}*/
2686 SCIP_CONSHDLRDATA* conshdlrdata;
2687 SCIP_CONSDATA* consdata;
2688
2689 assert(conshdlr != NULL);
2690 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2691 assert(cons != NULL);
2692 assert(SCIPconsIsTransformed(cons));
2693
2694 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2695 assert(conshdlrdata != NULL);
2696 consdata = SCIPconsGetData(cons);
2697 assert(consdata != NULL);
2698 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
2699
2700 SCIPdebugMsg(scip, "activating information for bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2701 SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
2702
2703 /* catch events on watched variables */
2704 if( consdata->watchedvar1 != -1 )
2705 {
2706 SCIP_CALL( catchEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar1,
2707 &consdata->filterpos1) );
2708 }
2709 if( consdata->watchedvar2 != -1 )
2710 {
2711 SCIP_CALL( catchEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar2,
2712 &consdata->filterpos2) );
2713 }
2714
2715 return SCIP_OKAY;
2716}
2717
2718
2719/** constraint deactivation notification method of constraint handler */
2720static
2721SCIP_DECL_CONSDEACTIVE(consDeactiveBounddisjunction)
2722{ /*lint --e{715}*/
2723 SCIP_CONSHDLRDATA* conshdlrdata;
2724 SCIP_CONSDATA* consdata;
2725
2726 assert(conshdlr != NULL);
2727 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2728 assert(cons != NULL);
2729 assert(SCIPconsIsTransformed(cons));
2730
2731 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2732 assert(conshdlrdata != NULL);
2733 consdata = SCIPconsGetData(cons);
2734 assert(consdata != NULL);
2735 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
2736
2737 SCIPdebugMsg(scip, "deactivating information for bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2738 SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
2739
2740 /* drop events on watched variables */
2741 if( consdata->watchedvar1 != -1 )
2742 {
2743 assert(consdata->filterpos1 != -1);
2744 SCIP_CALL( dropEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
2745 consdata->watchedvar1 = -1;
2746 }
2747 if( consdata->watchedvar2 != -1 )
2748 {
2749 assert(consdata->filterpos2 != -1);
2750 SCIP_CALL( dropEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
2751 consdata->watchedvar2 = -1;
2752 }
2753
2754 return SCIP_OKAY;
2755}
2756
2757
2758/** constraint display method of constraint handler */
2759static
2760SCIP_DECL_CONSPRINT(consPrintBounddisjunction)
2761{ /*lint --e{715}*/
2762 assert( scip != NULL );
2763 assert( conshdlr != NULL );
2764 assert( cons != NULL );
2765
2766 consdataPrint(scip, SCIPconsGetData(cons), file, FALSE);
2767
2768 return SCIP_OKAY;
2769}
2770
2771/** constraint copying method of constraint handler */
2772static
2773SCIP_DECL_CONSCOPY(consCopyBounddisjunction)
2774{ /*lint --e{715}*/
2775 SCIP_VAR** sourcevars;
2776 SCIP_VAR** targetvars;
2777 SCIP_BOUNDTYPE* boundtypes;
2778 SCIP_Real* bounds;
2779 int nvars;
2780 int v;
2781
2782 assert(valid != NULL);
2783
2784 *valid = TRUE;
2785
2786 /* get source data */
2787 sourcevars = SCIPgetVarsBounddisjunction(sourcescip, sourcecons);
2788 nvars = SCIPgetNVarsBounddisjunction(sourcescip, sourcecons);
2789 boundtypes = SCIPgetBoundtypesBounddisjunction(sourcescip, sourcecons);
2790 bounds = SCIPgetBoundsBounddisjunction(sourcescip, sourcecons);
2791
2792 SCIP_CALL( SCIPallocBufferArray(scip, &targetvars, nvars) );
2793
2794 /* map source variables to active variables of the target SCIP */
2795 for( v = 0; v < nvars && *valid; ++v )
2796 {
2797 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &targetvars[v], varmap, consmap, global, valid) );
2798 assert(!(*valid) || targetvars[v] != NULL);
2799 }
2800
2801 /* only create the target constraint, if all variables could be copied */
2802 if( *valid )
2803 {
2804 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name ? name : SCIPconsGetName(sourcecons), nvars, targetvars, boundtypes,
2805 bounds, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2806 }
2807
2808 SCIPfreeBufferArray(scip, &targetvars);
2809
2810 return SCIP_OKAY;
2811}
2812
2813/** constraint parsing method of constraint handler */
2814static
2815SCIP_DECL_CONSPARSE(consParseBounddisjunction)
2816{ /*lint --e{715}*/
2817 SCIP_BOUNDTYPE* boundtypes;
2818 SCIP_Real* bounds;
2819 SCIP_VAR** vars;
2820 char* endptr;
2821 int varssize;
2822 int nvars;
2823
2824 assert( success != NULL );
2825 *success = TRUE;
2826
2827 SCIPdebugMsg(scip, "parse <%s> as bounddisjunction constraint\n", str);
2828
2829 /* skip white space */
2830 SCIP_CALL( SCIPskipSpace((char**)&str) );
2831
2832 /* check for string "bounddisjunction" */
2833 if( strncmp(str, "bounddisjunction(", 16) != 0 )
2834 {
2835 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "error during parsing: expected \"bounddisjunction(\" in <%s>.\n", str);
2836 *success = FALSE;
2837 return SCIP_OKAY;
2838 }
2839
2840 /* skip "bounddisjunction(" */
2841 str += 17;
2842
2843 varssize = 100;
2844 nvars = 0;
2845
2846 /* allocate buffer array for variables */
2847 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
2848 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, varssize) );
2849 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, varssize) );
2850
2851 /* parse string until ")" */
2852 while( *str != ')' )
2853 {
2854 SCIP_VAR* var;
2855
2856 /* parse variable name */
2857 SCIP_CALL( SCIPparseVarName(scip, str, &var, &endptr) );
2858
2859 if( var == NULL )
2860 {
2861 endptr = strchr(endptr, ')');
2862
2863 if( endptr == NULL )
2864 {
2865 *success = FALSE;
2866 goto TERMINATE;
2867 }
2868
2869 break;
2870 }
2871
2872 str = endptr;
2873
2874 /* skip white space */
2875 SCIP_CALL( SCIPskipSpace((char**)&str) );
2876
2877 /* parse bound type */
2878 switch( *str )
2879 {
2880 case '<':
2881 boundtypes[nvars] = SCIP_BOUNDTYPE_UPPER;
2882 break;
2883 case '>':
2884 boundtypes[nvars] = SCIP_BOUNDTYPE_LOWER;
2885 break;
2886 default:
2887 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "variable with name <%s> does not exist\n", SCIPvarGetName(var));
2888 *success = FALSE;
2889 goto TERMINATE;
2890 }
2891
2892 ++str;
2893 if( *str != '=' )
2894 {
2895 SCIPdebugMsg(scip, "expected '=': %s\n", str);
2896 *success = FALSE;
2897 goto TERMINATE;
2898 }
2899
2900 /* skip '=' */
2901 ++str;
2902
2903 /* parse bound value */
2904 if( !SCIPparseReal(scip, str, &bounds[nvars], &endptr) )
2905 {
2906 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error during parsing of the weight: %s\n", str);
2907 *success = FALSE;
2908 goto TERMINATE;
2909 }
2910
2911 str = endptr;
2912
2913 /* set variable */
2914 vars[nvars++] = var;
2915
2916 /* check if the size of the variable array was big enough */
2917 if( nvars > varssize )
2918 {
2919 /* reallocate memory */
2920 varssize *= 2;
2921 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
2922 SCIP_CALL( SCIPreallocBufferArray(scip, &boundtypes, varssize) );
2923 SCIP_CALL( SCIPreallocBufferArray(scip, &bounds, varssize) );
2924 }
2925
2926 /* skip white space */
2927 SCIP_CALL( SCIPskipSpace((char**)&str) );
2928
2929 /* skip ',' */
2930 if( *str == ',' )
2931 ++str;
2932 }
2933
2934 /* add bounddisjunction */
2935 if( *success && nvars > 0 )
2936 {
2937 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name, nvars, vars, boundtypes, bounds,
2938 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2939 }
2940
2941 TERMINATE:
2942 /* free variable buffer */
2943 SCIPfreeBufferArray(scip, &bounds);
2944 SCIPfreeBufferArray(scip, &boundtypes);
2945 SCIPfreeBufferArray(scip, &vars);
2946
2947 return SCIP_OKAY;
2948}
2949
2950/** constraint method of constraint handler which returns the variables (if possible) */
2951static
2952SCIP_DECL_CONSGETVARS(consGetVarsBounddisjunction)
2953{ /*lint --e{715}*/
2954 SCIP_CONSDATA* consdata;
2955
2956 assert(cons != NULL);
2957
2958 consdata = SCIPconsGetData(cons);
2959 assert(consdata != NULL);
2960
2961 if( varssize < consdata->nvars )
2962 (*success) = FALSE;
2963 else
2964 {
2965 assert(vars != NULL);
2966
2967 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
2968 (*success) = TRUE;
2969 }
2970
2971 return SCIP_OKAY;
2972}
2973
2974/** constraint method of constraint handler which returns the number of variables (if possible) */
2975static
2976SCIP_DECL_CONSGETNVARS(consGetNVarsBounddisjunction)
2977{ /*lint --e{715}*/
2978 SCIP_CONSDATA* consdata;
2979
2980 assert(cons != NULL);
2981
2982 consdata = SCIPconsGetData(cons);
2983 assert(consdata != NULL);
2984
2985 (*nvars) = consdata->nvars;
2986 (*success) = TRUE;
2987
2988 return SCIP_OKAY;
2989}
2990
2991/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
2992static
2993SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphBounddisjunction)
2994{ /*lint --e{715}*/
2995 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
2996
2997 return SCIP_OKAY;
2998}
2999
3000/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
3001static
3002SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphBounddisjunction)
3003{ /*lint --e{715}*/
3004 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
3005
3006 return SCIP_OKAY;
3007}
3008
3009/**@} */
3010
3011/**@name Callback methods of event handler
3012 *
3013 * @{
3014 */
3015
3016static
3017SCIP_DECL_EVENTEXEC(eventExecBounddisjunction)
3018{ /*lint --e{715}*/
3019 assert(eventhdlr != NULL);
3020 assert(eventdata != NULL);
3021 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
3022 assert(event != NULL);
3023
3024 /*SCIPdebugMsg(scip, "exec method of event handler for bound disjunction constraints\n");*/
3025
3026 assert(SCIPconsGetData((SCIP_CONS*)eventdata) != NULL);
3027 assert(SCIPconsIsActive((SCIP_CONS*)eventdata) || SCIPconsIsUpdatedeactivate((SCIP_CONS*)eventdata));
3028
3029 if( (SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDRELAXED) != 0 )
3030 {
3031 SCIP_CALL( SCIPenableCons(scip, (SCIP_CONS*)eventdata) );
3032 }
3033 else
3034 assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0);
3035
3037
3038 return SCIP_OKAY;
3039}
3040
3041/**@} */
3042
3043/**@name Callback methods of conflict handler
3044 *
3045 * @{
3046 */
3047
3048/** conflict handler data struct */
3049struct SCIP_ConflicthdlrData
3050{
3051 SCIP_Real continuousfrac; /**< maximal percantage of continuous variables within a conflict */
3052};
3053
3054/** conflict processing method of conflict handler (called when conflict was found) */
3055static
3056SCIP_DECL_CONFLICTEXEC(conflictExecBounddisjunction)
3057{ /*lint --e{715}*/
3058 SCIP_VAR** vars;
3059 SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3060 SCIP_BOUNDTYPE* boundtypes;
3061 SCIP_Real* bounds;
3062 SCIP_CONS* cons;
3063 char consname[SCIP_MAXSTRLEN];
3064 int nliterals;
3065 int ncontinuous;
3066 int i;
3067
3068 assert(conflicthdlr != NULL);
3069 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
3070 assert(bdchginfos != NULL || nbdchginfos == 0);
3071 assert(result != NULL);
3072
3073 /* don't process already resolved conflicts */
3074 if( resolved )
3075 {
3076 *result = SCIP_DIDNOTRUN;
3077 return SCIP_OKAY;
3078 }
3079
3080 conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
3081 assert(conflicthdlrdata != NULL);
3082
3083 *result = SCIP_DIDNOTFIND;
3084 ncontinuous = 0;
3085
3086 /* create array of variables, boundtypes, and bound values in conflict constraint */
3087 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
3088 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nbdchginfos) );
3089 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nbdchginfos) );
3090
3091 nliterals = 0;
3092
3093 for( i = 0; i < nbdchginfos; ++i )
3094 {
3095 SCIP_VAR* var;
3097 SCIP_BOUNDTYPE boundtype;
3098 int j;
3099
3100 assert(bdchginfos != NULL);
3101
3102 var = SCIPbdchginfoGetVar(bdchginfos[i]);
3103 assert(var != NULL);
3104
3105 boundtype = SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[i]));
3106 bound = relaxedbds[i];
3107
3108 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
3109 if( SCIPvarIsIntegral(var) )
3110 bound += (boundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
3111
3112 /* check whether we have seen the variable before */
3113 for( j = nliterals-1; j >= 0; --j )
3114 {
3115 if( vars[j] != var )
3116 continue;
3117
3118 /* check whether both literals contribute with the same bound type */
3119 if( boundtypes[j] == boundtype )
3120 {
3121 /* check whether the lower bound can be relaxed */
3122 if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLT(scip, bound, bounds[j]) )
3123 {
3124 SCIPdebugMsg(scip, "relax lower bound of variable <%s> from %g to %g in bounddisjunction conflict\n",
3125 SCIPvarGetName(var), bounds[j], bound);
3126 bounds[j] = bound;
3127 }
3128 /* check whether the upper bound can be relaxed */
3129 else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisGT(scip, bound, bounds[j]) )
3130 {
3131 SCIPdebugMsg(scip, "relax upper bound of variable <%s> from %g to %g in bounddisjunction conflict\n",
3132 SCIPvarGetName(var), bounds[j], bound);
3133 bounds[j] = bound;
3134 }
3135
3136 continue;
3137 }
3138 /* check whether the bounds are overlapping */
3139 else if( isOverlapping(scip, var, boundtype, bound, boundtypes[j], bounds[j]) )
3140 {
3141 /* the conflict is redundant -> discard the conflict constraint */
3142 SCIPdebugMsg(scip, "redundant bounddisjunction conflict due to overlapping\n");
3143 goto DISCARDCONFLICT;
3144 }
3145 }
3146
3147 vars[nliterals] = var;
3148 boundtypes[nliterals] = boundtype;
3149 bounds[nliterals] = bound;
3150
3151 /* check if the relaxed bound is really a relaxed bound */
3152 assert(SCIPbdchginfoGetBoundtype(bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER || SCIPisGE(scip, relaxedbds[i], SCIPbdchginfoGetNewbound(bdchginfos[i])));
3153 assert(SCIPbdchginfoGetBoundtype(bdchginfos[i]) == SCIP_BOUNDTYPE_UPPER || SCIPisLE(scip, relaxedbds[i], SCIPbdchginfoGetNewbound(bdchginfos[i])));
3154
3155 /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
3156 if( !SCIPvarIsIntegral(vars[nliterals]) )
3157 {
3158 if( (boundtypes[i] == SCIP_BOUNDTYPE_LOWER && SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), bounds[nliterals]))
3159 || (boundtypes[i] == SCIP_BOUNDTYPE_UPPER && SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), bounds[nliterals])) )
3160 {
3161 /* the literal is satisfied in global bounds (may happen due to weak "negation" of continuous variables)
3162 * -> discard the conflict constraint
3163 */
3164 SCIPdebugMsg(scip, "redundant bounddisjunction conflict due to globally fulfilled literal\n");
3165 goto DISCARDCONFLICT;
3166 }
3167 else
3168 ncontinuous++;
3169 }
3170
3171 nliterals++;
3172 }
3173
3174 /* create a constraint out of the conflict set */
3175 if( i == nbdchginfos && ncontinuous < conflicthdlrdata->continuousfrac * nbdchginfos + 0.5 )
3176 {
3178 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, consname, nliterals, vars, boundtypes, bounds,
3179 FALSE, FALSE, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
3180
3181 /* add conflict to SCIP */
3182 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
3183 SCIPdebugMsg(scip, "added conflict\n");
3184 *result = SCIP_CONSADDED;
3185 }
3186
3187 DISCARDCONFLICT:
3188 /* free temporary memory */
3189 SCIPfreeBufferArray(scip, &bounds);
3190 SCIPfreeBufferArray(scip, &boundtypes);
3191 SCIPfreeBufferArray(scip, &vars);
3192
3193 return SCIP_OKAY;
3194}
3195
3196/** free method of conflict handler */
3197static
3198SCIP_DECL_CONFLICTFREE(conflictFreeBounddisjunction)
3199{
3200 SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3201
3202 assert(conflicthdlr != NULL);
3203
3204 /* get conflict handler data */
3205 conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
3206 assert(conflicthdlrdata != NULL);
3207
3208 /* free conflict handler structure */
3209 SCIPfreeBlockMemory(scip, &conflicthdlrdata);
3210
3211 return SCIP_OKAY;
3212}
3213
3214/**@} */
3215
3216/** creates the handler for bound disjunction constraints and includes it in SCIP */
3218 SCIP* scip /**< SCIP data structure */
3219 )
3220{
3221 SCIP_CONSHDLRDATA* conshdlrdata;
3222 SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3223 SCIP_CONFLICTHDLR* conflicthdlr;
3224 SCIP_CONSHDLR* conshdlr;
3225 SCIP_EVENTHDLR* eventhdlr;
3226
3227 /* create event handler for events on watched variables */
3229 eventExecBounddisjunction, NULL) );
3230
3231 /* allocate memory for conflict handler data */
3232 SCIP_CALL( SCIPallocBlockMemory(scip, &conflicthdlrdata) );
3233
3234 /* create conflict handler parameter */
3236 "conflict/" CONSHDLR_NAME "/continuousfrac", "maximal percantage of continuous variables within a conflict",
3237 &conflicthdlrdata->continuousfrac, FALSE, DEFAULT_CONTINUOUSFRAC, 0.0, 1.0, NULL, NULL) );
3238
3239 /* create conflict handler for bound disjunction constraints */
3241 conflictExecBounddisjunction, conflicthdlrdata) );
3242
3243 SCIP_CALL( SCIPsetConflicthdlrFree(scip, conflicthdlr, conflictFreeBounddisjunction) );
3244
3245 /* create constraint handler data */
3246 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
3247
3248 /* include constraint handler */
3251 consEnfolpBounddisjunction, consEnfopsBounddisjunction, consCheckBounddisjunction, consLockBounddisjunction,
3252 conshdlrdata) );
3253
3254 assert(conshdlr != NULL);
3255
3256 /* set non-fundamental callbacks via specific setter functions */
3257 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveBounddisjunction) );
3258 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyBounddisjunction, consCopyBounddisjunction) );
3259 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveBounddisjunction) );
3260 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteBounddisjunction) );
3261 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreBounddisjunction) );
3262 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolBounddisjunction) );
3263 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeBounddisjunction) );
3264 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsBounddisjunction) );
3265 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsBounddisjunction) );
3266 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseBounddisjunction) );
3267 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolBounddisjunction, CONSHDLR_MAXPREROUNDS,
3269 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintBounddisjunction) );
3270 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropBounddisjunction, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
3272 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropBounddisjunction) );
3273 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransBounddisjunction) );
3274 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxBounddisjunction) );
3275 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphBounddisjunction) );
3276 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphBounddisjunction) );
3277
3278 return SCIP_OKAY;
3279}
3280
3281
3282/** creates and captures a bound disjunction constraint
3283 *
3284 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3285 */
3287 SCIP* scip, /**< SCIP data structure */
3288 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3289 const char* name, /**< name of constraint */
3290 int nvars, /**< number of variables in the constraint */
3291 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3292 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3293 SCIP_Real* bounds, /**< bounds of the literals */
3294 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3295 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3296 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3297 * Usually set to TRUE. */
3298 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3299 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3300 SCIP_Bool check, /**< should the constraint be checked for feasibility?
3301 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3302 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3303 * Usually set to TRUE. */
3304 SCIP_Bool local, /**< is constraint only valid locally?
3305 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3306 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3307 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3308 * adds coefficients to this constraint. */
3309 SCIP_Bool dynamic, /**< is constraint subject to aging?
3310 * Usually set to FALSE. Set to TRUE for own cuts which
3311 * are separated as constraints. */
3312 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3313 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3314 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3315 * if it may be moved to a more global node?
3316 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3317 )
3318{
3319 SCIP_CONSHDLR* conshdlr;
3320 SCIP_CONSDATA* consdata;
3321
3322 assert(scip != NULL);
3323
3324 /* find the bounddisjunction constraint handler */
3325 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3326 if( conshdlr == NULL )
3327 {
3328 SCIPerrorMessage("bound disjunction constraint handler not found\n");
3329 return SCIP_PLUGINNOTFOUND;
3330 }
3331
3332#ifndef NDEBUG
3333 {
3334 int v1;
3335 /* ensure that the given data neither contains overlapping nor redundant literals */
3336 for( v1 = 0; v1 < nvars; v1++ )
3337 {
3338 int v2;
3339 for( v2 = v1+1; v2 < nvars; v2++ )
3340 {
3341 assert(vars[v1] != vars[v2] || (SCIPboundtypeOpposite(boundtypes[v1]) == boundtypes[v2]
3342 && !isOverlapping(scip, vars[v1], boundtypes[v1], bounds[v1], boundtypes[v2], bounds[v2])));
3343 }
3344 }
3345 }
3346#endif
3347
3348 /* create the constraint specific data */
3349 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, boundtypes, bounds) );
3350
3351 /* create constraint */
3352 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3353 local, modifiable, dynamic, removable, stickingatnode) );
3354
3355 return SCIP_OKAY;
3356}
3357
3358/** creates and captures a bound disjunction constraint
3359 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3360 * method SCIPcreateConsBounddisjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
3361 *
3362 * @see SCIPcreateConsBounddisjunction() for information about the basic constraint flag configuration
3363 *
3364 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3365 */
3367 SCIP* scip, /**< SCIP data structure */
3368 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3369 const char* name, /**< name of constraint */
3370 int nvars, /**< number of variables in the constraint */
3371 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3372 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3373 SCIP_Real* bounds /**< bounds of the literals */
3374 )
3375{
3376 assert(scip != NULL);
3377
3378 SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name, nvars, vars, boundtypes, bounds,
3380
3381 return SCIP_OKAY;
3382}
3383
3384/** creates and captures a bound disjunction constraint with possibly redundant literals
3385 *
3386 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3387 */
3389 SCIP* scip, /**< SCIP data structure */
3390 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3391 const char* name, /**< name of constraint */
3392 int nvars, /**< number of variables in the constraint */
3393 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3394 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3395 SCIP_Real* bounds, /**< bounds of the literals */
3396 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3397 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3398 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3399 * Usually set to TRUE. */
3400 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3401 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3402 SCIP_Bool check, /**< should the constraint be checked for feasibility?
3403 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3404 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3405 * Usually set to TRUE. */
3406 SCIP_Bool local, /**< is constraint only valid locally?
3407 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3408 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3409 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3410 * adds coefficients to this constraint. */
3411 SCIP_Bool dynamic, /**< is constraint subject to aging?
3412 * Usually set to FALSE. Set to TRUE for own cuts which
3413 * are separated as constraints. */
3414 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3415 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3416 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3417 * if it may be moved to a more global node?
3418 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3419 )
3420{
3421 SCIP_CONSHDLR* conshdlr;
3422 SCIP_CONSDATA* consdata;
3423
3424 assert(scip != NULL);
3425
3426 /* find the bounddisjunction constraint handler */
3427 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3428 if( conshdlr == NULL )
3429 {
3430 SCIPerrorMessage("bound disjunction constraint handler not found\n");
3431 return SCIP_PLUGINNOTFOUND;
3432 }
3433
3434 /* create the constraint specific data */
3435 SCIP_CALL( consdataCreateRedundant(scip, &consdata, nvars, vars, boundtypes, bounds) );
3436
3437 /* create constraint */
3438 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3439 local, modifiable, dynamic, removable, stickingatnode) );
3440
3441 return SCIP_OKAY;
3442}
3443
3444/** creates and captures a bound disjunction constraint with possibly redundant literals
3445 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3446 * method SCIPcreateConsBounddisjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
3447 *
3448 * @see SCIPcreateConsBounddisjunction() for information about the basic constraint flag configuration
3449 *
3450 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3451 */
3453 SCIP* scip, /**< SCIP data structure */
3454 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3455 const char* name, /**< name of constraint */
3456 int nvars, /**< number of variables in the constraint */
3457 SCIP_VAR** vars, /**< variables of the literals in the constraint */
3458 SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3459 SCIP_Real* bounds /**< bounds of the literals */
3460 )
3461{
3462 assert(scip != NULL);
3463
3464 SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, cons, name, nvars, vars, boundtypes, bounds,
3466
3467 return SCIP_OKAY;
3468}
3469
3470/** gets number of variables in bound disjunction constraint */ /*lint -e{715}*/
3472 SCIP* scip, /**< SCIP data structure */
3473 SCIP_CONS* cons /**< constraint data */
3474 )
3475{
3476 SCIP_CONSDATA* consdata;
3477
3478 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3479 {
3480 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3481 SCIPABORT();
3482 return 0; /*lint !e527*/
3483 }
3484
3485 consdata = SCIPconsGetData(cons);
3486 assert(consdata != NULL);
3487
3488 return consdata->nvars;
3489}
3490
3491/** gets array of variables in bound disjunction constraint */ /*lint -e{715}*/
3493 SCIP* scip, /**< SCIP data structure */
3494 SCIP_CONS* cons /**< constraint data */
3495 )
3496{
3497 SCIP_CONSDATA* consdata;
3498
3499 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3500 {
3501 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3502 SCIPABORT();
3503 return NULL; /*lint !e527*/
3504 }
3505
3506 consdata = SCIPconsGetData(cons);
3507 assert(consdata != NULL);
3508
3509 return consdata->vars;
3510}
3511
3512/** gets array of bound types in bound disjunction constraint */ /*lint -e{715}*/
3514 SCIP* scip, /**< SCIP data structure */
3515 SCIP_CONS* cons /**< constraint data */
3516 )
3517{
3518 SCIP_CONSDATA* consdata;
3519
3520 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3521 {
3522 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3523 SCIPABORT();
3524 return NULL; /*lint !e527*/
3525 }
3526
3527 consdata = SCIPconsGetData(cons);
3528 assert(consdata != NULL);
3529
3530 return consdata->boundtypes;
3531}
3532
3533/** gets array of bounds in bound disjunction constraint */ /*lint -e{715}*/
3535 SCIP* scip, /**< SCIP data structure */
3536 SCIP_CONS* cons /**< constraint data */
3537 )
3538{
3539 SCIP_CONSDATA* consdata;
3540
3541 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3542 {
3543 SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3544 SCIPABORT();
3545 return NULL; /*lint !e527*/
3546 }
3547
3548 consdata = SCIPconsGetData(cons);
3549 assert(consdata != NULL);
3550
3551 return consdata->bounds;
3552}
static long bound
SCIP_VAR * w
Definition: circlepacking.c:67
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:267
#define SCIP_MAXSTRLEN
Definition: def.h:288
#define SCIP_Longint
Definition: def.h:158
#define SCIP_REAL_MAX
Definition: def.h:174
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:173
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
#define SCIPABORT()
Definition: def.h:346
#define REALABS(x)
Definition: def.h:197
#define SCIP_LONGINT_MAX
Definition: def.h:159
#define SCIP_CALL(x)
Definition: def.h:374
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:9409
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:660
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:711
SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_var.c:390
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:3193
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:596
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:724
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:380
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
SCIP_RETCODE SCIPdelConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons)
Definition: scip_prob.c:3424
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3323
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3228
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:11184
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
SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
Definition: scip_branch.c:920
SCIP_RETCODE SCIPaddExternBranchCand(SCIP *scip, SCIP_VAR *var, SCIP_Real score, SCIP_Real solval)
Definition: scip_branch.c:665
SCIP_Real SCIPcalcChildEstimate(SCIP *scip, SCIP_VAR *var, SCIP_Real targetvalue)
Definition: scip_branch.c:947
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip_branch.c:1017
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:17203
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:4227
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:4197
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:941
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:4217
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:8244
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8473
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8234
SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1838
SCIP_Bool SCIPconsIsPropagationEnabled(SCIP_CONS *cons)
Definition: cons.c:8332
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8383
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2537
SCIP_RETCODE SCIPenableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1952
int SCIPconsGetValidDepth(SCIP_CONS *cons)
Definition: cons.c:8297
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8413
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8343
SCIP_Bool SCIPconsIsUpdatedeactivate(SCIP_CONS *cons)
Definition: cons.c:8285
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8523
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8403
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8275
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:998
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8433
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8453
SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1872
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1813
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8463
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:8643
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8493
SCIP_RETCODE SCIPdisableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1982
SCIP_RETCODE SCIPaddConsAge(SCIP *scip, SCIP_CONS *cons, SCIP_Real deltaage)
Definition: scip_cons.c:1756
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1174
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8393
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8483
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:104
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:324
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1030
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:354
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:400
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1417
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:97
void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:129
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1217
int SCIPgetNRuns(SCIP *scip)
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
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)
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:670
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5203
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12469
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4351
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17748
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17599
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1480
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17538
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18144
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17561
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:5615
SCIP_RETCODE SCIPchgVarUbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4890
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:12218
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5320
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip_var.c:533
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17584
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18088
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4259
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4437
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2128
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17419
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18680
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17610
SCIP_Real SCIPcomputeVarLbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6463
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:1527
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18134
SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6505
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18078
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:5501
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1992
SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4846
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15744
SCIP_Real SCIPcomputeVarUbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6484
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18700
SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6526
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18670
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:10877
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10866
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
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
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:60
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:173
#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:124
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:123
#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:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ SCIP_VERBLEVEL_MINIMAL
Definition: type_message.h:54
@ 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_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:52
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54