SCIP Doxygen Documentation
Loading...
Searching...
No Matches
cons_or.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_or.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief Constraint handler for "or" constraints, \f$r = x_1 \vee x_2 \vee \dots \vee x_n\f$
28 * @author Tobias Achterberg
29 * @author Stefan Heinz
30 * @author Michael Winkler
31 *
32 * This constraint handler deals with "or" constraint. These are constraint of the form:
33 *
34 * \f[
35 * r = x_1 \vee x_2 \vee \dots \vee x_n
36 * \f]
37 *
38 * where \f$x_i\f$ is a binary variable for all \f$i\f$. Hence, \f$r\f$ is also of binary type. The variable \f$r\f$ is
39 * called resultant and the \f$x\f$'s operators.
40 */
41
42/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
43
45#include "scip/cons_and.h"
46#include "scip/cons_or.h"
47#include "scip/pub_cons.h"
48#include "scip/pub_event.h"
49#include "scip/pub_lp.h"
50#include "scip/pub_message.h"
51#include "scip/pub_misc.h"
52#include "scip/pub_var.h"
53#include "scip/scip_conflict.h"
54#include "scip/scip_cons.h"
55#include "scip/scip_copy.h"
56#include "scip/scip_cut.h"
57#include "scip/scip_event.h"
58#include "scip/scip_general.h"
59#include "scip/scip_lp.h"
60#include "scip/scip_mem.h"
61#include "scip/scip_message.h"
62#include "scip/scip_numerics.h"
63#include "scip/scip_prob.h"
64#include "scip/scip_probing.h"
65#include "scip/scip_sol.h"
66#include "scip/scip_tree.h"
67#include "scip/scip_var.h"
68#include "scip/symmetry_graph.h"
70
71
72/* constraint handler properties */
73#define CONSHDLR_NAME "or"
74#define CONSHDLR_DESC "constraint handler for or constraints: r = or(x1, ..., xn)"
75#define CONSHDLR_SEPAPRIORITY +850000 /**< priority of the constraint handler for separation */
76#define CONSHDLR_ENFOPRIORITY -850000 /**< priority of the constraint handler for constraint enforcing */
77#define CONSHDLR_CHECKPRIORITY -850000 /**< priority of the constraint handler for checking feasibility */
78#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
79#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
80#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
81 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
82#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
83#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
84#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
85#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
86
87#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
88#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
89
90#define EVENTHDLR_NAME "or"
91#define EVENTHDLR_DESC "event handler for or constraints"
92
93
94/*
95 * Data structures
96 */
97
98/** constraint data for or constraints */
99struct SCIP_ConsData
100{
101 SCIP_VAR** vars; /**< variables in the or operation */
102 SCIP_VAR* resvar; /**< resultant variable */
103 SCIP_ROW** rows; /**< rows for linear relaxation of or constraint */
104 int nvars; /**< number of variables in or operation */
105 int varssize; /**< size of vars array */
106 int rowssize; /**< size of rows array */
107 int watchedvar1; /**< position of first watched operator variable */
108 int watchedvar2; /**< position of second watched operator variable */
109 int filterpos1; /**< event filter position of first watched operator variable */
110 int filterpos2; /**< event filter position of second watched operator variable */
111 unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
112 unsigned int nofixedone:1; /**< is none of the operator variables fixed to TRUE? */
113 unsigned int impladded:1; /**< were the implications of the constraint already added? */
114 unsigned int opimpladded:1; /**< was the implication for 2 operands with fixed resultant added? */
115};
116
117/** constraint handler data */
118struct SCIP_ConshdlrData
119{
120 SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
121};
122
123
124/*
125 * Propagation rules
126 */
127
129{
130 PROPRULE_1 = 0, /**< v_i = TRUE => r = TRUE */
131 PROPRULE_2 = 1, /**< r = FALSE => v_i = FALSE for all i */
132 PROPRULE_3 = 2, /**< v_i = FALSE for all i => r = FALSE */
133 PROPRULE_4 = 3, /**< r = TRUE, v_i = FALSE for all i except j => v_j = TRUE */
134 PROPRULE_INVALID = 4 /**< propagation was applied without a specific propagation rule */
135};
136typedef enum Proprule PROPRULE;
137
138
139/*
140 * Local methods
141 */
142
143/** installs rounding locks for the given variable in the given or constraint */
144static
146 SCIP* scip, /**< SCIP data structure */
147 SCIP_CONS* cons, /**< or constraint */
148 SCIP_VAR* var /**< variable of constraint entry */
149 )
150{
152
153 /* rounding in both directions may violate the constraint */
155
156 return SCIP_OKAY;
157}
158
159/** removes rounding locks for the given variable in the given or constraint */
160static
162 SCIP* scip, /**< SCIP data structure */
163 SCIP_CONS* cons, /**< or constraint */
164 SCIP_VAR* var /**< variable of constraint entry */
165 )
166{
168
169 /* rounding in both directions may violate the constraint */
171
172 return SCIP_OKAY;
173}
174
175/** creates constraint handler data */
176static
178 SCIP* scip, /**< SCIP data structure */
179 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
180 SCIP_EVENTHDLR* eventhdlr /**< event handler */
181 )
182{
183 assert(scip != NULL);
184 assert(conshdlrdata != NULL);
185 assert(eventhdlr != NULL);
186
187 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
188
189 /* set event handler for catching events on watched variables */
190 (*conshdlrdata)->eventhdlr = eventhdlr;
191
192 return SCIP_OKAY;
193}
194
195/** frees constraint handler data */
196static
198 SCIP* scip, /**< SCIP data structure */
199 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
200 )
201{
202 assert(conshdlrdata != NULL);
203 assert(*conshdlrdata != NULL);
204
205 SCIPfreeBlockMemory(scip, conshdlrdata);
206}
207
208/** gets number of LP rows needed for the LP relaxation of the constraint */
209static
211 SCIP_CONSDATA* consdata /**< constraint data */
212 )
213{
214 assert(consdata != NULL);
215
216 return consdata->nvars + 1;
217}
218
219/** catches events for the watched variable at given position */
220static
222 SCIP* scip, /**< SCIP data structure */
223 SCIP_CONSDATA* consdata, /**< or constraint data */
224 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
225 int pos, /**< array position of variable to catch bound change events for */
226 int* filterpos /**< pointer to store position of event filter entry */
227 )
228{
229 assert(consdata != NULL);
230 assert(consdata->vars != NULL);
231 assert(eventhdlr != NULL);
232 assert(0 <= pos && pos < consdata->nvars);
233 assert(filterpos != NULL);
234
235 /* catch tightening events for upper bound and relaxed events for lower bounds on watched variable */
237 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
238
239 return SCIP_OKAY;
240}
241
242
243/** drops events for the watched variable at given position */
244static
246 SCIP* scip, /**< SCIP data structure */
247 SCIP_CONSDATA* consdata, /**< or constraint data */
248 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
249 int pos, /**< array position of watched variable to drop bound change events for */
250 int filterpos /**< position of event filter entry */
251 )
252{
253 assert(consdata != NULL);
254 assert(consdata->vars != NULL);
255 assert(eventhdlr != NULL);
256 assert(0 <= pos && pos < consdata->nvars);
257 assert(filterpos >= 0);
258
259 /* drop tightening events for upper bound and relaxed events for lower bounds on watched variable */
261 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
262
263 return SCIP_OKAY;
264}
265
266/** catches needed events on all variables of constraint, except the special ones for watched variables */
267static
269 SCIP* scip, /**< SCIP data structure */
270 SCIP_CONSDATA* consdata, /**< or constraint data */
271 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
272 )
273{
274 int i;
275
276 assert(consdata != NULL);
277
278 /* catch bound change events for both bounds on resultant variable */
280 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
281
282 /* catch tightening events for lower bound and relaxed events for upper bounds on operator variables */
283 for( i = 0; i < consdata->nvars; ++i )
284 {
286 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
287 }
288
289 return SCIP_OKAY;
290}
291
292/** drops events on all variables of constraint, except the special ones for watched variables */
293static
295 SCIP* scip, /**< SCIP data structure */
296 SCIP_CONSDATA* consdata, /**< or constraint data */
297 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
298 )
299{
300 int i;
301
302 assert(consdata != NULL);
303
304 /* drop bound change events for both bounds on resultant variable */
306 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
307
308 /* drop tightening events for lower bound and relaxed events for upper bounds on operator variables */
309 for( i = 0; i < consdata->nvars; ++i )
310 {
312 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
313 }
314
315 return SCIP_OKAY;
316}
317
318/** stores the given variable numbers as watched variables, and updates the event processing */
319static
321 SCIP* scip, /**< SCIP data structure */
322 SCIP_CONSDATA* consdata, /**< or constraint data */
323 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
324 int watchedvar1, /**< new first watched variable */
325 int watchedvar2 /**< new second watched variable */
326 )
327{
328 assert(consdata != NULL);
329 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
330 assert(watchedvar1 != -1 || watchedvar2 == -1);
331 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
332 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
333
334 /* if one watched variable is equal to the old other watched variable, just switch positions */
335 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
336 {
337 int tmp;
338
339 tmp = consdata->watchedvar1;
340 consdata->watchedvar1 = consdata->watchedvar2;
341 consdata->watchedvar2 = tmp;
342 tmp = consdata->filterpos1;
343 consdata->filterpos1 = consdata->filterpos2;
344 consdata->filterpos2 = tmp;
345 }
346 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
347 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
348
349 /* drop events on old watched variables */
350 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
351 {
352 assert(consdata->filterpos1 != -1);
353 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
354 }
355 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
356 {
357 assert(consdata->filterpos2 != -1);
358 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
359 }
360
361 /* catch events on new watched variables */
362 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
363 {
364 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
365 }
366 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
367 {
368 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
369 }
370
371 /* set the new watched variables */
372 consdata->watchedvar1 = watchedvar1;
373 consdata->watchedvar2 = watchedvar2;
374
375 return SCIP_OKAY;
376}
377
378/** ensures, that the vars array can store at least num entries */
379static
381 SCIP* scip, /**< SCIP data structure */
382 SCIP_CONSDATA* consdata, /**< linear constraint data */
383 int num /**< minimum number of entries to store */
384 )
385{
386 assert(consdata != NULL);
387 assert(consdata->nvars <= consdata->varssize);
388
389 if( num > consdata->varssize )
390 {
391 int newsize;
392
393 newsize = SCIPcalcMemGrowSize(scip, num);
394 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
395 consdata->varssize = newsize;
396 }
397 assert(num <= consdata->varssize);
398
399 return SCIP_OKAY;
400}
401
402/** creates constraint data for or constraint */
403static
405 SCIP* scip, /**< SCIP data structure */
406 SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
407 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
408 int nvars, /**< number of variables in the or operation */
409 SCIP_VAR** vars, /**< variables in or operation */
410 SCIP_VAR* resvar /**< resultant variable */
411 )
412{
413 assert(consdata != NULL);
414 assert(nvars == 0 || vars != NULL);
415 assert(resvar != NULL);
416
417 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
418 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
419 (*consdata)->resvar = resvar;
420 (*consdata)->rows = NULL;
421 (*consdata)->nvars = nvars;
422 (*consdata)->varssize = nvars;
423 (*consdata)->rowssize = 0;
424 (*consdata)->watchedvar1 = -1;
425 (*consdata)->watchedvar2 = -1;
426 (*consdata)->filterpos1 = -1;
427 (*consdata)->filterpos2 = -1;
428 (*consdata)->propagated = FALSE;
429 (*consdata)->nofixedone = FALSE;
430 (*consdata)->impladded = FALSE;
431 (*consdata)->opimpladded = FALSE;
432
433 /* get transformed variables, if we are in the transformed problem */
435 {
436 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
437 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->resvar, &(*consdata)->resvar) );
438
439 /* catch needed events on variables */
440 SCIP_CALL( consdataCatchEvents(scip, *consdata, eventhdlr) );
441 }
442
443 return SCIP_OKAY;
444}
445
446/** releases LP rows of constraint data and frees rows array */
447static
449 SCIP* scip, /**< SCIP data structure */
450 SCIP_CONSDATA* consdata /**< constraint data */
451 )
452{
453 int r;
454
455 assert(consdata != NULL);
456
457 if( consdata->rows != NULL )
458 {
459 int nrows;
460
461 nrows = consdataGetNRows(consdata);
462
463 for( r = 0; r < nrows; ++r )
464 {
465 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
466 }
467 SCIPfreeBlockMemoryArray(scip, &consdata->rows, consdata->rowssize);
468 }
469
470 return SCIP_OKAY;
471}
472
473/** frees constraint data for or constraint */
474static
476 SCIP* scip, /**< SCIP data structure */
477 SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
478 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
479 )
480{
481 assert(consdata != NULL);
482 assert(*consdata != NULL);
483
485 {
486 /* drop events for watched variables */
487 SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
488
489 /* drop all other events on variables */
490 SCIP_CALL( consdataDropEvents(scip, *consdata, eventhdlr) );
491 }
492 else
493 {
494 assert((*consdata)->watchedvar1 == -1);
495 assert((*consdata)->watchedvar2 == -1);
496 }
497
498 /* release and free the rows */
499 SCIP_CALL( consdataFreeRows(scip, *consdata) );
500
501 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
502 SCIPfreeBlockMemory(scip, consdata);
503
504 return SCIP_OKAY;
505}
506
507/** prints or constraint to file stream */
508static
510 SCIP* scip, /**< SCIP data structure */
511 SCIP_CONSDATA* consdata, /**< or constraint data */
512 FILE* file /**< output file (or NULL for standard output) */
513 )
514{
515 assert(consdata != NULL);
516
517 /* print resultant */
518 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->resvar, TRUE) );
519
520 /* start the variable list */
521 SCIPinfoMessage(scip, file, " == or(");
522
523 /* print variable list */
524 SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
525
526 /* close the variable list */
527 SCIPinfoMessage(scip, file, ")");
528
529 return SCIP_OKAY;
530}
531
532/** adds coefficient in or constraint */
533static
535 SCIP* scip, /**< SCIP data structure */
536 SCIP_CONS* cons, /**< linear constraint */
537 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
538 SCIP_VAR* var /**< variable to add to the constraint */
539 )
540{
541 SCIP_CONSDATA* consdata;
542 SCIP_Bool transformed;
543
544 assert(var != NULL);
545
546 consdata = SCIPconsGetData(cons);
547 assert(consdata != NULL);
548 assert(consdata->rows == NULL);
549
550 /* are we in the transformed problem? */
551 transformed = SCIPconsIsTransformed(cons);
552
553 /* always use transformed variables in transformed constraints */
554 if( transformed )
555 {
557 }
558 assert(var != NULL);
559 assert(transformed == SCIPvarIsTransformed(var));
560
561 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
562 consdata->vars[consdata->nvars] = var;
563 consdata->nvars++;
564
565 /* if we are in transformed problem, catch the variable's events */
566 if( transformed )
567 {
568 /* catch bound change events of variable */
570 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
571 }
572
573 /* install the rounding locks for the new variable */
574 SCIP_CALL( lockRounding(scip, cons, var) );
575
576 /**@todo update LP rows */
577 if( consdata->rows != NULL )
578 {
579 SCIPerrorMessage("cannot add coefficients to or constraint after LP relaxation was created\n");
580 return SCIP_INVALIDCALL;
581 }
582
583 return SCIP_OKAY;
584}
585
586/** deletes coefficient at given position from or constraint data */
587static
589 SCIP* scip, /**< SCIP data structure */
590 SCIP_CONS* cons, /**< or constraint */
591 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
592 int pos /**< position of coefficient to delete */
593 )
594{
595 SCIP_CONSDATA* consdata;
596
597 assert(eventhdlr != NULL);
598
599 consdata = SCIPconsGetData(cons);
600 assert(consdata != NULL);
601 assert(0 <= pos && pos < consdata->nvars);
602 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
603
604 /* remove the rounding locks of the variable */
605 SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
606
607 if( SCIPconsIsTransformed(cons) )
608 {
609 /* drop bound change events of variable */
611 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
612 }
613
614 if( SCIPconsIsTransformed(cons) )
615 {
616 /* if the position is watched, stop watching the position */
617 if( consdata->watchedvar1 == pos )
618 {
619 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
620 }
621 if( consdata->watchedvar2 == pos )
622 {
623 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
624 }
625 }
626 assert(pos != consdata->watchedvar1);
627 assert(pos != consdata->watchedvar2);
628
629 /* move the last variable to the free slot */
630 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
631 consdata->nvars--;
632
633 /* if the last variable (that moved) was watched, update the watched position */
634 if( consdata->watchedvar1 == consdata->nvars )
635 consdata->watchedvar1 = pos;
636 if( consdata->watchedvar2 == consdata->nvars )
637 consdata->watchedvar2 = pos;
638
639 consdata->propagated = FALSE;
640
641 return SCIP_OKAY;
642}
643
644/** deletes all zero-fixed variables */
645static
647 SCIP* scip, /**< SCIP data structure */
648 SCIP_CONS* cons, /**< or constraint */
649 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
650 )
651{
652 SCIP_CONSDATA* consdata;
653 SCIP_VAR* var;
654 int v;
655
656 consdata = SCIPconsGetData(cons);
657 assert(consdata != NULL);
658 assert(consdata->nvars == 0 || consdata->vars != NULL);
659
660 v = 0;
661 while( v < consdata->nvars )
662 {
663 var = consdata->vars[v];
665
666 if( SCIPvarGetUbGlobal(var) < 0.5 )
667 {
669 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
670 }
671 else
672 {
673 SCIP_VAR* repvar;
674 SCIP_Bool negated;
675
676 /* get binary representative of variable */
677 SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
678
679 /* check, if the variable should be replaced with the representative */
680 if( repvar != var )
681 {
682 /* delete old (aggregated) variable */
683 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
684
685 /* add representative instead */
686 SCIP_CALL( addCoef(scip, cons, eventhdlr, repvar) );
687 }
688 else
689 ++v;
690 }
691 }
692
693 SCIPdebugMsg(scip, "after fixings: ");
694 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL) ) );
695 SCIPdebugMsgPrint(scip, "\n");
696
697 return SCIP_OKAY;
698}
699
700/** creates LP rows corresponding to or constraint:
701 * - for each operator variable vi: resvar - vi >= 0
702 * - one additional row: resvar - v1 - ... - vn <= 0
703 */
704static
706 SCIP* scip, /**< SCIP data structure */
707 SCIP_CONS* cons /**< constraint to check */
708 )
709{
710 SCIP_CONSDATA* consdata;
711 char rowname[SCIP_MAXSTRLEN];
712 int nvars;
713 int i;
714
715 consdata = SCIPconsGetData(cons);
716 assert(consdata != NULL);
717 assert(consdata->rows == NULL);
718
719 nvars = consdata->nvars;
720
721 /* get memory for rows */
722 consdata->rowssize = consdataGetNRows(consdata);
723 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->rows, consdata->rowssize) );
724 assert(consdata->rowssize == nvars+1);
725
726 /* create operator rows */
727 for( i = 0; i < nvars; ++i )
728 {
729 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), i);
730 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[i], cons, rowname, 0.0, SCIPinfinity(scip),
732 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i], consdata->resvar, 1.0) );
733 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i], consdata->vars[i], -1.0) );
734 }
735
736 /* create additional row */
737 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
738 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[nvars], cons, rowname, -SCIPinfinity(scip), 0.0,
740 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[nvars], consdata->resvar, 1.0) );
741 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[nvars], nvars, consdata->vars, -1.0) );
742
743 return SCIP_OKAY;
744}
745
746/** adds linear relaxation of or constraint to the LP */
747static
749 SCIP* scip, /**< SCIP data structure */
750 SCIP_CONS* cons, /**< constraint to check */
751 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected */
752 )
753{
754 SCIP_CONSDATA* consdata;
755 int r;
756 int nrows;
757
758 consdata = SCIPconsGetData(cons);
759 assert(consdata != NULL);
760
761 if( consdata->rows == NULL )
762 {
764 }
765 assert( consdata->rows != NULL );
766
767 nrows = consdataGetNRows(consdata);
768
769 for( r = 0; r < nrows && !(*infeasible); ++r )
770 {
771 if( !SCIProwIsInLP(consdata->rows[r]) )
772 {
773 SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, infeasible) );
774 }
775 }
776
777 return SCIP_OKAY;
778}
779
780/** checks or constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
781static
783 SCIP* scip, /**< SCIP data structure */
784 SCIP_CONS* cons, /**< constraint to check */
785 SCIP_SOL* sol, /**< solution to check, NULL for current solution */
786 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
787 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
788 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
789 )
790{
791 SCIP_CONSDATA* consdata;
792 SCIP_Bool mustcheck;
793 int r;
794
795 assert(violated != NULL);
796
797 consdata = SCIPconsGetData(cons);
798 assert(consdata != NULL);
799
800 *violated = FALSE;
801
802 /* check, if we can skip this feasibility check, because all rows are in the LP and doesn't have to be checked */
803 mustcheck = checklprows;
804 mustcheck = mustcheck || (consdata->rows == NULL);
805 if( !mustcheck )
806 {
807 int nrows;
808
809 assert(consdata->rows != NULL);
810
811 nrows = consdataGetNRows(consdata);
812
813 for( r = 0; r < nrows; ++r )
814 {
815 mustcheck = !SCIProwIsInLP(consdata->rows[r]);
816 if( mustcheck )
817 break;
818 }
819 }
820
821 /* check feasibility of constraint if necessary */
822 if( mustcheck )
823 {
824 SCIP_Real maxsolval = 0.0;
825 SCIP_Real sumsolval = 0.0;
826 SCIP_Real solval;
827 SCIP_Real viol;
828 int maxsolind = 0;
829 int i;
830
831 /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
832 * enforcement
833 */
834 if( sol == NULL )
835 {
836 SCIP_CALL( SCIPincConsAge(scip, cons) );
837 }
838
839 /* evaluate operator variables */
840 for( i = 0; i < consdata->nvars; ++i )
841 {
842 solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
843
844 if( maxsolval < solval )
845 {
846 maxsolind = i;
847 maxsolval = solval;
848 }
849
850 sumsolval += solval;
851 }
852
853 /* the resultant must be at least as large as every operator
854 * and at most as large as the sum of operators
855 */
856 solval = SCIPgetSolVal(scip, sol, consdata->resvar);
857 viol = MAX3(0.0, maxsolval - solval, solval - sumsolval);
858
859 if( SCIPisFeasPositive(scip, viol) )
860 {
861 *violated = TRUE;
862
863 /* only reset constraint age if we are in enforcement */
864 if( sol == NULL )
865 {
867 }
868
869 if( printreason )
870 {
871 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
872 SCIPinfoMessage(scip, NULL, ";\n");
873 SCIPinfoMessage(scip, NULL, "violation:");
874
875 if( SCIPisFeasPositive(scip, maxsolval - solval) )
876 {
877 SCIPinfoMessage(scip, NULL, " operand <%s> = TRUE and resultant <%s> = FALSE\n",
878 SCIPvarGetName(consdata->vars[maxsolind]), SCIPvarGetName(consdata->resvar));
879 }
880 else
881 {
882 SCIPinfoMessage(scip, NULL, " all operands are FALSE and resultant <%s> = TRUE\n",
883 SCIPvarGetName(consdata->resvar));
884 }
885 }
886 }
887
888 /* update constraint violation in solution */
889 if( sol != NULL )
890 SCIPupdateSolConsViolation(scip, sol, viol, viol);
891 }
892
893 return SCIP_OKAY;
894}
895
896/** separates current LP solution */
897static
899 SCIP* scip, /**< SCIP data structure */
900 SCIP_CONS* cons, /**< constraint to check */
901 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
902 SCIP_Bool* separated /**< pointer to store whether a cut was found */
903 )
904{
905 SCIP_CONSDATA* consdata;
906 SCIP_Real feasibility;
907 int r;
908 int nrows;
909
910 assert(separated != NULL);
911
912 consdata = SCIPconsGetData(cons);
913 assert(consdata != NULL);
914
915 *separated = FALSE;
916
917 /* create all necessary rows for the linear relaxation */
918 if( consdata->rows == NULL )
919 {
921 }
922 assert(consdata->rows != NULL);
923
924 nrows = consdataGetNRows(consdata);
925
926 /* test all rows for feasibility and add infeasible rows */
927 for( r = 0; r < nrows; ++r )
928 {
929 if( !SCIProwIsInLP(consdata->rows[r]) )
930 {
931 feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
932 if( SCIPisFeasNegative(scip, feasibility) )
933 {
934 SCIP_Bool infeasible;
935
936 SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, &infeasible) );
937 assert( ! infeasible );
938 *separated = TRUE;
939 }
940 }
941 }
942
943 return SCIP_OKAY;
944}
945
946/** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
947static
949 SCIP* scip, /**< SCIP data structure */
950 SCIP_CONS* cons, /**< or constraint that detected the conflict */
951 int truepos /**< position of operand that is fixed to TRUE */
952 )
953{
954 SCIP_CONSDATA* consdata;
955
956 /* conflict analysis can only be applied in solving stage and if it is applicable */
958 return SCIP_OKAY;
959
960 consdata = SCIPconsGetData(cons);
961 assert(consdata != NULL);
962 assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
963 assert(0 <= truepos && truepos < consdata->nvars);
964 assert(SCIPvarGetLbLocal(consdata->vars[truepos]) > 0.5);
965
966 /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
968
969 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
970 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[truepos]) );
971
972 /* analyze the conflict */
974
975 return SCIP_OKAY;
976}
977
978/** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
979static
981 SCIP* scip, /**< SCIP data structure */
982 SCIP_CONS* cons /**< or constraint that detected the conflict */
983 )
984{
985 SCIP_CONSDATA* consdata;
986 int v;
987
989
990 /* conflict analysis can only be applied in solving stage and if it is applicable */
992 return SCIP_OKAY;
993
994 consdata = SCIPconsGetData(cons);
995 assert(consdata != NULL);
996 assert(SCIPvarGetLbLocal(consdata->resvar) > 0.5);
997
998 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
1000
1001 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1002 for( v = 0; v < consdata->nvars; ++v )
1003 {
1004 assert(SCIPvarGetUbLocal(consdata->vars[v]) < 0.5);
1005 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
1006 }
1007
1008 /* analyze the conflict */
1010
1011 return SCIP_OKAY;
1012}
1013
1014/** propagates constraint with the following rules:
1015 * (1) v_i = TRUE => r = TRUE
1016 * (2) r = FALSE => v_i = FALSE for all i
1017 * (3) v_i = FALSE for all i => r = FALSE
1018 * (4) r = TRUE, v_i = FALSE for all i except j => v_j = TRUE
1019 */
1020static
1022 SCIP* scip, /**< SCIP data structure */
1023 SCIP_CONS* cons, /**< or constraint to be processed */
1024 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1025 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1026 int* nfixedvars /**< pointer to add up the number of found domain reductions */
1027 )
1028{
1029 SCIP_CONSDATA* consdata;
1030 SCIP_VAR* resvar;
1031 SCIP_VAR** vars;
1032 int nvars;
1033 int watchedvar1;
1034 int watchedvar2;
1035 int i;
1036 SCIP_Bool infeasible;
1037 SCIP_Bool tightened;
1038
1039 assert(cutoff != NULL);
1040 assert(nfixedvars != NULL);
1041
1042 consdata = SCIPconsGetData(cons);
1043 assert(consdata != NULL);
1044
1045 resvar = consdata->resvar;
1046 vars = consdata->vars;
1047 nvars = consdata->nvars;
1048
1049 /* don't process the constraint, if none of the operator variables was fixed to TRUE, and if the watched variables
1050 * and the resultant weren't fixed to any value since last propagation call
1051 */
1052 if( consdata->propagated )
1053 {
1054 assert(consdata->nofixedone);
1055 assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(resvar), 1.0));
1056 return SCIP_OKAY;
1057 }
1058
1059 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1061 {
1062 SCIP_CALL( SCIPincConsAge(scip, cons) );
1063 }
1064
1065 /* if one of the operator variables was fixed to TRUE, the resultant can be fixed to TRUE (rule (1)) */
1066 if( !consdata->nofixedone )
1067 {
1068 for( i = 0; i < nvars && SCIPvarGetLbLocal(vars[i]) < 0.5; ++i ) /* search fixed operator */
1069 {}
1070 if( i < nvars )
1071 {
1072 SCIPdebugMsg(scip, "constraint <%s>: operator var <%s> fixed to 1.0 -> fix resultant <%s> to 1.0\n",
1074 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
1075 if( infeasible )
1076 {
1077 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1080 *cutoff = TRUE;
1081 }
1082 else
1083 {
1085 if( tightened )
1086 {
1088 (*nfixedvars)++;
1089 }
1090 }
1091
1092 return SCIP_OKAY;
1093 }
1094 else
1095 consdata->nofixedone = TRUE;
1096 }
1097 assert(consdata->nofixedone);
1098
1099 /* if resultant is fixed to FALSE, all operator variables can be fixed to FALSE (rule (2)) */
1100 if( SCIPvarGetUbLocal(resvar) < 0.5 )
1101 {
1102 for( i = 0; i < nvars && !(*cutoff); ++i )
1103 {
1104 SCIPdebugMsg(scip, "constraint <%s>: resultant var <%s> fixed to 0.0 -> fix operator var <%s> to 0.0\n",
1106 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i], FALSE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
1107 if( infeasible )
1108 {
1109 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1112 *cutoff = TRUE;
1113 }
1114 else if( tightened )
1115 {
1117 (*nfixedvars)++;
1118 }
1119 }
1120
1121 if( !(*cutoff) )
1122 {
1124 }
1125
1126 return SCIP_OKAY;
1127 }
1128
1129 /* rules (3) and (4) can only be applied, if we know all operator variables */
1130 if( SCIPconsIsModifiable(cons) )
1131 return SCIP_OKAY;
1132
1133 /* rules (3) and (4) cannot be applied, if we have at least two unfixed variables left;
1134 * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
1135 * if these ones get fixed
1136 */
1137 watchedvar1 = consdata->watchedvar1;
1138 watchedvar2 = consdata->watchedvar2;
1139
1140 /* check, if watched variables are still unfixed */
1141 if( watchedvar1 != -1 )
1142 {
1143 assert(SCIPvarGetLbLocal(vars[watchedvar1]) < 0.5); /* otherwise, rule (1) could be applied */
1144 if( SCIPvarGetUbLocal(vars[watchedvar1]) < 0.5 )
1145 watchedvar1 = -1;
1146 }
1147 if( watchedvar2 != -1 )
1148 {
1149 assert(SCIPvarGetLbLocal(vars[watchedvar2]) < 0.5); /* otherwise, rule (1) could be applied */
1150 if( SCIPvarGetUbLocal(vars[watchedvar2]) < 0.5 )
1151 watchedvar2 = -1;
1152 }
1153
1154 /* if only one watched variable is still unfixed, make it the first one */
1155 if( watchedvar1 == -1 )
1156 {
1157 watchedvar1 = watchedvar2;
1158 watchedvar2 = -1;
1159 }
1160 assert(watchedvar1 != -1 || watchedvar2 == -1);
1161
1162 /* if the watched variables are invalid (fixed), find new ones if existing */
1163 if( watchedvar2 == -1 )
1164 {
1165 for( i = 0; i < nvars; ++i )
1166 {
1167 assert(SCIPvarGetLbLocal(vars[i]) < 0.5); /* otherwise, rule (1) could be applied */
1168 if( SCIPvarGetUbLocal(vars[i]) > 0.5 )
1169 {
1170 if( watchedvar1 == -1 )
1171 {
1172 assert(watchedvar2 == -1);
1173 watchedvar1 = i;
1174 }
1175 else if( watchedvar1 != i )
1176 {
1177 watchedvar2 = i;
1178 break;
1179 }
1180 }
1181 }
1182 }
1183 assert(watchedvar1 != -1 || watchedvar2 == -1);
1184
1185 /* if all variables are fixed to FALSE, the resultant can also be fixed to FALSE (rule (3)) */
1186 if( watchedvar1 == -1 )
1187 {
1188 assert(watchedvar2 == -1);
1189
1190 SCIPdebugMsg(scip, "constraint <%s>: all operator vars fixed to 0.0 -> fix resultant <%s> to 0.0\n",
1191 SCIPconsGetName(cons), SCIPvarGetName(resvar));
1192 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
1193 if( infeasible )
1194 {
1195 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1198 *cutoff = TRUE;
1199 }
1200 else
1201 {
1203 if( tightened )
1204 {
1206 (*nfixedvars)++;
1207 }
1208 }
1209
1210 return SCIP_OKAY;
1211 }
1212
1213 /* if resultant is fixed to TRUE, and only one operator variable is not fixed to FALSE, this operator variable
1214 * can be fixed to TRUE (rule (4))
1215 */
1216 if( SCIPvarGetLbLocal(resvar) > 0.5 && watchedvar2 == -1 )
1217 {
1218 assert(watchedvar1 != -1);
1219
1220 SCIPdebugMsg(scip, "constraint <%s>: resultant <%s> fixed to 1.0, only one unfixed operand -> fix operand <%s> to 1.0\n",
1221 SCIPconsGetName(cons), SCIPvarGetName(resvar), SCIPvarGetName(vars[watchedvar1]));
1222 SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], TRUE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
1223 if( infeasible )
1224 {
1225 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1228 *cutoff = TRUE;
1229 }
1230 else
1231 {
1233 if( tightened )
1234 {
1236 (*nfixedvars)++;
1237 }
1238 }
1239
1240 return SCIP_OKAY;
1241 }
1242
1243 /* switch to the new watched variables */
1244 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
1245
1246 /* mark the constraint propagated */
1247 consdata->propagated = TRUE;
1248
1249 return SCIP_OKAY;
1250}
1251
1252/** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
1253 * propagation rule (see propagateCons()):
1254 * (1) v_i = TRUE => r = TRUE
1255 * (2) r = FALSE => v_i = FALSE for all i
1256 * (3) v_i = FALSE for all i => r = FALSE
1257 * (4) r = TRUE, v_i = FALSE for all i except j => v_j = TRUE
1258 */
1259static
1261 SCIP* scip, /**< SCIP data structure */
1262 SCIP_CONS* cons, /**< constraint that inferred the bound change */
1263 SCIP_VAR* infervar, /**< variable that was deduced */
1264 PROPRULE proprule, /**< propagation rule that deduced the value */
1265 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1266 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1267 )
1268{
1269 SCIP_CONSDATA* consdata;
1270 SCIP_VAR** vars;
1271 int nvars;
1272 int i;
1273
1274 assert(result != NULL);
1275
1276 consdata = SCIPconsGetData(cons);
1277 assert(consdata != NULL);
1278 vars = consdata->vars;
1279 nvars = consdata->nvars;
1280
1281 switch( proprule )
1282 {
1283 case PROPRULE_1:
1284 /* the resultant was inferred to TRUE, because one operand variable was TRUE */
1285 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1286 assert(infervar == consdata->resvar);
1287 for( i = 0; i < nvars; ++i )
1288 {
1289 if( SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5 )
1290 {
1292 break;
1293 }
1294 }
1295 assert(i < nvars);
1297 break;
1298
1299 case PROPRULE_2:
1300 /* the operand variable was inferred to FALSE, because the resultant was FALSE */
1301 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1302 assert(SCIPgetVarUbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) < 0.5);
1303 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1305 break;
1306
1307 case PROPRULE_3:
1308 /* the resultant was inferred to FALSE, because all operand variables were FALSE */
1309 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1310 assert(infervar == consdata->resvar);
1311 for( i = 0; i < nvars; ++i )
1312 {
1313 assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5);
1315 }
1317 break;
1318
1319 case PROPRULE_4:
1320 /* the operand variable was inferred to TRUE, because the resultant was TRUE and all other operands were FALSE */
1321 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1322 assert(SCIPgetVarLbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) > 0.5);
1323 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1324 for( i = 0; i < nvars; ++i )
1325 {
1326 if( vars[i] != infervar )
1327 {
1328 assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5);
1330 }
1331 }
1333 break;
1334
1335 case PROPRULE_INVALID:
1336 default:
1337 SCIPerrorMessage("invalid inference information %d in or constraint <%s>\n", proprule, SCIPconsGetName(cons));
1338 return SCIP_INVALIDDATA;
1339 }
1340
1341 return SCIP_OKAY;
1342}
1343
1344/** upgrades unmodifiable or constraint into an and constraint on negated variables */
1345static
1347 SCIP* scip, /**< SCIP data structure */
1348 SCIP_CONS* cons, /**< constraint that inferred the bound change */
1349 int* nupgdconss /**< pointer to count the number of constraint upgrades */
1350 )
1351{
1352 SCIP_CONSDATA* consdata;
1353 SCIP_VAR** negvars;
1354 SCIP_VAR* negresvar;
1355 SCIP_CONS* andcons;
1356 int i;
1357
1358 assert(nupgdconss != NULL);
1359
1360 /* we cannot upgrade a modifiable constraint, since we don't know what additional variables to expect */
1361 if( SCIPconsIsModifiable(cons) || SCIPconsGetNUpgradeLocks(cons) >= 1 )
1362 return SCIP_OKAY;
1363
1364 SCIPdebugMsg(scip, "upgrading or constraint <%s> into equivalent and constraint on negated variables\n",
1365 SCIPconsGetName(cons));
1366
1367 consdata = SCIPconsGetData(cons);
1368 assert(consdata != NULL);
1369
1370 /* get the negated versions of the variables */
1371 SCIP_CALL( SCIPallocBufferArray(scip, &negvars, consdata->nvars) );
1372 for( i = 0; i < consdata->nvars; ++i )
1373 {
1374 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[i], &negvars[i]) );
1375 }
1376 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->resvar, &negresvar) );
1377
1378 /* create and add the and constraint */
1379 SCIP_CALL( SCIPcreateConsAnd(scip, &andcons, SCIPconsGetName(cons), negresvar, consdata->nvars, negvars,
1383 SCIPconsIsStickingAtNode(cons)) );
1384 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &andcons) );
1385
1386 /* delete the or constraint */
1387 SCIP_CALL( SCIPdelCons(scip, cons) );
1388
1389 /* free temporary memory */
1390 SCIPfreeBufferArray(scip, &negvars);
1391
1392 (*nupgdconss)++;
1393
1394 return SCIP_OKAY;
1395}
1396
1397/** adds symmetry information of constraint to a symmetry detection graph */
1398static
1400 SCIP* scip, /**< SCIP pointer */
1401 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
1402 SCIP_CONS* cons, /**< constraint */
1403 SYM_GRAPH* graph, /**< symmetry detection graph */
1404 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
1405 )
1406{
1407 SCIP_CONSDATA* consdata;
1408 SCIP_VAR** orvars;
1409 SCIP_VAR** vars;
1410 SCIP_Real* vals;
1411 SCIP_Real constant;
1412 int consnodeidx;
1413 int ornodeidx;
1414 int nlocvars;
1415 int i;
1416
1417 assert(scip != NULL);
1418 assert(cons != NULL);
1419 assert(graph != NULL);
1420 assert(success != NULL);
1421
1422 consdata = SCIPconsGetData(cons);
1423 assert(consdata != NULL);
1424
1425 /* create arrays to store active representation of variables */
1426 nlocvars = 1;
1427 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlocvars) );
1428 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlocvars) );
1429
1430 /* add constraint node */
1431 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
1432
1433 /* add resultant to symmetry detection graph */
1434 assert(consdata->resvar != NULL);
1435 vars[0] = consdata->resvar;
1436 vals[0] = 1.0;
1437 constant = 0.0;
1438 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
1439 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, consnodeidx, vars, vals, nlocvars, constant) );
1440
1441 /* add node modeling the OR-part and connect it with constraint node */
1442 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int)SYM_CONSOPTYPE_OR, &ornodeidx) );
1443 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, ornodeidx, FALSE, 0.0) );
1444
1445 /* add variables */
1446 orvars = consdata->vars;
1447 for( i = 0; i < consdata->nvars; ++i )
1448 {
1449 assert(orvars[i] != NULL);
1450 vars[0] = orvars[i];
1451 vals[0] = 1.0;
1452 constant = 0.0;
1453 nlocvars = 1;
1454 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
1455 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, ornodeidx, vars, vals, nlocvars, constant) );
1456 }
1457
1458 SCIPfreeBufferArray(scip, &vals);
1460
1461 *success = TRUE;
1462
1463 return SCIP_OKAY;
1464}
1465
1466/*
1467 * Callback methods of constraint handler
1468 */
1469
1470/** copy method for constraint handler plugins (called when SCIP copies plugins) */
1471static
1473{ /*lint --e{715}*/
1474 assert(scip != NULL);
1475 assert(conshdlr != NULL);
1476
1478
1479 /* call inclusion method of constraint handler */
1481
1482 *valid = TRUE;
1483
1484 return SCIP_OKAY;
1485}
1486
1487/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
1488static
1490{ /*lint --e{715}*/
1491 SCIP_CONSHDLRDATA* conshdlrdata;
1492
1493 /* free constraint handler data */
1494 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1495 assert(conshdlrdata != NULL);
1496
1497 conshdlrdataFree(scip, &conshdlrdata);
1498
1499 SCIPconshdlrSetData(conshdlr, NULL);
1500
1501 return SCIP_OKAY;
1502}
1503
1504
1505/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
1506static
1508{ /*lint --e{715}*/
1509 SCIP_CONSDATA* consdata;
1510 int c;
1511
1512 /* release and free the rows of all constraints */
1513 for( c = 0; c < nconss; ++c )
1514 {
1515 consdata = SCIPconsGetData(conss[c]);
1516 SCIP_CALL( consdataFreeRows(scip, consdata) );
1517 }
1518
1519 return SCIP_OKAY;
1520}
1521
1522
1523/** frees specific constraint data */
1524static
1526{ /*lint --e{715}*/
1527 SCIP_CONSHDLRDATA* conshdlrdata;
1528
1529 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1530 assert(conshdlrdata != NULL);
1531
1532 SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
1533
1534 return SCIP_OKAY;
1535}
1536
1537
1538/** transforms constraint data into data belonging to the transformed problem */
1539static
1541{ /*lint --e{715}*/
1542 SCIP_CONSHDLRDATA* conshdlrdata;
1543 SCIP_CONSDATA* sourcedata;
1544 SCIP_CONSDATA* targetdata;
1545
1546 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1547 assert(conshdlrdata != NULL);
1548
1549 sourcedata = SCIPconsGetData(sourcecons);
1550 assert(sourcedata != NULL);
1551
1552 /* create target constraint data */
1553 SCIP_CALL( consdataCreate(scip, &targetdata, conshdlrdata->eventhdlr,
1554 sourcedata->nvars, sourcedata->vars, sourcedata->resvar) );
1555
1556 /* create target constraint */
1557 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
1558 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1559 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
1560 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons),
1561 SCIPconsIsStickingAtNode(sourcecons)) );
1562
1563 return SCIP_OKAY;
1564}
1565
1566
1567/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1568static
1570{ /*lint --e{715}*/
1571 int i;
1572
1573 *infeasible = FALSE;
1574
1575 for( i = 0; i < nconss && !(*infeasible); i++ )
1576 {
1577 assert(SCIPconsIsInitial(conss[i]));
1578 SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
1579 }
1580
1581 return SCIP_OKAY;
1582}
1583
1584
1585/** separation method of constraint handler for LP solutions */
1586static
1588{ /*lint --e{715}*/
1589 SCIP_Bool separated;
1590 int c;
1591
1593
1594 /* separate all useful constraints */
1595 for( c = 0; c < nusefulconss; ++c )
1596 {
1597 SCIP_CALL( separateCons(scip, conss[c], NULL, &separated) );
1598 if( separated )
1600 }
1601
1602 /* combine constraints to get more cuts */
1603 /**@todo combine constraints to get further cuts */
1604
1605 return SCIP_OKAY;
1606}
1607
1608
1609/** separation method of constraint handler for arbitrary primal solutions */
1610static
1612{ /*lint --e{715}*/
1613 SCIP_Bool separated;
1614 int c;
1615
1617
1618 /* separate all useful constraints */
1619 for( c = 0; c < nusefulconss; ++c )
1620 {
1621 SCIP_CALL( separateCons(scip, conss[c], sol, &separated) );
1622 if( separated )
1624 }
1625
1626 /* combine constraints to get more cuts */
1627 /**@todo combine constraints to get further cuts */
1628
1629 return SCIP_OKAY;
1630}
1631
1632
1633/** constraint enforcing method of constraint handler for LP solutions */
1634static
1636{ /*lint --e{715}*/
1637 SCIP_Bool violated;
1638 int i;
1639
1640 /* method is called only for integral solutions, because the enforcing priority is negative */
1641 for( i = 0; i < nconss; i++ )
1642 {
1643 SCIP_CALL( checkCons(scip, conss[i], NULL, FALSE, FALSE, &violated) );
1644 if( violated )
1645 {
1646 SCIP_Bool separated;
1647
1648 SCIP_CALL( separateCons(scip, conss[i], NULL, &separated) );
1649
1650 /* if the solution is integral, the separation always finds a cut
1651 * if some implicit binary variable is not integral, then some other constraint needs to be enforced first
1652 */
1653 if( separated )
1655 else
1657
1658 return SCIP_OKAY;
1659 }
1660 }
1662
1663 return SCIP_OKAY;
1664}
1665
1666
1667/** constraint enforcing method of constraint handler for relaxation solutions */
1668static
1670{ /*lint --e{715}*/
1671 SCIP_Bool violated;
1672 int i;
1673
1674 /* method is called only for integral solutions, because the enforcing priority is negative */
1675 for( i = 0; i < nconss; i++ )
1676 {
1677 SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
1678 if( violated )
1679 {
1680 SCIP_Bool separated;
1681
1682 SCIP_CALL( separateCons(scip, conss[i], sol, &separated) );
1683
1684 /* if the solution is integral, the separation always finds a cut
1685 * if some implicit binary variable is not integral, then some other constraint needs to be enforced first
1686 */
1687 if( separated )
1689 else
1691
1692 return SCIP_OKAY;
1693 }
1694 }
1696
1697 return SCIP_OKAY;
1698}
1699
1700
1701/** constraint enforcing method of constraint handler for pseudo solutions */
1702static
1704{ /*lint --e{715}*/
1705 SCIP_Bool violated;
1706 int i;
1707
1708 /* method is called only for integral solutions, because the enforcing priority is negative */
1709 for( i = 0; i < nconss; i++ )
1710 {
1711 SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
1712 if( violated )
1713 {
1715 return SCIP_OKAY;
1716 }
1717 }
1719
1720 return SCIP_OKAY;
1721}
1722
1723/** feasibility check method of constraint handler or */
1724static
1726{ /*lint --e{715}*/
1727 SCIP_Bool violated;
1728 int i;
1729
1731
1732 for( i = 0; i < nconss && ( *result == SCIP_FEASIBLE || completely ); ++i )
1733 {
1734 SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
1735 if( violated )
1737 }
1738
1739 return SCIP_OKAY;
1740}
1741
1742/** domain propagation method of constraint handler */
1743static
1745{ /*lint --e{715}*/
1746 SCIP_CONSHDLRDATA* conshdlrdata;
1748 int nfixedvars;
1749 int c;
1750
1751 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1752 assert(conshdlrdata != NULL);
1753
1754 cutoff = FALSE;
1755 nfixedvars = 0;
1756
1757 /* propagate all useful constraints */
1758 for( c = 0; c < nusefulconss && !cutoff; ++c )
1759 {
1760 SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars) );
1761 }
1762
1763 /* return the correct result */
1764 if( cutoff )
1766 else if( nfixedvars > 0 )
1768 else
1770
1771 return SCIP_OKAY;
1772}
1773
1774
1775/** presolving method of constraint handler */
1776static
1778{ /*lint --e{715}*/
1779 SCIP_CONSHDLRDATA* conshdlrdata;
1780 SCIP_CONS* cons;
1781 SCIP_CONSDATA* consdata;
1783 SCIP_Bool redundant;
1784 SCIP_Bool aggregated;
1785 int oldnfixedvars;
1786 int oldnaggrvars;
1787 int oldnupgdconss;
1788 int c;
1789
1790 assert(result != NULL);
1791
1793 oldnfixedvars = *nfixedvars;
1794 oldnaggrvars = *naggrvars;
1795 oldnupgdconss = *nupgdconss;
1796
1797 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1798 assert(conshdlrdata != NULL);
1799
1800 /* process constraints */
1801 cutoff = FALSE;
1802 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
1803 {
1804 cons = conss[c];
1805 assert(cons != NULL);
1806 consdata = SCIPconsGetData(cons);
1807 assert(consdata != NULL);
1808
1809 /* force presolving the constraint in the initial round */
1810 if( nrounds == 0 )
1811 consdata->propagated = FALSE;
1812
1813 /* propagate constraint */
1814 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars) );
1815
1816 /* remove all variables that are fixed to one */
1817 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr) );
1818
1819 /* transform or constraints into and constraints on the negated variables in order to improve
1820 * the pairwise constraint presolving possibilities
1821 */
1822 SCIP_CALL( upgradeCons(scip, cons, nupgdconss) );
1823
1824 if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
1825 {
1826 assert(consdata->nvars >= 1); /* otherwise, propagateCons() has deleted the constraint */
1827
1828 /* if only one variable is left, the resultant has to be equal to this single variable */
1829 if( consdata->nvars == 1 )
1830 {
1831 SCIPdebugMsg(scip, "or constraint <%s> has only one variable not fixed to 0.0\n", SCIPconsGetName(cons));
1832
1833 assert(consdata->vars != NULL);
1834 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
1835 assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
1836
1837 /* aggregate variables: resultant - operand == 0 */
1838 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
1839 &cutoff, &redundant, &aggregated) );
1840 assert(redundant || SCIPdoNotAggr(scip));
1841
1842 if( aggregated )
1843 {
1844 assert(redundant);
1845 (*naggrvars)++;
1846 }
1847
1848 if( redundant )
1849 {
1850 /* delete constraint */
1851 SCIP_CALL( SCIPdelCons(scip, cons) );
1852 (*ndelconss)++;
1853 }
1854 }
1855 else if( !consdata->impladded )
1856 {
1857 int i;
1858
1859 /* add implications: resultant == 0 -> all operands == 0 */
1860 for( i = 0; i < consdata->nvars && !cutoff; ++i )
1861 {
1862 int nimplbdchgs;
1863
1864 SCIP_CALL( SCIPaddVarImplication(scip, consdata->resvar, FALSE, consdata->vars[i],
1865 SCIP_BOUNDTYPE_UPPER, 0.0, &cutoff, &nimplbdchgs) );
1866 *nchgbds += nimplbdchgs;
1867 }
1868 consdata->impladded = TRUE;
1869 }
1870
1871 /* if in r = x or y, the resultant is fixed to one, add implication x = 0 -> y = 1 */
1872 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 2 && !consdata->opimpladded
1873 && SCIPvarGetLbGlobal(consdata->resvar) > 0.5 )
1874 {
1875 int nimplbdchgs;
1876
1877 SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], FALSE, consdata->vars[1],
1878 SCIP_BOUNDTYPE_LOWER, 1.0, &cutoff, &nimplbdchgs) );
1879 (*nchgbds) += nimplbdchgs;
1880 consdata->opimpladded = TRUE;
1881 }
1882 }
1883 }
1884
1885 /* return the correct result code */
1886 if( cutoff )
1888 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nupgdconss > oldnupgdconss )
1890
1891 return SCIP_OKAY;
1892}
1893
1894
1895/** propagation conflict resolving method of constraint handler */
1896static
1898{ /*lint --e{715}*/
1899 SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
1900
1901 return SCIP_OKAY;
1902}
1903
1904
1905/** variable rounding lock method of constraint handler */
1906static
1908{ /*lint --e{715}*/
1909 SCIP_CONSDATA* consdata;
1910 int i;
1911
1912 assert(locktype == SCIP_LOCKTYPE_MODEL);
1913
1914 consdata = SCIPconsGetData(cons);
1915 assert(consdata != NULL);
1916
1917 /* lock resultant variable */
1918 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->resvar, locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
1919
1920 /* lock all operand variables */
1921 for( i = 0; i < consdata->nvars; ++i )
1922 {
1923 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
1924 }
1925
1926 return SCIP_OKAY;
1927}
1928
1929
1930/** constraint display method of constraint handler */
1931static
1933{ /*lint --e{715}*/
1934 assert( scip != NULL );
1935 assert( conshdlr != NULL );
1936 assert( cons != NULL );
1937
1939
1940 return SCIP_OKAY;
1941}
1942
1943/** constraint copying method of constraint handler */
1944static
1946{ /*lint --e{715}*/
1947 SCIP_VAR** sourcevars;
1948 SCIP_VAR** vars;
1949 SCIP_VAR* sourceresvar;
1950 SCIP_VAR* resvar;
1951 int nvars;
1952 int v;
1953
1954 assert(valid != NULL);
1955 (*valid) = TRUE;
1956 resvar = NULL;
1957
1958 /* get variables that need to be copied */
1959 sourceresvar = SCIPgetResultantOr(sourcescip, sourcecons);
1960 sourcevars = SCIPgetVarsOr(sourcescip, sourcecons);
1961 nvars = SCIPgetNVarsOr(sourcescip, sourcecons);
1962
1963 if( nvars == -1 )
1964 return SCIP_INVALIDCALL;
1965
1966 /* allocate buffer array */
1968
1969 /* map operand variables to active variables of the target SCIP */
1970 for( v = 0; v < nvars && *valid; ++v )
1971 {
1972 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, valid) );
1973 assert(!(*valid) || vars[v] != NULL);
1974 }
1975
1976 /* map resultant to active variable of the target SCIP */
1977 if( *valid )
1978 {
1979 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceresvar, &resvar, varmap, consmap, global, valid) );
1980 assert(!(*valid) || resvar != NULL);
1981
1982 if( *valid )
1983 {
1984 assert(resvar != NULL);
1985 SCIP_CALL( SCIPcreateConsOr(scip, cons, SCIPconsGetName(sourcecons), resvar, nvars, vars,
1986 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1987 }
1988 }
1989
1990 /* free buffer array */
1992
1993 return SCIP_OKAY;
1994}
1995
1996/** constraint parsing method of constraint handler */
1997static
1999{ /*lint --e{715}*/
2000 SCIP_VAR** vars;
2001 SCIP_VAR* resvar;
2002 char* strcopy;
2003 char* token;
2004 char* saveptr;
2005 char* endptr;
2006 int requiredsize;
2007 int varssize;
2008 int nvars;
2009
2010 SCIPdebugMsg(scip, "parse <%s> as or constraint\n", str);
2011
2012 *success = FALSE;
2013
2014 /* copy string for truncating it */
2015 SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, str, (int)(strlen(str)+1)) );
2016
2017 /* cutoff "or" form the constraint string */
2018 token = SCIPstrtok(strcopy, "=", &saveptr );
2019
2020 /* parse variable name */
2021 SCIP_CALL( SCIPparseVarName(scip, token, &resvar, &endptr) );
2022
2023 if( resvar == NULL )
2024 {
2025 SCIPerrorMessage("resultant variable does not exist\n");
2026 }
2027 else
2028 {
2029 /* cutoff "or" form the constraint string */
2030 (void) SCIPstrtok(NULL, "(", &saveptr );
2031
2032 /* cutoff ")" form the constraint string */
2033 token = SCIPstrtok(NULL, ")", &saveptr );
2034
2035 varssize = 100;
2036 nvars = 0;
2037
2038 /* allocate buffer array for variables */
2039 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
2040
2041 /* parse string */
2042 SCIP_CALL( SCIPparseVarsList(scip, token, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
2043
2044 if( *success )
2045 {
2046 /* check if the size of the variable array was great enough */
2047 if( varssize < requiredsize )
2048 {
2049 /* reallocate memory */
2050 varssize = requiredsize;
2051 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
2052
2053 /* parse string again with the correct size of the variable array */
2054 SCIP_CALL( SCIPparseVarsList(scip, token, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
2055 }
2056
2057 assert(*success);
2058 assert(varssize >= requiredsize);
2059
2060 /* create and constraint */
2061 SCIP_CALL( SCIPcreateConsOr(scip, cons, name, resvar, nvars, vars,
2062 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2063 }
2064
2065 /* free variable buffer */
2067 }
2068
2069 /* free string buffer */
2070 SCIPfreeBufferArray(scip, &strcopy);
2071
2072 return SCIP_OKAY;
2073}
2074
2075/** constraint method of constraint handler which returns the variables (if possible) */
2076static
2078{ /*lint --e{715}*/
2079 SCIP_CONSDATA* consdata;
2080
2081 consdata = SCIPconsGetData(cons);
2082 assert(consdata != NULL);
2083
2084 if( varssize < consdata->nvars + 1 )
2085 (*success) = FALSE;
2086 else
2087 {
2088 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
2089 vars[consdata->nvars] = consdata->resvar;
2090 (*success) = TRUE;
2091 }
2092
2093 return SCIP_OKAY;
2094}
2095
2096/** constraint method of constraint handler which returns the number of variable (if possible) */
2097static
2099{ /*lint --e{715}*/
2100 SCIP_CONSDATA* consdata;
2101
2102 assert(cons != NULL);
2103
2104 consdata = SCIPconsGetData(cons);
2105 assert(consdata != NULL);
2106
2107 (*nvars) = consdata->nvars + 1;
2108 (*success) = TRUE;
2109
2110 return SCIP_OKAY;
2111}
2112
2113/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
2114static
2115SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphOr)
2116{ /*lint --e{715}*/
2117 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
2118
2119 return SCIP_OKAY;
2120}
2121
2122/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
2123static
2124SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphOr)
2125{ /*lint --e{715}*/
2126 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
2127
2128 return SCIP_OKAY;
2129}
2130
2131/*
2132 * Callback methods of event handler
2133 */
2134
2135static
2137{ /*lint --e{715}*/
2138 SCIP_CONSDATA* consdata;
2139
2140 assert(eventhdlr != NULL);
2141 assert(eventdata != NULL);
2142 assert(event != NULL);
2143
2144 consdata = (SCIP_CONSDATA*)eventdata;
2145 assert(consdata != NULL);
2146
2147 /* check, if the variable was fixed to one */
2149 consdata->nofixedone = FALSE;
2150
2151 consdata->propagated = FALSE;
2152
2153 return SCIP_OKAY;
2154}
2155
2156
2157/*
2158 * constraint specific interface methods
2159 */
2160
2161/** creates the handler for or constraints and includes it in SCIP */
2163 SCIP* scip /**< SCIP data structure */
2164 )
2165{
2166 SCIP_CONSHDLRDATA* conshdlrdata;
2167 SCIP_CONSHDLR* conshdlr;
2168 SCIP_EVENTHDLR* eventhdlr;
2169
2170 /* create event handler for events on variables */
2172 eventExecOr, NULL) );
2173
2174 /* create constraint handler data */
2175 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
2176
2177 /* include constraint handler */
2180 consEnfolpOr, consEnfopsOr, consCheckOr, consLockOr,
2181 conshdlrdata) );
2182 assert(conshdlr != NULL);
2183
2184 /* set non-fundamental callbacks via specific setter functions */
2185 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOr, consCopyOr) );
2186 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOr) );
2187 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolOr) );
2188 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOr) );
2189 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOr) );
2190 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOr) );
2191 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpOr) );
2192 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOr) );
2194 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOr) );
2197 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOr) );
2198 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOr, consSepasolOr, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY,
2200 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOr) );
2201 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOr) );
2202 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphOr) );
2203 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphOr) );
2204
2205 return SCIP_OKAY;
2206}
2207
2208/** creates and captures an or constraint
2209 *
2210 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2211 */
2213 SCIP* scip, /**< SCIP data structure */
2214 SCIP_CONS** cons, /**< pointer to hold the created constraint */
2215 const char* name, /**< name of constraint */
2216 SCIP_VAR* resvar, /**< resultant variable of the operation */
2217 int nvars, /**< number of operator variables in the constraint */
2218 SCIP_VAR** vars, /**< array with operator variables of constraint */
2219 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2220 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2221 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2222 * Usually set to TRUE. */
2223 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2224 * TRUE for model constraints, FALSE for additional, redundant constraints. */
2225 SCIP_Bool check, /**< should the constraint be checked for feasibility?
2226 * TRUE for model constraints, FALSE for additional, redundant constraints. */
2227 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2228 * Usually set to TRUE. */
2229 SCIP_Bool local, /**< is constraint only valid locally?
2230 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2231 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2232 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2233 * adds coefficients to this constraint. */
2234 SCIP_Bool dynamic, /**< is constraint subject to aging?
2235 * Usually set to FALSE. Set to TRUE for own cuts which
2236 * are separated as constraints. */
2237 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2238 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2239 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2240 * if it may be moved to a more global node?
2241 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2242 )
2243{
2244 SCIP_CONSHDLR* conshdlr;
2245 SCIP_CONSHDLRDATA* conshdlrdata;
2246 SCIP_CONSDATA* consdata;
2247 int i;
2248
2249 /* find the or constraint handler */
2250 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2251 if( conshdlr == NULL )
2252 {
2253 SCIPerrorMessage("or constraint handler not found\n");
2254 return SCIP_PLUGINNOTFOUND;
2255 }
2256
2257 /* check whether resultant variable is binary */
2258 if( !SCIPvarIsBinary(resvar) )
2259 {
2260 SCIPerrorMessage("resultant <%s> is not binary\n", SCIPvarGetName(resvar));
2261 return SCIP_INVALIDDATA;
2262 }
2263
2264 /* check whether all variables are binary */
2265 assert(vars != NULL || nvars == 0);
2266 for( i = 0; i < nvars; ++i )
2267 {
2268 if( !SCIPvarIsBinary(vars[i]) )
2269 {
2270 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
2271 return SCIP_INVALIDDATA;
2272 }
2273 }
2274
2275 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2276 assert(conshdlrdata != NULL);
2277
2278 /* create constraint data */
2279 SCIP_CALL( consdataCreate(scip, &consdata, conshdlrdata->eventhdlr, nvars, vars, resvar) );
2280
2281 /* create constraint */
2282 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2283 local, modifiable, dynamic, removable, stickingatnode) );
2284
2285 return SCIP_OKAY;
2286}
2287
2288/** creates and captures an or constraint
2289 * in its most basic variant, i. e., with all constraint flags set to their default values
2290 *
2291 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2292 */
2294 SCIP* scip, /**< SCIP data structure */
2295 SCIP_CONS** cons, /**< pointer to hold the created constraint */
2296 const char* name, /**< name of constraint */
2297 SCIP_VAR* resvar, /**< resultant variable of the operation */
2298 int nvars, /**< number of operator variables in the constraint */
2299 SCIP_VAR** vars /**< array with operator variables of constraint */
2300 )
2301{
2302 SCIP_CALL( SCIPcreateConsOr(scip, cons, name, resvar, nvars, vars, TRUE, TRUE, TRUE, TRUE, TRUE,
2303 FALSE, FALSE, FALSE, FALSE, FALSE) );
2304
2305 return SCIP_OKAY;
2306}
2307
2308/** gets number of variables in or constraint */
2310 SCIP* scip, /**< SCIP data structure */
2311 SCIP_CONS* cons /**< constraint data */
2312 )
2313{
2314 SCIP_CONSDATA* consdata;
2315
2316 assert(scip != NULL);
2317
2319
2320 consdata = SCIPconsGetData(cons);
2321 assert(consdata != NULL);
2322
2323 return consdata->nvars;
2324}
2325
2326/** gets array of variables in or constraint */
2328 SCIP* scip, /**< SCIP data structure */
2329 SCIP_CONS* cons /**< constraint data */
2330 )
2331{
2332 SCIP_CONSDATA* consdata;
2333
2334 assert(scip != NULL);
2335
2337
2338 consdata = SCIPconsGetData(cons);
2339 assert(consdata != NULL);
2340
2341 return consdata->vars;
2342}
2343
2344/** gets the resultant variable in or constraint */
2346 SCIP* scip, /**< SCIP data structure */
2347 SCIP_CONS* cons /**< constraint data */
2348 )
2349{
2350 SCIP_CONSDATA* consdata;
2351
2352 assert(scip != NULL);
2353
2355
2356 consdata = SCIPconsGetData(cons);
2357 assert(consdata != NULL);
2358
2359 return consdata->resvar;
2360}
#define EVENTHDLR_NAME
#define EVENTHDLR_DESC
enum Proprule PROPRULE
Definition cons_and.c:172
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:96
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:89
#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_SEPAPRIORITY
Definition cons_and.c:86
Proprule
Definition cons_and.c:165
@ PROPRULE_2
Definition cons_and.c:168
@ PROPRULE_1
Definition cons_and.c:167
@ PROPRULE_3
Definition cons_and.c:169
@ PROPRULE_INVALID
Definition cons_and.c:166
@ PROPRULE_4
Definition cons_and.c:170
#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_DELAYSEPA
Definition cons_and.c:94
#define CONSHDLR_NAME
Definition cons_and.c:84
#define CONSHDLR_DELAYPROP
Definition cons_and.c:95
Constraint handler for AND constraints, .
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition cons_or.c:748
static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
Definition cons_or.c:448
static int consdataGetNRows(SCIP_CONSDATA *consdata)
Definition cons_or.c:210
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition cons_or.c:509
static SCIP_RETCODE consdataCatchWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
Definition cons_or.c:221
static SCIP_RETCODE consdataDropEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_or.c:294
static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
Definition cons_or.c:320
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition cons_or.c:588
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
Definition cons_or.c:534
static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
Definition cons_or.c:705
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition cons_or.c:197
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition cons_or.c:161
static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons)
Definition cons_or.c:980
static SCIP_RETCODE analyzeConflictZero(SCIP *scip, SCIP_CONS *cons, int truepos)
Definition cons_or.c:948
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
Definition cons_or.c:1399
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition cons_or.c:145
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition cons_or.c:380
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool *violated)
Definition cons_or.c:782
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_or.c:475
static SCIP_RETCODE consdataDropWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int filterpos)
Definition cons_or.c:245
static SCIP_RETCODE upgradeCons(SCIP *scip, SCIP_CONS *cons, int *nupgdconss)
Definition cons_or.c:1346
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars)
Definition cons_or.c:1021
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *separated)
Definition cons_or.c:898
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_or.c:177
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr, int nvars, SCIP_VAR **vars, SCIP_VAR *resvar)
Definition cons_or.c:404
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition cons_or.c:646
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition cons_or.c:1260
static SCIP_RETCODE consdataCatchEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_or.c:268
Constraint handler for "or" constraints, .
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Bool
Definition def.h:100
#define MAX3(x, y, z)
Definition def.h:237
#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_CALL(x)
Definition def.h:364
SCIP_VAR ** SCIPgetVarsOr(SCIP *scip, SCIP_CONS *cons)
Definition cons_or.c:2327
int SCIPgetNVarsOr(SCIP *scip, SCIP_CONS *cons)
Definition cons_or.c:2309
SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition cons_and.c:5059
SCIP_RETCODE SCIPcreateConsBasicOr(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars)
Definition cons_or.c:2293
SCIP_VAR * SCIPgetResultantOr(SCIP *scip, SCIP_CONS *cons)
Definition cons_or.c:2345
SCIP_RETCODE SCIPcreateConsOr(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition cons_or.c:2212
SCIP_RETCODE SCIPincludeConshdlrOr(SCIP *scip)
Definition cons_or.c:2162
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_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
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:4067
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsgPrint
#define SCIPdebugMsg
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
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 SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition scip_cons.c:235
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_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 SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:468
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:624
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_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_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8702
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition cons.c:8786
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
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 SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8672
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
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
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
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
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 SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:105
SCIP_Bool SCIPinProbing(SCIP *scip)
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition scip_lp.c:1718
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1398
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2131
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17917
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
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition scip_tree.c:146
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5210
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_Bool SCIPdoNotAggr(SCIP *scip)
Definition scip_var.c:10909
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23462
SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
Definition scip_var.c:805
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition scip_var.c:10550
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_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition scip_var.c:2166
SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition scip_var.c:8740
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2736
SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:7412
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition scip_var.c:361
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition scip_var.c:2236
SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
Definition scip_var.c:423
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition scip_var.c:2078
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition misc.c:10768
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 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
int r
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 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
public data structures and miscellaneous methods
public methods for problem variables
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 cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
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
@ SCIP_CONFTYPE_PROPAGATION
#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_CONSPRINT(x)
Definition type_cons.h:769
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
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_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_CONSPRESOL(x)
Definition type_cons.h:561
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:259
#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_CONSEXITSOL(x)
Definition type_cons.h:216
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:116
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:320
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition type_event.h:127
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_LBTIGHTENED
Definition type_event.h:77
#define SCIP_EVENTTYPE_UBRELAXED
Definition type_event.h:80
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
@ 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_SEPARATED
Definition type_result.h:49
@ 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_INVALIDDATA
@ 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
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
enum SYM_Symtype SYM_SYMTYPE
@ SYM_CONSOPTYPE_OR
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
@ SCIP_LOCKTYPE_CONFLICT
Definition type_var.h:142
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141