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