SCIP Doxygen Documentation
Loading...
Searching...
No Matches
cons_and.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_and.c
26 * @ingroup DEFPLUGINS_CONS
27 * @ingroup CONSHDLRS
28 * @brief Constraint handler for AND-constraints, \f$r = x_1 \wedge x_2 \wedge \dots \wedge x_n\f$
29 * @author Tobias Achterberg
30 * @author Stefan Heinz
31 * @author Michael Winkler
32 *
33 * This constraint handler deals with AND-constraints. These are constraint of the form:
34 *
35 * \f[
36 * r = x_1 \wedge x_2 \wedge \dots \wedge x_n
37 * \f]
38 *
39 * 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
40 * called resultant and the \f$x\f$'s operators.
41 */
42
43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44
46#include "scip/cons_and.h"
47#include "scip/cons_linear.h"
48#include "scip/cons_logicor.h"
50#include "scip/cons_setppc.h"
51#include "scip/expr_product.h"
52#include "scip/expr_var.h"
53#include "scip/debug.h"
54#include "scip/pub_cons.h"
55#include "scip/pub_event.h"
56#include "scip/pub_lp.h"
57#include "scip/pub_message.h"
58#include "scip/pub_misc.h"
59#include "scip/pub_misc_sort.h"
60#include "scip/pub_var.h"
61#include "scip/scip_conflict.h"
62#include "scip/scip_cons.h"
63#include "scip/scip_copy.h"
64#include "scip/scip_cut.h"
65#include "scip/scip_event.h"
66#include "scip/scip_expr.h"
67#include "scip/scip_general.h"
68#include "scip/scip_lp.h"
69#include "scip/scip_mem.h"
70#include "scip/scip_message.h"
71#include "scip/scip_nlp.h"
72#include "scip/scip_numerics.h"
73#include "scip/scip_param.h"
74#include "scip/scip_prob.h"
75#include "scip/scip_probing.h"
76#include "scip/scip_sol.h"
77#include "scip/scip_tree.h"
78#include "scip/scip_var.h"
79#include "scip/symmetry_graph.h"
81
82
83/* constraint handler properties */
84#define CONSHDLR_NAME "and"
85#define CONSHDLR_DESC "constraint handler for AND-constraints: r = and(x1, ..., xn)"
86#define CONSHDLR_SEPAPRIORITY +850100 /**< priority of the constraint handler for separation */
87#define CONSHDLR_ENFOPRIORITY -850100 /**< priority of the constraint handler for constraint enforcing */
88#define CONSHDLR_CHECKPRIORITY -850100 /**< priority of the constraint handler for checking feasibility */
89#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
90#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
91#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
92 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
93#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
94#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
95#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
96#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
97
98#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE)
99#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
100
101#define EVENTHDLR_NAME "and"
102#define EVENTHDLR_DESC "bound change event handler for AND-constraints"
103
104#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
105#define DEFAULT_LINEARIZE FALSE /**< should constraint get linearized and removed? */
106#define DEFAULT_ENFORCECUTS TRUE /**< should cuts be separated during LP enforcing? */
107#define DEFAULT_AGGRLINEARIZATION FALSE /**< should an aggregated linearization be used? */
108#define DEFAULT_UPGRRESULTANT FALSE /**< should implied integrality of resultant variables be detected? */
109#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving be performed? */
110
111#define HASHSIZE_ANDCONS 500 /**< minimal size of hash table in and constraint tables */
112#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
113#define NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
114#define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
115
116/* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
117
118/*
119 * Data structures
120 */
121
122/** constraint data for AND-constraints */
123struct SCIP_ConsData
124{
125 SCIP_VAR** vars; /**< variables in the AND-constraint */
126 SCIP_VAR* resvar; /**< resultant variable */
127 SCIP_ROW** rows; /**< rows for linear relaxation of AND-constraint */
128 SCIP_ROW* aggrrow; /**< aggregated row for linear relaxation of AND-constraint */
129 SCIP_NLROW* nlrow; /**< row for representation in nonlinear relaxation */
130 int nvars; /**< number of variables in AND-constraint */
131 int varssize; /**< size of vars array */
132 int nrows; /**< number of rows for linear relaxation of AND-constraint */
133 int watchedvar1; /**< position of first watched operator variable */
134 int watchedvar2; /**< position of second watched operator variable */
135 int filterpos1; /**< event filter position of first watched operator variable */
136 int filterpos2; /**< event filter position of second watched operator variable */
137 unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
138 unsigned int nofixedzero:1; /**< is none of the operator variables fixed to FALSE? */
139 unsigned int impladded:1; /**< were the implications of the constraint already added? */
140 unsigned int opimpladded:1; /**< was the implication for 2 operands with fixed resultant added? */
141 unsigned int sorted:1; /**< are the constraint's variables sorted? */
142 unsigned int changed:1; /**< was constraint changed since last pair preprocessing round? */
143 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
144};
145
146/** constraint handler data */
147struct SCIP_ConshdlrData
148{
149 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events on watched variables */
150 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
151 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
152 SCIP_Bool linearize; /**< should constraint get linearized and removed? */
153 SCIP_Bool enforcecuts; /**< should cuts be separated during LP enforcing? */
154 SCIP_Bool aggrlinearization; /**< should an aggregated linearization be used? */
155 SCIP_Bool upgrresultant; /**< should implied integrality of resultant variables be detected? */
156 SCIP_Bool dualpresolving; /**< should dual presolving be performed? */
157};
158
159
160/*
161 * Propagation rules
162 */
163
165{
166 PROPRULE_INVALID = 0, /**< propagation was applied without a specific propagation rule */
167 PROPRULE_1 = 1, /**< v_i = FALSE => r = FALSE */
168 PROPRULE_2 = 2, /**< r = TRUE => v_i = TRUE for all i */
169 PROPRULE_3 = 3, /**< v_i = TRUE for all i => r = TRUE */
170 PROPRULE_4 = 4 /**< r = FALSE, v_i = TRUE for all i except j => v_j = FALSE */
171};
172typedef enum Proprule PROPRULE;
173
174
175/*
176 * Local methods
177 */
178
179/** installs rounding locks for the given variable in the given AND-constraint */
180static
182 SCIP* scip, /**< SCIP data structure */
183 SCIP_CONS* cons, /**< constraint data */
184 SCIP_VAR* var /**< variable of constraint entry */
185 )
186{
187 /* rounding in both directions may violate the constraint */
189
190 return SCIP_OKAY;
191}
192
193/** removes rounding locks for the given variable in the given AND-constraint */
194static
196 SCIP* scip, /**< SCIP data structure */
197 SCIP_CONS* cons, /**< constraint data */
198 SCIP_VAR* var /**< variable of constraint entry */
199 )
200{
201 /* rounding in both directions may violate the constraint */
203
204 return SCIP_OKAY;
205}
206
207/** creates constraint handler data */
208static
210 SCIP* scip, /**< SCIP data structure */
211 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
212 SCIP_EVENTHDLR* eventhdlr /**< event handler */
213 )
214{
215 assert(scip != NULL);
216 assert(conshdlrdata != NULL);
217 assert(eventhdlr != NULL);
218
219 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
220
221 /* set event handler for catching bound change events on variables */
222 (*conshdlrdata)->eventhdlr = eventhdlr;
223
224 return SCIP_OKAY;
225}
226
227/** frees constraint handler data */
228static
230 SCIP* scip, /**< SCIP data structure */
231 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
232 )
233{
234 assert(conshdlrdata != NULL);
235 assert(*conshdlrdata != NULL);
236
237 SCIPfreeBlockMemory(scip, conshdlrdata);
238}
239
240/** catches events for the watched variable at given position */
241static
243 SCIP* scip, /**< SCIP data structure */
244 SCIP_CONSDATA* consdata, /**< AND-constraint data */
245 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
246 int pos, /**< array position of variable to catch bound change events for */
247 int* filterpos /**< pointer to store position of event filter entry */
248 )
249{
250 assert(consdata != NULL);
251 assert(consdata->vars != NULL);
252 assert(eventhdlr != NULL);
253 assert(0 <= pos && pos < consdata->nvars);
254 assert(filterpos != NULL);
255
256 /* catch tightening events for lower bound and relaxed events for upper bounds on watched variable */
258 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
259
260 return SCIP_OKAY;
261}
262
263
264/** drops events for the watched variable at given position */
265static
267 SCIP* scip, /**< SCIP data structure */
268 SCIP_CONSDATA* consdata, /**< AND-constraint data */
269 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
270 int pos, /**< array position of watched variable to drop bound change events for */
271 int filterpos /**< position of event filter entry */
272 )
273{
274 assert(consdata != NULL);
275 assert(consdata->vars != NULL);
276 assert(eventhdlr != NULL);
277 assert(0 <= pos && pos < consdata->nvars);
278 assert(filterpos >= 0);
279
280 /* drop tightening events for lower bound and relaxed events for upper bounds on watched variable */
282 eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
283
284 return SCIP_OKAY;
285}
286
287/** catches needed events on all variables of constraint, except the special ones for watched variables */
288static
290 SCIP* scip, /**< SCIP data structure */
291 SCIP_CONSDATA* consdata, /**< AND-constraint data */
292 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
293 )
294{
295 int i;
296
297 assert(consdata != NULL);
298
299 /* catch bound change events for both bounds on resultant variable */
301 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
302
303 /* catch tightening events for upper bound and relaxed events for lower bounds on operator variables */
304 for( i = 0; i < consdata->nvars; ++i )
305 {
307 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
308 }
309
310 return SCIP_OKAY;
311}
312
313/** drops events on all variables of constraint, except the special ones for watched variables */
314static
316 SCIP* scip, /**< SCIP data structure */
317 SCIP_CONSDATA* consdata, /**< AND-constraint data */
318 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
319 )
320{
321 int i;
322
323 assert(consdata != NULL);
324
325 /* drop bound change events for both bounds on resultant variable */
327 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
328
329 /* drop tightening events for upper bound and relaxed events for lower bounds on operator variables */
330 for( i = 0; i < consdata->nvars; ++i )
331 {
333 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
334 }
335
336 return SCIP_OKAY;
337}
338
339/** stores the given variable numbers as watched variables, and updates the event processing */
340static
342 SCIP* scip, /**< SCIP data structure */
343 SCIP_CONSDATA* consdata, /**< AND-constraint data */
344 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
345 int watchedvar1, /**< new first watched variable */
346 int watchedvar2 /**< new second watched variable */
347 )
348{
349 assert(consdata != NULL);
350 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
351 assert(watchedvar1 != -1 || watchedvar2 == -1);
352 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
353 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
354
355 /* if one watched variable is equal to the old other watched variable, just switch positions */
356 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
357 {
358 int tmp;
359
360 tmp = consdata->watchedvar1;
361 consdata->watchedvar1 = consdata->watchedvar2;
362 consdata->watchedvar2 = tmp;
363 tmp = consdata->filterpos1;
364 consdata->filterpos1 = consdata->filterpos2;
365 consdata->filterpos2 = tmp;
366 }
367 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
368 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
369
370 /* drop events on old watched variables */
371 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
372 {
373 assert(consdata->filterpos1 != -1);
374 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
375 }
376 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
377 {
378 assert(consdata->filterpos2 != -1);
379 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
380 }
381
382 /* catch events on new watched variables */
383 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
384 {
385 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
386 }
387 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
388 {
389 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
390 }
391
392 /* set the new watched variables */
393 consdata->watchedvar1 = watchedvar1;
394 consdata->watchedvar2 = watchedvar2;
395
396 return SCIP_OKAY;
397}
398
399/** ensures, that the vars array can store at least num entries */
400static
402 SCIP* scip, /**< SCIP data structure */
403 SCIP_CONSDATA* consdata, /**< linear constraint data */
404 int num /**< minimum number of entries to store */
405 )
406{
407 assert(consdata != NULL);
408 assert(consdata->nvars <= consdata->varssize);
409
410 if( num > consdata->varssize )
411 {
412 int newsize;
413
414 newsize = SCIPcalcMemGrowSize(scip, num);
415 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
416 consdata->varssize = newsize;
417 }
418 assert(num <= consdata->varssize);
419
420 return SCIP_OKAY;
421}
422
423/** creates constraint data for AND-constraint */
424static
426 SCIP* scip, /**< SCIP data structure */
427 SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
428 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
429 int nvars, /**< number of variables in the AND-constraint */
430 SCIP_VAR** vars, /**< variables in AND-constraint */
431 SCIP_VAR* resvar /**< resultant variable */
432 )
433{
434 int v;
435
436 assert(consdata != NULL);
437 assert(nvars == 0 || vars != NULL);
438 assert(resvar != NULL);
439
440 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
441 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
442 (*consdata)->resvar = resvar;
443 (*consdata)->rows = NULL;
444 (*consdata)->aggrrow = NULL;
445 (*consdata)->nlrow = NULL;
446 (*consdata)->nvars = nvars;
447 (*consdata)->varssize = nvars;
448 (*consdata)->nrows = 0;
449 (*consdata)->watchedvar1 = -1;
450 (*consdata)->watchedvar2 = -1;
451 (*consdata)->filterpos1 = -1;
452 (*consdata)->filterpos2 = -1;
453 (*consdata)->propagated = FALSE;
454 (*consdata)->nofixedzero = FALSE;
455 (*consdata)->impladded = FALSE;
456 (*consdata)->opimpladded = FALSE;
457 (*consdata)->sorted = FALSE;
458 (*consdata)->changed = TRUE;
459 (*consdata)->merged = FALSE;
460
461 /* get transformed variables, if we are in the transformed problem */
463 {
464 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
465 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->resvar, &(*consdata)->resvar) );
466
467 /* catch needed events on variables */
468 SCIP_CALL( consdataCatchEvents(scip, *consdata, eventhdlr) );
469 }
470
471 assert(SCIPvarIsBinary((*consdata)->resvar));
472
473 /* note: currently, this constraint handler does not handle multiaggregations (e.g. during propagation), hence we forbid
474 * multiaggregation from the beginning for the involved variables
475 */
477 {
478 for( v = 0; v < (*consdata)->nvars; ++v )
479 {
480 assert((*consdata)->vars[v] != NULL);
481 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[v]) );
482 }
483 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->resvar) );
484 }
485
486 /* capture vars */
487 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->resvar) );
488 for( v = 0; v < (*consdata)->nvars; v++ )
489 {
490 assert((*consdata)->vars[v] != NULL);
491 assert(SCIPvarIsBinary((*consdata)->vars[v]));
492 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
493 }
494
495 return SCIP_OKAY;
496}
497
498/** releases LP rows of constraint data and frees rows array */
499static
501 SCIP* scip, /**< SCIP data structure */
502 SCIP_CONSDATA* consdata /**< constraint data */
503 )
504{
505 int r;
506
507 assert(consdata != NULL);
508
509 if( consdata->rows != NULL )
510 {
511 for( r = 0; r < consdata->nrows; ++r )
512 {
513 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
514 }
515 SCIPfreeBlockMemoryArray(scip, &consdata->rows, consdata->nrows);
516
517 consdata->nrows = 0;
518 }
519
520 if( consdata->aggrrow != NULL )
521 {
522 SCIP_CALL( SCIPreleaseRow(scip, &consdata->aggrrow) );
523 consdata->aggrrow = NULL;
524 }
525
526 return SCIP_OKAY;
527}
528
529/** frees constraint data for AND-constraint */
530static
532 SCIP* scip, /**< SCIP data structure */
533 SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
534 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
535 )
536{
537 int v;
538
539 assert(consdata != NULL);
540 assert(*consdata != NULL);
541
543 {
544 /* drop events for watched variables */
545 SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
546
547 /* drop all other events on variables */
548 SCIP_CALL( consdataDropEvents(scip, *consdata, eventhdlr) );
549 }
550 else
551 {
552 assert((*consdata)->watchedvar1 == -1);
553 assert((*consdata)->watchedvar2 == -1);
554 }
555
556 /* release and free the rows */
557 SCIP_CALL( consdataFreeRows(scip, *consdata) );
558
559 /* release the nlrow */
560 if( (*consdata)->nlrow != NULL )
561 {
562 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
563 }
564
565 /* release vars */
566 for( v = 0; v < (*consdata)->nvars; v++ )
567 {
568 assert((*consdata)->vars[v] != NULL);
569 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
570 }
571 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->resvar)) );
572
573 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
574 SCIPfreeBlockMemory(scip, consdata);
575
576 return SCIP_OKAY;
577}
578
579/** prints AND-constraint to file stream */
580static
582 SCIP* scip, /**< SCIP data structure */
583 SCIP_CONSDATA* consdata, /**< AND-constraint data */
584 FILE* file /**< output file (or NULL for standard output) */
585 )
586{
587 assert(consdata != NULL);
588
589 /* print resultant */
590 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->resvar, TRUE) );
591
592 /* start the variable list */
593 SCIPinfoMessage(scip, file, " == and(");
594
595 /* print variable list */
596 SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
597
598 /* close the variable list */
599 SCIPinfoMessage(scip, file, ")");
600
601 return SCIP_OKAY;
602}
603
604/** adds coefficient to AND-constraint */
605static
607 SCIP* scip, /**< SCIP data structure */
608 SCIP_CONS* cons, /**< linear constraint */
609 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
610 SCIP_VAR* var /**< variable to add to the constraint */
611 )
612{
613 SCIP_CONSDATA* consdata;
614 SCIP_Bool transformed;
615
616 assert(var != NULL);
617
618 consdata = SCIPconsGetData(cons);
619 assert(consdata != NULL);
620 assert(consdata->rows == NULL);
621
622 /* are we in the transformed problem? */
623 transformed = SCIPconsIsTransformed(cons);
624
625 /* always use transformed variables in transformed constraints */
626 if( transformed )
627 {
629 }
630 assert(var != NULL);
631 assert(transformed == SCIPvarIsTransformed(var));
632
633 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
634 consdata->vars[consdata->nvars] = var;
635 consdata->nvars++;
636 consdata->sorted = (consdata->nvars == 1);
637 consdata->changed = TRUE;
638 consdata->merged = FALSE;
639
640 /* capture variable */
642
643 /* if we are in transformed problem, catch the variable's events */
644 if( transformed )
645 {
646 /* catch bound change events of variable */
648 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
649 }
650
651 /* install the rounding locks for the new variable */
652 SCIP_CALL( lockRounding(scip, cons, var) );
653
654 /**@todo update LP rows */
655 if( consdata->rows != NULL )
656 {
657 SCIPerrorMessage("cannot add coefficients to AND-constraint after LP relaxation was created\n");
658 return SCIP_INVALIDCALL;
659 }
660
661 return SCIP_OKAY;
662}
663
664/** deletes coefficient at given position from AND-constraint data */
665static
667 SCIP* scip, /**< SCIP data structure */
668 SCIP_CONS* cons, /**< AND-constraint */
669 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
670 int pos /**< position of coefficient to delete */
671 )
672{
673 SCIP_CONSDATA* consdata;
674
675 assert(eventhdlr != NULL);
676
677 consdata = SCIPconsGetData(cons);
678 assert(consdata != NULL);
679 assert(0 <= pos && pos < consdata->nvars);
680 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
681
682 /* remove the rounding locks of the variable */
683 SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
684
685 if( SCIPconsIsTransformed(cons) )
686 {
687 /* drop bound change events of variable */
689 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
690 }
691
692 if( SCIPconsIsTransformed(cons) )
693 {
694 /* if the position is watched, stop watching the position */
695 if( consdata->watchedvar1 == pos )
696 {
697 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
698 }
699 if( consdata->watchedvar2 == pos )
700 {
701 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
702 }
703 }
704 assert(pos != consdata->watchedvar1);
705 assert(pos != consdata->watchedvar2);
706
707 /* release variable */
708 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->vars[pos])) );
709
710 /* move the last variable to the free slot */
711 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
712 consdata->nvars--;
713
714 /* if the last variable (that moved) was watched, update the watched position */
715 if( consdata->watchedvar1 == consdata->nvars )
716 consdata->watchedvar1 = pos;
717 if( consdata->watchedvar2 == consdata->nvars )
718 consdata->watchedvar2 = pos;
719
720 consdata->propagated = FALSE;
721 consdata->sorted = FALSE;
722 consdata->changed = TRUE;
723
724 return SCIP_OKAY;
725}
726
727/** sorts AND-constraint's variables by non-decreasing variable index */
728static
730 SCIP_CONSDATA* consdata /**< constraint data */
731 )
732{
733 assert(consdata != NULL);
734
735 if( !consdata->sorted )
736 {
737 if( consdata->nvars <= 1 )
738 consdata->sorted = TRUE;
739 else
740 {
741 SCIP_VAR* var1 = NULL;
742 SCIP_VAR* var2 = NULL;
743
744 /* remember watch variables */
745 if( consdata->watchedvar1 != -1 )
746 {
747 var1 = consdata->vars[consdata->watchedvar1];
748 assert(var1 != NULL);
749 consdata->watchedvar1 = -1;
750 if( consdata->watchedvar2 != -1 )
751 {
752 var2 = consdata->vars[consdata->watchedvar2];
753 assert(var2 != NULL);
754 consdata->watchedvar2 = -1;
755 }
756 }
757 assert(consdata->watchedvar1 == -1);
758 assert(consdata->watchedvar2 == -1);
759 assert(var1 != NULL || var2 == NULL);
760
761 /* sort variables after index */
762 SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
763 consdata->sorted = TRUE;
764
765 /* correct watched variables */
766 if( var1 != NULL )
767 {
768 int pos;
769#ifndef NDEBUG
770 SCIP_Bool found;
771
772 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
773 assert(found);
774#else
775 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
776#endif
777 assert(pos >= 0 && pos < consdata->nvars);
778 consdata->watchedvar1 = pos;
779
780 if( var2 != NULL )
781 {
782#ifndef NDEBUG
783 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
784 assert(found);
785#else
786 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
787#endif
788 assert(pos >= 0 && pos < consdata->nvars);
789 consdata->watchedvar2 = pos;
790 }
791 }
792 }
793 }
794
795#ifdef SCIP_DEBUG
796 /* check sorting */
797 {
798 int v;
799
800 for( v = 0; v < consdata->nvars; ++v )
801 {
802 assert(v == consdata->nvars-1 || SCIPvarCompare(consdata->vars[v], consdata->vars[v+1]) <= 0);
803 }
804 }
805#endif
806}
807
808/** deletes all one-fixed variables */
809static
811 SCIP* scip, /**< SCIP data structure */
812 SCIP_CONS* cons, /**< AND-constraint */
813 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
814 int* nchgcoefs /**< pointer to add up the number of changed coefficients */
815 )
816{
817 SCIP_CONSDATA* consdata;
818 SCIP_VAR* var;
819 int v;
820
821 assert(scip != NULL);
822 assert(cons != NULL);
823 assert(eventhdlr != NULL);
824 assert(nchgcoefs != NULL);
825
826 consdata = SCIPconsGetData(cons);
827 assert(consdata != NULL);
828 assert(consdata->nvars == 0 || consdata->vars != NULL);
829
830 v = 0;
831 while( v < consdata->nvars )
832 {
833 var = consdata->vars[v];
835
836 if( SCIPvarGetLbGlobal(var) > 0.5 )
837 {
839 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
840 (*nchgcoefs)++;
841 }
842 else
843 {
844 SCIP_VAR* repvar;
845 SCIP_Bool negated;
846
847 /* get binary representative of variable */
848 SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
849
850 /* check, if the variable should be replaced with the representative */
851 if( repvar != var )
852 {
853 /* delete old (aggregated) variable */
854 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
855
856 /* add representative instead */
857 SCIP_CALL( addCoef(scip, cons, eventhdlr, repvar) );
858 }
859 else
860 ++v;
861 }
862 }
863
864#ifdef SCIP_DISABLED_CODE /* does not work with pseudoboolean constraint handler, need to be fixed */
865 /* check, if the resultant should be replaced with the active representative */
866 if( !SCIPvarIsActive(consdata->resvar) )
867 {
868 SCIP_VAR* repvar;
869 SCIP_Bool negated;
870
871 /* get binary representative of variable */
872 SCIP_CALL( SCIPgetBinvarRepresentative(scip, consdata->resvar, &repvar, &negated) );
873 assert(SCIPvarIsBinary(repvar));
874
875 /* check, if the variable should be replaced with the representative */
876 if( repvar != consdata->resvar )
877 {
878 if( SCIPconsIsTransformed(cons) )
879 {
880 /* drop bound change events of old resultant */
882 eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
883
884 /* catch bound change events of new resultant */
886 eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
887 }
888
889 /* release old resultant */
890 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->resvar)) );
891
892 /* capture new resultant */
893 SCIP_CALL( SCIPcaptureVar(scip, repvar) );
894
895 consdata->resvar = repvar;
896 consdata->changed = TRUE;
897 }
898 }
899#endif
900
901 SCIPdebugMsg(scip, "after fixings: ");
902 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL)) );
903 SCIPdebugMsgPrint(scip, "\n");
904
905 return SCIP_OKAY;
906}
907
908/** creates a linearization of the AND-constraint */
909static
911 SCIP* scip, /**< SCIP data structure */
912 SCIP_CONS* cons /**< constraint to check */
913 )
914{
915 SCIP_CONSDATA* consdata;
916 char rowname[SCIP_MAXSTRLEN];
917 int nvars;
918 int i;
919
920 consdata = SCIPconsGetData(cons);
921 assert(consdata != NULL);
922 assert(consdata->rows == NULL);
923
924 nvars = consdata->nvars;
925
926 /* get memory for rows */
927 consdata->nrows = nvars + 1;
928 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->rows, consdata->nrows) );
929
930 /* creates LP rows corresponding to AND-constraint:
931 * - one additional row: resvar - v1 - ... - vn >= 1-n
932 * - for each operator variable vi: resvar - vi <= 0
933 */
934
935 /* create additional row */
936 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
937 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[0], cons, rowname, -consdata->nvars + 1.0, SCIPinfinity(scip),
939 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[0], consdata->resvar, 1.0) );
940 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[0], nvars, consdata->vars, -1.0) );
941
942 /* create operator rows */
943 for( i = 0; i < nvars; ++i )
944 {
945 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), i);
946 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[i+1], cons, rowname, -SCIPinfinity(scip), 0.0,
948 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->resvar, 1.0) );
949 SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->vars[i], -1.0) );
950 }
951
952 return SCIP_OKAY;
953}
954
955/** adds linear relaxation of AND-constraint to the LP */
956static
958 SCIP* scip, /**< SCIP data structure */
959 SCIP_CONS* cons, /**< constraint to check */
960 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected */
961 )
962{
963 SCIP_CONSDATA* consdata;
964
965 /* in the root LP we only add the weaker relaxation which consists of two rows:
966 * - one additional row: resvar - v1 - ... - vn >= 1-n
967 * - aggregated row: n*resvar - v1 - ... - vn <= 0.0
968 *
969 * during separation we separate the stronger relaxation which consists of n+1 row:
970 * - one additional row: resvar - v1 - ... - vn >= 1-n
971 * - for each operator variable vi: resvar - vi <= 0.0
972 */
973
974 consdata = SCIPconsGetData(cons);
975 assert(consdata != NULL);
976
977 /* create the aggregated row */
978 if( consdata->aggrrow == NULL )
979 {
980 char rowname[SCIP_MAXSTRLEN];
981
982 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_operators", SCIPconsGetName(cons));
983 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->aggrrow, cons, rowname, -SCIPinfinity(scip), 0.0,
985 SCIP_CALL( SCIPaddVarToRow(scip, consdata->aggrrow, consdata->resvar, (SCIP_Real) consdata->nvars) );
986 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->aggrrow, consdata->nvars, consdata->vars, -1.0) );
987 }
988
989 /* insert aggregated LP row as cut */
990 if( !SCIProwIsInLP(consdata->aggrrow) )
991 {
992 SCIP_CALL( SCIPaddRow(scip, consdata->aggrrow, FALSE, infeasible) );
993 }
994
995 if( !(*infeasible) )
996 {
997 if( consdata->rows == NULL )
998 {
999 /* create the n+1 row relaxation */
1001 }
1002
1003 assert(consdata->rows != NULL);
1004
1005 /* add additional row */
1006 if( !SCIProwIsInLP(consdata->rows[0]) )
1007 {
1008 SCIP_CALL( SCIPaddRow(scip, consdata->rows[0], FALSE, infeasible) );
1009 }
1010 }
1011
1012 return SCIP_OKAY;
1013}
1014
1015/** adds constraint as row to the NLP, if not added yet */
1016static
1018 SCIP* scip, /**< SCIP data structure */
1019 SCIP_CONS* cons /**< and constraint */
1020 )
1021{
1022 SCIP_CONSDATA* consdata;
1023
1025
1026 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
1027 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
1028 return SCIP_OKAY;
1029
1030 consdata = SCIPconsGetData(cons);
1031 assert(consdata != NULL);
1032 assert(consdata->resvar != NULL);
1033
1034 if( consdata->nlrow == NULL )
1035 {
1036 SCIP_EXPR* expr;
1037 SCIP_EXPR** varexprs;
1038 SCIP_Real minusone = -1.0;
1039 int i;
1040
1041 SCIP_CALL( SCIPallocBufferArray(scip, &varexprs, consdata->nvars) );
1042 for( i = 0; i < consdata->nvars; ++i )
1043 {
1044 SCIP_CALL( SCIPcreateExprVar(scip, &varexprs[i], consdata->vars[i], NULL, NULL) );
1045 }
1046 SCIP_CALL( SCIPcreateExprProduct(scip, &expr, consdata->nvars, varexprs, 1.0, NULL, NULL) );
1047
1048 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
1049 0.0, 1, &consdata->resvar, &minusone, expr, 0.0, 0.0, SCIP_EXPRCURV_UNKNOWN) );
1050 assert(consdata->nlrow != NULL);
1051
1052 SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
1053 for( i = 0; i < consdata->nvars; ++i )
1054 {
1055 SCIP_CALL( SCIPreleaseExpr(scip, &varexprs[i]) );
1056 }
1057 SCIPfreeBufferArray(scip, &varexprs);
1058 }
1059
1060 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
1061 {
1062 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
1063 }
1064
1065 return SCIP_OKAY;
1066}
1067
1068/** checks AND-constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
1069static
1071 SCIP* scip, /**< SCIP data structure */
1072 SCIP_CONS* cons, /**< constraint to check */
1073 SCIP_SOL* sol, /**< solution to check, NULL for current solution */
1074 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
1075 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
1076 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
1077 )
1078{
1079 SCIP_CONSDATA* consdata;
1080 SCIP_Bool mustcheck;
1081 int r;
1082
1083 assert(violated != NULL);
1084
1085 consdata = SCIPconsGetData(cons);
1086 assert(consdata != NULL);
1087
1088 *violated = FALSE;
1089
1090 /* check whether we can skip this feasibility check, because all rows are in the LP and do not have to be checked */
1091 mustcheck = checklprows;
1092 mustcheck = mustcheck || (consdata->rows == NULL);
1093 if( !mustcheck )
1094 {
1095 assert(consdata->rows != NULL);
1096
1097 for( r = 0; r < consdata->nrows; ++r )
1098 {
1099 mustcheck = !SCIProwIsInLP(consdata->rows[r]);
1100 if( mustcheck )
1101 break;
1102 }
1103 }
1104
1105 /* check feasibility of constraint if necessary */
1106 if( mustcheck )
1107 {
1108 SCIP_Real minsolval = 1.0;
1109 SCIP_Real sumsolval = 0.0;
1110 SCIP_Real solval;
1111 SCIP_Real viol;
1112 int minsolind = 0;
1113 int i;
1114
1115 /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
1116 * enforcement
1117 */
1118 if( sol == NULL )
1119 {
1120 SCIP_CALL( SCIPincConsAge(scip, cons) );
1121 }
1122
1123 /* evaluate operator variables */
1124 for( i = 0; i < consdata->nvars; ++i )
1125 {
1126 solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
1127
1128 if( minsolval > solval )
1129 {
1130 minsolind = i;
1131 minsolval = solval;
1132 }
1133
1134 sumsolval += solval;
1135 }
1136
1137 /* the resultant must be at most as large as every operator
1138 * and at least as large as one minus the sum of negated operators
1139 */
1140 solval = SCIPgetSolVal(scip, sol, consdata->resvar);
1141 viol = MAX3(0.0, solval - minsolval, sumsolval - (consdata->nvars - 1.0 + solval));
1142
1143 if( SCIPisFeasPositive(scip, viol) )
1144 {
1145 *violated = TRUE;
1146
1147 /* only reset constraint age if we are in enforcement */
1148 if( sol == NULL )
1149 {
1151 }
1152
1153 if( printreason )
1154 {
1155 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
1156 SCIPinfoMessage(scip, NULL, ";\n");
1157 SCIPinfoMessage(scip, NULL, "violation:");
1158
1159 if( SCIPisFeasPositive(scip, solval - minsolval) )
1160 {
1161 SCIPinfoMessage(scip, NULL, " operand <%s> = FALSE and resultant <%s> = TRUE\n",
1162 SCIPvarGetName(consdata->vars[minsolind]), SCIPvarGetName(consdata->resvar));
1163 }
1164 else
1165 {
1166 SCIPinfoMessage(scip, NULL, " all operands are TRUE and resultant <%s> = FALSE\n",
1167 SCIPvarGetName(consdata->resvar));
1168 }
1169 }
1170 }
1171
1172 /* update constraint violation in solution */
1173 if( sol != NULL )
1174 SCIPupdateSolConsViolation(scip, sol, viol, viol);
1175 }
1176
1177 return SCIP_OKAY;
1178}
1179
1180/** separates given primal solution */
1181static
1183 SCIP* scip, /**< SCIP data structure */
1184 SCIP_CONS* cons, /**< constraint to check */
1185 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1186 SCIP_Bool* separated, /**< pointer to store whether a cut was found */
1187 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
1188 )
1189{
1190 SCIP_CONSDATA* consdata;
1191 SCIP_Real feasibility;
1192 int r;
1193
1194 assert(separated != NULL);
1195 assert(cutoff != NULL);
1196
1197 *separated = FALSE;
1198 *cutoff = FALSE;
1199
1200 consdata = SCIPconsGetData(cons);
1201 assert(consdata != NULL);
1202
1203 /* create all necessary rows for the linear relaxation */
1204 if( consdata->rows == NULL )
1205 {
1207 }
1208 assert(consdata->rows != NULL);
1209
1210 /* test all rows for feasibility and add infeasible rows */
1211 for( r = 0; r < consdata->nrows; ++r )
1212 {
1213 if( !SCIProwIsInLP(consdata->rows[r]) )
1214 {
1215 feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
1216 if( SCIPisFeasNegative(scip, feasibility) )
1217 {
1218 SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, cutoff) );
1219 if ( *cutoff )
1220 return SCIP_OKAY;
1221 *separated = TRUE;
1222 }
1223 }
1224 }
1225
1226 return SCIP_OKAY;
1227}
1228
1229/** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
1230static
1232 SCIP* scip, /**< SCIP data structure */
1233 SCIP_CONS* cons, /**< AND-constraint that detected the conflict */
1234 int falsepos /**< position of operand that is fixed to FALSE */
1235 )
1236{
1237 SCIP_CONSDATA* consdata;
1238
1239 /* conflict analysis can only be applied in solving stage and if it turned on */
1241 return SCIP_OKAY;
1242
1243 consdata = SCIPconsGetData(cons);
1244 assert(consdata != NULL);
1245 assert(SCIPvarGetLbLocal(consdata->resvar) > 0.5);
1246 assert(0 <= falsepos && falsepos < consdata->nvars);
1247 assert(SCIPvarGetUbLocal(consdata->vars[falsepos]) < 0.5);
1248
1249 /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
1251
1252 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1253 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[falsepos]) );
1254
1255 /* analyze the conflict */
1257
1258 return SCIP_OKAY;
1259}
1260
1261/** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
1262static
1264 SCIP* scip, /**< SCIP data structure */
1265 SCIP_CONS* cons /**< or constraint that detected the conflict */
1266 )
1267{
1268 SCIP_CONSDATA* consdata;
1269 int v;
1270
1272
1273 /* conflict analysis can only be applied in solving stage and if it is applicable */
1275 return SCIP_OKAY;
1276
1277 consdata = SCIPconsGetData(cons);
1278 assert(consdata != NULL);
1279 assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
1280
1281 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
1283
1284 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1285 for( v = 0; v < consdata->nvars; ++v )
1286 {
1287 assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
1288 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
1289 }
1290
1291 /* analyze the conflict */
1293
1294 return SCIP_OKAY;
1295}
1296
1297/** tries to fix the given resultant to zero */
1298static
1300 SCIP* scip, /**< SCIP data structure */
1301 SCIP_CONS* cons, /**< AND-constraint to be processed */
1302 SCIP_VAR* resvar, /**< resultant variable to fix to zero */
1303 int pos, /**< position of operand that is fixed to FALSE */
1304 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1305 int* nfixedvars /**< pointer to add up the number of found domain reductions */
1306 )
1307{
1308 SCIP_Bool infeasible;
1309 SCIP_Bool tightened;
1310
1311 SCIPdebugMsg(scip, "constraint <%s>: operator %d fixed to 0.0 -> fix resultant <%s> to 0.0\n",
1312 SCIPconsGetName(cons), pos, SCIPvarGetName(resvar));
1313
1314 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
1315
1316 if( infeasible )
1317 {
1318 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1319 SCIP_CALL( analyzeConflictOne(scip, cons, pos) );
1321 (*cutoff) = TRUE;
1322 }
1323 else
1324 {
1326 if( tightened )
1327 {
1329 (*nfixedvars)++;
1330 }
1331 }
1332
1333 return SCIP_OKAY;
1334}
1335
1336/** fix all operands to one */
1337static
1339 SCIP* scip, /**< SCIP data structure */
1340 SCIP_CONS* cons, /**< AND-constraint to be processed */
1341 SCIP_VAR** vars, /**< array of operands */
1342 int nvars, /**< number of operands */
1343 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1344 int* nfixedvars /**< pointer to add up the number of found domain reductions */
1345 )
1346{
1347 SCIP_Bool infeasible;
1348 SCIP_Bool tightened;
1349 int v;
1350
1351 for( v = 0; v < nvars && !(*cutoff); ++v )
1352 {
1353 SCIPdebugMsg(scip, "constraint <%s>: resultant fixed to 1.0 -> fix operator var <%s> to 1.0\n",
1355
1356 SCIP_CALL( SCIPinferBinvarCons(scip, vars[v], TRUE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
1357
1358 if( infeasible )
1359 {
1360 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1361 SCIP_CALL( analyzeConflictOne(scip, cons, v) );
1363 (*cutoff) = TRUE;
1364 }
1365 else if( tightened )
1366 {
1368 (*nfixedvars)++;
1369 }
1370 }
1371
1372 if( !(*cutoff) )
1373 {
1375 }
1376
1377 return SCIP_OKAY;
1378}
1379
1380/** linearize AND-constraint due to a globally to zero fixed resultant; that is, creates, adds, and releases a logicor
1381 * constraint and remove the AND-constraint globally.
1382 *
1383 * Since the resultant is fixed to zero the AND-constraint collapses to linear constraint of the form:
1384 *
1385 * - \f$\sum_{i=0}^{n-1} v_i \leq n-1\f$
1386 *
1387 * This can be transformed into a logicor constraint of the form
1388 *
1389 * - \f$\sum_{i=0}^{n-1} ~v_i \geq 1\f$
1390 */
1391static
1393 SCIP* scip, /**< SCIP data structure */
1394 SCIP_CONS* cons, /**< AND-constraint to linearize */
1395 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1396 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
1397 int* nupgdconss /**< pointer to add up the number of upgraded constraints */
1398 )
1399{
1400 SCIP_CONSDATA* consdata;
1401 SCIP_VAR** vars;
1402 SCIP_CONS* lincons;
1403 SCIP_Bool conscreated;
1404 int nvars;
1405
1406 consdata = SCIPconsGetData(cons);
1407 assert(consdata != NULL);
1408
1409 assert(!(*cutoff));
1410 assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
1411
1412 nvars = consdata->nvars;
1413 conscreated = FALSE;
1414
1415 /* allocate memory for variables for updated constraint */
1417
1418 /* if we only have two variables, we prefer a set packing constraint instead of a logicor constraint */
1419 if( nvars == 2 && !SCIPconsIsModifiable(cons) )
1420 {
1421 SCIP_Bool* negated;
1422 SCIP_Bool infeasible;
1423 SCIP_Bool tightened;
1424
1425 /* get active representation */
1427 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, consdata->vars, vars, negated) );
1428 SCIPfreeBufferArray(scip, &negated);
1429
1430 /* if one of the two operators is globally fixed to one it follows that the other has to be zero */
1431 if( SCIPvarGetLbGlobal(vars[0]) > 0.5 )
1432 {
1433 SCIP_CALL( SCIPfixVar(scip, vars[1], 0.0, &infeasible, &tightened) );
1434
1435 if( infeasible )
1436 *cutoff = TRUE;
1437 else if( tightened )
1438 ++(*nfixedvars);
1439 }
1440 else if( SCIPvarGetLbGlobal(vars[1]) > 0.5 )
1441 {
1442 SCIP_CALL( SCIPfixVar(scip, vars[0], 0.0, &infeasible, &tightened) );
1443
1444 if( infeasible )
1445 *cutoff = TRUE;
1446 else if( tightened )
1447 ++(*nfixedvars);
1448 }
1449 else if( SCIPvarGetUbGlobal(vars[0]) > 0.5 && SCIPvarGetUbGlobal(vars[1]) > 0.5 )
1450 {
1451 /* create, add, and release the setppc constraint */
1456 SCIPconsIsStickingAtNode(cons)) );
1457
1458 conscreated = TRUE;
1459 }
1460 }
1461 else
1462 {
1463 int v;
1464
1465 /* collect negated variables */
1466 for( v = 0; v < nvars; ++v )
1467 {
1468 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &vars[v]) );
1469 }
1470
1471 /* create, add, and release the logicor constraint */
1476 SCIPconsIsStickingAtNode(cons)) );
1477
1478 conscreated = TRUE;
1479 }
1480
1481 if( conscreated )
1482 {
1483 /* add and release new constraint */
1484 SCIPdebugPrintCons(scip, lincons, NULL); /*lint !e644*/
1485 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &lincons) );
1486 ++(*nupgdconss);
1487 }
1488
1489 /* remove the AND-constraint globally */
1490 SCIP_CALL( SCIPdelCons(scip, cons) );
1491
1492 /* delete temporary memory */
1494
1495 return SCIP_OKAY;
1496}
1497
1498/** the resultant is fixed to zero; in case all except one operator are fixed to TRUE the last operator has to fixed to FALSE */
1499/** @note consdata->watchedvars might not be the same to the watchedvar parameters, because the update was not yet done */
1500static
1502 SCIP* scip, /**< SCIP data structure */
1503 SCIP_CONS* cons, /**< AND-constraint to be processed */
1504 int watchedvar1, /**< maybe last unfixed variable position */
1505 int watchedvar2, /**< second watched position */
1506 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1507 int* nfixedvars /**< pointer to add up the number of found domain reductions */
1508 )
1509{
1510 SCIP_CONSDATA* consdata;
1511
1512 consdata = SCIPconsGetData(cons);
1513 assert(consdata != NULL);
1514 assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
1515
1516 if( watchedvar2 == -1 )
1517 {
1518 SCIP_Bool infeasible;
1519 SCIP_Bool tightened;
1520
1521 assert(watchedvar1 != -1);
1522
1523#ifndef NDEBUG
1524 /* check that all variables regardless of wathcedvar1 are fixed to 1 */
1525 {
1526 int v;
1527
1528 for( v = consdata->nvars - 1; v >= 0; --v )
1529 if( v != watchedvar1 )
1530 assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
1531 }
1532#endif
1533
1534 SCIPdebugMsg(scip, "constraint <%s>: resultant <%s> fixed to 0.0, only one unfixed operand -> fix operand <%s> to 0.0\n",
1535 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar), SCIPvarGetName(consdata->vars[watchedvar1]));
1536
1537 SCIP_CALL( SCIPinferBinvarCons(scip, consdata->vars[watchedvar1], FALSE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
1538
1539 if( infeasible )
1540 {
1541 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1544 *cutoff = TRUE;
1545 }
1546 else
1547 {
1549 if( tightened )
1550 {
1552 (*nfixedvars)++;
1553 }
1554 }
1555 }
1556
1557 return SCIP_OKAY;
1558}
1559
1560/** replaces multiple occurrences of variables */
1561static
1563 SCIP* scip, /**< SCIP data structure */
1564 SCIP_CONS* cons, /**< AND-constraint */
1565 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1566 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
1567 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
1568 int* nfixedvars, /**< pointer to store number of fixed variables */
1569 int* nchgcoefs, /**< pointer to store number of changed coefficients */
1570 int* ndelconss /**< pointer to store number of deleted constraints */
1571 )
1572{
1573 SCIP_CONSDATA* consdata;
1574 SCIP_VAR** vars;
1575 SCIP_VAR* var;
1576 SCIP_VAR* probvar;
1577 int probidx;
1578 int nvars;
1579 int v;
1580#ifndef NDEBUG
1581 int nbinvars;
1582 int nintvars;
1583 int nimplvars;
1584#endif
1585
1586 assert(scip != NULL);
1587 assert(cons != NULL);
1588 assert(eventhdlr != NULL);
1589 assert(*entries != NULL);
1590 assert(nentries != NULL);
1591 assert(nfixedvars != NULL);
1592 assert(nchgcoefs != NULL);
1593 assert(ndelconss != NULL);
1594
1595 consdata = SCIPconsGetData(cons);
1596 assert(consdata != NULL);
1597
1598 if( consdata->merged )
1599 return SCIP_OKAY;
1600
1601 /* nothing to merge */
1602 if( consdata->nvars <= 1 )
1603 {
1604 consdata->merged = TRUE;
1605 return SCIP_OKAY;
1606 }
1607
1608 vars = consdata->vars;
1609 nvars = consdata->nvars;
1610
1611 assert(vars != NULL);
1612 assert(nvars >= 2);
1613
1614#ifndef NDEBUG
1615 nbinvars = SCIPgetNBinVars(scip);
1616 nintvars = SCIPgetNIntVars(scip);
1617 nimplvars = SCIPgetNImplVars(scip);
1618 assert(*nentries >= nbinvars + nintvars + nimplvars);
1619#endif
1620
1621 /* initialize entries array */
1622 for( v = nvars - 1; v >= 0; --v )
1623 {
1624 var = vars[v];
1625 assert(var != NULL);
1627
1629 assert(probvar != NULL);
1630
1631 probidx = SCIPvarGetProbindex(probvar);
1632 assert(0 <= probidx);
1633
1634 /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
1635 assert((probidx < nbinvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(probvar))
1636 || (SCIPvarIsBinary(probvar) &&
1637 ((probidx >= nbinvars && probidx < nbinvars + nintvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_INTEGER
1638 && !SCIPvarIsImpliedIntegral(probvar)) ||
1639 (probidx >= nbinvars + nintvars && probidx < nbinvars + nintvars + nimplvars &&
1640 SCIPvarIsImpliedIntegral(probvar)))));
1641
1642 /* var is not active yet */
1643 (*entries)[probidx] = 0;
1644 }
1645
1646 /* search for multiple variables; scan from back to front because deletion doesn't affect the order of the front
1647 * variables
1648 * @note don't reorder variables because we would loose the watched variables and filter position inforamtion
1649 */
1650 for( v = nvars - 1; v >= 0; --v )
1651 {
1652 var = vars[v];
1653 assert(var != NULL);
1655
1657 assert(probvar != NULL);
1658
1659 probidx = SCIPvarGetProbindex(probvar);
1660 assert(0 <= probidx && probidx < *nentries);
1661
1662 /* if var occurs first time in constraint init entries array */
1663 if( (*entries)[probidx] == 0 )
1664 {
1665 (*entries)[probidx] = (SCIPvarIsActive(var) ? 1 : 2);
1666 }
1667 /* if var occurs second time in constraint, first time it was not negated */
1668 else if( ((*entries)[probidx] == 1 && SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && !SCIPvarIsActive(var)) )
1669 {
1670 /* delete the multiple variable */
1671 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1672 ++(*nchgcoefs);
1673 }
1674 else
1675 {
1676 SCIP_Bool infeasible;
1677 SCIP_Bool fixed;
1678
1679 assert(((*entries)[probidx] == 1 && !SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && SCIPvarIsActive(var)));
1680
1681 SCIPdebugMsg(scip, "AND-constraint <%s> is redundant: variable <%s> and its negation are present -> fix resultant <%s> = 0\n",
1682 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(consdata->resvar));
1683
1684 /* negation of the variable is already present in the constraint: fix resultant to zero */
1685#ifndef NDEBUG
1686 {
1687 int i;
1688 for( i = consdata->nvars - 1; i > v && var != SCIPvarGetNegatedVar(vars[i]); --i )
1689 {}
1690 assert(i > v);
1691 }
1692#endif
1693
1694 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
1695 assert(!infeasible);
1696 if( fixed )
1697 ++(*nfixedvars);
1698
1699 SCIP_CALL( SCIPdelCons(scip, cons) );
1700 break;
1701 }
1702 }
1703
1704 consdata->merged = TRUE;
1705
1706 return SCIP_OKAY;
1707}
1708
1709/** propagates constraint with the following rules:
1710 * (1) v_i = FALSE => r = FALSE
1711 * (2) r = TRUE => v_i = TRUE for all i
1712 * (3) v_i = TRUE for all i => r = TRUE
1713 * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
1714 *
1715 * additional if the resultant is fixed to zero during presolving or in the root node (globally), then the
1716 * AND-constraint is collapsed to a linear (logicor) constraint of the form
1717 * -> sum_{i=0}^{n-1} ~v_i >= 1
1718 */
1719static
1721 SCIP* scip, /**< SCIP data structure */
1722 SCIP_CONS* cons, /**< AND-constraint to be processed */
1723 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1724 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1725 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
1726 int* nupgdconss /**< pointer to add up the number of upgraded constraints */
1727 )
1728{
1729 SCIP_CONSDATA* consdata;
1730 SCIP_VAR* resvar;
1731 SCIP_VAR** vars;
1732 int nvars;
1733 int watchedvar1;
1734 int watchedvar2;
1735 int i;
1736 SCIP_Bool infeasible;
1737 SCIP_Bool tightened;
1738
1739 assert(cutoff != NULL);
1740 assert(nfixedvars != NULL);
1741
1742 consdata = SCIPconsGetData(cons);
1743 assert(consdata != NULL);
1744
1745 resvar = consdata->resvar;
1746 vars = consdata->vars;
1747 nvars = consdata->nvars;
1748
1749 /* don't process the constraint, if none of the operator variables was fixed to FALSE, and if the watched variables
1750 * and the resultant weren't fixed to any value since last propagation call
1751 */
1752 if( consdata->propagated )
1753 {
1754 assert(consdata->nofixedzero);
1755 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(resvar), 0.0));
1756 return SCIP_OKAY;
1757 }
1758
1759 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1761 {
1762 SCIP_CALL( SCIPincConsAge(scip, cons) );
1763 }
1764
1765 /* if one of the operator variables was fixed to FALSE, the resultant can be fixed to FALSE (rule (1)) */
1766 if( !consdata->nofixedzero )
1767 {
1768 for( i = 0; i < nvars && SCIPvarGetUbLocal(vars[i]) > 0.5; ++i ) /* search for operator fixed to zero */
1769 {}
1770 if( i < nvars )
1771 {
1772 /* fix resultant to zero */
1773 SCIP_CALL( consdataFixResultantZero(scip, cons, resvar, i, cutoff, nfixedvars) );
1774 }
1775 else
1776 consdata->nofixedzero = TRUE;
1777 }
1778
1779 /* check if resultant variables is globally fixed to zero */
1780 if( !SCIPinProbing(scip) && SCIPconsGetNUpgradeLocks(cons) == 0 && SCIPvarGetUbGlobal(resvar) < 0.5 )
1781 {
1782 SCIP_CALL( consdataLinearize(scip, cons, cutoff, nfixedvars, nupgdconss) );
1783
1784 if( *cutoff && SCIPgetDepth(scip) > 0 )
1785 {
1786 /* we are done with solving since a global bound change was infeasible */
1788 }
1789
1790 return SCIP_OKAY;
1791 }
1792
1793 /* if the resultant and at least one operand are locally fixed to zero, the constraint is locally redundant */
1794 if( SCIPvarGetUbLocal(resvar) < 0.5 && !consdata->nofixedzero )
1795 {
1797 return SCIP_OKAY;
1798 }
1799
1800 /* if resultant is fixed to TRUE, all operator variables can be fixed to TRUE (rule (2)) */
1801 if( SCIPvarGetLbLocal(resvar) > 0.5 )
1802 {
1803 /* fix operands to one */
1804 SCIP_CALL( consdataFixOperandsOne(scip, cons, vars, nvars, cutoff, nfixedvars) );
1805
1806 return SCIP_OKAY;
1807 }
1808
1809 /* rules (3) and (4) can only be applied, if we know all operator variables */
1810 if( SCIPconsIsModifiable(cons) )
1811 return SCIP_OKAY;
1812
1813 /* rules (3) and (4) cannot be applied, if we have at least two unfixed variables left;
1814 * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
1815 * if these ones get fixed
1816 */
1817 watchedvar1 = consdata->watchedvar1;
1818 watchedvar2 = consdata->watchedvar2;
1819
1820 /* check, if watched variables are still unfixed */
1821 if( watchedvar1 != -1 )
1822 {
1823 assert(SCIPvarGetUbLocal(vars[watchedvar1]) > 0.5); /* otherwise, rule (1) could be applied */
1824 if( SCIPvarGetLbLocal(vars[watchedvar1]) > 0.5 )
1825 watchedvar1 = -1;
1826 }
1827 if( watchedvar2 != -1 )
1828 {
1829 assert(SCIPvarGetUbLocal(vars[watchedvar2]) > 0.5); /* otherwise, rule (1) could be applied */
1830 if( SCIPvarGetLbLocal(vars[watchedvar2]) > 0.5 )
1831 watchedvar2 = -1;
1832 }
1833
1834 /* if only one watched variable is still unfixed, make it the first one */
1835 if( watchedvar1 == -1 )
1836 {
1837 watchedvar1 = watchedvar2;
1838 watchedvar2 = -1;
1839 }
1840 assert(watchedvar1 != -1 || watchedvar2 == -1);
1841
1842 /* if the watched variables are invalid (fixed), find new ones if existing */
1843 if( watchedvar2 == -1 )
1844 {
1845 for( i = 0; i < nvars; ++i )
1846 {
1847 assert(SCIPvarGetUbLocal(vars[i]) > 0.5); /* otherwise, rule (1) could be applied */
1848 if( SCIPvarGetLbLocal(vars[i]) < 0.5 )
1849 {
1850 if( watchedvar1 == -1 )
1851 {
1852 assert(watchedvar2 == -1);
1853 watchedvar1 = i;
1854 }
1855 else if( watchedvar1 != i )
1856 {
1857 watchedvar2 = i;
1858 break;
1859 }
1860 }
1861 }
1862 }
1863 assert(watchedvar1 != -1 || watchedvar2 == -1);
1864
1865 /* if all variables are fixed to TRUE, the resultant can also be fixed to TRUE (rule (3)) */
1866 if( watchedvar1 == -1 )
1867 {
1868 assert(watchedvar2 == -1);
1869
1870 SCIPdebugMsg(scip, "constraint <%s>: all operator vars fixed to 1.0 -> fix resultant <%s> to 1.0\n",
1871 SCIPconsGetName(cons), SCIPvarGetName(resvar));
1872 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
1873
1874 if( infeasible )
1875 {
1876 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1879 *cutoff = TRUE;
1880 }
1881 else
1882 {
1884 if( tightened )
1885 {
1887 (*nfixedvars)++;
1888 }
1889 }
1890
1891 return SCIP_OKAY;
1892 }
1893
1894 /* if resultant is fixed to FALSE, and only one operator variable is not fixed to TRUE, this operator variable
1895 * can be fixed to FALSE (rule (4))
1896 */
1897 if( watchedvar2 == -1 && SCIPvarGetUbLocal(resvar) < 0.5 )
1898 {
1899 assert(watchedvar1 != -1);
1900
1901 SCIP_CALL( analyzeZeroResultant(scip, cons, watchedvar1, watchedvar2, cutoff, nfixedvars) );
1902
1903 return SCIP_OKAY;
1904 }
1905
1906 /* switch to the new watched variables */
1907 SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
1908
1909 /* mark the constraint propagated if we have an unfixed resultant or are not in probing, it is necessary that a fixed
1910 * resulting in probing mode does not lead to a propagated constraint, because the constraint upgrade needs to be performed
1911 */
1912 consdata->propagated = (!SCIPinProbing(scip) || (SCIPvarGetLbLocal(consdata->resvar) < 0.5 && SCIPvarGetUbLocal(consdata->resvar) > 0.5));
1913
1914 return SCIP_OKAY;
1915}
1916
1917/** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
1918 * propagation rule (see propagateCons()):
1919 * (1) v_i = FALSE => r = FALSE
1920 * (2) r = TRUE => v_i = TRUE for all i
1921 * (3) v_i = TRUE for all i => r = TRUE
1922 * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
1923 */
1924static
1926 SCIP* scip, /**< SCIP data structure */
1927 SCIP_CONS* cons, /**< constraint that inferred the bound change */
1928 SCIP_VAR* infervar, /**< variable that was deduced */
1929 PROPRULE proprule, /**< propagation rule that deduced the value */
1930 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1931 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1932 )
1933{
1934 SCIP_CONSDATA* consdata;
1935 SCIP_VAR** vars;
1936 int nvars;
1937 int i;
1938
1939 assert(result != NULL);
1940
1941 consdata = SCIPconsGetData(cons);
1942 assert(consdata != NULL);
1943 vars = consdata->vars;
1944 nvars = consdata->nvars;
1945
1946 switch( proprule )
1947 {
1948 case PROPRULE_1:
1949 /* the resultant was inferred to FALSE, because one operand variable was FALSE */
1950 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1951 assert(infervar == consdata->resvar);
1952 for( i = 0; i < nvars; ++i )
1953 {
1954 if( SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5 )
1955 {
1957 break;
1958 }
1959 }
1960 assert(i < nvars);
1962 break;
1963
1964 case PROPRULE_2:
1965 /* the operand variable was inferred to TRUE, because the resultant was TRUE */
1966 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1967 assert(SCIPgetVarLbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) > 0.5);
1968 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1970 break;
1971
1972 case PROPRULE_3:
1973 /* the resultant was inferred to TRUE, because all operand variables were TRUE */
1974 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1975 assert(infervar == consdata->resvar);
1976 for( i = 0; i < nvars; ++i )
1977 {
1978 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5);
1980 }
1982 break;
1983
1984 case PROPRULE_4:
1985 /* the operand variable was inferred to FALSE, because the resultant was FALSE and all other operands were TRUE */
1986 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1987 assert(SCIPgetVarUbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) < 0.5);
1988 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1989 for( i = 0; i < nvars; ++i )
1990 {
1991 if( vars[i] != infervar )
1992 {
1993 assert(SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5);
1995 }
1996 }
1998 break;
1999
2000 case PROPRULE_INVALID:
2001 default:
2002 SCIPerrorMessage("invalid inference information %d in AND-constraint <%s>\n", proprule, SCIPconsGetName(cons));
2003 return SCIP_INVALIDDATA;
2004 }
2005
2006 return SCIP_OKAY;
2007}
2008
2009/** perform dual presolving on AND-constraints */
2010static
2012 SCIP* scip, /**< SCIP data structure */
2013 SCIP_CONS** conss, /**< AND-constraints to perform dual presolving on */
2014 int nconss, /**< number of AND-constraints */
2015 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2016 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
2017 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
2018 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2019 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
2020 int* naggrvars, /**< pointer to add up the number of aggregated variables */
2021 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
2022 int* ndelconss, /**< pointer to add up the number of deleted constraints */
2023 int* nupgdconss, /**< pointer to add up the number of upgraded constraints */
2024 int* naddconss /**< pointer to add up the number of added constraints */
2025 )
2026{
2027 SCIP_CONS* cons;
2028 SCIP_CONSDATA* consdata;
2029 SCIP_VAR** impoperands;
2030 SCIP_VAR** vars;
2031 SCIP_VAR* resvar;
2032 SCIP_VAR* var;
2033 int nimpoperands;
2034 int nvars;
2035 int size;
2036 int v;
2037 int c;
2038 SCIP_Bool infeasible;
2039 SCIP_Bool fixed;
2040
2041 assert(scip != NULL);
2042 assert(conss != NULL || nconss == 0);
2043 assert(eventhdlr != NULL);
2044 assert(*entries != NULL);
2045 assert(nentries != NULL);
2046 assert(cutoff != NULL);
2047 assert(nfixedvars != NULL);
2048 assert(naggrvars != NULL);
2049 assert(nchgcoefs != NULL);
2050 assert(ndelconss != NULL);
2051 assert(nupgdconss != NULL);
2052 assert(naddconss != NULL);
2053
2054 if( nconss == 0 )
2055 return SCIP_OKAY;
2056
2057 assert(conss != NULL);
2058
2059 size = 2 * (SCIPgetNBinVars(scip) + SCIPgetNImplVars(scip));
2060
2061 SCIP_CALL( SCIPallocBufferArray(scip, &impoperands, size) );
2062
2063 for( c = nconss - 1; c >= 0 && !(*cutoff); --c )
2064 {
2065 cons = conss[c];
2066 assert(cons != NULL);
2067
2068 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsModifiable(cons) )
2069 continue;
2070
2071 /* propagate constraint */
2072 SCIP_CALL( propagateCons(scip, cons, eventhdlr, cutoff, nfixedvars, nupgdconss) );
2073
2074 if( !SCIPconsIsActive(cons) )
2075 continue;
2076
2077 if( *cutoff )
2078 break;
2079
2080 SCIP_CALL( applyFixings(scip, cons, eventhdlr, nchgcoefs) );
2081
2082 /* merge multiple occurances of variables or variables with their negated variables */
2083 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, nfixedvars, nchgcoefs, ndelconss) );
2084
2085 if( !SCIPconsIsActive(cons) )
2086 continue;
2087
2088 consdata = SCIPconsGetData(cons);
2089 assert(consdata != NULL);
2090
2091 vars = consdata->vars;
2092 nvars = consdata->nvars;
2093 assert(vars != NULL || nvars == 0);
2094
2095 if( nvars == 0 )
2096 continue;
2097
2098 assert(vars != NULL);
2099
2100 resvar = consdata->resvar;
2101 assert(SCIPvarGetLbGlobal(resvar) < 0.5);
2102
2103 /* dual presolving does not apply to a fixed resultant */
2104 if( SCIPvarGetUbGlobal(resvar) < 0.5 )
2105 continue;
2106
2109
2112 {
2113 SCIP_Real resobj;
2114 SCIP_Real obj;
2115 SCIP_Real posobjsum = 0;
2116 SCIP_Real maxobj = -SCIPinfinity(scip);
2117 int maxpos = -1;
2118 int oldnfixedvars = *nfixedvars;
2119 int oldnaggrvars = *naggrvars;
2120
2121 nimpoperands = 0;
2122
2123 /* collect important operands */
2124 for( v = nvars - 1; v >= 0; --v )
2125 {
2126 var = vars[v];
2127 assert(var != NULL);
2130
2133 {
2134 impoperands[nimpoperands] = var;
2135 ++nimpoperands;
2136
2137 /* get aggregated objective value of active variable */
2139
2140 /* add up all positive objective values of operands which have exactly one lock in both directions */
2141 if( obj > 0 )
2142 posobjsum += obj;
2143
2144 /* memorize maximal objective value of operands and its position */
2145 if( obj > maxobj )
2146 {
2147 maxpos = nimpoperands - 1;
2148 maxobj = obj;
2149 }
2150 }
2151 }
2152 assert(nimpoperands >= 0 && nimpoperands <= nvars);
2153
2154 /* no dual fixable variables found */
2155 if( nimpoperands == 0 )
2156 continue;
2157
2158 /* get aggregated objective value of active variable */
2159 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
2160
2161 /* resultant contributes to the objective with a negative value */
2162 if( SCIPisLE(scip, resobj, 0.0) )
2163 {
2164 SCIP_Bool poscontissmall = SCIPisLE(scip, posobjsum, REALABS(resobj));
2165
2166 /* if all variables are only locked by this constraint and the resultants contribution more then compensates
2167 * the positive contribution, we can fix all variables to 1
2168 */
2169 if( nimpoperands == nvars && poscontissmall )
2170 {
2171 SCIPdebugMsg(scip, "dual-fixing all variables in constraint <%s> to 1\n", SCIPconsGetName(cons));
2172
2173 SCIP_CALL( SCIPfixVar(scip, resvar, 1.0, &infeasible, &fixed) );
2174
2175 *cutoff = *cutoff || infeasible;
2176 if( fixed )
2177 ++(*nfixedvars);
2178
2179 for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
2180 {
2181 SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
2182
2183 *cutoff = *cutoff || infeasible;
2184 if( fixed )
2185 ++(*nfixedvars);
2186 }
2187
2188 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are fixed to one\n", SCIPconsGetName(cons));
2189
2190 SCIP_CALL( SCIPdelCons(scip, cons) );
2191 ++(*ndelconss);
2192 }
2193 else
2194 {
2195 SCIP_Bool aggregationperformed = FALSE;
2196 SCIP_Bool zerofix = FALSE;
2197
2198 assert(nimpoperands > 0);
2199
2200 SCIPdebugMsg(scip, "dual-fixing all variables in constraint <%s> with positive contribution (when together exceeding the negative contribution of the resultant) to 0 and with negative contribution to 1\n", SCIPconsGetName(cons));
2201
2202 for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
2203 {
2204 /* get aggregated objective value of active variable */
2205 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
2206
2207 if( SCIPisLE(scip, obj, 0.0) )
2208 {
2209 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
2210
2211 *cutoff = *cutoff || infeasible;
2212 if( fixed )
2213 ++(*nfixedvars);
2214 }
2215 else if( !poscontissmall )
2216 {
2217 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
2218 assert(!infeasible);
2219 assert(fixed);
2220
2221 ++(*nfixedvars);
2222 zerofix = TRUE;
2223 }
2224 else
2225 {
2226 SCIP_Bool redundant;
2227 SCIP_Bool aggregated;
2228
2229 /* aggregate resultant to operand */
2230 SCIP_CALL( SCIPaggregateVars(scip, resvar, impoperands[v], 1.0, -1.0, 0.0,
2231 &infeasible, &redundant, &aggregated) );
2232 assert(!infeasible);
2233
2234 if( aggregated )
2235 {
2236 /* note that we cannot remove the aggregated operand because we do not know the position */
2237 ++(*naggrvars);
2238
2239 aggregationperformed = TRUE;
2240
2241 SCIPdebugMsg(scip, "dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(impoperands[v]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2242 }
2243 }
2244 }
2245 assert(*nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars <= nimpoperands);
2246
2247 /* did we aggregate the resultant, then we can decide the value to fix it on the (aggregated) objective
2248 * value since it was a independant variable
2249 */
2250 if( aggregationperformed || zerofix )
2251 {
2252 SCIP_Real fixval;
2253
2254 if( zerofix )
2255 fixval = 0.0;
2256 else
2257 {
2258 /* get aggregated objective value of active variable, that might be changed */
2261
2262 fixval = (SCIPisNegative(scip, obj) ? 1.0 : 0.0);
2263 }
2264
2265 if( fixval < 0.5 || *nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars == nvars )
2266 {
2267 SCIPdebugMsg(scip, "constraint <%s> we can fix the resultant <%s> to %g, because the AND-constraint will alwys be fulfilled\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), fixval);
2268
2269 SCIP_CALL( SCIPfixVar(scip, resvar, fixval, &infeasible, &fixed) );
2270 assert(!infeasible);
2271 assert(fixed);
2272
2273 ++(*nfixedvars);
2274
2275 SCIPdebugMsg(scip, "deleting constraint <%s> because \n", SCIPconsGetName(cons));
2276
2277 SCIP_CALL( SCIPdelCons(scip, cons) );
2278 ++(*ndelconss);
2279 }
2280 }
2281 }
2282 }
2283 /* resultant contributes to the objective with a positive value */
2284 else
2285 {
2286 SCIP_Bool zerofix = FALSE;
2287#ifndef NDEBUG
2288 SCIP_Real tmpobj;
2289
2290 assert(nimpoperands > 0);
2291 assert(maxpos >= 0 && maxpos <= consdata->nvars);
2292 assert(!SCIPisInfinity(scip, -maxobj));
2293 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[maxpos], &tmpobj) );
2294 assert(SCIPisEQ(scip, tmpobj, maxobj));
2295#endif
2296
2297 /* if the smallest possible contribution is negative, but does not compensate the positive contribution of
2298 * the resultant we need to fix this variable to 0
2299 */
2300 if( nimpoperands == nvars && SCIPisLE(scip, maxobj, 0.0) )
2301 {
2302 SCIP_Real fixval = (SCIPisLE(scip, REALABS(maxobj), resobj) ? 0.0 : 1.0);
2303
2304 SCIPdebugMsg(scip, "dual-fixing variable <%s> in constraint <%s> to %g, because the contribution is%s " \
2305 "enough to nullify/exceed the contribution of the resultant \n",
2306 SCIPvarGetName(impoperands[maxpos]), SCIPconsGetName(cons), fixval, (fixval < 0.5) ? " not" : "");
2307
2308 SCIP_CALL( SCIPfixVar(scip, impoperands[maxpos], fixval, &infeasible, &fixed) );
2309 zerofix = (fixval < 0.5);
2310
2311 *cutoff = *cutoff || infeasible;
2312 if( fixed )
2313 ++(*nfixedvars);
2314 }
2315
2316 SCIPdebugMsg(scip, "dual-fixing all variables, except the variable with the highest contribution to " \
2317 "the objective, in constraint <%s> with positive contribution to 0 and with negative contribution to 1\n",
2318 SCIPconsGetName(cons));
2319
2320 for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
2321 {
2322 /* get aggregated objective value of active variable */
2323 SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
2324
2325 if( SCIPisLE(scip, obj, 0.0) )
2326 {
2327 if( v == maxpos )
2328 continue;
2329
2330 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
2331 }
2332 else
2333 {
2334 SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
2335 zerofix = TRUE;
2336 }
2337
2338 *cutoff = *cutoff || infeasible;
2339 if( fixed )
2340 ++(*nfixedvars);
2341 }
2342 assert(*nfixedvars - oldnfixedvars <= nimpoperands);
2343 /* iff we have fixed all variables, all variables needed to be stored in the impoperands array */
2344 assert((*nfixedvars - oldnfixedvars == nvars) == (nimpoperands == nvars));
2345
2346 if( *nfixedvars - oldnfixedvars == nvars )
2347 {
2348 SCIPdebugMsg(scip, "all operands are fixed in constraint <%s> => fix resultant <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), (zerofix ? 0.0 : 1.0));
2349
2350 SCIP_CALL( SCIPfixVar(scip, resvar, zerofix ? 0.0 : 1.0, &infeasible, &fixed) );
2351
2352 *cutoff = *cutoff || infeasible;
2353 if( fixed )
2354 ++(*nfixedvars);
2355
2356 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are fixed\n", SCIPconsGetName(cons));
2357
2358 SCIP_CALL( SCIPdelCons(scip, cons) );
2359 ++(*ndelconss);
2360 }
2361 }
2362 }
2363 /* resultant is lock by another constraint (handler), check for operands with only one down- and uplock */
2364 else
2365 {
2366 SCIP_Real maxobj = -SCIPinfinity(scip);
2367 SCIP_Real resobj;
2368 SCIP_Real obj;
2369 SCIP_Bool redundant;
2370 SCIP_Bool aggregated;
2371 SCIP_Bool resobjispos;
2372 SCIP_Bool linearize = FALSE;
2373 SCIP_Bool zerofix = FALSE;
2374#ifndef NDEBUG
2375 int oldnchgcoefs = *nchgcoefs;
2376 int oldnfixedvars = *nfixedvars;
2377#endif
2378
2379 /* get aggregated objective value of active variable */
2380 SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
2381
2382 resobjispos = SCIPisGT(scip, resobj, 0.0);
2383
2384 /* we can only aggregate when the objective contribution of the resultant is less or equal to 0 */
2385 if( !resobjispos )
2386 {
2387 SCIP_Bool goodvarsfound = FALSE;
2388
2389 for( v = nvars - 1; v >= 0; --v )
2390 {
2391 var = vars[v];
2392 assert(var != NULL);
2395
2396 /* get aggregated objective value of active variable */
2398
2399 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
2400 * to 0 can be aggregated to the resultant
2401 */
2404 {
2405 if( !SCIPisNegative(scip, obj) )
2406 {
2407 /* aggregate resultant to operand */
2408 SCIP_CALL( SCIPaggregateVars(scip, resvar, var, 1.0, -1.0, 0.0, &infeasible, &redundant,
2409 &aggregated) );
2410
2411 if( aggregated && SCIPconsGetNUpgradeLocks(cons) == 0 )
2412 {
2413 ++(*naggrvars);
2414
2415 linearize = TRUE;
2416
2417 /* delete redundant entry from constraint */
2418 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
2419 ++(*nchgcoefs);
2420
2422 "dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n",
2424 }
2425
2426 *cutoff = *cutoff || infeasible;
2427 }
2428 else
2429 goodvarsfound = TRUE;
2430 }
2431 }
2432 assert(*nchgcoefs - oldnchgcoefs <= nvars);
2433
2434 /* if we aggregated an operands with the resultant we can also fix "good" independant operands to 1, since
2435 * the correctness of "resultant = 0 => at least one operand = 0" in enforced by that aggregation
2436 * without an aggregation we cannot fix these variables since it might lead to infeasibility, e.g.
2437 *
2438 * obj(x3) = -1
2439 * r = x1 * x2 * x3
2440 * r = 0
2441 * x1 = 1
2442 * x2 = 1
2443 */
2444 if( !*cutoff && goodvarsfound && linearize )
2445 {
2446 /* fix good variables to 1 */
2447 for( v = consdata->nvars - 1; v >= 0; --v )
2448 {
2449 var = vars[v];
2450 assert(var != NULL);
2451
2454 {
2455#ifndef NDEBUG
2456 /* aggregated objective value of active variable need to be negative */
2459#endif
2461 "dual-fixing variable <%s> in constraint <%s> to 1, because the contribution is negative\n",
2463
2464 SCIP_CALL( SCIPfixVar(scip, var, 1.0, &infeasible, &fixed) );
2465
2466 assert(!infeasible);
2467 if( fixed )
2468 ++(*nfixedvars);
2469 }
2470 }
2471 assert(*nfixedvars - oldnfixedvars <= consdata->nvars);
2472 }
2473 assert(*nchgcoefs - oldnchgcoefs + *nfixedvars - oldnfixedvars <= nvars);
2474 }
2475 /* if the downlocks of the resultant are only from this constraint and the objective contribution is positive,
2476 * we can try to fix operands
2477 */
2478 else if( SCIPvarGetNLocksDownType(resvar, SCIP_LOCKTYPE_MODEL) == 1 )
2479 {
2480 SCIP_Bool locksareone = TRUE;
2481 int maxpos = -1;
2482
2483 for( v = nvars - 1; v >= 0; --v )
2484 {
2485 var = vars[v];
2486 assert(var != NULL);
2489
2490 /* check if all resultants are only locked by this constraint */
2491 locksareone = locksareone && (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
2493
2494 /* get aggregated objective value of active variable */
2496
2497 /* memorize maximal objective value of operands and its position */
2498 if( obj > maxobj )
2499 {
2500 maxpos = v;
2501 maxobj = obj;
2502 }
2503
2504 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
2505 * to 0, and the absolute value of the contribution of the resultant exceeds can be eliminated and
2506 * aggregated to the resultant
2507 */
2510 {
2511 SCIPdebugMsg(scip, "dualfix operand <%s> in constraint <%s> to 0\n", SCIPvarGetName(var), SCIPconsGetName(cons));
2512
2513 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
2514
2515 *cutoff = *cutoff || infeasible;
2516 if( fixed )
2517 ++(*nfixedvars);
2518
2519 zerofix = TRUE;
2520 }
2521 }
2522 assert(*nchgcoefs - oldnchgcoefs <= nvars);
2523
2524 /* if constraint is still active and all operands are only lock by this constraint, we check if we can fix
2525 * the worst (in objective contribution) operand to zero
2526 */
2527 if( !zerofix && locksareone && SCIPisGE(scip, resobj, REALABS(maxobj)) )
2528 {
2529 assert(!zerofix);
2530 /* objective contribution needs to be negative, otherwise, the variable should already be fixed to 0 */
2531 assert(SCIPisLT(scip, maxobj, 0.0));
2532
2533 SCIPdebugMsg(scip, "dualfix operand <%s> with worst contribution in constraint <%s> to 0\n", SCIPvarGetName(vars[maxpos]), SCIPconsGetName(cons));
2534
2535 SCIP_CALL( SCIPfixVar(scip, vars[maxpos], 0.0, &infeasible, &fixed) );
2536
2537 *cutoff = *cutoff || infeasible;
2538 if( fixed )
2539 ++(*nfixedvars);
2540
2541 zerofix = TRUE;
2542 }
2543
2544 /* fix the resultant if one operand was fixed to zero and delete the constraint */
2545 if( zerofix )
2546 {
2547 SCIPdebugMsg(scip, "fix resultant <%s> in constraint <%s> to 0\n", SCIPvarGetName(resvar), SCIPconsGetName(cons));
2548
2549 SCIP_CALL( SCIPfixVar(scip, resvar, 0.0, &infeasible, &fixed) );
2550
2551 *cutoff = *cutoff || infeasible;
2552 if( fixed )
2553 ++(*nfixedvars);
2554
2555 SCIPdebugMsg(scip, "deleting constraint <%s> because at least one operand and the resultant is fixed to zero\n", SCIPconsGetName(cons));
2556
2557 SCIP_CALL( SCIPdelCons(scip, cons) );
2558 ++(*ndelconss);
2559 }
2560 }
2561
2562 /* we have to linearize the constraint, otherwise we might get wrong propagations, since due to aggregations a
2563 * resultant fixed to zero is already fulfilling the constraint, and we must not ensure that some remaining
2564 * operand needs to be 0
2565 */
2566 if( linearize )
2567 {
2568 SCIP_CONS* newcons;
2569 char consname[SCIP_MAXSTRLEN];
2570 SCIP_VAR* consvars[2];
2571 SCIP_Real vals[2];
2572
2573 assert(SCIPconsIsActive(cons));
2574 assert(SCIPconsGetNUpgradeLocks(cons) == 0);
2575
2576 consvars[0] = consdata->resvar;
2577 vals[0] = 1.0;
2578 vals[1] = -1.0;
2579
2580 /* create operator linear constraints */
2581 for( v = consdata->nvars - 1; v >= 0; --v )
2582 {
2583 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), v);
2584 consvars[1] = consdata->vars[v];
2585
2586 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, consvars, vals, -SCIPinfinity(scip), 0.0,
2590 SCIPconsIsStickingAtNode(cons)) );
2591
2592 /* add constraint */
2593 SCIP_CALL( SCIPaddCons(scip, newcons) );
2594 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
2595 }
2596 (*naddconss) += consdata->nvars;
2597
2598 SCIPdebugMsg(scip, "deleting constraint <%s> because it was linearized\n", SCIPconsGetName(cons));
2599
2600 SCIP_CALL( SCIPdelCons(scip, cons) );
2601 ++(*ndelconss);
2602 }
2603 /* if only one operand is leftover, aggregate it to the resultant */
2604 else if( consdata->nvars == 1 )
2605 {
2606 SCIPdebugMsg(scip, "aggregating last operand <%s> to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2607
2608 /* aggregate resultant to operand */
2609 SCIP_CALL( SCIPaggregateVars(scip, resvar, consdata->vars[0], 1.0, -1.0, 0.0,
2610 &infeasible, &redundant, &aggregated) );
2611
2612 if( aggregated )
2613 ++(*naggrvars);
2614
2615 *cutoff = *cutoff || infeasible;
2616
2617 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
2618
2619 SCIP_CALL( SCIPdelCons(scip, cons) );
2620 ++(*ndelconss);
2621 }
2622
2623 /* if no operand is leftover delete the constraint */
2624 if( SCIPconsIsActive(cons) && consdata->nvars == 0 )
2625 {
2626 SCIPdebugMsg(scip, "deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
2627
2628 SCIP_CALL( SCIPdelCons(scip, cons) );
2629 ++(*ndelconss);
2630 }
2631 }
2632 }
2633
2634 SCIPfreeBufferArray(scip, &impoperands);
2635
2636 return SCIP_OKAY;
2637}
2638
2639/** 1. check if at least two operands or one operand and the resultant are in one clique, if so, we can fix the
2640 * resultant to zero and in the former case we can also delete this constraint but we need to extract the clique
2641 * information as constraint
2642 *
2643 * x == AND(y, z) and clique(y,z) => x = 0, delete constraint and create y + z <= 1
2644 * x == AND(y, z) and clique(x,y) => x = 0
2645 *
2646 * special handled cases are:
2647 * - if the resultant is a negation of an operand, in that case we fix the resultant to 0
2648 * - if the resultant is equal to an operand, we will linearize this constraint by adding all necessary
2649 * set-packing constraints like resultant + ~operand <= 1 and delete the old constraint
2650 *
2651 * x == AND(~x, y) => x = 0
2652 * x == AND(x, y) => add x + ~y <= 1 and delete the constraint
2653 *
2654 * 2. check if one operand is in a clique with the negation of all other operands, this means we can aggregate this
2655 * operand to the resultant
2656 *
2657 * r == AND(x,y,z) and clique(x,~y) and clique(x,~z) => r == x
2658 *
2659 * 3. check if the resultant and the negations of all operands are in a clique
2660 *
2661 * r == AND(x,y) and clique(r, ~x,~y) => upgrade the constraint to a set-partitioning constraint r + ~x + ~y = 1
2662 *
2663 * @note We removed also fixed variables and propagate them, and if only one operand is remaining due to removal, we
2664 * will aggregate the resultant with this operand
2665 */
2666static
2668 SCIP* scip, /**< SCIP data structure */
2669 SCIP_CONS* cons, /**< constraint to process */
2670 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2671 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2672 int* nfixedvars, /**< pointer to add up the number of found domain reductions */
2673 int* naggrvars, /**< pointer to add up the number of aggregated variables */
2674 int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
2675 int* ndelconss, /**< pointer to add up the number of deleted constraints */
2676 int* naddconss /**< pointer to add up the number of added constraints */
2677 )
2678{
2679 SCIP_CONSDATA* consdata;
2680 SCIP_VAR** vars;
2681 SCIP_VAR* var1;
2682 SCIP_VAR* var2;
2683 int nvars;
2684 int vstart;
2685 int vend;
2686 int v;
2687 int v2;
2688 SCIP_Bool negated;
2689 SCIP_Bool value1;
2690 SCIP_Bool value2;
2691 SCIP_Bool infeasible;
2692 SCIP_Bool fixed;
2693 SCIP_Bool allnegoperandsexist;
2694
2695 assert(scip != NULL);
2696 assert(cons != NULL);
2697 assert(eventhdlr != NULL);
2698 assert(cutoff != NULL);
2699 assert(nfixedvars != NULL);
2700 assert(naggrvars != NULL);
2701 assert(nchgcoefs != NULL);
2702 assert(ndelconss != NULL);
2703 assert(naddconss != NULL);
2704
2705 consdata = SCIPconsGetData(cons);
2706 assert(consdata != NULL);
2707
2708 if( !SCIPconsIsActive(cons) || SCIPconsIsModifiable(cons) )
2709 return SCIP_OKAY;
2710
2711 vars = consdata->vars;
2712 nvars = consdata->nvars;
2713 assert(vars != NULL || nvars == 0);
2714
2715 /* remove fixed variables to be able to ask for cliques
2716 *
2717 * if an operand is fixed to 0 fix the resultant to 0 and delete the constraint
2718 * if an operand is fixed to 1 remove it from the constraint
2719 */
2720 for( v = nvars - 1; v >= 0; --v )
2721 {
2722 assert(vars != NULL);
2723
2724 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
2725 {
2726 SCIPdebugMsg(scip, "In constraint <%s> the operand <%s> is fixed to 1 so remove it from the constraint\n",
2728
2729 /* because we loop from back to front we can delete the entry in the consdata structure */
2730 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
2731 ++(*nchgcoefs);
2732
2733 assert(consdata->vars == vars);
2734
2735 continue;
2736 }
2737 else if( SCIPvarGetUbGlobal(vars[v]) < 0.5 )
2738 {
2739 SCIPdebugMsg(scip, "constraint <%s> redundant: because operand <%s> is fixed to zero so we can fix the resultant <%s> to 0\n",
2740 SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
2741
2742 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2743 *cutoff = *cutoff || infeasible;
2744 if( fixed )
2745 ++(*nfixedvars);
2746
2747 SCIP_CALL( SCIPdelCons(scip, cons) );
2748 ++(*ndelconss);
2749
2750 return SCIP_OKAY;
2751 }
2752 }
2753
2754 /* if we deleted some operands constraint might be redundant */
2755 if( consdata->nvars < nvars )
2756 {
2757 assert(vars == consdata->vars);
2758
2759 /* all operands fixed to one were removed, so if no operand is left this means we can fix the resultant to 1
2760 * too
2761 */
2762 if( consdata->nvars == 0 )
2763 {
2764 SCIPdebugMsg(scip, "All operand in constraint <%s> were deleted, so the resultant needs to be fixed to 1\n",
2765 SCIPconsGetName(cons));
2766
2767 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 1.0, &infeasible, &fixed) );
2768 *cutoff = *cutoff || infeasible;
2769 if( fixed )
2770 ++(*nfixedvars);
2771
2772 SCIP_CALL( SCIPdelCons(scip, cons) );
2773 ++(*ndelconss);
2774
2775 return SCIP_OKAY;
2776 }
2777 /* if only one not fixed operand is left, we can aggregate it to the resultant */
2778 else if( consdata->nvars == 1 )
2779 {
2780 SCIP_Bool redundant;
2781 SCIP_Bool aggregated;
2782
2783 /* aggregate resultant to last operand */
2784 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
2785 &infeasible, &redundant, &aggregated) );
2786
2787 if( aggregated )
2788 ++(*naggrvars);
2789
2790 SCIP_CALL( SCIPdelCons(scip, cons) );
2791 ++(*ndelconss);
2792
2793 *cutoff = *cutoff || infeasible;
2794
2795 return SCIP_OKAY;
2796 }
2797
2798 nvars = consdata->nvars;
2799 }
2800
2801 /* @todo when cliques are improved, we only need to collect all clique-ids for all variables and check for doubled
2802 * entries
2803 */
2804 /* case 1 first part */
2805 /* check if two operands are in a clique */
2806 if( SCIPconsGetNUpgradeLocks(cons) == 0 )
2807 {
2808 for( v = nvars - 1; v > 0; --v )
2809 {
2810 assert(vars != NULL);
2811
2812 var1 = vars[v];
2813 assert(var1 != NULL);
2814 negated = FALSE;
2815
2816 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
2817 assert(var1 != NULL);
2818
2819 if( negated )
2820 value1 = FALSE;
2821 else
2822 value1 = TRUE;
2823
2825
2826 for( v2 = v - 1; v2 >= 0; --v2 )
2827 {
2828 var2 = vars[v2];
2829 assert(var2 != NULL);
2830
2831 negated = FALSE;
2832 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
2833 assert(var2 != NULL);
2834
2835 if( negated )
2836 value2 = FALSE;
2837 else
2838 value2 = TRUE;
2839
2841
2842 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
2843 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better
2844 * continue
2845 */
2846 if( var1 == var2 )
2847 continue;
2848
2849 if( SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
2850 {
2851 SCIP_CONS* cliquecons;
2852 SCIP_VAR* consvars[2];
2853 char name[SCIP_MAXSTRLEN];
2854
2855 SCIPdebugMsg(scip, "constraint <%s> redundant: because variable <%s> and variable <%s> are in a clique, the resultant <%s> can be fixed to 0\n",
2856 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2), SCIPvarGetName(consdata->resvar));
2857
2858 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2859 *cutoff = *cutoff || infeasible;
2860 if( fixed )
2861 ++(*nfixedvars);
2862
2863 /* create clique constraint which lead to the last fixing */
2864 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%d", SCIPconsGetName(cons), v2);
2865
2866 if( value1 )
2867 consvars[0] = var1;
2868 else
2869 {
2870 SCIP_CALL( SCIPgetNegatedVar(scip, var1, &(consvars[0])) );
2871 }
2872
2873 if( value2 )
2874 consvars[1] = var2;
2875 else
2876 {
2877 SCIP_CALL( SCIPgetNegatedVar(scip, var2, &(consvars[1])) );
2878 }
2879
2880 SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
2884 SCIPconsIsStickingAtNode(cons)) );
2885 SCIPdebugMsg(scip, " -> adding clique constraint: ");
2886 SCIPdebugPrintCons(scip, cliquecons, NULL);
2887 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &cliquecons) );
2888 ++(*naddconss);
2889
2890 SCIP_CALL( SCIPdelCons(scip, cons) );
2891 ++(*ndelconss);
2892
2893 return SCIP_OKAY;
2894 }
2895 }
2896 }
2897 }
2898
2899 var1 = consdata->resvar;
2900 assert(var1 != NULL);
2901
2902 negated = FALSE;
2903 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
2904 assert(var1 != NULL);
2905
2906 /* it may appear that we have a fixed resultant */
2908 {
2909 /* resultant is fixed to 1, so fix all operands to 1 */
2910 if( SCIPvarGetLbGlobal(consdata->resvar) > 0.5 )
2911 {
2912 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> is fixed to 1 so fix all operands to 1\n",
2913 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
2914
2915 /* fix all operands to 1 */
2916 for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
2917 {
2918 assert(vars != NULL);
2919
2920 SCIPdebugMsg(scip, "Fixing operand <%s> to 1.\n", SCIPvarGetName(vars[v]));
2921
2922 SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
2923 *cutoff = *cutoff || infeasible;
2924
2925 if( fixed )
2926 ++(*nfixedvars);
2927 }
2928
2929 SCIP_CALL( SCIPdelCons(scip, cons) );
2930 ++(*ndelconss);
2931 }
2932 /* the upgrade to a linear constraint because of the to 0 fixed resultant we do in propagateCons() */
2933 else
2934 assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
2935
2936 return SCIP_OKAY;
2937 }
2938
2939 if( negated )
2940 value1 = FALSE;
2941 else
2942 value1 = TRUE;
2943
2944 /* case 1 second part */
2945 /* check if one operands is in a clique with the resultant */
2946 for( v = nvars - 1; v >= 0; --v )
2947 {
2948 assert(vars != NULL);
2949
2950 var2 = vars[v];
2951 assert(var2 != NULL);
2952
2953 negated = FALSE;
2954 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
2955 assert(var2 != NULL);
2956
2957 if( negated )
2958 value2 = FALSE;
2959 else
2960 value2 = TRUE;
2961
2962 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
2963 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better continue
2964 */
2965 if( var1 == var2 )
2966 {
2967 /* x1 == AND(~x1, x2 ...) => x1 = 0 */
2968 if( value1 != value2 )
2969 {
2970 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
2971 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
2972
2973 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2974 *cutoff = *cutoff || infeasible;
2975
2976 if( fixed )
2977 ++(*nfixedvars);
2978
2979 return SCIP_OKAY;
2980 }
2981 /* x1 == AND(x1, x2 ...) => delete constraint and create all set-packing constraints x1 + ~x2 <= 1, x1 + ~... <= 1 */
2982 else if( SCIPconsGetNUpgradeLocks(cons) == 0 )
2983 {
2984 SCIP_CONS* cliquecons;
2985 SCIP_VAR* consvars[2];
2986 char name[SCIP_MAXSTRLEN];
2987
2988 assert(value1 == value2);
2989
2990 consvars[0] = consdata->resvar;
2991
2992 for( v2 = nvars - 1; v2 >= 0; --v2 )
2993 {
2994 var2 = vars[v2];
2995 negated = FALSE;
2996 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
2997
2998 /* if the active representations of the resultant and an operand are different then we need to extract
2999 * this as a clique constraint
3000 *
3001 * if the active representations of the resultant and an operand are equal then the clique constraint
3002 * would look like x1 + ~x1 <= 1, which is redundant
3003 *
3004 * if the active representations of the resultant and an operand are negated of each other then the
3005 * clique constraint would look like x1 + x1 <= 1, which will lead to a fixation of the resultant later
3006 * on
3007 */
3008 if( var1 == var2 )
3009 {
3010 if( value1 == negated )
3011 {
3012 SCIPdebugMsg(scip, "In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
3013 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
3014
3015 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
3016 *cutoff = *cutoff || infeasible;
3017
3018 if( fixed )
3019 ++(*nfixedvars);
3020
3021 break;
3022 }
3023 }
3024 else
3025 {
3026 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v2], &consvars[1]) );
3027 assert(consvars[1] != NULL);
3028
3029 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%d", SCIPconsGetName(cons), v2);
3030
3031 SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
3035 SCIPconsIsStickingAtNode(cons)) );
3036 SCIPdebugMsg(scip, " -> adding clique constraint: ");
3037 SCIPdebugPrintCons(scip, cliquecons, NULL);
3038 SCIP_CALL( SCIPaddCons(scip, cliquecons) );
3039 SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
3040 ++(*naddconss);
3041 }
3042 }
3043
3044 /* delete old constraint */
3045 SCIP_CALL( SCIPdelCons(scip, cons) );
3046 ++(*ndelconss);
3047
3048 return SCIP_OKAY;
3049 }
3050 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to
3051 * handle it explicitly
3052 */
3053 else
3054 continue;
3055 }
3056
3057 /* fix resultant in operand clique */
3058 if( SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
3059 {
3060 SCIPdebugMsg(scip, "in constraint <%s> the resultant <%s> can be fixed to 0 because it is in a clique with operand <%s>\n",
3061 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
3062
3063 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
3064 *cutoff = *cutoff || infeasible;
3065 if( fixed )
3066 ++(*nfixedvars);
3067
3068 return SCIP_OKAY;
3069 }
3070 }
3071
3072 if( !SCIPconsIsActive(cons) )
3073 return SCIP_OKAY;
3074
3075 v2 = -1;
3076 /* check which operands have a negated variable */
3077 for( v = nvars - 1; v >= 0; --v )
3078 {
3079 assert(vars != NULL);
3080
3081 var1 = vars[v];
3082 assert(var1 != NULL);
3083
3084 negated = FALSE;
3085 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
3086 assert(var1 != NULL);
3087
3088 if( SCIPvarGetNegatedVar(var1) == NULL )
3089 {
3090 if( v2 >= 0 )
3091 break;
3092 v2 = v;
3093 }
3094 }
3095
3096 allnegoperandsexist = FALSE;
3097
3098 /* all operands have a negated variable, so we will check for all possible negated ciques */
3099 if( v2 == -1 )
3100 {
3101 allnegoperandsexist = TRUE;
3102 vstart = nvars - 1;
3103 vend = 0;
3104 }
3105 /* exactly one operands has no negated variable, so only this variable can be in a clique with all other negations */
3106 else if( v2 >= 0 && v == -1 )
3107 {
3108 vstart = v2;
3109 vend = v2;
3110 }
3111 /* at least two operands have no negated variable, so there is no possible clique with negated variables */
3112 else
3113 {
3114 vstart = -1;
3115 vend = 0;
3116 }
3117
3118 /* case 2 */
3119 /* check for negated cliques in the operands */
3120 for( v = vstart; v >= vend; --v )
3121 {
3122 assert(vars != NULL);
3123
3124 var1 = vars[v];
3125 assert(var1 != NULL);
3126
3127 negated = FALSE;
3128 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
3129 assert(var1 != NULL);
3130
3131 if( negated )
3132 value1 = FALSE;
3133 else
3134 value1 = TRUE;
3135
3136 for( v2 = nvars - 1; v2 >= 0; --v2 )
3137 {
3138 if( v2 == v )
3139 continue;
3140
3141 var2 = vars[v2];
3142 assert(var2 != NULL);
3143
3144 negated = FALSE;
3145 SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
3146 assert(var2 != NULL);
3147
3148 if( negated )
3149 value2 = FALSE;
3150 else
3151 value2 = TRUE;
3152
3154
3155 /* invert flag, because we want to check var 1 against all negations of the other variables */
3156 value2 = !value2;
3157
3158 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to handle
3159 * it explicitly
3160 */
3161 if( var1 == var2 && value1 == value2 )
3162 {
3163 SCIPdebugMsg(scip, "in constraint <%s> the resultant <%s> can be fixed to 0 because two operands are negated of each other\n",
3164 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
3165
3166 SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
3167 *cutoff = *cutoff || infeasible;
3168 if( fixed )
3169 ++(*nfixedvars);
3170
3171 return SCIP_OKAY;
3172 }
3173
3174 /* due to SCIPvarsHaveCommonClique() returns on two negated variables that they are not in a clique, we need to
3175 * handle it explicitly
3176 */
3177 if( var1 == var2 && value1 != value2 )
3178 continue;
3179
3180 if( !SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
3181 break;
3182 }
3183
3184 if( v2 == -1 )
3185 {
3186 SCIP_Bool redundant;
3187 SCIP_Bool aggregated;
3188
3189 SCIPdebugMsg(scip, "In constraint <%s> the operand <%s> is in a negated clique with all other operands, so we can aggregated this operand to the resultant <%s>.\n",
3190 SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
3191
3192 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, vars[v], 1.0, -1.0, 0.0,
3193 &infeasible, &redundant, &aggregated) );
3194 *cutoff = *cutoff || infeasible;
3195
3196 if( aggregated )
3197 ++(*naggrvars);
3198
3199 return SCIP_OKAY;
3200 }
3201 }
3202
3203 /* case 3 */
3204 /* check if the resultant and the negations of the operands are in a clique, then we can upgrade this constraint to a
3205 * set-partitioning constraint
3206 */
3207 if( allnegoperandsexist && SCIPconsIsActive(cons) && SCIPconsGetNUpgradeLocks(cons) == 0 )
3208 {
3209 SCIP_VAR** newvars;
3210 SCIP_Bool* negations;
3211 SCIP_Bool upgrade;
3212
3213 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars + 1) );
3214 SCIP_CALL( SCIPallocBufferArray(scip, &negations, nvars + 1) );
3215 BMSclearMemoryArray(negations, nvars + 1);
3216
3217 var1 = consdata->resvar;
3218 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[nvars]) );
3219 assert(var1 != NULL);
3221
3222 newvars[nvars] = var1;
3223
3224 /* get active variables */
3225 for( v = nvars - 1; v >= 0; --v )
3226 {
3227 assert(vars != NULL);
3228
3229 var1 = vars[v];
3230 SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[v]) );
3231 assert(var1 != NULL);
3233
3234 newvars[v] = var1;
3235
3236 /* there should be no variable left that is equal or negated to the resultant */
3237 assert(newvars[v] != newvars[nvars]);
3238 }
3239
3240 upgrade = TRUE;
3241
3242 /* the resultant is in a clique with the negations of all operands, due to this AND-constraint */
3243 /* only check if the negations of all operands are in a clique */
3244 for( v = nvars - 1; v >= 0 && upgrade; --v )
3245 {
3246 for( v2 = v - 1; v2 >= 0; --v2 )
3247 {
3248 /* the resultant need to be in a clique with the negations of all operands */
3249 if( !SCIPvarsHaveCommonClique(newvars[v], negations[v], newvars[v2], negations[v2], TRUE) )
3250 {
3251 upgrade = FALSE;
3252 break;
3253 }
3254 }
3255 }
3256
3257 /* all variables are in a clique, so upgrade thi AND-constraint */
3258 if( upgrade )
3259 {
3260 SCIP_CONS* cliquecons;
3261 char name[SCIP_MAXSTRLEN];
3262
3263 /* get new constraint variables */
3264 if( negations[nvars] )
3265 {
3266 /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
3267 * (e.g. resultant = ~x = 1 - x and x = y = newvars[nvars] and negations[nvars] = TRUE,
3268 * then y does not need to have a negated variable, yet)
3269 */
3270 SCIP_CALL( SCIPgetNegatedVar(scip, newvars[nvars], &(newvars[nvars])) );
3271 }
3272 assert(newvars[nvars] != NULL);
3273
3274 for( v = nvars - 1; v >= 0; --v )
3275 {
3276 if( !negations[v] )
3277 {
3278 /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
3279 * (e.g. vars[v] = ~x = 1 - x and x = y = newvars[v] and negations[v] = TRUE,
3280 * then y does not need to have a negated variable, yet)
3281 */
3282 SCIP_CALL( SCIPgetNegatedVar(scip, newvars[v], &(newvars[v])) );
3283 }
3284 assert(newvars[v] != NULL);
3285 }
3286
3287 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clqeq", SCIPconsGetName(cons));
3288
3289 SCIP_CALL( SCIPcreateConsSetpart(scip, &cliquecons, name, nvars + 1, newvars,
3293 SCIPconsIsStickingAtNode(cons)) );
3294 SCIPdebugMsg(scip, " -> upgrading AND-constraint <%s> with use of clique information to a set-partitioning constraint: \n", SCIPconsGetName(cons));
3295 SCIPdebugPrintCons(scip, cliquecons, NULL);
3296 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &cliquecons) );
3297 ++(*naddconss);
3298
3299 /* delete old constraint */
3300 SCIP_CALL( SCIPdelCons(scip, cons) );
3301 ++(*ndelconss);
3302 }
3303
3304 SCIPfreeBufferArray(scip, &negations);
3305 SCIPfreeBufferArray(scip, &newvars);
3306 }
3307
3308 return SCIP_OKAY;
3309}
3310
3311/** gets the key of the given element */
3312static
3313SCIP_DECL_HASHGETKEY(hashGetKeyAndcons)
3314{ /*lint --e{715}*/
3315 /* the key is the element itself */
3316 return elem;
3317}
3318
3319/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
3320static
3321SCIP_DECL_HASHKEYEQ(hashKeyEqAndcons)
3322{
3323 SCIP_CONSDATA* consdata1;
3324 SCIP_CONSDATA* consdata2;
3325 SCIP_Bool coefsequal;
3326 int i;
3327#ifndef NDEBUG
3328 SCIP* scip;
3329
3330 scip = (SCIP*)userptr;
3331 assert(scip != NULL);
3332#endif
3333
3334 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
3335 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
3336
3337 /* checks trivial case */
3338 if( consdata1->nvars != consdata2->nvars )
3339 return FALSE;
3340
3341 /* sorts the constraints */
3342 consdataSort(consdata1);
3343 consdataSort(consdata2);
3344 assert(consdata1->sorted);
3345 assert(consdata2->sorted);
3346
3347 coefsequal = TRUE;
3348
3349 for( i = 0; i < consdata1->nvars ; ++i )
3350 {
3351 /* tests if variables are equal */
3352 if( consdata1->vars[i] != consdata2->vars[i] )
3353 {
3354 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
3355 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
3356 coefsequal = FALSE;
3357 break;
3358 }
3359 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
3360 }
3361
3362 return coefsequal;
3363}
3364
3365/** returns the hash value of the key */
3366static
3367SCIP_DECL_HASHKEYVAL(hashKeyValAndcons)
3368{ /*lint --e{715}*/
3369 SCIP_CONSDATA* consdata;
3370 int minidx;
3371 int mididx;
3372 int maxidx;
3373
3374 consdata = SCIPconsGetData((SCIP_CONS*)key);
3375 assert(consdata != NULL);
3376 assert(consdata->sorted);
3377 assert(consdata->nvars > 0);
3378
3379 minidx = SCIPvarGetIndex(consdata->vars[0]);
3380 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
3381 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
3382 assert(minidx >= 0 && minidx <= maxidx);
3383
3384 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
3385}
3386
3387/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
3388 * accordingly; in contrast to removeRedundantConstraints(), it uses a hash table
3389 */
3390static
3392 SCIP* scip, /**< SCIP data structure */
3393 BMS_BLKMEM* blkmem, /**< block memory */
3394 SCIP_CONS** conss, /**< constraint set */
3395 int nconss, /**< number of constraints in constraint set */
3396 int* firstchange, /**< pointer to store first changed constraint */
3397 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
3398 int* naggrvars, /**< pointer to count number of aggregated variables */
3399 int* ndelconss /**< pointer to count number of deleted constraints */
3400 )
3401{
3402 SCIP_HASHTABLE* hashtable;
3403 int hashtablesize;
3404 int c;
3405
3406 assert(conss != NULL);
3407 assert(ndelconss != NULL);
3408
3409 /* create a hash table for the constraint set */
3410 hashtablesize = nconss;
3411 hashtablesize = MAX(hashtablesize, HASHSIZE_ANDCONS);
3412 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
3413 hashGetKeyAndcons, hashKeyEqAndcons, hashKeyValAndcons, (void*) scip) );
3414
3415 *cutoff = FALSE;
3416
3417 /* check all constraints in the given set for redundancy */
3418 for( c = 0; c < nconss; ++c )
3419 {
3420 SCIP_CONS* cons0;
3421 SCIP_CONS* cons1;
3422 SCIP_CONSDATA* consdata0;
3423
3424 cons0 = conss[c];
3425
3426 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
3427 continue;
3428
3429 consdata0 = SCIPconsGetData(cons0);
3430
3431 /* sort the constraint */
3432 consdataSort(consdata0);
3433 assert(consdata0->sorted);
3434
3435 /* get constraint from current hash table with same variables as cons0 */
3436 cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
3437
3438 if( cons1 != NULL )
3439 {
3440 SCIP_CONSDATA* consdata1;
3441 SCIP_Bool redundant;
3442
3443 assert(SCIPconsIsActive(cons1));
3445
3446 consdata1 = SCIPconsGetData(cons1);
3447
3448 assert(consdata1 != NULL);
3449 assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
3450
3451 assert(consdata0->sorted && consdata1->sorted);
3452 assert(consdata0->vars[0] == consdata1->vars[0]);
3453
3454 redundant = FALSE;
3455
3456 if( consdata0->resvar != consdata1->resvar )
3457 {
3458 SCIP_Bool aggregated;
3459
3460 assert(SCIPvarCompare(consdata0->resvar, consdata1->resvar) != 0);
3461
3462 /* aggregate resultants */
3463 SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
3464 cutoff, &redundant, &aggregated) );
3465 assert(redundant || SCIPdoNotAggr(scip));
3466
3467 if( aggregated )
3468 ++(*naggrvars);
3469 if( *cutoff )
3470 goto TERMINATE;
3471 }
3472 else
3473 redundant = TRUE;
3474
3475 /* delete consdel */
3476 if( redundant )
3477 {
3478 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3479 /* coverity[swapped_arguments] */
3480 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
3481
3482 /* delete constraint */
3483 SCIP_CALL( SCIPdelCons(scip, cons0) );
3484 (*ndelconss)++;
3485 }
3486
3487 /* update the first changed constraint to begin the next aggregation round with */
3488 if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
3489 *firstchange = SCIPconsGetPos(cons1);
3490
3491 assert(SCIPconsIsActive(cons1));
3492 }
3493 else
3494 {
3495 /* no such constraint in current hash table: insert cons0 into hash table */
3496 SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
3497 }
3498 }
3499 TERMINATE:
3500 /* free hash table */
3501 SCIPhashtableFree(&hashtable);
3502
3503 return SCIP_OKAY;
3504}
3505
3506/** helper function to enforce constraints */
3507static
3509 SCIP* scip, /**< SCIP data structure */
3510 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3511 SCIP_CONS** conss, /**< constraints to process */
3512 int nconss, /**< number of constraints */
3513 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
3514 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
3515 )
3516{
3517 SCIP_CONSHDLRDATA* conshdlrdata;
3518 SCIP_Bool separated;
3519 SCIP_Bool violated;
3521 int i;
3522
3523 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3524 assert(conshdlrdata != NULL);
3525
3527
3528 /* method is called only for integral solutions, because the enforcing priority is negative */
3529 for( i = 0; i < nconss; i++ )
3530 {
3531 SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
3532 if( !violated )
3533 continue;
3534
3535 if( !conshdlrdata->enforcecuts )
3536 {
3538 return SCIP_OKAY;
3539 }
3540
3541 SCIP_CALL( separateCons(scip, conss[i], sol, &separated, &cutoff) );
3542 if( cutoff )
3543 {
3545 return SCIP_OKAY;
3546 }
3547 else if( separated )
3548 {
3550 }
3551 else if( *result == SCIP_FEASIBLE ) /* do not change result separated to infeasible */
3552 {
3554 }
3555 }
3556
3557 return SCIP_OKAY;
3558}
3559
3560
3561/** compares constraint with all prior constraints for possible redundancy or aggregation,
3562 * and removes or changes constraint accordingly
3563 */
3564static
3566 SCIP* scip, /**< SCIP data structure */
3567 SCIP_CONS** conss, /**< constraint set */
3568 int firstchange, /**< first constraint that changed since last pair preprocessing round */
3569 int chkind, /**< index of constraint to check against all prior indices upto startind */
3570 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
3571 int* naggrvars, /**< pointer to count number of aggregated variables */
3572 int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
3573 int* ndelconss /**< pointer to count number of deleted constraints */
3574 )
3575{
3576 SCIP_CONS* cons0;
3577 SCIP_CONSDATA* consdata0;
3578 SCIP_Bool cons0changed;
3579 int c;
3580
3581 assert(conss != NULL);
3582 assert(firstchange <= chkind);
3583 assert(cutoff != NULL);
3584 assert(naggrvars != NULL);
3585 assert(nbdchgs != NULL);
3586 assert(ndelconss != NULL);
3587
3588 /* get the constraint to be checked against all prior constraints */
3589 cons0 = conss[chkind];
3590 assert(SCIPconsIsActive(cons0));
3592
3593 consdata0 = SCIPconsGetData(cons0);
3594
3595 /* sort the constraint */
3596 consdataSort(consdata0);
3597
3598 assert(consdata0->nvars >= 1);
3599 assert(consdata0->sorted);
3600
3601 /* check constraint against all prior constraints */
3602 cons0changed = consdata0->changed;
3603
3604 if( SCIPconsIsActive(cons0) )
3605 {
3606 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff); ++c )
3607 {
3608 SCIP_CONS* cons1;
3609 SCIP_CONSDATA* consdata1;
3610 SCIP_Bool cons0superset;
3611 SCIP_Bool cons1superset;
3612 int v0;
3613 int v1;
3614
3615 if( c % 1000 == 0 && SCIPisStopped(scip) )
3616 break;
3617
3618 cons1 = conss[c];
3619
3620 /* ignore inactive and modifiable constraints */
3621 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
3622 continue;
3623
3624 consdata1 = SCIPconsGetData(cons1);
3625 assert(consdata1 != NULL);
3626
3627#ifdef SCIP_DISABLED_CODE
3628 SCIPdebugMsg(scip, "preprocess AND-constraint pair <%s>[chg:%d] and <%s>[chg:%d]\n",
3629 SCIPconsGetName(cons0), cons0changed, SCIPconsGetName(cons1), consdata1->changed);
3630#endif
3631
3632 /* if both constraints were not changed since last round, we can ignore the pair */
3633 if( !cons0changed && !consdata1->changed )
3634 continue;
3635
3636 assert(consdata1->nvars >= 1);
3637
3638 /* sort the constraint */
3639 consdataSort(consdata1);
3640 assert(consdata1->sorted);
3641
3642 /* check consdata0 against consdata1:
3643 * - if they consist of the same operands, the resultants can be aggregated
3644 * - if one operand list is a subset of the other, add implication r0 = 1 -> r1 = 1, or r1 = 1 -> r0 = 1
3645 */
3646 v0 = 0;
3647 v1 = 0;
3648 cons0superset = TRUE;
3649 cons1superset = TRUE;
3650 while( (v0 < consdata0->nvars || v1 < consdata1->nvars) && (cons0superset || cons1superset) )
3651 {
3652 int varcmp;
3653
3654 /* test, if variable appears in only one or in both constraints */
3655 if( v0 < consdata0->nvars && v1 < consdata1->nvars )
3656 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
3657 else if( v0 < consdata0->nvars )
3658 varcmp = -1;
3659 else
3660 varcmp = +1;
3661
3662 switch( varcmp )
3663 {
3664 case -1:
3665 /* variable doesn't appear in consdata1 */
3666 cons1superset = FALSE;
3667 v0++;
3668 break;
3669
3670 case +1:
3671 /* variable doesn't appear in consdata0 */
3672 cons0superset = FALSE;
3673 v1++;
3674 break;
3675
3676 case 0:
3677 /* variable appears in both constraints */
3678 v0++;
3679 v1++;
3680 break;
3681
3682 default:
3683 SCIPerrorMessage("invalid comparison result\n");
3684 SCIPABORT();
3685 return SCIP_INVALIDDATA; /*lint !e527*/
3686 }
3687 }
3688
3689 /* check for equivalence and domination */
3690 if( cons0superset && cons1superset )
3691 {
3692 SCIP_Bool infeasible;
3693 SCIP_Bool redundant;
3694 SCIP_Bool aggregated;
3695
3696 /* constraints are equivalent */
3697 SCIPdebugMsg(scip, "equivalent AND-constraints <%s> and <%s>: aggregate resultants <%s> == <%s>\n",
3698 SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
3699 SCIPvarGetName(consdata1->resvar));
3700
3701 /* aggregate resultants */
3702 SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
3703 &infeasible, &redundant, &aggregated) );
3704 assert(redundant || SCIPdoNotAggr(scip));
3705
3706 if( aggregated )
3707 {
3708 assert(redundant);
3709 (*naggrvars)++;
3710 }
3711
3712 if( redundant )
3713 {
3714 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3715 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3716
3717 /* delete constraint */
3718 SCIP_CALL( SCIPdelCons(scip, cons1) );
3719 (*ndelconss)++;
3720 }
3721
3722 *cutoff = *cutoff || infeasible;
3723 }
3724 else if( cons0superset )
3725 {
3726 SCIP_Bool infeasible;
3727 int nboundchgs;
3728
3729 /* the conjunction of cons0 is a superset of the conjunction of cons1 */
3730 SCIPdebugMsg(scip, "AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
3731 SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
3732 SCIPvarGetName(consdata1->resvar));
3733
3734 /* add implication */
3735 SCIP_CALL( SCIPaddVarImplication(scip, consdata0->resvar, TRUE, consdata1->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
3736 &infeasible, &nboundchgs) );
3737 *cutoff = *cutoff || infeasible;
3738 (*nbdchgs) += nboundchgs;
3739 }
3740 else if( cons1superset )
3741 {
3742 SCIP_Bool infeasible;
3743 int nboundchgs;
3744
3745 /* the conjunction of cons1 is a superset of the conjunction of cons0 */
3746 SCIPdebugMsg(scip, "AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
3747 SCIPconsGetName(cons1), SCIPconsGetName(cons0), SCIPvarGetName(consdata1->resvar),
3748 SCIPvarGetName(consdata0->resvar));
3749
3750 /* add implication */
3751 SCIP_CALL( SCIPaddVarImplication(scip, consdata1->resvar, TRUE, consdata0->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
3752 &infeasible, &nboundchgs) );
3753 *cutoff = *cutoff || infeasible;
3754 (*nbdchgs) += nboundchgs;
3755 }
3756 }
3757 }
3758 consdata0->changed = FALSE;
3759
3760 return SCIP_OKAY;
3761}
3762
3763/** adds symmetry information of constraint to a symmetry detection graph */
3764static
3766 SCIP* scip, /**< SCIP pointer */
3767 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
3768 SCIP_CONS* cons, /**< constraint */
3769 SYM_GRAPH* graph, /**< symmetry detection graph */
3770 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
3771 )
3772{
3773 SCIP_CONSDATA* consdata;
3774 SCIP_VAR** andvars;
3775 SCIP_VAR** vars;
3776 SCIP_Real* vals;
3777 SCIP_Real constant;
3778 int consnodeidx;
3779 int andnodeidx;
3780 int nlocvars;
3781 int i;
3782
3783 assert(scip != NULL);
3784 assert(cons != NULL);
3785 assert(graph != NULL);
3786 assert(success != NULL);
3787
3788 consdata = SCIPconsGetData(cons);
3789 assert(consdata != NULL);
3790
3791 /* create arrays to store active representation of variables */
3792 nlocvars = 1;
3793 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlocvars) );
3794 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlocvars) );
3795
3796 /* add constraint node */
3797 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
3798
3799 /* add resultant to symmetry detection graph */
3800 assert(consdata->resvar != NULL);
3801 vars[0] = consdata->resvar;
3802 vals[0] = 1.0;
3803 constant = 0.0;
3804 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
3805 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, consnodeidx, vars, vals, nlocvars, constant) );
3806
3807 /* add node modeling the AND-part and connect it with constraint node */
3808 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int)SYM_CONSOPTYPE_AND, &andnodeidx) );
3809 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, andnodeidx, FALSE, 0.0) );
3810
3811 /* add variables */
3812 andvars = consdata->vars;
3813 for( i = 0; i < consdata->nvars; ++i )
3814 {
3815 assert(andvars[i] != NULL);
3816 vars[0] = andvars[i];
3817 vals[0] = 1.0;
3818 constant = 0.0;
3819 nlocvars = 1;
3820 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
3821 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, andnodeidx, vars, vals, nlocvars, constant) );
3822 }
3823
3824 SCIPfreeBufferArray(scip, &vals);
3826
3827 *success = TRUE;
3828
3829 return SCIP_OKAY;
3830}
3831
3832/*
3833 * Callback methods of constraint handler
3834 */
3835
3836/** copy method for constraint handler plugins (called when SCIP copies plugins) */
3837static
3839{ /*lint --e{715}*/
3840 assert(scip != NULL);
3841 assert(conshdlr != NULL);
3842
3844
3845 /* call inclusion method of constraint handler */
3847
3848 *valid = TRUE;
3849
3850 return SCIP_OKAY;
3851}
3852
3853/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
3854static
3856{ /*lint --e{715}*/
3857 SCIP_CONSHDLRDATA* conshdlrdata;
3858
3859 /* free constraint handler data */
3860 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3861 assert(conshdlrdata != NULL);
3862
3863 conshdlrdataFree(scip, &conshdlrdata);
3864
3865 SCIPconshdlrSetData(conshdlr, NULL);
3866
3867 return SCIP_OKAY;
3868}
3869
3870
3871/** presolving initialization method of constraint handler (called when presolving is about to begin) */
3872static
3874{ /*lint --e{715}*/
3875 SCIP_CONSHDLRDATA* conshdlrdata;
3876
3877 assert( scip != NULL );
3878 assert( conshdlr != NULL );
3879 assert( nconss == 0 || conss != NULL );
3880
3881 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3882 assert(conshdlrdata != NULL);
3883
3884 if( conshdlrdata->linearize )
3885 {
3886 /* linearize all AND-constraints and remove the AND-constraints */
3887 SCIP_CONS* newcons;
3888 SCIP_CONS* cons;
3889 SCIP_CONSDATA* consdata;
3890 char consname[SCIP_MAXSTRLEN];
3891
3892 SCIP_VAR** vars;
3893 SCIP_Real* vals;
3894
3895 int nvars;
3896 int c, v;
3897
3898 /* allocate buffer array */
3900 SCIP_CALL( SCIPallocBufferArray(scip, &vals, 2) );
3901
3902 for( c = 0; c < nconss; ++c )
3903 {
3904 cons = conss[c];
3905 assert( cons != NULL );
3906
3907 /* only added constraints can be upgraded */
3908 if( !SCIPconsIsAdded(cons) || SCIPconsGetNUpgradeLocks(cons) >= 1 )
3909 continue;
3910
3911 consdata = SCIPconsGetData(cons);
3912 assert( consdata != NULL );
3913 assert( consdata->resvar != NULL );
3914
3915 nvars = consdata->nvars;
3916
3917 if( !conshdlrdata->aggrlinearization )
3918 {
3919 vars[0] = consdata->resvar;
3920 vals[0] = 1.0;
3921 vals[1] = -1.0;
3922
3923 /* create operator linear constraints */
3924 for( v = 0; v < nvars; ++v )
3925 {
3926 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), v);
3927 vars[1] = consdata->vars[v];
3928
3929 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, vars, vals, -SCIPinfinity(scip), 0.0,
3933 SCIPconsIsStickingAtNode(cons)) );
3934
3935 /* add constraint */
3936 SCIP_CALL( SCIPaddCons(scip, newcons) );
3937 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3938 }
3939 }
3940
3941 /* reallocate buffer array */
3944
3945 for( v = 0; v < nvars; ++v )
3946 {
3947 vars[v] = consdata->vars[v];
3948 vals[v] = -1.0;
3949 }
3950
3951 vars[nvars] = consdata->resvar;
3952
3953 if( conshdlrdata->aggrlinearization )
3954 {
3955 /* create additional linear constraint */
3956 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_operators", SCIPconsGetName(cons));
3957
3958 vals[nvars] = (SCIP_Real) nvars;
3959
3960 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -SCIPinfinity(scip), 0.0,
3964 SCIPconsIsStickingAtNode(cons)) );
3965
3966 /* add constraint */
3967 SCIP_CALL( SCIPaddCons(scip, newcons) );
3968 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3969 }
3970
3971 /* create additional linear constraint */
3972 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
3973
3974 vals[nvars] = 1.0;
3975
3976 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -nvars + 1.0, SCIPinfinity(scip),
3980 SCIPconsIsStickingAtNode(cons)) );
3981
3982 /* add constraint */
3983 SCIP_CALL( SCIPaddCons(scip, newcons) );
3984 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3985
3986 /* delete constraint */
3987 SCIP_CALL( SCIPdelCons(scip, cons) );
3988 }
3989
3990 /* free buffer array */
3992 SCIPfreeBufferArray(scip, &vals);
3993 }
3994
3995 return SCIP_OKAY;
3996}
3997
3998
3999#ifdef GMLGATEPRINTING
4000
4001/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
4002static
4003SCIP_DECL_CONSEXITPRE(consExitpreAnd)
4004{ /*lint --e{715}*/
4005 SCIP_HASHMAP* hashmap;
4006 FILE* gmlfile;
4007 char fname[SCIP_MAXSTRLEN];
4008 SCIP_CONS* cons;
4009 SCIP_CONSDATA* consdata;
4010 SCIP_VAR** activeconsvars;
4011 SCIP_VAR* activevar;
4012 int* varnodeids;
4013 SCIP_VAR** vars;
4014 int nvars;
4015 int nbinvars;
4016 int nintvars;
4017 int nimplvars;
4018 int ncontvars;
4019 int v;
4020 int c;
4021 int resid;
4022 int varid;
4023 int id = 1;
4024
4025 /* no AND-constraints available */
4026 if( nconss == 0 )
4027 return SCIP_OKAY;
4028
4030
4031 /* no variables left anymore */
4032 if( nvars == 0 )
4033 return SCIP_OKAY;
4034
4036 SCIP_CALL( SCIPallocBufferArray(scip, &varnodeids, nvars) );
4037 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, &nimplvars, &ncontvars) );
4038
4039 /* open gml file */
4040 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "and-gates%p.gml", scip);
4041 gmlfile = fopen(fname, "w");
4042
4043 if( gmlfile == NULL )
4044 {
4045 SCIPerrorMessage("cannot open graph file <%s>\n", fname);
4046 SCIPABORT();
4047 return SCIP_WRITEERROR; /*lint !e527*/
4048 }
4049
4050 /* create the variable mapping hash map */
4051 SCIP_CALL_FINALLY( SCIPhashmapCreate(&hashmap, SCIPblkmem(scip), nvars), fclose(gmlfile) );
4052
4053 /* write starting of gml file */
4054 SCIPgmlWriteOpening(gmlfile, TRUE);
4055
4056 /* walk over all AND-constraints */
4057 for( c = nconss - 1; c >= 0; --c )
4058 {
4059 cons = conss[c];
4060
4061 /* only handle active constraints */
4062 if( !SCIPconsIsActive(cons) )
4063 continue;
4064
4065 consdata = SCIPconsGetData(cons);
4066 assert(consdata != NULL);
4067
4068 /* only handle constraints which have operands */
4069 if( consdata->nvars == 0 )
4070 continue;
4071
4072 assert(consdata->vars != NULL);
4073 assert(consdata->resvar != NULL);
4074
4075 /* get active variable of resultant */
4076 activevar = SCIPvarGetProbvar(consdata->resvar);
4077
4078 /* check if we already found this variables */
4079 resid = SCIPhashmapGetImageInt(hashmap, activevar);
4080 assert(resid >= 0);
4081
4082 if( resid == 0 )
4083 {
4084 resid = id;
4085 ++id;
4086 SCIP_CALL( SCIPhashmapInsertInt(hashmap, (void*)activevar, resid) );
4087
4088 /* write new gml node for new resultant */
4089 SCIPgmlWriteNode(gmlfile, resid, SCIPvarGetName(activevar), NULL, NULL, NULL);
4090 }
4091
4092 /* copy operands to get problem variables for */
4093 SCIP_CALL( SCIPduplicateBufferArray(scip, &activeconsvars, consdata->vars, consdata->nvars) );
4094
4095 /* get problem variables of operands */
4096 SCIPvarsGetProbvar(activeconsvars, consdata->nvars);
4097
4098 for( v = consdata->nvars - 1; v >= 0; --v )
4099 {
4100 /* check if we already found this variables */
4101 varid = SCIPhashmapGetImageInt(hashmap, activeconsvars[v]);
4102 if( varid == 0 )
4103 {
4104 varid = id;
4105 ++id;
4106 SCIP_CALL( SCIPhashmapInsertInt(hashmap, (void*)activeconsvars[v], varid) );
4107
4108 /* write new gml node for new operand */
4109 SCIPgmlWriteNode(gmlfile, varid, SCIPvarGetName(activeconsvars[v]), NULL, NULL, NULL);
4110 }
4111 /* write gml arc between resultant and operand */
4112 SCIPgmlWriteArc(gmlfile, resid, varid, NULL, NULL);
4113 }
4114
4115 /* free temporary memory for active constraint variables */
4116 SCIPfreeBufferArray(scip, &activeconsvars);
4117 }
4118
4119 /* write all remaining variables as nodes */
4120#ifdef SCIP_DISABLED_CODE
4121 for( v = nvars - 1; v >= 0; --v )
4122 {
4123 activevar = SCIPvarGetProbvar(vars[v]);
4124
4125 varid = SCIPhashmapGetImageInt(hashmap, activevar);
4126 assert(varid >= 0);
4127
4128 if( varid == 0 )
4129 {
4130 varid = id;
4131 ++id;
4132 SCIP_CALL( SCIPhashmapInsertInt(hashmap, (void*)activeconsvars[v], varid) );
4133
4134 /* write new gml node for new operand */
4135 SCIPgmlWriteNode(gmlfile, varid, SCIPvarGetName(activevar), NULL, NULL, NULL);
4136 }
4137 }
4138#endif
4139
4140 /* free the variable mapping hash map */
4141 SCIPhashmapFree(&hashmap);
4142
4143 SCIPgmlWriteClosing(gmlfile);
4144
4145 fclose(gmlfile);
4146
4147 SCIPfreeBufferArray(scip, &varnodeids);
4149
4150 return SCIP_OKAY;
4151}
4152#endif
4153
4154/** solving process initialization method of constraint handler */
4155static
4157{ /*lint --e{715}*/
4158 /* add nlrow representation to NLP, if NLP had been constructed */
4160 {
4161 int c;
4162 for( c = 0; c < nconss; ++c )
4163 {
4164 SCIP_CALL( addNlrow(scip, conss[c]) );
4165 }
4166 }
4167
4168 return SCIP_OKAY;
4169}
4170
4171/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4172static
4174{ /*lint --e{715}*/
4175 SCIP_CONSDATA* consdata;
4176 int c;
4177
4178 /* release and free the rows and nlrow of all constraints */
4179 for( c = 0; c < nconss; ++c )
4180 {
4181 consdata = SCIPconsGetData(conss[c]);
4182 assert(consdata != NULL);
4183
4184 SCIP_CALL( consdataFreeRows(scip, consdata) );
4185
4186 if( consdata->nlrow != NULL )
4187 {
4188 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
4189 }
4190 }
4191
4192 return SCIP_OKAY;
4193}
4194
4195
4196/** frees specific constraint data */
4197static
4199{ /*lint --e{715}*/
4200 SCIP_CONSHDLRDATA* conshdlrdata;
4201
4202 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4203 assert(conshdlrdata != NULL);
4204
4205 SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
4206
4207 return SCIP_OKAY;
4208}
4209
4210
4211/** transforms constraint data into data belonging to the transformed problem */
4212static
4214{ /*lint --e{715}*/
4215 SCIP_CONSHDLRDATA* conshdlrdata;
4216 SCIP_CONSDATA* sourcedata;
4217 SCIP_CONSDATA* targetdata;
4218
4219 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4220 assert(conshdlrdata != NULL);
4221
4222 sourcedata = SCIPconsGetData(sourcecons);
4223 assert(sourcedata != NULL);
4224
4225 /* create target constraint data */
4226 SCIP_CALL( consdataCreate(scip, &targetdata, conshdlrdata->eventhdlr,
4227 sourcedata->nvars, sourcedata->vars, sourcedata->resvar) );
4228
4229 /* create target constraint */
4230 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
4231 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
4232 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
4233 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons),
4234 SCIPconsIsStickingAtNode(sourcecons)) );
4235
4236 return SCIP_OKAY;
4237}
4238
4239
4240/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
4241static
4243{ /*lint --e{715}*/
4244 int i;
4245
4246 *infeasible = FALSE;
4247
4248 for( i = 0; i < nconss && !(*infeasible); i++ )
4249 {
4250 assert(SCIPconsIsInitial(conss[i]));
4251 SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
4252 }
4253
4254 return SCIP_OKAY;
4255}
4256
4257
4258/** separation method of constraint handler for LP solutions */
4259static
4261{ /*lint --e{715}*/
4262 SCIP_Bool separated;
4264 int c;
4265
4267
4268 /* separate all useful constraints */
4269 for( c = 0; c < nusefulconss; ++c )
4270 {
4271 SCIP_CALL( separateCons(scip, conss[c], NULL, &separated, &cutoff) );
4272 if ( cutoff )
4274 else if ( separated )
4276 }
4277
4278 /* combine constraints to get more cuts */
4279 /**@todo combine constraints to get further cuts */
4280
4281 return SCIP_OKAY;
4282}
4283
4284
4285/** separation method of constraint handler for arbitrary primal solutions */
4286static
4288{ /*lint --e{715}*/
4289 SCIP_Bool separated;
4291 int c;
4292
4294
4295 /* separate all useful constraints */
4296 for( c = 0; c < nusefulconss; ++c )
4297 {
4298 SCIP_CALL( separateCons(scip, conss[c], sol, &separated, &cutoff) );
4299 if ( cutoff )
4301 else if ( separated )
4303 }
4304
4305 /* combine constraints to get more cuts */
4306 /**@todo combine constraints to get further cuts */
4307
4308 return SCIP_OKAY;
4309}
4310
4311
4312/** constraint enforcing method of constraint handler for LP solutions */
4313static
4315{ /*lint --e{715}*/
4316 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, NULL, result) );
4317
4318 return SCIP_OKAY;
4319}
4320
4321/** constraint enforcing method of constraint handler for relaxation solutions */
4322static
4324{ /*lint --e{715}*/
4325 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, sol, result) );
4326
4327 return SCIP_OKAY;
4328}
4329
4330/** constraint enforcing method of constraint handler for pseudo solutions */
4331static
4333{ /*lint --e{715}*/
4334 SCIP_Bool violated;
4335 int i;
4336
4337 /* method is called only for integral solutions, because the enforcing priority is negative */
4338 for( i = 0; i < nconss; i++ )
4339 {
4340 SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
4341 if( violated )
4342 {
4344 return SCIP_OKAY;
4345 }
4346 }
4348
4349 return SCIP_OKAY;
4350}
4351
4352/** feasibility check method of constraint handler and */
4353static
4355{ /*lint --e{715}*/
4356 SCIP_Bool violated;
4357 int i;
4358
4360
4361 for( i = 0; i < nconss && ( *result == SCIP_FEASIBLE || completely ); ++i )
4362 {
4363 SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
4364 if( violated )
4366 }
4367
4368 return SCIP_OKAY;
4369}
4370
4371/** domain propagation method of constraint handler */
4372static
4374{ /*lint --e{715}*/
4375 SCIP_CONSHDLRDATA* conshdlrdata;
4377 int nfixedvars;
4378 int nupgdconss;
4379 int c;
4380
4381 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4382 assert(conshdlrdata != NULL);
4383
4384 cutoff = FALSE;
4385 nfixedvars = 0;
4386 nupgdconss = 0;
4387
4388 /* propagate all useful constraints */
4389 for( c = 0; c < nusefulconss && !cutoff; ++c )
4390 {
4391 SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars, &nupgdconss) );
4392 }
4393
4394 /* return the correct result */
4395 if( cutoff )
4397 else if( nfixedvars > 0 || nupgdconss > 0 )
4399 else
4401
4402 return SCIP_OKAY;
4403}
4404
4405
4406/** presolving method of constraint handler */
4407static
4409{ /*lint --e{715}*/
4410 SCIP_CONSHDLRDATA* conshdlrdata;
4411 SCIP_CONS* cons;
4412 SCIP_CONSDATA* consdata;
4413 unsigned char* entries;
4415 int oldnfixedvars;
4416 int oldnaggrvars;
4417 int oldnchgbds;
4418 int oldndelconss;
4419 int oldnupgdconss;
4420 int firstchange;
4421 int nentries;
4422 int c;
4423
4424 assert(result != NULL);
4425
4426 oldnfixedvars = *nfixedvars;
4427 oldnaggrvars = *naggrvars;
4428 oldnchgbds = *nchgbds;
4429 oldndelconss = *ndelconss;
4430 oldnupgdconss = *nupgdconss;
4431
4432 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
4433 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
4434
4435 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4436 assert(conshdlrdata != NULL);
4437
4438 /* process constraints */
4439 cutoff = FALSE;
4440 firstchange = INT_MAX;
4441 for( c = 0; c < nconss && !cutoff && (c % 1000 != 0 || !SCIPisStopped(scip)); ++c )
4442 {
4443 cons = conss[c];
4444 assert(cons != NULL);
4445 consdata = SCIPconsGetData(cons);
4446 assert(consdata != NULL);
4447
4448 /* force presolving the constraint in the initial round */
4449 if( nrounds == 0 )
4450 consdata->propagated = FALSE;
4451
4452 /* remember the first changed constraint to begin the next aggregation round with */
4453 if( firstchange == INT_MAX && consdata->changed )
4454 firstchange = c;
4455
4456 /* propagate constraint */
4457 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nupgdconss) );
4458
4459 /* remove all variables that are fixed to one; merge multiple entries of the same variable;
4460 * fix resultant to zero if a pair of negated variables is contained in the operand variables
4461 */
4462 if( !cutoff && !SCIPconsIsDeleted(cons) )
4463 {
4464 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, nchgcoefs) );
4465
4466 /* merge multiple occurances of variables or variables with their negated variables */
4467 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, nfixedvars, nchgcoefs, ndelconss) );
4468 }
4469
4470 if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
4471 {
4472 assert(consdata->nvars >= 1); /* otherwise, propagateCons() has deleted the constraint */
4473
4474 /* if only one variable is left, the resultant has to be equal to this single variable */
4475 if( consdata->nvars == 1 )
4476 {
4477 SCIP_Bool redundant;
4478 SCIP_Bool aggregated;
4479
4480 SCIPdebugMsg(scip, "AND-constraint <%s> has only one variable not fixed to 1.0\n", SCIPconsGetName(cons));
4481
4482 assert(consdata->vars != NULL);
4483 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
4484 assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
4485
4486 /* aggregate variables: resultant - operand == 0 */
4487 SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
4488 &cutoff, &redundant, &aggregated) );
4489 assert(redundant || SCIPdoNotAggr(scip));
4490
4491 if( aggregated )
4492 {
4493 assert(redundant);
4494 (*naggrvars)++;
4495 }
4496
4497 if( redundant )
4498 {
4499 /* delete constraint */
4500 SCIP_CALL( SCIPdelCons(scip, cons) );
4501 (*ndelconss)++;
4502 }
4503 }
4504 else if( !consdata->impladded )
4505 {
4506 int i;
4507
4508 /* add implications: resultant == 1 -> all operands == 1 */
4509 for( i = 0; i < consdata->nvars && !cutoff; ++i )
4510 {
4511 int nimplbdchgs;
4512
4513 SCIP_CALL( SCIPaddVarImplication(scip, consdata->resvar, TRUE, consdata->vars[i],
4514 SCIP_BOUNDTYPE_LOWER, 1.0, &cutoff, &nimplbdchgs) );
4515 (*nchgbds) += nimplbdchgs;
4516 }
4517 consdata->impladded = TRUE;
4518 }
4519
4520 /* if in r = x and y, the resultant is fixed to zero, add implication x = 1 -> y = 0 */
4521 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 2 && !consdata->opimpladded
4522 && SCIPvarGetUbGlobal(consdata->resvar) < 0.5 )
4523 {
4524 int nimplbdchgs;
4525
4526 SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], TRUE, consdata->vars[1],
4527 SCIP_BOUNDTYPE_UPPER, 0.0, &cutoff, &nimplbdchgs) );
4528 (*nchgbds) += nimplbdchgs;
4529 consdata->opimpladded = TRUE;
4530 }
4531 }
4532 }
4533
4534 /* perform dual presolving on AND-constraints */
4535 if( conshdlrdata->dualpresolving && !cutoff && !SCIPisStopped(scip) && SCIPallowStrongDualReds(scip))
4536 {
4537 SCIP_CALL( dualPresolve(scip, conss, nconss, conshdlrdata->eventhdlr, &entries, &nentries, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, nupgdconss, naddconss) );
4538 }
4539
4540 /* check for cliques inside the AND constraint */
4541 if( (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4542 {
4543 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
4544 {
4545 cons = conss[c];
4546 assert(cons != NULL);
4547
4548 if( !SCIPconsIsActive(cons) )
4549 continue;
4550
4551 /* cliquePresolve() may aggregate variables which need to be removed from other constraints, we also need
4552 * to make sure that we remove fixed variables by calling propagateCons() to make sure that applyFixing()
4553 * and mergeMultiples() work
4554 */
4555 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nupgdconss) );
4556
4557 if( !cutoff && !SCIPconsIsDeleted(cons) )
4558 {
4559 /* remove all variables that are fixed to one; merge multiple entries of the same variable;
4560 * fix resultant to zero if a pair of negated variables is contained in the operand variables
4561 */
4562 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, nchgcoefs) );
4563 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, nfixedvars, nchgcoefs, ndelconss) );
4564
4565 /* check if at least two operands are in one clique */
4566 SCIP_CALL( cliquePresolve(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, naddconss) );
4567 }
4568 }
4569 }
4570
4571 /* process pairs of constraints: check them for equal operands in order to aggregate resultants;
4572 * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
4573 * (otherwise, we delay the presolving to be called again next time)
4574 */
4575 if( !cutoff && conshdlrdata->presolusehashing && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4576 {
4577 if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars )
4578 {
4579 if( firstchange < nconss )
4580 {
4581 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
4582 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff, naggrvars, ndelconss) );
4583 oldnaggrvars = *naggrvars;
4584 }
4585 }
4586 }
4587
4588 if( !cutoff && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4589 {
4590 if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars )
4591 {
4592 SCIP_Longint npaircomparisons;
4593 npaircomparisons = 0;
4594 oldndelconss = *ndelconss;
4595
4596 for( c = firstchange; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
4597 {
4598 if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
4599 {
4600 npaircomparisons += ((SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange));
4601
4602 SCIP_CALL( preprocessConstraintPairs(scip, conss, firstchange, c, &cutoff, naggrvars, nchgbds,
4603 ndelconss) );
4604
4605 if( npaircomparisons > NMINCOMPARISONS )
4606 {
4607 if( ((*ndelconss - oldndelconss) + (*naggrvars - oldnaggrvars) + (*nchgbds - oldnchgbds)/2.0) / ((SCIP_Real) npaircomparisons) < MINGAINPERNMINCOMPARISONS )
4608 break;
4609 oldndelconss = *ndelconss;
4610 oldnaggrvars = *naggrvars;
4611 oldnchgbds = *nchgbds;
4612
4613 npaircomparisons = 0;
4614 }
4615 }
4616 }
4617 }
4618 }
4619
4620 SCIPfreeBufferArray(scip, &entries);
4621
4622 /* return the correct result code */
4623 if( cutoff )
4625 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds
4626 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
4628 else
4630
4631 return SCIP_OKAY;
4632}
4633
4634
4635/** propagation conflict resolving method of constraint handler */
4636static
4638{ /*lint --e{715}*/
4639 SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
4640
4641 return SCIP_OKAY;
4642}
4643
4644
4645/** variable rounding lock method of constraint handler */
4646static
4648{ /*lint --e{715}*/
4649 SCIP_CONSDATA* consdata;
4650 int i;
4651
4652 consdata = SCIPconsGetData(cons);
4653 assert(consdata != NULL);
4654
4655 /* resultant variable */
4656 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->resvar, locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
4657
4658 /* operand variables */
4659 for( i = 0; i < consdata->nvars; ++i )
4660 {
4661 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
4662 }
4663
4664 return SCIP_OKAY;
4665}
4666
4667/** constraint activation notification method of constraint handler */
4668static
4670{ /*lint --e{715}*/
4672 {
4673 SCIP_CALL( addNlrow(scip, cons) );
4674 }
4675
4676 return SCIP_OKAY;
4677}
4678
4679/** constraint deactivation notification method of constraint handler */
4680static
4682{ /*lint --e{715}*/
4683 SCIP_CONSDATA* consdata;
4684
4685 assert(cons != NULL);
4686
4687 consdata = SCIPconsGetData(cons);
4688 assert(consdata != NULL);
4689
4690 /* remove row from NLP, if still in solving
4691 * if we are in exitsolve, the whole NLP will be freed anyway
4692 */
4693 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
4694 {
4695 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
4696 }
4697
4698 return SCIP_OKAY;
4699}
4700
4701/** constraint display method of constraint handler */
4702static
4704{ /*lint --e{715}*/
4705 assert( scip != NULL );
4706 assert( conshdlr != NULL );
4707 assert( cons != NULL );
4708
4710
4711 return SCIP_OKAY;
4712}
4713
4714/** constraint copying method of constraint handler */
4715static
4717{ /*lint --e{715}*/
4718 SCIP_VAR** sourcevars;
4719 SCIP_VAR** vars;
4720 SCIP_VAR* sourceresvar;
4721 SCIP_VAR* resvar;
4722 const char* consname;
4723 int nvars;
4724 int v;
4725
4726 assert(valid != NULL);
4727 (*valid) = TRUE;
4728
4729 sourceresvar = SCIPgetResultantAnd(sourcescip, sourcecons);
4730
4731 /* map resultant to active variable of the target SCIP */
4732 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceresvar, &resvar, varmap, consmap, global, valid) );
4733 assert(!(*valid) || resvar != NULL);
4734
4735 /* we do not copy, if a variable is missing */
4736 if( !(*valid) )
4737 return SCIP_OKAY;
4738
4739 /* map operand variables to active variables of the target SCIP */
4740 sourcevars = SCIPgetVarsAnd(sourcescip, sourcecons);
4741 nvars = SCIPgetNVarsAnd(sourcescip, sourcecons);
4742
4743 if( nvars == -1 )
4744 return SCIP_INVALIDCALL;
4745
4746 /* allocate buffer array */
4748
4749 for( v = 0; v < nvars; ++v )
4750 {
4751 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, valid) );
4752 assert(!(*valid) || vars[v] != NULL);
4753
4754 /* we do not copy, if a variable is missing */
4755 if( !(*valid) )
4756 goto TERMINATE;
4757 }
4758
4759 if( name != NULL )
4760 consname = name;
4761 else
4762 consname = SCIPconsGetName(sourcecons);
4763
4764 /* creates and captures a AND-constraint */
4765 SCIP_CALL( SCIPcreateConsAnd(scip, cons, consname, resvar, nvars, vars,
4766 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4767
4768 TERMINATE:
4769 /* free buffer array */
4771
4772 return SCIP_OKAY;
4773}
4774
4775/** constraint parsing method of constraint handler */
4776static
4778{ /*lint --e{715}*/
4779 SCIP_VAR** vars;
4780 SCIP_VAR* resvar;
4781 char* endptr;
4782 int requiredsize;
4783 int varssize;
4784 int nvars;
4785
4786 SCIPdebugMsg(scip, "parse <%s> as AND-constraint\n", str);
4787
4788 *success = FALSE;
4789
4790 /* parse variable name of resultant */
4791 SCIP_CALL( SCIPparseVarName(scip, str, &resvar, &endptr) );
4792
4793 if( resvar == NULL )
4794 {
4795 SCIPerrorMessage("resultant variable does not exist\n");
4796 }
4797 else
4798 {
4799 char* strcopy = NULL;
4800 char* startptr;
4801
4802 str = endptr;
4803
4804 /* cutoff "== and(" form the constraint string */
4805 startptr = strchr((char*)str, '(');
4806
4807 if( startptr == NULL )
4808 {
4809 SCIPerrorMessage("missing starting character '(' parsing AND-constraint\n");
4810 return SCIP_OKAY;
4811 }
4812
4813 /* skip '(' */
4814 ++startptr;
4815
4816 /* find end character ')' */
4817 endptr = strrchr(startptr, ')');
4818
4819 if( endptr == NULL )
4820 {
4821 SCIPerrorMessage("missing ending character ')' parsing AND-constraint\n");
4822 return SCIP_OKAY;
4823 }
4824 assert(endptr >= startptr);
4825
4826 if( endptr > startptr )
4827 {
4828 /* copy string for parsing; note that SCIPskipSpace() in SCIPparseVarsList() requires that strcopy ends with '\0' */
4829 SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, startptr, (int)(endptr-startptr+1)) );
4830 strcopy[endptr-startptr] = '\0';
4831 varssize = 100;
4832 nvars = 0;
4833
4834 /* allocate buffer array for variables */
4835 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
4836
4837 /* parse string */
4838 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4839
4840 if( *success )
4841 {
4842 /* check if the size of the variable array was great enough */
4843 if( varssize < requiredsize )
4844 {
4845 /* reallocate memory */
4846 varssize = requiredsize;
4847 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
4848
4849 /* parse string again with the correct size of the variable array */
4850 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4851 }
4852
4853 assert(*success);
4854 assert(varssize >= requiredsize);
4855
4856 /* create AND-constraint */
4857 SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, nvars, vars,
4858 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4859 }
4860
4861 /* free variable buffer */
4863 SCIPfreeBufferArray(scip, &strcopy);
4864 }
4865 else
4866 {
4867 if( !modifiable )
4868 {
4869 SCIPerrorMessage("cannot create empty AND-constraint\n");
4870 return SCIP_OKAY;
4871 }
4872
4873 /* create empty AND-constraint */
4874 SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, 0, NULL,
4875 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4876
4877 *success = TRUE;
4878 }
4879 }
4880
4881 return SCIP_OKAY;
4882}
4883
4884/** constraint method of constraint handler which returns the variables (if possible) */
4885static
4887{ /*lint --e{715}*/
4888 SCIP_CONSDATA* consdata;
4889
4890 consdata = SCIPconsGetData(cons);
4891 assert(consdata != NULL);
4892
4893 if( varssize < consdata->nvars + 1 )
4894 (*success) = FALSE;
4895 else
4896 {
4897 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
4898 vars[consdata->nvars] = consdata->resvar;
4899 (*success) = TRUE;
4900 }
4901
4902 return SCIP_OKAY;
4903}
4904
4905/** constraint method of constraint handler which returns the number of variable (if possible) */
4906static
4908{ /*lint --e{715}*/
4909 SCIP_CONSDATA* consdata;
4910
4911 assert(cons != NULL);
4912
4913 consdata = SCIPconsGetData(cons);
4914 assert(consdata != NULL);
4915
4916 (*nvars) = consdata->nvars + 1;
4917 (*success) = TRUE;
4918
4919 return SCIP_OKAY;
4920}
4921
4922/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
4923static
4924SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphAnd)
4925{ /*lint --e{715}*/
4926 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
4927
4928 return SCIP_OKAY;
4929}
4930
4931/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
4932static
4933SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphAnd)
4934{ /*lint --e{715}*/
4935 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
4936
4937 return SCIP_OKAY;
4938}
4939
4940/*
4941 * Callback methods of event handler
4942 */
4943
4944static
4946{ /*lint --e{715}*/
4947 SCIP_CONSDATA* consdata;
4948
4949 assert(eventhdlr != NULL);
4950 assert(eventdata != NULL);
4951 assert(event != NULL);
4952
4953 consdata = (SCIP_CONSDATA*)eventdata;
4954 assert(consdata != NULL);
4955
4956 /* check, if the variable was fixed to zero */
4958 consdata->nofixedzero = FALSE;
4959
4960 consdata->propagated = FALSE;
4961
4962 return SCIP_OKAY;
4963}
4964
4965
4966/*
4967 * constraint specific interface methods
4968 */
4969
4970/** creates the handler for AND-constraints and includes it in SCIP */
4972 SCIP* scip /**< SCIP data structure */
4973 )
4974{
4975 SCIP_CONSHDLRDATA* conshdlrdata;
4976 SCIP_CONSHDLR* conshdlr;
4977 SCIP_EVENTHDLR* eventhdlr;
4978
4979 /* create event handler for events on variables */
4981 eventExecAnd, NULL) );
4982
4983 /* create constraint handler data */
4984 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
4985
4986 /* include constraint handler */
4989 consEnfolpAnd, consEnfopsAnd, consCheckAnd, consLockAnd,
4990 conshdlrdata) );
4991
4992 assert(conshdlr != NULL);
4993
4994 /* set non-fundamental callbacks via specific setter functions */
4995 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyAnd, consCopyAnd) );
4996 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveAnd) );
4997 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveAnd) );
4998 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteAnd) );
4999#ifdef GMLGATEPRINTING
5000 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreAnd) );
5001#endif
5002 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolAnd) );
5003 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolAnd) );
5004 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeAnd) );
5005 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsAnd) );
5006 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsAnd) );
5007 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreAnd) );
5008 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpAnd) );
5009 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseAnd) );
5011 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintAnd) );
5014 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropAnd) );
5015 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpAnd, consSepasolAnd, CONSHDLR_SEPAFREQ,
5017 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransAnd) );
5018 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxAnd) );
5019 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphAnd) );
5020 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphAnd) );
5021
5022 /* add AND-constraint handler parameters */
5024 "constraints/" CONSHDLR_NAME "/presolpairwise",
5025 "should pairwise constraint comparison be performed in presolving?",
5026 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
5028 "constraints/and/presolusehashing",
5029 "should hash table be used for detecting redundant constraints in advance",
5030 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
5032 "constraints/" CONSHDLR_NAME "/linearize",
5033 "should the AND-constraint get linearized and removed (in presolving)?",
5034 &conshdlrdata->linearize, TRUE, DEFAULT_LINEARIZE, NULL, NULL) );
5036 "constraints/" CONSHDLR_NAME "/enforcecuts",
5037 "should cuts be separated during LP enforcing?",
5038 &conshdlrdata->enforcecuts, TRUE, DEFAULT_ENFORCECUTS, NULL, NULL) );
5040 "constraints/" CONSHDLR_NAME "/aggrlinearization",
5041 "should an aggregated linearization be used?",
5042 &conshdlrdata->aggrlinearization, TRUE, DEFAULT_AGGRLINEARIZATION, NULL, NULL) );
5044 "constraints/" CONSHDLR_NAME "/upgraderesultant",
5045 "should implied integrality of resultant variables be detected?",
5046 &conshdlrdata->upgrresultant, TRUE, DEFAULT_UPGRRESULTANT, NULL, NULL) );
5048 "constraints/" CONSHDLR_NAME "/dualpresolving",
5049 "should dual presolving be performed?",
5050 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
5051
5052 return SCIP_OKAY;
5053}
5054
5055/** creates and captures a AND-constraint
5056 *
5057 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5058 */
5060 SCIP* scip, /**< SCIP data structure */
5061 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5062 const char* name, /**< name of constraint */
5063 SCIP_VAR* resvar, /**< resultant variable of the operation */
5064 int nvars, /**< number of operator variables in the constraint */
5065 SCIP_VAR** vars, /**< array with operator variables of constraint */
5066 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
5067 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5068 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
5069 * Usually set to TRUE. */
5070 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
5071 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5072 SCIP_Bool check, /**< should the constraint be checked for feasibility?
5073 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5074 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
5075 * Usually set to TRUE. */
5076 SCIP_Bool local, /**< is constraint only valid locally?
5077 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5078 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
5079 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
5080 * adds coefficients to this constraint. */
5081 SCIP_Bool dynamic, /**< is constraint subject to aging?
5082 * Usually set to FALSE. Set to TRUE for own cuts which
5083 * are separated as constraints. */
5084 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
5085 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5086 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
5087 * if it may be moved to a more global node?
5088 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
5089 )
5090{
5091 SCIP_CONSHDLR* conshdlr;
5092 SCIP_CONSHDLRDATA* conshdlrdata;
5093 SCIP_CONSDATA* consdata;
5094 SCIP_Bool infeasible;
5095 int i;
5096
5097 /* find the AND-constraint handler */
5098 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5099 if( conshdlr == NULL )
5100 {
5101 SCIPerrorMessage("AND-constraint handler not found\n");
5102 return SCIP_PLUGINNOTFOUND;
5103 }
5104
5105 /* check whether resultant variable is binary */
5106 if( !SCIPvarIsBinary(resvar) )
5107 {
5108 SCIPerrorMessage("resultant <%s> is not binary\n", SCIPvarGetName(resvar));
5109 return SCIP_INVALIDDATA;
5110 }
5111
5112 /* check whether all variables are binary */
5113 assert(vars != NULL || nvars == 0);
5114 for( i = 0; i < nvars; ++i )
5115 {
5116 if( !SCIPvarIsBinary(vars[i]) )
5117 {
5118 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
5119 return SCIP_INVALIDDATA;
5120 }
5121 }
5122
5123 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5124 assert(conshdlrdata != NULL);
5125
5126 /* upgrade binary resultant variable to an implicit binary variable */
5127 /* @todo add implicit upgrade in presolving, improve decision making for upgrade by creating an implication graph */
5128 if( conshdlrdata->upgrresultant && !SCIPvarIsImpliedIntegral(resvar) )
5129 {
5130 SCIP_VAR* activeresvar;
5131 SCIP_VAR* activevar;
5132 int v;
5133
5134 if( SCIPisTransformed(scip) )
5135 activeresvar = SCIPvarGetProbvar(resvar);
5136 else
5137 activeresvar = resvar;
5138
5139 if( SCIPvarGetType(activeresvar) == SCIP_VARTYPE_BINARY && !SCIPvarIsImpliedIntegral(activeresvar) )
5140 {
5141 /* check if we can upgrade the variable type of the resultant */
5142 for( v = nvars - 1; v >= 0; --v )
5143 {
5144 if( SCIPisTransformed(scip) )
5145 activevar = SCIPvarGetProbvar(vars[v]);
5146 else
5147 activevar = vars[v];
5148
5149 if( activevar == activeresvar || SCIPvarIsImpliedIntegral(activevar) )
5150 break;
5151 }
5152
5153 /* upgrade the type of the resultant */
5154 if( v < 0 )
5155 {
5156 SCIP_CALL( SCIPchgVarImplType(scip, resvar, SCIP_IMPLINTTYPE_STRONG, &infeasible) );
5157 assert(!infeasible);
5158 }
5159 }
5160 }
5161
5162 /* create constraint data */
5163 SCIP_CALL( consdataCreate(scip, &consdata, conshdlrdata->eventhdlr, nvars, vars, resvar) );
5164
5165 /* create constraint */
5166 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5167 local, modifiable, dynamic, removable, stickingatnode) );
5168
5169 return SCIP_OKAY;
5170}
5171
5172/** creates and captures an AND-constraint
5173 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
5174 * method SCIPcreateConsAnd(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
5175 *
5176 * @see SCIPcreateConsAnd() for information about the basic constraint flag configuration
5177 *
5178 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5179 */
5181 SCIP* scip, /**< SCIP data structure */
5182 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5183 const char* name, /**< name of constraint */
5184 SCIP_VAR* resvar, /**< resultant variable of the operation */
5185 int nvars, /**< number of operator variables in the constraint */
5186 SCIP_VAR** vars /**< array with operator variables of constraint */
5187 )
5188{
5189 assert(scip != NULL);
5190
5191 SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, nvars, vars,
5193
5194 return SCIP_OKAY;
5195}
5196
5197
5198/** gets number of variables in AND-constraint */
5200 SCIP* scip, /**< SCIP data structure */
5201 SCIP_CONS* cons /**< constraint data */
5202 )
5203{
5204 SCIP_CONSDATA* consdata;
5205
5206 assert(scip != NULL);
5207 assert(cons != NULL);
5208
5210
5211 consdata = SCIPconsGetData(cons);
5212 assert(consdata != NULL);
5213
5214 return consdata->nvars;
5215}
5216
5217/** gets array of variables in AND-constraint */
5219 SCIP* scip, /**< SCIP data structure */
5220 SCIP_CONS* cons /**< constraint data */
5221 )
5222{ /*lint --e{715}*/
5223 SCIP_CONSDATA* consdata;
5224
5225 assert(scip != NULL);
5226 assert(cons != NULL);
5227
5229
5230 consdata = SCIPconsGetData(cons);
5231 assert(consdata != NULL);
5232
5233 return consdata->vars;
5234}
5235
5236
5237/** gets the resultant variable in AND-constraint */ /*lint -e715*/
5239 SCIP* scip, /**< SCIP data structure */
5240 SCIP_CONS* cons /**< constraint data */
5241 )
5242{
5243 SCIP_CONSDATA* consdata;
5244
5245 assert(cons != NULL);
5246
5248
5249 consdata = SCIPconsGetData(cons);
5250 assert(consdata != NULL);
5251
5252 return consdata->resvar;
5253}
5254
5255/** return if the variables of the AND-constraint are sorted with respect to their indices */
5257 SCIP* scip, /**< SCIP data structure */
5258 SCIP_CONS* cons /**< constraint data */
5259 )
5260{
5261 SCIP_CONSDATA* consdata;
5262
5263 assert(scip != NULL);
5264 assert(cons != NULL);
5265
5267
5268 consdata = SCIPconsGetData(cons);
5269 assert(consdata != NULL);
5270
5271 return consdata->sorted;
5272}
5273
5274/** sort the variables of the AND-constraint with respect to their indices */
5276 SCIP* scip, /**< SCIP data structure */
5277 SCIP_CONS* cons /**< constraint data */
5278 )
5279{
5280 SCIP_CONSDATA* consdata;
5281
5282 assert(scip != NULL);
5283 assert(cons != NULL);
5284
5286
5287 consdata = SCIPconsGetData(cons);
5288 assert(consdata != NULL);
5289
5290 consdataSort(consdata);
5291 assert(consdata->sorted);
5292
5293 return SCIP_OKAY;
5294}
#define EVENTHDLR_NAME
#define EVENTHDLR_DESC
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition cons_and.c:957
enum Proprule PROPRULE
Definition cons_and.c:172
static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
Definition cons_and.c:500
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition cons_and.c:581
static SCIP_RETCODE consdataCatchWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
Definition cons_and.c:242
static SCIP_RETCODE consdataDropEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_and.c:315
#define DEFAULT_DUALPRESOLVING
Definition cons_and.c:109
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *nchgcoefs, int *ndelconss, int *nupgdconss, int *naddconss)
Definition cons_and.c:2011
static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
Definition cons_and.c:341
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:96
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:89
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition cons_and.c:666
#define CONSHDLR_CHECKPRIORITY
Definition cons_and.c:88
#define CONSHDLR_DESC
Definition cons_and.c:85
static SCIP_RETCODE consdataFixOperandsOne(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_Bool *cutoff, int *nfixedvars)
Definition cons_and.c:1338
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *separated, SCIP_Bool *cutoff)
Definition cons_and.c:1182
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
Definition cons_and.c:606
static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:910
#define CONSHDLR_PROP_TIMING
Definition cons_and.c:99
#define HASHSIZE_ANDCONS
Definition cons_and.c:111
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition cons_and.c:229
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition cons_and.c:195
static SCIP_RETCODE analyzeZeroResultant(SCIP *scip, SCIP_CONS *cons, int watchedvar1, int watchedvar2, SCIP_Bool *cutoff, int *nfixedvars)
Definition cons_and.c:1501
#define DEFAULT_UPGRRESULTANT
Definition cons_and.c:108
#define CONSHDLR_MAXPREROUNDS
Definition cons_and.c:93
static SCIP_RETCODE consdataFixResultantZero(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *resvar, int pos, SCIP_Bool *cutoff, int *nfixedvars)
Definition cons_and.c:1299
#define DEFAULT_PRESOLPAIRWISE
Definition cons_and.c:104
#define CONSHDLR_SEPAPRIORITY
Definition cons_and.c:86
static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons, int falsepos)
Definition cons_and.c:1231
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition cons_and.c:3391
#define DEFAULT_LINEARIZE
Definition cons_and.c:105
static SCIP_RETCODE cliquePresolve(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *nchgcoefs, int *ndelconss, int *naddconss)
Definition cons_and.c:2667
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Bool *cutoff, int *naggrvars, int *nbdchgs, int *ndelconss)
Definition cons_and.c:3565
static SCIP_RETCODE consdataLinearize(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nupgdconss)
Definition cons_and.c:1392
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
Definition cons_and.c:3765
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition cons_and.c:181
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition cons_and.c:401
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
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool *violated)
Definition cons_and.c:1070
#define DEFAULT_PRESOLUSEHASHING
Definition cons_and.c:112
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_and.c:531
static SCIP_RETCODE consdataDropWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int filterpos)
Definition cons_and.c:266
#define MINGAINPERNMINCOMPARISONS
Definition cons_and.c:114
static SCIP_RETCODE analyzeConflictZero(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:1263
#define CONSHDLR_PROPFREQ
Definition cons_and.c:90
#define NMINCOMPARISONS
Definition cons_and.c:113
#define DEFAULT_ENFORCECUTS
Definition cons_and.c:106
#define CONSHDLR_PRESOLTIMING
Definition cons_and.c:98
static void consdataSort(SCIP_CONSDATA *consdata)
Definition cons_and.c:729
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:1017
#define CONSHDLR_EAGERFREQ
Definition cons_and.c:91
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_and.c:209
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr, int nvars, SCIP_VAR **vars, SCIP_VAR *resvar)
Definition cons_and.c:425
#define CONSHDLR_ENFOPRIORITY
Definition cons_and.c:87
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int *nchgcoefs)
Definition cons_and.c:810
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition cons_and.c:1925
#define CONSHDLR_DELAYSEPA
Definition cons_and.c:94
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, int *nfixedvars, int *nchgcoefs, int *ndelconss)
Definition cons_and.c:1562
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_RESULT *result)
Definition cons_and.c:3508
#define CONSHDLR_NAME
Definition cons_and.c:84
#define DEFAULT_AGGRLINEARIZATION
Definition cons_and.c:107
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *nupgdconss)
Definition cons_and.c:1720
#define CONSHDLR_DELAYPROP
Definition cons_and.c:95
static SCIP_RETCODE consdataCatchEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition cons_and.c:289
Constraint handler for AND constraints, .
Constraint handler for linear constraints in their most general form, .
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
constraint handler for pseudoboolean constraints
Constraint handler for the set partitioning / packing / covering constraints .
methods for debugging
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#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 MAX(x, y)
Definition def.h:229
#define SCIPABORT()
Definition def.h:336
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
#define SCIP_CALL_FINALLY(x, y)
Definition def.h:406
product expression handler
variable expression handler
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_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:5238
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:5199
SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPsortAndCons(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:5275
SCIP_Bool SCIPisAndConsSorted(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:5256
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition cons_and.c:5218
SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsBasicAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars)
Definition cons_and.c:5180
SCIP_RETCODE SCIPincludeConshdlrAnd(SCIP *scip)
Definition cons_and.c:4971
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition scip_copy.c:713
SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_var.c:397
SCIP_RETCODE SCIPcreateExprProduct(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real coefficient, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition misc.c:501
void SCIPgmlWriteClosing(FILE *file)
Definition misc.c:703
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition misc.c:687
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition misc.c:643
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
int SCIPgetNIntVars(SCIP *scip)
Definition scip_prob.c:2340
SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
Definition scip_prob.c:3368
int SCIPgetNImplVars(SCIP *scip)
Definition scip_prob.c:2387
int SCIPgetNContVars(SCIP *scip)
Definition scip_prob.c:2569
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition scip_prob.c:2115
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3304
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3061
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition misc.c:3179
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition misc.c:2348
#define SCIPhashFour(a, b, c, d)
Definition pub_misc.h:573
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition misc.c:2298
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition misc.c:2596
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition misc.c:2535
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 SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
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 SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:670
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:492
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_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:444
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:693
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4340
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:516
SCIP_RETCODE 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
int SCIPconsGetPos(SCIP_CONS *cons)
Definition cons.c:8403
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 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 SCIPconsIsAdded(SCIP_CONS *cons)
Definition cons.c:8822
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition scip_cons.c:1524
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8672
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
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
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition scip_expr.c:1443
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
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_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition scip_nlp.c:1058
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition nlp.c:1953
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition scip_nlp.c:954
SCIP_Bool SCIPinProbing(SCIP *scip)
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 SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition scip_tree.c:146
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
Definition scip_tree.c:436
SCIP_NODE * SCIPgetRootNode(SCIP *scip)
Definition scip_tree.c:110
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5210
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition var.c:17575
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23900
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition scip_var.c:2119
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition scip_var.c:10909
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition var.c:23976
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
Definition scip_var.c:2283
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_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17595
SCIP_RETCODE SCIPchgVarImplType(SCIP *scip, SCIP_VAR *var, SCIP_IMPLINTTYPE impltype, SCIP_Bool *infeasible)
Definition scip_var.c:10218
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition scip_var.c:728
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
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
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition var.c:23694
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
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_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:11057
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition scip_var.c:10318
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2736
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition var.c:17319
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition var.c:17687
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_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition var.c:16852
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition scip_var.c:2078
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1853
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition scip_var.c:10984
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
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
SCIP_Real obj
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
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:437
public methods for managing constraints
public methods for managing events
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
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
public functions to work with algebraic expressions
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 nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for 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_CONSINITPRE(x)
Definition type_cons.h:156
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:867
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:201
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:769
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#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_CONSACTIVE(x)
Definition type_cons.h:691
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:845
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:706
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:561
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:259
#define SCIP_DECL_CONSEXITPRE(x)
Definition type_cons.h:180
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:676
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:810
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:474
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:108
#define SCIP_DECL_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_Expr SCIP_EXPR
Definition type_expr.h:55
@ SCIP_EXPRCURV_UNKNOWN
Definition type_expr.h:62
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
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
struct SCIP_HashTable SCIP_HASHTABLE
Definition type_misc.h:88
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
@ 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_WRITEERROR
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_EXITPRESOLVE
Definition type_set.h:50
@ 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_AND
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition type_timing.h:54
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_IMPLINTTYPE_STRONG
Definition type_var.h:106
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
@ SCIP_VARTYPE_INTEGER
Definition type_var.h:65
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141