SCIP Doxygen Documentation
Loading...
Searching...
No Matches
cons_logicor.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_logicor.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief Constraint handler for logic or constraints \f$1^T x \ge 1\f$
28 * (equivalent to set covering, but algorithms are suited for depth first search).
29 * @author Tobias Achterberg
30 * @author Michael Winkler
31 */
32
33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34
36#include "scip/cons_linear.h"
37#include "scip/cons_logicor.h"
38#include "scip/cons_setppc.h"
39#include "scip/presolve.h"
40#include "scip/pub_conflict.h"
41#include "scip/pub_cons.h"
42#include "scip/pub_event.h"
43#include "scip/pub_lp.h"
44#include "scip/pub_message.h"
45#include "scip/pub_misc.h"
46#include "scip/pub_misc_sort.h"
47#include "scip/pub_var.h"
48#include "scip/scip_conflict.h"
49#include "scip/scip_cons.h"
50#include "scip/scip_cut.h"
51#include "scip/scip_event.h"
52#include "scip/scip_general.h"
53#include "scip/scip_lp.h"
54#include "scip/scip_mem.h"
55#include "scip/scip_message.h"
56#include "scip/scip_nlp.h"
57#include "scip/scip_numerics.h"
58#include "scip/scip_param.h"
59#include "scip/scip_prob.h"
60#include "scip/scip_probing.h"
61#include "scip/scip_sol.h"
63#include "scip/scip_tree.h"
64#include "scip/scip_var.h"
65#include "scip/symmetry_graph.h"
67
68
69#define CONSHDLR_NAME "logicor"
70#define CONSHDLR_DESC "logic or constraints"
71#define CONSHDLR_SEPAPRIORITY +10000 /**< priority of the constraint handler for separation */
72#define CONSHDLR_ENFOPRIORITY -2000000 /**< priority of the constraint handler for constraint enforcing */
73#define CONSHDLR_CHECKPRIORITY -2000000 /**< priority of the constraint handler for checking feasibility */
74#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
75#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
76#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
77 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
78#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
79#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
80#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
81#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
82
83#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_ALWAYS
84#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
85
86#define LINCONSUPGD_PRIORITY +800000 /**< priority of the constraint handler for upgrading of linear constraints */
87
88#define EVENTHDLR_NAME "logicor"
89#define EVENTHDLR_DESC "event handler for logic or constraints"
90
91#define CONFLICTHDLR_NAME "logicor"
92#define CONFLICTHDLR_DESC "conflict handler creating logic or constraints"
93#define CONFLICTHDLR_PRIORITY LINCONSUPGD_PRIORITY
94
95#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
96#define DEFAULT_STRENGTHEN TRUE /**< should pairwise constraint comparison try to strengthen constraints by removing superflous non-zeros? */
97
98#define HASHSIZE_LOGICORCONS 500 /**< minimal size of hash table in logicor constraint tables */
99#define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
100#define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
101#define DEFAULT_NEGATEDCLIQUE TRUE /**< should negated clique information be used in presolving */
102#define DEFAULT_COPYTYPEDCONS FALSE /**< should logicor constraints be copied as logicor instead of linear? */
103#define DEFAULT_IMPLICATIONS TRUE /**< should we try to shrink the variables and derive global boundchanges by
104 * using cliques and implications */
105
106/* @todo make this a parameter setting */
107#if 1 /* @todo test which AGEINCREASE formula is better! */
108#define AGEINCREASE(n) (1.0 + 0.2 * (n))
109#else
110#define AGEINCREASE(n) (0.1 * (n))
111#endif
112
113
114/* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
115
116/*
117 * Data structures
118 */
119
120/** constraint handler data */
121struct SCIP_ConshdlrData
122{
123 SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
124 SCIP_CONSHDLR* conshdlrlinear; /**< pointer to linear constraint handler or NULL if not included */
125 SCIP_CONSHDLR* conshdlrsetppc; /**< pointer to setppc constraint handler or NULL if not included */
126 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
127 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in
128 * advance */
129 SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
130 SCIP_Bool usenegatedclique; /**< should negated clique information be used in presolving */
131 SCIP_Bool useimplications; /**< should we try to shrink the variables and derive global boundchanges
132 * by using clique and implications */
133 SCIP_Bool usestrengthening; /**< should pairwise constraint comparison try to strengthen constraints by
134 * removing superflous non-zeros? */
135 SCIP_Bool copytypedcons; /**< should logicor constraints be copied as logicor instead of linear? */
136 int nlastcliquesneg; /**< number of cliques after last negated clique presolving round */
137 int nlastimplsneg; /**< number of implications after last negated clique presolving round */
138 int nlastcliquesshorten;/**< number of cliques after last shortening of constraints */
139 int nlastimplsshorten; /**< number of implications after last shortening of constraints */
140};
141
142/* @todo it might speed up exit-presolve to remember all positions for variables when catching the varfixed event, or we
143 * change catching and dropping the events like it is done in cons_setppc, which probably makes the code more
144 * clear
145 */
146
147/** logic or constraint data */
148struct SCIP_ConsData
149{
150 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
151 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
152 SCIP_VAR** vars; /**< variables of the constraint */
153 int varssize; /**< size of vars array */
154 int nvars; /**< number of variables in the constraint */
155 int watchedvar1; /**< position of the first watched variable */
156 int watchedvar2; /**< position of the second watched variable */
157 int filterpos1; /**< event filter position of first watched variable */
158 int filterpos2; /**< event filter position of second watched variable */
159 unsigned int signature; /**< constraint signature which is need for pairwise comparison */
160 unsigned int presolved:1; /**< flag indicates if we have some fixed, aggregated or multi-aggregated
161 * variables
162 */
163 unsigned int impladded:1; /**< was the 2-variable logic or constraint already added as implication? */
164 unsigned int sorted:1; /**< are the constraint's variables sorted? */
165 unsigned int changed:1; /**< was constraint changed since last redundancy round in preprocessing? */
166 unsigned int merged:1; /**< are the constraint's equal/negated variables already merged? */
167 unsigned int existmultaggr:1; /**< does this constraint contain aggregations */
168 unsigned int validsignature:1; /**< is the signature valid */
169};
170
171
172/*
173 * Local methods
174 */
175
176/** installs rounding locks for the given variable in the given logic or constraint */
177static
179 SCIP* scip, /**< SCIP data structure */
180 SCIP_CONS* cons, /**< logic or constraint */
181 SCIP_VAR* var /**< variable of constraint entry */
182 )
183{
185
186 return SCIP_OKAY;
187}
188
189/** removes rounding locks for the given variable in the given logic or constraint */
190static
192 SCIP* scip, /**< SCIP data structure */
193 SCIP_CONS* cons, /**< logic or constraint */
194 SCIP_VAR* var /**< variable of constraint entry */
195 )
196{
198
199 return SCIP_OKAY;
200}
201
202/** creates constraint handler data for logic or constraint handler */
203static
205 SCIP* scip, /**< SCIP data structure */
206 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
207 SCIP_EVENTHDLR* eventhdlr /**< event handler */
208 )
209{
210 assert(scip != NULL);
211 assert(conshdlrdata != NULL);
212 assert(eventhdlr != NULL);
213
214 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
215
216 (*conshdlrdata)->nlastcliquesneg = 0;
217 (*conshdlrdata)->nlastimplsneg = 0;
218 (*conshdlrdata)->nlastcliquesshorten = 0;
219 (*conshdlrdata)->nlastimplsshorten = 0;
220
221 /* set event handler for catching events on watched variables */
222 (*conshdlrdata)->eventhdlr = eventhdlr;
223
224 return SCIP_OKAY;
225}
226
227/** frees constraint handler data for logic or constraint handler */
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/** ensures, that the vars array can store at least num entries */
241static
243 SCIP* scip, /**< SCIP data structure */
244 SCIP_CONSDATA* consdata, /**< logicor constraint data */
245 int num /**< minimum number of entries to store */
246 )
247{
248 assert(consdata != NULL);
249 assert(consdata->nvars <= consdata->varssize);
250
251 if( num > consdata->varssize )
252 {
253 int newsize;
254
255 newsize = SCIPcalcMemGrowSize(scip, num);
256 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
257 consdata->varssize = newsize;
258 }
259 assert(num <= consdata->varssize);
260
261 return SCIP_OKAY;
262}
263
264/** creates a logic or constraint data object */
265static
267 SCIP* scip, /**< SCIP data structure */
268 SCIP_CONSDATA** consdata, /**< pointer to store the logic or constraint data */
269 int nvars, /**< number of variables in the constraint */
270 SCIP_VAR** vars /**< variables of the constraint */
271 )
272{
273 int v;
274
275 assert(consdata != NULL);
276 assert(nvars == 0 || vars != NULL);
277
278 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
279
280 (*consdata)->row = NULL;
281 (*consdata)->nlrow = NULL;
282 if( nvars > 0 )
283 {
284 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
285 (*consdata)->varssize = nvars;
286 (*consdata)->nvars = nvars;
287 }
288 else
289 {
290 (*consdata)->vars = NULL;
291 (*consdata)->varssize = 0;
292 (*consdata)->nvars = 0;
293 }
294 (*consdata)->watchedvar1 = -1;
295 (*consdata)->watchedvar2 = -1;
296 (*consdata)->filterpos1 = -1;
297 (*consdata)->filterpos2 = -1;
298 (*consdata)->presolved = FALSE;
299 (*consdata)->impladded = FALSE;
300 (*consdata)->changed = TRUE;
301 (*consdata)->sorted = (nvars <= 1);
302 (*consdata)->merged = (nvars <= 1);
303 (*consdata)->existmultaggr = FALSE;
304 (*consdata)->validsignature = FALSE;
305
306 /* get transformed variables, if we are in the transformed problem */
308 {
309 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
310
311 /* check for multi-aggregations and capture variables */
312 for( v = 0; v < (*consdata)->nvars; v++ )
313 {
314 SCIP_VAR* var = SCIPvarGetProbvar((*consdata)->vars[v]);
315 assert(var != NULL);
316 (*consdata)->existmultaggr = (*consdata)->existmultaggr || (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
317 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
318 }
319 }
320 else
321 {
322 /* capture variables */
323 for( v = 0; v < (*consdata)->nvars; v++ )
324 {
325 assert((*consdata)->vars[v] != NULL);
326 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
327 }
328 }
329
330 return SCIP_OKAY;
331}
332
333/** frees a logic or constraint data */
334static
336 SCIP* scip, /**< SCIP data structure */
337 SCIP_CONSDATA** consdata /**< pointer to the logic or constraint */
338 )
339{
340 int v;
341
342 assert(consdata != NULL);
343 assert(*consdata != NULL);
344
345 /* release the row */
346 if( (*consdata)->row != NULL )
347 {
348 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
349 }
350
351 /* release the nlrow */
352 if( (*consdata)->nlrow != NULL )
353 {
354 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
355 }
356
357 /* release variables */
358 for( v = 0; v < (*consdata)->nvars; v++ )
359 {
360 assert((*consdata)->vars[v] != NULL);
361 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
362 }
363
364 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
365 SCIPfreeBlockMemory(scip, consdata);
366
367 return SCIP_OKAY;
368}
369
370/** prints logic or constraint to file stream */
371static
373 SCIP* scip, /**< SCIP data structure */
374 SCIP_CONSDATA* consdata, /**< logic or constraint data */
375 FILE* file, /**< output file (or NULL for standard output) */
376 SCIP_Bool endline /**< should an endline be set? */
377 )
378{
379 assert(consdata != NULL);
380
381 /* print constraint type */
382 SCIPinfoMessage(scip, file, "logicor(");
383
384 /* print variable list */
385 SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
386
387 /* close bracket */
388 SCIPinfoMessage(scip, file, ")");
389
390 if( endline )
391 SCIPinfoMessage(scip, file, "\n");
392
393 return SCIP_OKAY;
394}
395
396/** stores the given variable numbers as watched variables, and updates the event processing */
397static
399 SCIP* scip, /**< SCIP data structure */
400 SCIP_CONS* cons, /**< logic or constraint */
401 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
402 int watchedvar1, /**< new first watched variable */
403 int watchedvar2 /**< new second watched variable */
404 )
405{
406 SCIP_CONSDATA* consdata;
407
408 consdata = SCIPconsGetData(cons);
409 assert(consdata != NULL);
410 assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
411 assert(watchedvar1 != -1 || watchedvar2 == -1);
412 assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
413 assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
414
415 /* if one watched variable is equal to the old other watched variable, just switch positions */
416 if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
417 {
418 int tmp;
419
420 tmp = consdata->watchedvar1;
421 consdata->watchedvar1 = consdata->watchedvar2;
422 consdata->watchedvar2 = tmp;
423 tmp = consdata->filterpos1;
424 consdata->filterpos1 = consdata->filterpos2;
425 consdata->filterpos2 = tmp;
426 }
427 assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
428 assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
429
430 /* drop events on old watched variables */
431 if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
432 {
433 assert(consdata->filterpos1 != -1);
434 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1],
436 consdata->filterpos1) );
437 }
438 if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
439 {
440 assert(consdata->filterpos2 != -1);
441 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2],
443 consdata->filterpos2) );
444 }
445
446 /* catch events on new watched variables */
447 if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
448 {
449 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar1],
451 &consdata->filterpos1) );
452 }
453 if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
454 {
455 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar2],
457 &consdata->filterpos2) );
458 }
459
460 /* set the new watched variables */
461 consdata->watchedvar1 = watchedvar1;
462 consdata->watchedvar2 = watchedvar2;
463
464 return SCIP_OKAY;
465}
466
467/** adds coefficient in logicor constraint */
468static
470 SCIP* scip, /**< SCIP data structure */
471 SCIP_CONS* cons, /**< logicor constraint */
472 SCIP_VAR* var /**< variable to add to the constraint */
473 )
474{
475 SCIP_CONSDATA* consdata;
476 SCIP_Bool transformed;
477
478 assert(var != NULL);
479
480 consdata = SCIPconsGetData(cons);
481 assert(consdata != NULL);
482
483 /* are we in the transformed problem? */
484 transformed = SCIPconsIsTransformed(cons);
485
486 /* always use transformed variables in transformed constraints */
487 if( transformed )
488 {
490
491 if( !consdata->existmultaggr && SCIPvarGetStatus(SCIPvarGetProbvar(var)) == SCIP_VARSTATUS_MULTAGGR )
492 consdata->existmultaggr = TRUE;
493
494 consdata->presolved = FALSE;
495 }
496 assert(var != NULL);
497 assert(transformed == SCIPvarIsTransformed(var));
498
499 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars + 1) );
500 consdata->vars[consdata->nvars] = var;
501 SCIP_CALL( SCIPcaptureVar(scip, consdata->vars[consdata->nvars]) );
502 consdata->nvars++;
503
504 /* we only catch this event in presolving stage */
506 {
507 SCIP_CONSHDLRDATA* conshdlrdata;
508 SCIP_CONSHDLR* conshdlr;
509
511 assert(conshdlr != NULL);
512 conshdlrdata = SCIPconshdlrGetData(conshdlr);
513 assert(conshdlrdata != NULL);
514
515 SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
516 (SCIP_EVENTDATA*)cons, NULL) );
517 }
518
519 consdata->sorted = (consdata->nvars == 1);
520 consdata->changed = TRUE;
521 consdata->validsignature = FALSE;
522
523 /* install the rounding locks for the new variable */
524 SCIP_CALL( lockRounding(scip, cons, var) );
525
526 /* add the new coefficient to the LP row */
527 if( consdata->row != NULL )
528 {
529 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, 1.0) );
530 }
531
532 consdata->merged = FALSE;
533
534 return SCIP_OKAY;
535}
536
537/** deletes coefficient at given position from logic or constraint data */
538static
540 SCIP* scip, /**< SCIP data structure */
541 SCIP_CONS* cons, /**< logic or constraint */
542 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
543 int pos /**< position of coefficient to delete */
544 )
545{
546 SCIP_CONSDATA* consdata;
547
548 assert(eventhdlr != NULL);
549
550 consdata = SCIPconsGetData(cons);
551 assert(consdata != NULL);
552 assert(0 <= pos && pos < consdata->nvars);
553 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
554
555 /* remove the rounding locks of variable */
556 SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
557
558 /* we only catch this event in presolving stage, so we need to only drop it there */
560 {
561 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], SCIP_EVENTTYPE_VARFIXED, eventhdlr,
562 (SCIP_EVENTDATA*)cons, -1) );
563 }
564
565 if( SCIPconsIsTransformed(cons) )
566 {
567 /* if the position is watched, stop watching the position */
568 if( consdata->watchedvar1 == pos )
569 {
570 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar2, -1) );
571 }
572 if( consdata->watchedvar2 == pos )
573 {
574 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, -1) );
575 }
576 }
577 assert(pos != consdata->watchedvar1);
578 assert(pos != consdata->watchedvar2);
579
580 /* release variable */
581 SCIP_CALL( SCIPreleaseVar(scip, &consdata->vars[pos]) );
582
583 /* move the last variable to the free slot */
584 if( pos != consdata->nvars - 1 )
585 {
586 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
587 consdata->sorted = FALSE;
588 }
589 consdata->nvars--;
590
591 /* if the last variable (that moved) was watched, update the watched position */
592 if( consdata->watchedvar1 == consdata->nvars )
593 consdata->watchedvar1 = pos;
594 if( consdata->watchedvar2 == consdata->nvars )
595 consdata->watchedvar2 = pos;
596
597 consdata->changed = TRUE;
598 consdata->validsignature = FALSE;
599
601
602 return SCIP_OKAY;
603}
604
605/** in case a part (more than one variable) in the logic or constraint is independent of every else, we can perform dual
606 * reductions;
607 * - fix the variable with the smallest object coefficient to one if the constraint is not modifiable and all
608 * variable are independant
609 * - fix all independant variables with negative object coefficient to one
610 * - fix all remaining independant variables to zero
611 *
612 * also added the special case were exactly one variable is locked by this constraint and another variable without any
613 * uplocks has a better objective value than this single variable
614 * - here we fix the variable to 0.0 (if the objective contribution is non-negative)
615 *
616 * Moreover, if there exists a variable that is only locked by a constraint with two variables, one can aggregate variables.
617 *
618 * Note: the following dual reduction for logic or constraints is already performed by the presolver "dualfix"
619 * - if a variable in a set covering constraint is only locked by that constraint and has negative or zero
620 * objective coefficient than it can be fixed to one
621 */
622static
624 SCIP* scip, /**< SCIP data structure */
625 SCIP_CONS* cons, /**< setppc constraint */
626 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
627 int* nfixedvars, /**< pointer to count number of fixings */
628 int* ndelconss, /**< pointer to count number of deleted constraints */
629 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
630 int* naggrvars, /**< pointer to count number of variables aggregated */
631 SCIP_RESULT* result /**< pointer to store the result SCIP_SUCCESS, if presolving was performed */
632 )
633{
634 SCIP_CONSDATA* consdata;
635 SCIP_VAR** vars;
636 SCIP_VAR* var;
637 SCIP_VAR* activevar;
638 SCIP_Real bestobjval;
639 SCIP_Real bestobjvalnouplocks;
641 SCIP_Real fixval;
642 SCIP_Bool infeasible;
643 SCIP_Bool fixed;
644 SCIP_Bool negated;
645 int nfixables;
646 int nvars;
647 int idx;
648 int indepidx = -1;
649 int idxnouplocks;
650 int v;
651
652 assert(scip != NULL);
653 assert(cons != NULL);
654 assert(eventhdlr != NULL);
655 assert(nfixedvars != NULL);
656 assert(ndelconss != NULL);
657 assert(nchgcoefs != NULL);
658 assert(result != NULL);
659
660 /* constraints for which the check flag is set to FALSE, did not contribute to the lock numbers; therefore, we cannot
661 * use the locks to decide for a dual reduction using this constraint; for example after a restart the cuts which are
662 * added to the problems have the check flag set to FALSE
663 */
664 if( !SCIPconsIsChecked(cons) )
665 return SCIP_OKAY;
666
668
669 consdata = SCIPconsGetData(cons);
670 assert(consdata != NULL);
671
672 nvars = consdata->nvars;
673
674 /* we don't want to consider small constraints (note that the constraints can be modifiable, so we can't delete this
675 * constraint)
676 */
677 if( nvars < 2 )
678 return SCIP_OKAY;
679
680 vars = consdata->vars;
681 idx = -1;
682 idxnouplocks = -1;
683 bestobjval = SCIP_INVALID;
684 bestobjvalnouplocks = SCIP_INVALID;
685
686 nfixables = 0;
687
688 /* check if we can apply the dual reduction; therefore count the number of variables where the logic or has the only
689 * locks on
690 */
691 for( v = nvars - 1; v >= 0; --v )
692 {
693 var = vars[v];
694 assert(var != NULL);
695
696 /* variables with varstatus not equal to SCIP_VARSTATUS_FIXED can also have fixed bounds, but were not removed yet */
697 if( SCIPvarGetUbGlobal(var) < 0.5 )
698 {
699#ifndef NDEBUG
700 SCIP_VAR* bestvar = NULL;
701#endif
702 if( idx == consdata->nvars - 1 )
703 {
704#ifndef NDEBUG
705 bestvar = consdata->vars[idx];
706#endif
707 idx = v;
708 }
709
710 if( idxnouplocks == consdata->nvars - 1 )
711 idxnouplocks = v;
712
713 if( indepidx == consdata->nvars - 1 )
714 indepidx = v;
715
716 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
717 ++(*nchgcoefs);
718
719 assert(bestvar == NULL || bestvar == consdata->vars[v]);
720
721 continue;
722 }
723 if( SCIPvarGetLbGlobal(var) > 0.5 )
724 {
725 /* remove constraint since it is redundant */
726 SCIP_CALL( SCIPdelCons(scip, cons) );
727 ++(*ndelconss);
728
729 return SCIP_OKAY;
730 }
731
732 /* remember best variable with no uplocks, this variable dominates all other with exactly one downlock */
735 {
737
738 /* check if the current variable has a smaller objective coefficient then the best one */
739 if( SCIPisLT(scip, objval, bestobjval) )
740 {
741 idxnouplocks = v;
742 bestobjvalnouplocks = objval;
743 }
744 }
745
746 /* in case an other constraints has also locks on that variable we cannot perform a dual reduction on these
747 * variables
748 */
751 continue;
752
753 ++nfixables;
754 negated = FALSE;
755
756 /* get the active variable */
759
760 if( negated )
762 else
764
765 /* check if the current variable has a smaller objective coefficient */
766 if( SCIPisLT(scip, objval, bestobjval) )
767 {
768 idx = v;
769 bestobjval = objval;
770 }
771
772 if ( objval >= 0.0 )
773 indepidx = v;
774 }
775
776 nvars = consdata->nvars;
777
778 /* In the special case of two variables, where one variable is independent and is minimized, we can aggregate variables:
779 * We have var1 + var2 >= 1 and var1 is independent with positive objective. Then var1 + var2 == 1 holds. */
780 if( nvars == 2 && indepidx >= 0 )
781 {
782 SCIP_Bool redundant;
783 SCIP_Bool aggregated;
784 int idx2;
785
786 idx2 = 1 - indepidx;
787 assert(0 <= idx2 && idx2 < 2);
788
789 SCIP_CALL( SCIPaggregateVars(scip, vars[indepidx], vars[idx2], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
790 assert(!infeasible);
791 assert(redundant);
792 assert(aggregated);
793 ++(*naggrvars);
794
795 /* remove constraint since it is now redundant */
796 SCIP_CALL( SCIPdelCons(scip, cons) );
797 ++(*ndelconss);
798
800
801 return SCIP_OKAY;
802 }
803
804 /* check if we have a single variable dominated by another */
805 if( nfixables == 1 && idxnouplocks >= 0 )
806 {
807 assert(bestobjvalnouplocks != SCIP_INVALID); /*lint !e777*/
808
809 for( v = nvars - 1; v >= 0; --v )
810 {
811 var = vars[v];
812 assert(var != NULL);
813
814 /* check if a variable only appearing in this constraint is dominated by another */
817 {
818 assert(idxnouplocks != v);
819
821
822 if( SCIPisGE(scip, objval, bestobjvalnouplocks) && !SCIPisNegative(scip, objval) )
823 {
824 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
825 assert(!infeasible);
826 assert(fixed);
827
828 SCIPdebugMsg(scip, " -> dual fixing <%s> == 0.0\n", SCIPvarGetName(var));
829 ++(*nfixedvars);
830 }
831
832 break;
833 }
834 }
835 }
836
837 if( nfixables < 2 )
838 return SCIP_OKAY;
839
840 nvars = consdata->nvars;
841
842 assert(idx >= 0 && idx < nvars);
843 assert(bestobjval < SCIPinfinity(scip));
844
846
847 /* fix all redundant variables to their best bound */
848
849 /* first part of all variables */
850 for( v = 0; v < nvars; ++v )
851 {
852 var = vars[v];
853 assert(var != NULL);
854
855 /* in case an other constraints has also locks on that variable we cannot perform a dual reduction on these
856 * variables
857 */
860 continue;
861
862 if( v == idx )
863 continue;
864
865 activevar = var;
866 negated = FALSE;
867
868 /* get the active variable */
869 SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
870 assert(SCIPvarIsActive(activevar));
871
872 if( negated )
873 objval = -SCIPvarGetObj(activevar);
874 else
875 objval = SCIPvarGetObj(activevar);
876
877 if( objval > 0.0 )
878 fixval = 0.0;
879 else
880 fixval = 1.0;
881
882 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
883 assert(!infeasible);
884 assert(fixed);
885
886 SCIPdebugMsg(scip, " -> dual fixing <%s> == %g\n", SCIPvarGetName(var), fixval);
887 ++(*nfixedvars);
888 }
889
890 /* if all variable have our appreciated number of locks and the constraint is not modifiable, or if the bestobjval is
891 * less than or equal to zero, we can fix the variable with the smallest objective coefficient to one and the
892 * constraint gets redundant
893 */
894 if( (nfixables == nvars && !SCIPconsIsModifiable(cons)) || bestobjval <= 0.0 )
895 {
896 SCIP_CALL( SCIPfixVar(scip, vars[idx], 1.0, &infeasible, &fixed) );
897 assert(!infeasible);
898 assert(fixed);
899
900 SCIPdebugMsg(scip, " -> fixed <%s> == 1.0\n", SCIPvarGetName(vars[idx]));
901 ++(*nfixedvars);
902
903 /* remove constraint since it is now redundant */
904 SCIP_CALL( SCIPdelCons(scip, cons) );
905 ++(*ndelconss);
906 }
907
908 return SCIP_OKAY;
909}
910
911/** deletes all zero-fixed variables, checks for variables fixed to one, replace all variables which are not active or
912 * not a negation of an active variable by their active or negation of an active counterpart
913 */
914static
916 SCIP* scip, /**< SCIP data structure */
917 SCIP_CONS* cons, /**< logic or constraint */
918 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
919 SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
920 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
921 int* naddconss, /**< pointer to count number of added constraints, or NULL indicating we
922 * can not resolve multi-aggregations
923 */
924 int* ndelconss /**< pointer to count number of deleted constraints, or NULL indicating we
925 * can not resolve multi-aggregations
926 */
927 )
928{
929 SCIP_CONSDATA* consdata;
930 SCIP_VAR* var;
931 int v;
932 SCIP_VAR** vars;
933 SCIP_Bool* negarray;
934 int nvars;
935
936 assert(eventhdlr != NULL);
937 assert(redundant != NULL);
938
939 consdata = SCIPconsGetData(cons);
940 assert(consdata != NULL);
941 assert(consdata->nvars == 0 || consdata->vars != NULL);
942
943 *redundant = FALSE;
944 v = 0;
945
946 /* all multi-aggregations should be resolved */
947 consdata->existmultaggr = FALSE;
948 consdata->presolved = TRUE;
949
950 /* remove zeros and mark constraint redundant when found one variable fixed to one */
951 while( v < consdata->nvars )
952 {
953 var = consdata->vars[v];
955
956 if( SCIPvarGetLbGlobal(var) > 0.5 )
957 {
959 *redundant = TRUE;
960
961 return SCIP_OKAY;
962 }
963 else if( SCIPvarGetUbGlobal(var) < 0.5 )
964 {
966 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
967 ++(*nchgcoefs);
968 }
969 else
970 ++v;
971 }
972
973 if( consdata->nvars == 0 )
974 return SCIP_OKAY;
975
976 nvars = consdata->nvars;
977
978 /* allocate temporary memory */
981
982 /* get active or negation of active variables */
983 SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, consdata->vars, vars, negarray) );
984
985 /* renew all variables, important that we do a backwards loop because deletion only affects rear items */
986 for( v = nvars - 1; v >= 0; --v )
987 {
988 var = vars[v];
989
990 /* resolve multi-aggregation */
992 {
993 SCIP_VAR** consvars;
994 SCIP_Real* consvals;
995 SCIP_Real constant = 0.0;
996 SCIP_Bool easycase;
997 int nconsvars;
998 int requiredsize;
999 int size = 1;
1000 int v2;
1001
1002 nconsvars = 1;
1003 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 1) );
1004 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 1) );
1005 consvars[0] = var;
1006 consvals[0] = 1.0;
1007
1008 /* get active variables for new constraint */
1009 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
1010 /* if space was not enough we need to resize the buffers */
1011 if( requiredsize > size )
1012 {
1013 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
1014 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
1015 size = requiredsize;
1016
1017 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
1018 assert(requiredsize <= size);
1019 }
1020 assert(requiredsize == nconsvars);
1021
1022 easycase = FALSE;
1023
1024 if( SCIPisZero(scip, constant) )
1025 {
1026 /* add active representation */
1027 for( v2 = nconsvars - 1; v2 >= 0; --v2 )
1028 {
1029 if( !SCIPvarIsBinary(consvars[v2]) )
1030 break;
1031
1032 if( !SCIPisEQ(scip, consvals[v2], 1.0) )
1033 break;
1034 }
1035
1036 if( v2 < 0 )
1037 easycase = TRUE;
1038 }
1039
1040 /* we can easily add the coefficients and still have a logicor constraint */
1041 if( easycase )
1042 {
1043 /* delete old (multi-aggregated) variable */
1044 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1045 ++(*nchgcoefs);
1046
1047 /* add active representation */
1048 for( v2 = nconsvars - 1; v2 >= 0; --v2 )
1049 {
1050 assert(SCIPvarIsBinary(consvars[v2]));
1051 assert(SCIPvarIsActive(consvars[v2]) || (SCIPvarGetStatus(consvars[v2]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(consvars[v2]))));
1052
1053 SCIP_CALL( addCoef(scip, cons, consvars[v2]) );
1054 ++(*nchgcoefs);
1055 }
1056 }
1057 /* we need to degrade this logicor constraint to a linear constraint */
1058 else if( (ndelconss != NULL && naddconss != NULL) || SCIPconsIsAdded(cons) )
1059 {
1060 char name[SCIP_MAXSTRLEN];
1061 SCIP_CONS* newcons;
1062 SCIP_Real lhs;
1063 SCIP_Real rhs;
1064 int k;
1065
1066 /* it might happen that there is more than one multi-aggregated variable, so we need to get the whole probvar sum over all variables */
1067
1068 size = MAX(nconsvars, 1) + nvars - 1;
1069
1070 /* memory needed is at least old number of variables - 1 + number of variables in first multi-aggregation */
1071 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, size) );
1072 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, size) );
1073
1074 nconsvars = nvars;
1075
1076 /* add constraint variables to new linear variables */
1077 for( k = nvars - 1; k >= 0; --k )
1078 {
1079 consvars[k] = vars[k];
1080 consvals[k] = 1.0;
1081 }
1082
1083 constant = 0.0;
1084
1085 /* get active variables for new constraint */
1086 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
1087
1088 /* if space was not enough (we found another multi-aggregation), we need to resize the buffers */
1089 if( requiredsize > size )
1090 {
1091 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
1092 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
1093 size = requiredsize;
1094
1095 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize) );
1096 assert(requiredsize <= size);
1097 }
1098 assert(requiredsize == nconsvars);
1099
1100 lhs = 1.0 - constant;
1101 rhs = SCIPinfinity(scip);
1102
1103 /* create linear constraint */
1104 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPconsGetName(cons));
1105 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, nconsvars, consvars, consvals, lhs, rhs,
1106 SCIPconsIsInitial(cons),
1110
1111 /* add the downgraded constraint to the problem */
1112 SCIPdebugMsg(scip, "adding linear constraint: ");
1113 SCIPdebugPrintCons(scip, newcons, NULL);
1114 SCIP_CALL( SCIPaddCons(scip, newcons) );
1115 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1116
1117 /* free constraint arrays */
1118 SCIPfreeBufferArray(scip, &consvals);
1119 SCIPfreeBufferArray(scip, &consvars);
1120
1121 /* delete old constraint */
1122 SCIP_CALL( SCIPdelCons(scip, cons) );
1123 if( ndelconss != NULL && naddconss != NULL )
1124 {
1125 assert( naddconss != NULL ); /* for lint */
1126 ++(*ndelconss);
1127 ++(*naddconss);
1128 }
1129
1130 goto TERMINATE;
1131 }
1132 /* we need to degrade this logicor constraint to a linear constraint */
1133 else
1134 {
1135 if( var != consdata->vars[v] )
1136 {
1137 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1138 SCIP_CALL( addCoef(scip, cons, var) );
1139 }
1140
1141 SCIPwarningMessage(scip, "logicor constraint <%s> has a multi-aggregated variable, which was not resolved and therefore could lead to aborts\n", SCIPconsGetName(cons));
1142 }
1143
1144 SCIPfreeBufferArray(scip, &consvals);
1145 SCIPfreeBufferArray(scip, &consvars);
1146 }
1147 else if( var != consdata->vars[v] )
1148 {
1150
1151 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1152
1153 /* the binvar representative might be fixed:
1154 * - if fixed to 1, the constraint is redundant
1155 * - if fixed to 0, the representative does not need to be added to the constraint
1156 * - if not fixed, we add the representative to the constraint
1157 */
1158 if( SCIPvarGetLbGlobal(var) > 0.5 )
1159 {
1161 *redundant = TRUE;
1162
1163 goto TERMINATE;
1164 }
1165 else if( SCIPvarGetUbGlobal(var) < 0.5 )
1166 {
1168 ++(*nchgcoefs);
1169 }
1170 else
1171 {
1172 SCIP_CALL( addCoef(scip, cons, var) );
1173 }
1174 }
1175 }
1176
1177 SCIPdebugMsg(scip, "after fixings: ");
1178 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
1179
1180 TERMINATE:
1181 /* free temporary memory */
1182 SCIPfreeBufferArray(scip, &negarray);
1184
1185 consdata->presolved = TRUE;
1186
1187 return SCIP_OKAY;
1188}
1189
1190/** analyzes conflicting assignment on given constraint, and adds conflict constraint to problem */
1191static
1193 SCIP* scip, /**< SCIP data structure */
1194 SCIP_CONS* cons /**< logic or constraint that detected the conflict */
1195 )
1196{
1197 SCIP_CONSDATA* consdata;
1198 int v;
1199
1200 /* conflict analysis can only be applied in solving stage and if it is applicable */
1202 return SCIP_OKAY;
1203
1204 consdata = SCIPconsGetData(cons);
1205 assert(consdata != NULL);
1206
1207 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
1209
1210 for( v = 0; v < consdata->nvars; ++v )
1211 {
1212 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
1213 }
1214
1215 /* analyze the conflict */
1217
1218 return SCIP_OKAY;
1219}
1220
1221/** disables or deletes the given constraint, depending on the current depth */
1222static
1224 SCIP* scip, /**< SCIP data structure */
1225 SCIP_CONS* cons /**< bound disjunction constraint to be disabled */
1226 )
1227{
1229
1230 /* in case the logic or constraint is satisfied in the depth where it is also valid, we can delete it */
1232 {
1233 SCIP_CALL( SCIPdelCons(scip, cons) );
1234 }
1235 else
1236 {
1237 SCIPdebugMsg(scip, "disabling constraint cons <%s> at depth %d\n", SCIPconsGetName(cons), SCIPgetDepth(scip));
1238 SCIP_CALL( SCIPdisableCons(scip, cons) );
1239 }
1240
1241 return SCIP_OKAY;
1242}
1243
1244/** find pairs of negated variables in constraint: constraint is redundant */
1245/** find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
1246static
1248 SCIP* scip, /**< SCIP data structure */
1249 SCIP_CONS* cons, /**< logic or constraint */
1250 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1251 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
1252 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
1253 SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
1254 int* nchgcoefs /**< pointer to count number of changed/deleted coefficients */
1255 )
1256{
1257 SCIP_CONSDATA* consdata;
1258 SCIP_VAR** vars;
1259 int nvars;
1260 SCIP_Bool* negarray;
1261 SCIP_VAR* var;
1262 int v;
1263 int pos;
1264#ifndef NDEBUG
1265 int nbinvars;
1266 int nintvars;
1267 int nimplvars;
1268#endif
1269
1270 assert(scip != NULL);
1271 assert(cons != NULL);
1272 assert(eventhdlr != NULL);
1273 assert(*entries != NULL);
1274 assert(nentries != NULL);
1275 assert(redundant != NULL);
1276 assert(nchgcoefs != NULL);
1277
1278 consdata = SCIPconsGetData(cons);
1279 assert(consdata != NULL);
1280
1281 nvars = consdata->nvars;
1282
1283 *redundant = FALSE;
1284
1285 if( consdata->merged )
1286 return SCIP_OKAY;
1287
1288 if( consdata->nvars <= 1 )
1289 {
1290 consdata->merged = TRUE;
1291 return SCIP_OKAY;
1292 }
1293
1294 assert(consdata->vars != NULL && nvars > 0);
1295
1296#ifndef NDEBUG
1297 nbinvars = SCIPgetNBinVars(scip);
1298 nintvars = SCIPgetNIntVars(scip);
1299 nimplvars = SCIPgetNImplVars(scip);
1300 assert(*nentries >= nbinvars + nintvars + nimplvars);
1301
1302 /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
1303 * called before mergeMultiples()
1304 */
1305 assert(consdata->presolved);
1306#endif
1307
1308 /* allocate temporary memory */
1309 SCIP_CALL( SCIPallocBufferArray(scip, &negarray, nvars) );
1310
1311 vars = consdata->vars;
1312
1313 /* initialize entries array */
1314 for( v = nvars - 1; v >= 0; --v )
1315 {
1316 /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
1317 * called before mergeMultiples()
1318 */
1321 negarray[v] = SCIPvarIsNegated(vars[v]);
1322 var = negarray[v] ? SCIPvarGetNegationVar(vars[v]) : vars[v];
1324
1325 pos = SCIPvarGetProbindex(var);
1326
1327 /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
1329 || (SCIPvarIsBinary(var) &&
1330 ((pos >= nbinvars && pos < nbinvars + nintvars && SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER
1332 (pos >= nbinvars + nintvars && pos < nbinvars + nintvars + nimplvars &&
1334
1335 /* var is not active yet */
1336 (*entries)[pos] = 0;
1337 }
1338
1339 /* check all vars for multiple entries, do necessary backwards loop because deletion only affect rear items */
1340 for( v = nvars - 1; v >= 0; --v )
1341 {
1342 var = negarray[v] ? SCIPvarGetNegationVar(vars[v]) : vars[v];
1344
1345 pos = SCIPvarGetProbindex(var);
1346
1347 /* if var occurs first time in constraint init entries array */
1348 if( (*entries)[pos] == 0 )
1349 (*entries)[pos] = negarray[v] ? 2 : 1;
1350 /* if var occurs second time in constraint, first time it was not negated */
1351 else if( (*entries)[pos] == 1 )
1352 {
1353 if( negarray[v] )
1354 {
1355 SCIPdebugMsg(scip, "logicor constraint <%s> redundant: variable <%s> and its negation are present\n",
1357
1358 *redundant = TRUE;
1359 goto TERMINATE;
1360 }
1361 else
1362 {
1363 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1364 ++(*nchgcoefs);
1365 }
1366 }
1367 /* if var occurs second time in constraint, first time it was negated */
1368 else
1369 {
1370 if( !negarray[v] )
1371 {
1372 SCIPdebugMsg(scip, "logicor constraint <%s> redundant: variable <%s> and its negation are present\n",
1374
1375 *redundant = TRUE;
1376 goto TERMINATE;
1377 }
1378 else
1379 {
1380 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1381 ++(*nchgcoefs);
1382 }
1383 }
1384 }
1385
1386 TERMINATE:
1387 /* free temporary memory */
1388 SCIPfreeBufferArray(scip, &negarray);
1389
1390 consdata->merged = TRUE;
1391
1392 return SCIP_OKAY;
1393}
1394
1395/** checks constraint for violation only looking at the watched variables, applies fixings if possible */
1396static
1398 SCIP* scip, /**< SCIP data structure */
1399 SCIP_CONS* cons, /**< logic or constraint to be processed */
1400 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1401 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1402 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1403 SCIP_Bool* addcut, /**< pointer to store whether this constraint must be added as a cut */
1404 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1405 )
1406{
1407 SCIP_CONSDATA* consdata;
1408 SCIP_VAR** vars;
1409 SCIP_Longint nbranchings1;
1410 SCIP_Longint nbranchings2;
1411 int nvars;
1412 int watchedvar1;
1413 int watchedvar2;
1414
1415 assert(cons != NULL);
1416 assert(SCIPconsGetHdlr(cons) != NULL);
1417 assert(cutoff != NULL);
1418 assert(reduceddom != NULL);
1419 assert(addcut != NULL);
1420 assert(mustcheck != NULL);
1421
1423
1424 consdata = SCIPconsGetData(cons);
1425 assert(consdata != NULL);
1426 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
1427
1428 *addcut = FALSE;
1429 *mustcheck = FALSE;
1430
1431 SCIPdebugMsg(scip, "processing watched variables of constraint <%s>\n", SCIPconsGetName(cons));
1432
1433 vars = consdata->vars;
1434 nvars = consdata->nvars;
1435 assert(nvars == 0 || vars != NULL);
1436
1437 /* check watched variables if they are fixed to one */
1438 if( consdata->watchedvar1 >= 0 && SCIPvarGetLbLocal(vars[consdata->watchedvar1]) > 0.5 )
1439 {
1440 /* the variable is fixed to one, making the constraint redundant -> disable the constraint */
1441 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar1 fixed to 1.0)\n", SCIPconsGetName(cons));
1442 SCIP_CALL( disableCons(scip, cons) );
1443 return SCIP_OKAY;
1444 }
1445 if( consdata->watchedvar2 >= 0 && SCIPvarGetLbLocal(vars[consdata->watchedvar2]) > 0.5 )
1446 {
1447 /* the variable is fixed to one, making the constraint redundant -> disable the constraint */
1448 SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar2 fixed to 1.0)\n", SCIPconsGetName(cons));
1449 SCIP_CALL( disableCons(scip, cons) );
1450 return SCIP_OKAY;
1451 }
1452
1453 /* check if watched variables are still unfixed */
1454 watchedvar1 = -1;
1455 watchedvar2 = -1;
1456 nbranchings1 = SCIP_LONGINT_MAX;
1457 nbranchings2 = SCIP_LONGINT_MAX;
1458 if( consdata->watchedvar1 >= 0 && SCIPvarGetUbLocal(vars[consdata->watchedvar1]) > 0.5 )
1459 {
1460 watchedvar1 = consdata->watchedvar1;
1461 nbranchings1 = -1; /* prefer keeping the watched variable */
1462 }
1463 if( consdata->watchedvar2 >= 0 && SCIPvarGetUbLocal(vars[consdata->watchedvar2]) > 0.5 )
1464 {
1465 if( watchedvar1 == -1 )
1466 {
1467 watchedvar1 = consdata->watchedvar2;
1468 nbranchings1 = -1; /* prefer keeping the watched variable */
1469 }
1470 else
1471 {
1472 watchedvar2 = consdata->watchedvar2;
1473 nbranchings2 = -1; /* prefer keeping the watched variable */
1474 }
1475 }
1476 assert(watchedvar1 >= 0 || watchedvar2 == -1);
1477 assert(nbranchings1 <= nbranchings2);
1478
1479 /* search for new watched variables */
1480 if( watchedvar2 == -1 )
1481 {
1482 int v;
1483
1484 for( v = 0; v < nvars; ++v )
1485 {
1486 SCIP_Longint nbranchings;
1487
1488 /* don't process the watched variables again */
1489 if( v == consdata->watchedvar1 || v == consdata->watchedvar2 )
1490 continue;
1491
1492 /* check, if the variable is fixed */
1493 if( SCIPvarGetUbLocal(vars[v]) < 0.5 )
1494 continue;
1495
1496 /* check, if the literal is satisfied */
1497 if( SCIPvarGetLbLocal(vars[v]) > 0.5 )
1498 {
1499 assert(v != consdata->watchedvar1);
1500 assert(v != consdata->watchedvar2);
1501
1502 /* the variable is fixed to one, making the constraint redundant;
1503 * make sure, the feasible variable is watched and disable the constraint
1504 */
1505 SCIPdebugMsg(scip, " -> disabling constraint <%s> (variable <%s> fixed to 1.0)\n",
1507 if( consdata->watchedvar1 != -1 )
1508 {
1509 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, v) );
1510 }
1511 else
1512 {
1513 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, v, consdata->watchedvar2) );
1514 }
1515 SCIP_CALL( disableCons(scip, cons) );
1516 return SCIP_OKAY;
1517 }
1518
1519 /* the variable is unfixed and can be used as watched variable */
1521 assert(nbranchings >= 0);
1522 if( nbranchings < nbranchings2 )
1523 {
1524 if( nbranchings < nbranchings1 )
1525 {
1526 watchedvar2 = watchedvar1;
1527 nbranchings2 = nbranchings1;
1528 watchedvar1 = v;
1529 nbranchings1 = nbranchings;
1530 }
1531 else
1532 {
1533 watchedvar2 = v;
1534 nbranchings2 = nbranchings;
1535 }
1536 }
1537 }
1538 }
1539 assert(nbranchings1 <= nbranchings2);
1540 assert(watchedvar1 >= 0 || watchedvar2 == -1);
1541
1542 if( watchedvar1 == -1 )
1543 {
1544 /* there is no unfixed variable left -> the constraint is infeasible
1545 * - a modifiable constraint must be added as a cut and further pricing must be performed in the LP solving loop
1546 * - an unmodifiable constraint is infeasible and the node can be cut off
1547 */
1548 assert(watchedvar2 == -1);
1549
1550 SCIPdebugMsg(scip, " -> constraint <%s> is infeasible\n", SCIPconsGetName(cons));
1551
1553 if( SCIPconsIsModifiable(cons) )
1554 *addcut = TRUE;
1555 else
1556 {
1557 /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1558 SCIP_CALL( analyzeConflict(scip, cons) );
1559
1560 /* mark the node to be cut off */
1561 *cutoff = TRUE;
1562 }
1563 }
1564 else if( watchedvar2 == -1 )
1565 {
1566 /* there is only one unfixed variable:
1567 * - a modifiable constraint must be checked manually
1568 * - an unmodifiable constraint is feasible and can be disabled after the remaining variable is fixed to one
1569 */
1570 assert(0 <= watchedvar1 && watchedvar1 < nvars);
1571 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vars[watchedvar1]), 0.0));
1572 assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(vars[watchedvar1]), 1.0));
1573 if( SCIPconsIsModifiable(cons) )
1574 *mustcheck = TRUE;
1575 else
1576 {
1577 SCIP_Bool infbdchg;
1578
1579 /* fixed remaining variable to one and disable constraint; make sure, the fixed-to-one variable is watched */
1580 SCIPdebugMsg(scip, " -> single-literal constraint <%s> (fix <%s> to 1.0) at depth %d\n",
1581 SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]), SCIPgetDepth(scip));
1582 SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], TRUE, cons, 0, &infbdchg, NULL) );
1583 assert(!infbdchg);
1585 if( watchedvar1 != consdata->watchedvar1 ) /* keep one of the watched variables */
1586 {
1587 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, consdata->watchedvar1) );
1588 }
1589 SCIP_CALL( disableCons(scip, cons) );
1590 *reduceddom = TRUE;
1591 }
1592 }
1593 else
1594 {
1595 SCIPdebugMsg(scip, " -> new watched variables <%s> and <%s> of constraint <%s> are still unfixed\n",
1596 SCIPvarGetName(vars[watchedvar1]), SCIPvarGetName(vars[watchedvar2]), SCIPconsGetName(cons));
1597
1598 /* switch to the new watched variables */
1599 SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, watchedvar2) );
1600
1601 /* there are at least two unfixed variables -> the constraint must be checked manually */
1602 *mustcheck = TRUE;
1603
1604 /* disable propagation of constraint until a watched variable gets fixed */
1606
1607 /* increase aging counter */
1608 SCIP_CALL( SCIPaddConsAge(scip, cons, AGEINCREASE(consdata->nvars)) );
1609 }
1610
1611 return SCIP_OKAY;
1612}
1613
1614/** checks constraint for violation, returns TRUE iff constraint is feasible */
1615static
1617 SCIP* scip, /**< SCIP data structure */
1618 SCIP_CONS* cons, /**< logic or constraint to be checked */
1619 SCIP_SOL* sol /**< primal CIP solution */
1620 )
1621{
1622 SCIP_CONSDATA* consdata;
1623 SCIP_VAR** vars;
1624 SCIP_Real solval;
1625 SCIP_Real sum;
1626 int nvars;
1627 int v;
1628
1629 consdata = SCIPconsGetData(cons);
1630 assert(consdata != NULL);
1631
1632 vars = consdata->vars;
1633 nvars = consdata->nvars;
1634
1635 /* calculate the constraint's activity */
1636 sum = 0.0;
1637 for( v = 0; v < nvars && sum < 1.0; ++v )
1638 {
1640
1641 solval = SCIPgetSolVal(scip, sol, vars[v]);
1642 assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
1643
1644 sum += solval;
1645 }
1646
1647 /* calculate constraint violation and update it in solution */
1648 if( sol != NULL ){
1649 SCIP_Real absviol = 1.0 - sum;
1650 SCIP_Real relviol = SCIPrelDiff(1.0, sum);
1651 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
1652 }
1653
1654 return SCIPisFeasLT(scip, sum, 1.0);
1655}
1656
1657/** creates an LP row in a logic or constraint data object */
1658static
1660 SCIP* scip, /**< SCIP data structure */
1661 SCIP_CONS* cons /**< logic or constraint */
1662 )
1663{
1664 SCIP_CONSDATA* consdata;
1665
1666 consdata = SCIPconsGetData(cons);
1667 assert(consdata != NULL);
1668 assert(consdata->row == NULL);
1669
1670 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), 1.0, SCIPinfinity(scip),
1672
1673 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
1674
1675 return SCIP_OKAY;
1676}
1677
1678/** adds logicor constraint as row to the NLP, if not added yet */
1679static
1681 SCIP* scip, /**< SCIP data structure */
1682 SCIP_CONS* cons /**< logicor constraint */
1683 )
1684{
1685 SCIP_CONSDATA* consdata;
1686
1688
1689 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
1690 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
1691 return SCIP_OKAY;
1692
1693 consdata = SCIPconsGetData(cons);
1694 assert(consdata != NULL);
1695
1696 if( consdata->nlrow == NULL )
1697 {
1698 SCIP_Real* coefs;
1699 int i;
1700
1701 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, consdata->nvars) );
1702 for( i = 0; i < consdata->nvars; ++i )
1703 coefs[i] = 1.0;
1704
1705 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
1706 0.0, consdata->nvars, consdata->vars, coefs, NULL, 1.0, SCIPinfinity(scip), SCIP_EXPRCURV_LINEAR) );
1707 assert(consdata->nlrow != NULL);
1708
1709 SCIPfreeBufferArray(scip, &coefs);
1710 }
1711
1712 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
1713 {
1714 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
1715 }
1716
1717 return SCIP_OKAY;
1718}
1719
1720/** adds logic or constraint as cut to the LP */
1721static
1723 SCIP* scip, /**< SCIP data structure */
1724 SCIP_CONS* cons, /**< logic or constraint */
1725 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
1726 )
1727{
1728 SCIP_CONSDATA* consdata;
1729
1730 assert( cutoff != NULL );
1731 *cutoff = FALSE;
1732
1733 consdata = SCIPconsGetData(cons);
1734 assert(consdata != NULL);
1735
1736 if( consdata->row == NULL )
1737 {
1738 /* convert logic or constraint data into LP row */
1739 SCIP_CALL( createRow(scip, cons) );
1740 }
1741 assert(consdata->row != NULL);
1742
1743 /* insert LP row as cut */
1744 if( !SCIProwIsInLP(consdata->row) )
1745 {
1746 SCIPdebugMsg(scip, "adding constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1747 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
1748 }
1749
1750 return SCIP_OKAY;
1751}
1752
1753/** checks constraint for violation, and adds it as a cut if possible */
1754static
1756 SCIP* scip, /**< SCIP data structure */
1757 SCIP_CONS* cons, /**< logic or constraint to be separated */
1758 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1759 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1760 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1761 SCIP_Bool* separated, /**< pointer to store TRUE, if a cut was found */
1762 SCIP_Bool* reduceddom /**< pointer to store TRUE, if a domain reduction was found */
1763 )
1764{
1765 SCIP_Bool addcut;
1766 SCIP_Bool mustcheck;
1767
1768 assert(cons != NULL);
1769 assert(SCIPconsGetHdlr(cons) != NULL);
1770 assert(cutoff != NULL);
1771 assert(separated != NULL);
1772 assert(reduceddom != NULL);
1773
1775
1776 *cutoff = FALSE;
1777 SCIPdebugMsg(scip, "separating constraint <%s>\n", SCIPconsGetName(cons));
1778
1779 /* update and check the watched variables, if they were changed since last processing */
1780 if( sol == NULL && SCIPconsIsPropagationEnabled(cons) )
1781 {
1782 SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, reduceddom, &addcut, &mustcheck) );
1783 }
1784 else
1785 {
1786 addcut = FALSE;
1787 mustcheck = TRUE;
1788 }
1789
1790 if( mustcheck )
1791 {
1792 SCIP_CONSDATA* consdata;
1793
1794 assert(!addcut);
1795
1796 consdata = SCIPconsGetData(cons);
1797 assert(consdata != NULL);
1798
1799 /* variable's fixings didn't give us any information -> we have to check the constraint */
1800 if( sol == NULL && consdata->row != NULL )
1801 {
1802 /* skip constraints already in the LP */
1803 if( SCIProwIsInLP(consdata->row) )
1804 return SCIP_OKAY;
1805 else
1806 {
1807 SCIP_Real feasibility;
1808
1809 assert(!SCIProwIsInLP(consdata->row));
1810 feasibility = SCIPgetRowLPFeasibility(scip, consdata->row);
1811 addcut = SCIPisFeasNegative(scip, feasibility);
1812 }
1813 }
1814 else
1815 {
1816 addcut = isConsViolated(scip, cons, sol);
1817 }
1818 }
1819
1820 if( addcut )
1821 {
1822 /* insert LP row as cut */
1823 SCIP_CALL( addCut(scip, cons, cutoff) );
1825 *separated = TRUE;
1826 }
1827
1828 return SCIP_OKAY;
1829}
1830
1831/** enforces the pseudo solution on the given constraint */
1832static
1834 SCIP* scip, /**< SCIP data structure */
1835 SCIP_CONS* cons, /**< logic or constraint to be separated */
1836 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1837 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1838 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
1839 SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1840 SCIP_Bool* solvelp /**< pointer to store TRUE, if the LP has to be solved */
1841 )
1842{
1843 SCIP_Bool addcut;
1844 SCIP_Bool mustcheck;
1845
1847 assert(cons != NULL);
1848 assert(SCIPconsGetHdlr(cons) != NULL);
1849 assert(cutoff != NULL);
1850 assert(infeasible != NULL);
1851 assert(reduceddom != NULL);
1852 assert(solvelp != NULL);
1853
1855
1856 /* update and check the watched variables, if they were changed since last processing */
1858 {
1859 SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, reduceddom, &addcut, &mustcheck) );
1860 }
1861 else
1862 {
1863 addcut = FALSE;
1864 mustcheck = TRUE;
1865 }
1866
1867 if( mustcheck )
1868 {
1869 assert(!addcut);
1870
1871 if( isConsViolated(scip, cons, NULL) )
1872 {
1873 /* constraint was infeasible -> reset age */
1875 *infeasible = TRUE;
1876 }
1877 }
1878 else if( addcut )
1879 {
1880 /* a cut must be added to the LP -> we have to solve the LP immediately */
1882 *solvelp = TRUE;
1883 }
1884
1885 return SCIP_OKAY;
1886}
1887
1888/** sorts logicor constraint's variables by non-decreasing variable index */
1889static
1891 SCIP_CONSDATA* consdata /**< linear constraint data */
1892 )
1893{
1894 assert(consdata != NULL);
1895
1896 if( !consdata->sorted )
1897 {
1898 if( consdata->nvars <= 1 )
1899 consdata->sorted = TRUE;
1900 else
1901 {
1902 SCIP_VAR* var1 = NULL;
1903 SCIP_VAR* var2 = NULL;
1904
1905 /* remember watch variables */
1906 if( consdata->watchedvar1 != -1 )
1907 {
1908 var1 = consdata->vars[consdata->watchedvar1];
1909 assert(var1 != NULL);
1910 consdata->watchedvar1 = -1;
1911 if( consdata->watchedvar2 != -1 )
1912 {
1913 var2 = consdata->vars[consdata->watchedvar2];
1914 assert(var2 != NULL);
1915 consdata->watchedvar2 = -1;
1916 }
1917 }
1918 assert(consdata->watchedvar1 == -1);
1919 assert(consdata->watchedvar2 == -1);
1920 assert(var1 != NULL || var2 == NULL);
1921
1922 /* sort variables after index */
1923 SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
1924 consdata->sorted = TRUE;
1925
1926 /* correct watched variables */
1927 if( var1 != NULL )
1928 {
1929 int pos;
1930#ifndef NDEBUG
1931 SCIP_Bool found;
1932
1933 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
1934 assert(found);
1935#else
1936 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
1937#endif
1938 assert(pos >= 0 && pos < consdata->nvars);
1939 consdata->watchedvar1 = pos;
1940
1941 if( var2 != NULL )
1942 {
1943#ifndef NDEBUG
1944 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
1945 assert(found);
1946#else
1947 (void) SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
1948#endif
1949 assert(pos >= 0 && pos < consdata->nvars);
1950 consdata->watchedvar2 = pos;
1951 }
1952 }
1953 }
1954 }
1955
1956#ifdef SCIP_DEBUG
1957 /* check sorting */
1958 {
1959 int v;
1960
1961 for( v = consdata->nvars - 1; v > 0; --v )
1962 {
1963 assert(SCIPvarCompare(consdata->vars[v], consdata->vars[v - 1]) >= 0);
1964 }
1965 }
1966#endif
1967}
1968
1969/** gets the key of the given element */
1970static
1971SCIP_DECL_HASHGETKEY(hashGetKeyLogicorcons)
1972{ /*lint --e{715}*/
1973 /* the key is the element itself */
1974 return elem;
1975}
1976
1977/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
1978static
1979SCIP_DECL_HASHKEYEQ(hashKeyEqLogicorcons)
1980{
1981 SCIP_CONSDATA* consdata1;
1982 SCIP_CONSDATA* consdata2;
1983 SCIP_Bool coefsequal;
1984 int i;
1985#ifndef NDEBUG
1986 SCIP* scip;
1987
1988 scip = (SCIP*)userptr;
1989 assert(scip != NULL);
1990#endif
1991
1992 consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
1993 consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
1994
1995 /* checks trivial case */
1996 if( consdata1->nvars != consdata2->nvars )
1997 return FALSE;
1998
1999 /* sorts the constraints */
2000 consdataSort(consdata1);
2001 consdataSort(consdata2);
2002 assert(consdata1->sorted);
2003 assert(consdata2->sorted);
2004
2005 coefsequal = TRUE;
2006
2007 for( i = 0; i < consdata1->nvars ; ++i )
2008 {
2009 /* tests if variables are equal */
2010 if( consdata1->vars[i] != consdata2->vars[i] )
2011 {
2012 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
2013 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
2014 coefsequal = FALSE;
2015 break;
2016 }
2017 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
2018 }
2019
2020 return coefsequal;
2021}
2022
2023/** returns the hash value of the key */
2024static
2025SCIP_DECL_HASHKEYVAL(hashKeyValLogicorcons)
2026{ /*lint --e{715}*/
2027 SCIP_CONSDATA* consdata;
2028 int minidx;
2029 int mididx;
2030 int maxidx;
2031
2032 consdata = SCIPconsGetData((SCIP_CONS*)key);
2033 assert(consdata != NULL);
2034 assert(consdata->sorted);
2035 assert(consdata->nvars > 0);
2036
2037 minidx = SCIPvarGetIndex(consdata->vars[0]);
2038 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
2039 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
2040 assert(minidx >= 0 && minidx <= maxidx);
2041
2042 return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
2043}
2044
2045/** compares each constraint with all other constraints for a possible duplication and removes duplicates using a hash
2046 * table; also @see removeRedundantConssAndNonzeros()
2047 */
2048static
2050 SCIP* scip, /**< SCIP data structure */
2051 BMS_BLKMEM* blkmem, /**< block memory */
2052 SCIP_CONS** conss, /**< constraint set */
2053 int nconss, /**< number of constraints in constraint set */
2054 int* firstchange, /**< pointer to store first changed constraint */
2055 int* ndelconss /**< pointer to count number of deleted constraints */
2056 )
2057{
2058 SCIP_HASHTABLE* hashtable;
2059 int hashtablesize;
2060 int c;
2061
2062 assert(conss != NULL);
2063 assert(ndelconss != NULL);
2064
2065 /* create a hash table for the constraint set */
2066 hashtablesize = nconss;
2067 hashtablesize = MAX(hashtablesize, HASHSIZE_LOGICORCONS);
2068 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
2069 hashGetKeyLogicorcons, hashKeyEqLogicorcons, hashKeyValLogicorcons, (void*) scip) );
2070
2071 /* check all constraints in the given set for redundancy */
2072 for( c = 0; c < nconss; ++c )
2073 {
2074 SCIP_CONS* cons0;
2075 SCIP_CONS* cons1;
2076 SCIP_CONSDATA* consdata0;
2077
2078 cons0 = conss[c];
2079
2080 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
2081 continue;
2082
2083 consdata0 = SCIPconsGetData(cons0);
2084 /* sort the constraint */
2085 consdataSort(consdata0);
2086 assert(consdata0->sorted);
2087
2088 /* get constraint from current hash table with same variables as cons0 */
2089 cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
2090
2091 if( cons1 != NULL )
2092 {
2093#ifndef NDEBUG
2094 SCIP_CONSDATA* consdata1;
2095#endif
2096
2097 assert(SCIPconsIsActive(cons1));
2099
2100#ifndef NDEBUG
2101 consdata1 = SCIPconsGetData(cons1);
2102#endif
2103 assert(consdata1 != NULL);
2104 assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
2105
2106 assert(consdata0->sorted && consdata1->sorted);
2107 assert(consdata0->vars[0] == consdata1->vars[0]);
2108
2109 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2110 /* coverity[swapped_arguments] */
2111 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2112
2113 /* delete consdel */
2114 SCIP_CALL( SCIPdelCons(scip, cons0) );
2115 (*ndelconss)++;
2116
2117 /* update the first changed constraint to begin the next aggregation round with */
2118 if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
2119 *firstchange = SCIPconsGetPos(cons1);
2120
2121 assert(SCIPconsIsActive(cons1));
2122 }
2123 else
2124 {
2125 /* no such constraint in current hash table: insert cons0 into hash table */
2126 SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
2127 }
2128 }
2129
2130 /* free hash table */
2131 SCIPhashtableFree(&hashtable);
2132
2133 return SCIP_OKAY;
2134}
2135
2136/** removes the redundant second constraint and updates the flags of the first one */
2137static
2139 SCIP* scip, /**< SCIP data structure */
2140 SCIP_CONS* cons0, /**< constraint that should stay */
2141 SCIP_CONS* cons1, /**< constraint that should be deleted */
2142 int* ndelconss /**< pointer to count number of deleted constraints */
2143 )
2144{
2145 assert(ndelconss != NULL);
2146
2147 SCIPdebugMsg(scip, " -> removing logicor constraint <%s> which is redundant to <%s>\n",
2148 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
2149 SCIPdebugPrintCons(scip, cons0, NULL);
2150 SCIPdebugPrintCons(scip, cons1, NULL);
2151
2152 /* update flags of cons0 */
2153 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2154
2155 /* delete cons1 */
2156 SCIP_CALL( SCIPdelCons(scip, cons1) );
2157 (*ndelconss)++;
2158
2159 return SCIP_OKAY;
2160}
2161
2162
2163/** compute and return a signature for given variables */
2164static
2165unsigned int calcSignature(
2166 SCIP_VAR** vars, /**< variables to calculate the signature for */
2167 int nvars /**< number of variables to calculate the signature for */
2168 )
2169{
2170 unsigned int signature = 0;
2171 int v;
2172
2173 assert(vars != NULL);
2174 assert(nvars >= 1);
2175
2176 for( v = nvars - 1; v >= 0; --v )
2177 {
2178 signature |= ((unsigned int)1 << ((unsigned int)SCIPvarGetIndex(vars[v]) % (sizeof(unsigned int) * 8)));
2179 }
2180
2181 return signature;
2182}
2183
2184/** compute the constraint signature which is used to detect constraints, that contain potentially the same set of
2185 * variables
2186 */
2187static
2189 SCIP_CONSDATA* consdata /**< logicor constraint data */
2190 )
2191{
2192 if( consdata->validsignature )
2193 return;
2194
2195 consdata->signature = calcSignature(consdata->vars, consdata->nvars);
2196 consdata->validsignature = TRUE;
2197}
2198
2199/** remove a constraint from the column representation */
2200static
2202 SCIP_CONS* cons, /**< logicor constraint */
2203 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2204 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2205 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2206 int occurlistlength /**< number of columns in the occurlist */
2207 )
2208{
2209 SCIP_VAR** vars;
2210 SCIP_VAR* var;
2211 SCIP_CONSDATA* consdata;
2212 int nvars;
2213 int pos;
2214 int v;
2215 int l;
2216
2217 assert(cons != NULL);
2218 assert(SCIPconsIsActive(cons));
2219 assert(varstopos != NULL);
2220 assert(occurlist != NULL);
2221 assert(noccurlistentries != NULL);
2222
2223 consdata = SCIPconsGetData(cons);
2224 assert(consdata != NULL);
2225
2226 nvars = consdata->nvars;
2227 assert(nvars >= 1);
2228 vars = consdata->vars;
2229 assert(vars != NULL);
2230
2231 /* remove constraint from list */
2232 for( v = nvars - 1; v >= 0; --v )
2233 {
2234 var = vars[v];
2235
2236 assert(SCIPhashmapExists(varstopos, (void*) var));
2237
2238 pos = SCIPhashmapGetImageInt(varstopos, (void*)var);
2239 assert(0 < pos && pos <= occurlistlength);
2240
2241 --pos;
2242
2243 /* remove for each variable one corresponding entry */
2244 for( l = noccurlistentries[pos] - 1; l >= 0; --l )
2245 {
2246 if( occurlist[pos][l] == cons )
2247 {
2248 --noccurlistentries[pos];
2249 assert(noccurlistentries[pos] >= 0);
2250
2251 occurlist[pos][l] = occurlist[pos][noccurlistentries[pos]];
2252 break;
2253 }
2254 }
2255 assert(l >= 0);
2256 }
2257}
2258
2259/** determine shortest constraint list in column representation */
2260static
2262 SCIP_VAR** vars, /**< variables to find the shortestlist for */
2263 int nvars, /**< number of variables */
2264 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2265 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2266 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2267 int occurlistlength, /**< number of columns in the occurlist */
2268 int* nentries, /**< pointer to store the number of entries in the shortest list */
2269 SCIP_CONS*** shortestlist /**< pointer to store smallest array with constraints */
2270 )
2271{
2272 SCIP_VAR* var;
2273 int pos;
2274 int v;
2275
2276 assert(vars != 0);
2277 assert(nvars >= 1);
2278 assert(varstopos != NULL);
2279 assert(occurlist != NULL);
2280 assert(noccurlistentries != NULL);
2281 assert(nentries != NULL);
2282 assert(shortestlist != NULL);
2283
2284 *nentries = INT_MAX;
2285 *shortestlist = NULL;
2286
2287 /* find the shortest list */
2288 for( v = nvars - 1; v >= 0; --v )
2289 {
2290 var = vars[v];
2291 assert(var != NULL);
2292
2293 /* it might be that a variable is not yet put into the occurlist, then this constraint cannot cover another */
2294 if( !SCIPhashmapExists(varstopos, (void*) var) )
2295 {
2296 *nentries = 0;
2297 return;
2298 }
2299
2300 pos = SCIPhashmapGetImageInt(varstopos, (void*)var);
2301 assert(0 < pos && pos <= occurlistlength);
2302
2303 --pos;
2304
2305 /* remember the shortest list */
2306 if( noccurlistentries[pos] < *nentries )
2307 {
2308 *nentries = noccurlistentries[pos];
2309 *shortestlist = occurlist[pos];
2310 }
2311 }
2312}
2313
2314/** run a pairwise comparison for detecting subset-constraints of other constraint while using a signature */
2315static
2317 SCIP* scip, /**< SCIP data structure */
2318 SCIP_CONS* cons, /**< logicor constraint to check if it covers another */
2319 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2320 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2321 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2322 int occurlistlength, /**< number of columns in the occurlist */
2323 int* ndelconss /**< pointer to store the number of deleted constraints */
2324 )
2325{
2326 SCIP_CONS** shortestlist;
2327 SCIP_VAR** vars;
2328 SCIP_CONS* cons1;
2329 SCIP_VAR* var;
2330 SCIP_CONSDATA* consdata;
2331 int nentries;
2332 int c;
2333 int v;
2334
2335 assert(scip != NULL);
2336 assert(cons != NULL);
2337 assert(SCIPconsIsActive(cons));
2339 assert(varstopos != NULL);
2340 assert(occurlist != NULL);
2341 assert(noccurlistentries != NULL);
2342 assert(ndelconss != NULL);
2343
2344 consdata = SCIPconsGetData(cons);
2345 assert(consdata != NULL);
2346 assert(consdata->nvars > 1);
2347 assert(consdata->validsignature);
2348 assert(consdata->sorted);
2349
2350 vars = consdata->vars;
2351 assert(vars != NULL);
2352
2353 /* determine shortest column */
2354 findShortestOccurlist(vars, consdata->nvars, varstopos, occurlist, noccurlistentries, occurlistlength, &nentries, &shortestlist);
2355
2356 /* one variable which does not appear in the column representation anymore */
2357 if( nentries == 0 )
2358 return SCIP_OKAY;
2359
2360 assert(shortestlist != NULL);
2361 assert(0 < nentries);
2362
2363 /* check all constraints in the shortest list for coverage */
2364 for( c = nentries - 1; c >= 0; --c )
2365 {
2366 cons1 = shortestlist[c];
2367 assert(cons1 != NULL);
2369 assert(SCIPconsIsActive(cons1));
2370
2371 if( cons != cons1 )
2372 {
2373 SCIP_CONSDATA* consdata1 = SCIPconsGetData(cons1);
2374 assert(consdata1 != NULL);
2375 assert(consdata1->nvars >= consdata->nvars);
2376
2377 /* constraints with the same length cannot be covered and same constraints are removed in
2378 * detectRedundantConstraints()
2379 */
2380 if( consdata1->nvars == consdata->nvars )
2381 continue;
2382
2383 assert(consdata->validsignature);
2384 assert(consdata->sorted);
2385 assert(consdata1->validsignature);
2386 assert(consdata1->sorted);
2387
2388 if( (consdata->signature & (~consdata1->signature)) == 0 )
2389 {
2390 SCIP_VAR* var1;
2391 int v1;
2392
2393 v = 0;
2394 v1 = 0;
2395
2396 while( v < consdata->nvars && v1 < consdata1->nvars )
2397 {
2398 int comp;
2399
2400 var = vars[v];
2401 var1 = consdata1->vars[v1];
2402
2403 comp = SCIPvarCompare(var, var1);
2404
2405 if( comp == 0 )
2406 {
2407 ++v;
2408 ++v1;
2409 }
2410 else if( comp > 0 )
2411 ++v1;
2412 else
2413 break;
2414 }
2415
2416 /* cons1 is covered by cons */
2417 if( v == consdata->nvars )
2418 {
2419 /* remove cons1 from columns representation */
2420 removeConsFromOccurList(cons1, varstopos, occurlist, noccurlistentries, occurlistlength);
2421
2422 /* delete redundant constraint and update constraint flags if necessary */
2423 SCIP_CALL( removeRedundantCons(scip, cons, cons1, ndelconss) );
2424 }
2425 }
2426 }
2427 }
2428
2429 return SCIP_OKAY;
2430}
2431
2432/** compararer for sorting constraints after their number of variables */
2433static
2434SCIP_DECL_SORTPTRCOMP(conssLogicorComp)
2435{
2436 SCIP_CONSDATA* consdata1;
2437 SCIP_CONSDATA* consdata2;
2438
2439 assert(elem1 != NULL);
2440 assert(elem2 != NULL);
2441
2442 consdata1 = SCIPconsGetData((SCIP_CONS*) elem1);
2443 consdata2 = SCIPconsGetData((SCIP_CONS*) elem2);
2444
2445 assert(consdata1 != NULL);
2446 assert(consdata2 != NULL);
2447
2448 return consdata1->nvars - consdata2->nvars;
2449}
2450
2451/** add a constraint to the column representation */
2452static
2454 SCIP* scip, /**< SCIP data structure */
2455 SCIP_CONS* cons, /**< logicor constraint */
2456 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2457 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2458 int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2459 int* occurlistsizes, /**< array of sizes for each variable in the occurlist */
2460 int* occurlistlength, /**< number of columns in the occurlist */
2461 int occurlistsize /**< size of occurlist */
2462 )
2463{
2464 SCIP_VAR** vars;
2465 SCIP_VAR* var;
2466 SCIP_CONSDATA* consdata;
2467 int pos;
2468 int v;
2469
2470 assert(scip != NULL);
2471 assert(cons != NULL);
2472 assert(SCIPconsIsActive(cons));
2473 assert(varstopos != NULL);
2474 assert(occurlist != NULL);
2475 assert(noccurlistentries != NULL);
2476 assert(occurlistsizes != NULL);
2477 assert(occurlistlength != NULL);
2478 assert(*occurlistlength <= occurlistsize);
2479
2480 consdata = SCIPconsGetData(cons);
2481 assert(consdata != NULL);
2482 assert(consdata->nvars > 1);
2483
2484 vars = consdata->vars;
2485 assert(vars != NULL);
2486
2487 for( v = consdata->nvars - 1; v >= 0; --v )
2488 {
2489 var = vars[v];
2490 assert(var != NULL);
2492
2493 /* check if the variable is not yet put into the occurlist */
2494 if( !SCIPhashmapExists(varstopos, (void*) var) )
2495 {
2496 pos = *occurlistlength;
2497 assert(pos <= occurlistsize);
2498
2499 /* occurlist values need to be clear */
2500 assert(occurlist[pos] == NULL);
2501 assert(noccurlistentries[pos] == 0);
2502 assert(occurlistsizes[pos] == 0);
2503
2504 /* allocate memory */
2506 occurlistsizes[pos] = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) + 1;
2507 SCIP_CALL( SCIPallocBufferArray(scip, &(occurlist[pos]), occurlistsizes[pos]) ); /*lint !e866*/
2508
2509 /* put constraint in list of current variable */
2510 occurlist[pos][noccurlistentries[pos]] = cons;
2511 ++(noccurlistentries[pos]);
2512
2513 /* add new variable to map */
2514 SCIP_CALL( SCIPhashmapInsertInt(varstopos, var, pos + 1) );
2515
2516 ++(*occurlistlength);
2517 }
2518 else
2519 {
2520 pos = SCIPhashmapGetImageInt(varstopos, (void*)var);
2521 assert(0 < pos && pos <= *occurlistlength);
2522
2523 --pos;
2524
2525 assert(occurlist[pos] != NULL);
2526 assert(occurlistsizes[pos] > 0);
2527
2528 /* do we need to resize the array */
2529 if( noccurlistentries[pos] == occurlistsizes[pos] )
2530 {
2531 occurlistsizes[pos] = SCIPcalcMemGrowSize(scip, occurlistsizes[pos] + 1);
2532 assert(occurlistsizes[pos] > noccurlistentries[pos] && occurlistsizes[pos] < INT_MAX);
2533
2534 /* resize occurlist for current variable */
2535 SCIP_CALL( SCIPreallocBufferArray(scip, &(occurlist[pos]), occurlistsizes[pos]) ); /*lint !e866*/
2536 }
2537 assert(noccurlistentries[pos] < occurlistsizes[pos]);
2538
2539 /* put constraint in list of current variable */
2540 occurlist[pos][noccurlistentries[pos]] = cons;
2541 ++(noccurlistentries[pos]);
2542 }
2543 }
2544
2545 return SCIP_OKAY;
2546}
2547
2548/** run a pairwise comparison for the given variables against all constraits to detect redundant non-zeros in these
2549 * constraints
2550 */
2551static
2553 SCIP* scip, /**< SCIP data structure */
2554 SCIP_CONS* cons, /**< logicor constraint to check if it covers another */
2555 SCIP_VAR* artvar, /**< artificial negated variable of constraint */
2556 int artpos, /**< position to replace constraint variable with artvar */
2557 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2558 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2559 int* noccurlistentries, /**< number of constraints for each variable in the occurlist */
2560 int occurlistlength, /**< number of columns in the occurlist */
2561 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
2562 int* nchgcoefs, /**< pointer to store the number of deleted non-zeros */
2563 SCIP_Bool* deleted /**< pointer to store if cons will be deleted */
2564 )
2565{
2566 SCIP_CONS** shortestlist;
2567 SCIP_VAR** vars;
2568 SCIP_CONS* cons1;
2569 SCIP_VAR* oldvar;
2570 SCIP_VAR* var;
2571 SCIP_CONSDATA* consdata;
2572 unsigned int signature;
2573 int nentries;
2574 int nvars;
2575 int c;
2576 int v;
2577 int pos;
2578
2579 assert(scip != NULL);
2580 assert(cons != NULL);
2581 assert(artvar != NULL);
2582 assert(SCIPconsIsActive(cons));
2584 assert(varstopos != NULL);
2585 assert(SCIPhashmapExists(varstopos, (void*) artvar));
2586 assert(occurlist != NULL);
2587 assert(noccurlistentries != NULL);
2588 assert(nchgcoefs != NULL);
2589 assert(deleted != NULL);
2590
2591 consdata = SCIPconsGetData(cons);
2592 assert(consdata != NULL);
2593 assert(consdata->sorted);
2594
2595 nvars = consdata->nvars;
2596 assert(nvars > 1);
2597 assert(0 <= artpos && artpos < nvars);
2598
2599 vars = consdata->vars;
2600 assert(vars != NULL);
2601
2602 *deleted = FALSE;
2603
2604 /* temporary exchange the variable for finding the shortest list */
2605 oldvar = vars[artpos];
2606 assert(oldvar == SCIPvarGetNegatedVar(artvar));
2607 vars[artpos] = artvar;
2608
2609 /* determine shortest column */
2610 findShortestOccurlist(vars, nvars, varstopos, occurlist, noccurlistentries, occurlistlength, &nentries, &shortestlist);
2611
2612 /* correct exchanged variable with constraint variables */
2613 vars[artpos] = oldvar;
2614
2615 /* one variable which does not appear in the column representation anymore */
2616 if( nentries == 0 )
2617 return SCIP_OKAY;
2618
2619 assert(shortestlist != NULL);
2620 assert(0 < nentries);
2621
2622 /* temporary exchange the variable for calculating a valid signature */
2623 vars[artpos] = artvar;
2624 signature = calcSignature(vars, nvars);
2625
2626 /* correct exchanged variable with constraint variables */
2627 vars[artpos] = oldvar;
2628
2629 /* check all constraints in the shortest list for coverage */
2630 for( c = nentries - 1; c >= 0; --c )
2631 {
2632 cons1 = shortestlist[c];
2633 assert(cons1 != NULL);
2635
2636 if( !SCIPconsIsActive(cons1) )
2637 continue;
2638
2639 if( cons != cons1 )
2640 {
2641 SCIP_CONSDATA* consdata1 = SCIPconsGetData(cons1);
2642 assert(consdata1 != NULL);
2643
2644 /* constraints with the less variables cannot be covered */
2645 if( consdata1->nvars < nvars )
2646 continue;
2647
2648 pos = -1;
2649
2650 assert(consdata->sorted);
2651 assert(consdata->merged);
2652 assert(consdata1->validsignature);
2653 assert(consdata1->sorted);
2654 assert(consdata1->merged);
2655
2656 if( (signature & (~consdata1->signature)) == 0 )
2657 {
2658 SCIP_VAR* var1;
2659 int v1;
2660
2661 v = 0;
2662 v1 = 0;
2663
2664 while( v < nvars && v1 < consdata1->nvars )
2665 {
2666 int comp;
2667
2668 /* skip position of artificial variable */
2669 if( artpos == v )
2670 {
2671 ++v;
2672 continue;
2673 }
2674
2675 var1 = consdata1->vars[v1];
2676
2677 /* did we find the artificial variable in cons1 */
2678 if( artvar == var1 )
2679 {
2680 /* remember of possible redundant variable */
2681 assert(pos == -1);
2682 pos = v1;
2683
2684 ++v1;
2685 continue;
2686 }
2687
2688 var = vars[v];
2689 comp = SCIPvarCompare(var, var1);
2690
2691 /* check if the cons1 can still be covered */
2692 if( comp == 0 )
2693 {
2694 ++v;
2695 ++v1;
2696 }
2697 else if( comp > 0 )
2698 ++v1;
2699 else
2700 break;
2701 }
2702
2703 /* cons1 is might be covered by the changed constraints cons, meaning that we might remove the artvar from
2704 * cons1
2705 */
2706 if( v == nvars )
2707 {
2708 int l;
2709
2710 /* if the artificial variable was not yet found, search over the rear variables in constraint cons1 */
2711 if( pos == -1 )
2712 {
2713 while( v1 < consdata1->nvars )
2714 {
2715 if( artvar == consdata1->vars[v1] )
2716 {
2717 /* remember of possible redundant variable */
2718 pos = v1;
2719 break;
2720 }
2721 ++v1;
2722 }
2723 }
2724
2725 if( pos >= 0 )
2726 {
2727 int conspos;
2728
2729 assert(pos < consdata1->nvars);
2730 assert(artvar == consdata1->vars[pos]);
2731
2732 /* remove redudant entry in cons1 */
2733 SCIPdebugMsg(scip, "variable %s in logicor constraint <%s> is redundant and will be removed (used constraint %s)\n",
2734 SCIPvarGetName(artvar), SCIPconsGetName(cons1), SCIPconsGetName(cons));
2735 SCIPdebugPrintCons(scip, cons1, NULL);
2736 conspos = pos;
2737
2738 if( consdata1->nvars > nvars )
2739 {
2740 pos = SCIPhashmapGetImageInt(varstopos, (void*)artvar);
2741 assert(0 < pos && pos <= occurlistlength);
2742
2743 --pos;
2744
2745 /* remove corresponding entry in column representation */
2746 for( l = noccurlistentries[pos] - 1; l >= 0; --l )
2747 {
2748 if( occurlist[pos][l] == cons1 )
2749 {
2750 --noccurlistentries[pos];
2751 assert(noccurlistentries[pos] >= 0);
2752
2753 occurlist[pos][l] = occurlist[pos][noccurlistentries[pos]];
2754 break;
2755 }
2756 }
2757 assert(l >= 0);
2758 }
2759 else
2760 {
2761 assert(consdata1->nvars == nvars);
2762
2763 /* delete cons */
2764 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to constraint <%s> after removing variable <%s>\n",
2765 SCIPconsGetName(cons), SCIPconsGetName(cons1), SCIPvarGetName(artvar));
2766
2767 /* remove cons from columns representation */
2768 removeConsFromOccurList(cons, varstopos, occurlist, noccurlistentries, occurlistlength);
2769
2770 /* update flags of cons1 */
2771 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
2772
2773 SCIP_CALL( SCIPdelCons(scip, cons) );
2774 *deleted = TRUE;
2775 }
2776
2777 /* remove variable */
2778 SCIP_CALL( delCoefPos(scip, cons1, eventhdlr, conspos) );
2779 ++(*nchgcoefs);
2780 consdataSort(consdata1);
2781 consdataCalcSignature(consdata1);
2782
2783 if( *deleted )
2784 return SCIP_OKAY;
2785 }
2786 }
2787 }
2788 }
2789 }
2790
2791 return SCIP_OKAY;
2792}
2793
2794/** find and remove redundant non-zero entries */
2795static
2797 SCIP* scip, /**< SCIP data structure */
2798 SCIP_CONS** conss, /**< sorted array of logicor constraint */
2799 int nconss, /**< number of sorted constraints */
2800 SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2801 SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2802 int* noccurlistentries, /**< number of constraints for each variable in the occurlist */
2803 int occurlistlength, /**< number of columns in the occurlist */
2804 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2805 int* ndelconss, /**< pointer to store the number of deleted constraints */
2806 int* nchgcoefs /**< pointer to store the number of remove coefficients */
2807 )
2808{
2809 SCIP_VAR** vars;
2810 SCIP_CONSDATA* consdata;
2811 SCIP_CONS* cons;
2812 SCIP_VAR* artvar;
2813 int nvars;
2814 int c;
2815 int v;
2816
2817 assert(scip != NULL);
2818 assert(conss != NULL || nconss == 0);
2819 assert(varstopos != NULL);
2820 assert(occurlist != NULL);
2821 assert(noccurlistentries != NULL);
2822 assert(eventhdlr != NULL);
2823 assert(ndelconss != NULL);
2824 assert(nchgcoefs != NULL);
2825
2826 if( nconss == 0 )
2827 return SCIP_OKAY;
2828
2829 assert(conss != NULL);
2830
2831 for( c = 0; c < nconss; ++c )
2832 {
2833 cons = conss[c];
2834 assert(cons != NULL);
2836
2837 if( !SCIPconsIsActive(cons) )
2838 continue;
2839
2840 consdata = SCIPconsGetData(cons);
2841 assert(consdata != NULL);
2842
2843 nvars = consdata->nvars;
2844 assert(nvars >= 1);
2845
2846 if( nvars == 1 )
2847 continue;
2848
2849 vars = consdata->vars;
2850 assert(vars != NULL);
2851
2852 for( v = nvars - 1; v >= 0; --v )
2853 {
2854 artvar = SCIPvarGetNegatedVar(vars[v]);
2855
2856 if( artvar != NULL && SCIPhashmapExists(varstopos, (void*) artvar) )
2857 {
2858 SCIP_Bool deleted;
2859
2860 /* detect and remove redundant non-zero entries */
2861 /* @todo: improve this algorithm by using the information that a constraint variables does not appaer in any
2862 * other constraint, which means that only this variable needs to be negated to check for redundant
2863 * non-zeros, therefor change also findShortestOccurlist() to return the corresponding
2864 * variable/position
2865 */
2866 SCIP_CALL( removeRedundantNonZeros(scip, cons, artvar, v, varstopos, occurlist, noccurlistentries,
2867 occurlistlength, eventhdlr, nchgcoefs, &deleted) );
2868
2869 if( deleted )
2870 {
2872 ++(*ndelconss);
2873 break;
2874 }
2875 else
2876 assert(SCIPconsIsActive(cons));
2877 }
2878 }
2879 }
2880
2881 return SCIP_OKAY;
2882}
2883
2884
2885/** prepares a constraint by removing fixings and merge it */
2886static
2888 SCIP* scip, /**< SCIP data structure */
2889 SCIP_CONS* cons, /**< logic or constraint */
2890 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2891 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
2892 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
2893 SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
2894 int* nfixedvars, /**< pointer to count number of fixings */
2895 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
2896 int* ndelconss, /**< pointer to count number of deleted constraints */
2897 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
2898 )
2899{
2900 SCIP_CONSDATA* consdata;
2901
2902 assert(scip != NULL);
2903 assert(cons != NULL);
2904 assert(!SCIPconsIsDeleted(cons));
2905 assert(eventhdlr != NULL);
2906 assert(*entries != NULL);
2907 assert(nentries != NULL);
2908 assert(redundant != NULL);
2909 assert(nfixedvars != NULL);
2910 assert(nchgcoefs != NULL);
2911 assert(ndelconss != NULL);
2912 assert(redundant != NULL);
2913
2914 consdata = SCIPconsGetData(cons);
2915 assert(consdata != NULL);
2916 assert(consdata->nvars > 0);
2917
2918 *redundant = FALSE;
2919
2920 /* remove old fixings */
2921 if( !consdata->presolved )
2922 {
2923 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
2924 SCIP_CALL( applyFixings(scip, cons, eventhdlr, redundant, nchgcoefs, NULL, NULL) );
2925 }
2926
2927 if( !*redundant )
2928 {
2929 /* merge constraint */
2930 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, redundant, nchgcoefs) );
2931 }
2932
2933 if( *redundant )
2934 {
2935 SCIP_CALL( SCIPdelCons(scip, cons) );
2936 ++(*ndelconss);
2937
2938 return SCIP_OKAY;
2939 }
2940
2941 if( consdata->nvars == 0 )
2942 {
2943 *cutoff = TRUE;
2944 }
2945 else if( consdata->nvars == 1 )
2946 {
2947 SCIP_Bool infeasible;
2948 SCIP_Bool fixed;
2949
2950 SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
2951
2952 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
2953 assert(!infeasible);
2954 assert(fixed);
2955 ++(*nfixedvars);
2956
2957 SCIP_CALL( SCIPdelCons(scip, cons) );
2958 ++(*ndelconss);
2959
2960 *redundant = TRUE;
2961 }
2962 consdata->presolved = TRUE;
2963
2964 return SCIP_OKAY;
2965}
2966
2967
2968/** find covered/subsumed constraints and redundant non-zero entries
2969 *
2970 * covered:
2971 * e.g.: c1: x1 + x2 + x3 >= 1
2972 * c2: x1 + x2 + x3 + x4 >= 1
2973 *
2974 * strengthen:
2975 * e.g.: c1: x1 + x2 + x3 >= 1
2976 * c2: x1 + x2 + ~x3 + x4 >= 1
2977 *
2978 * => c2: x1 + x2 + x4 >= 1
2979 *
2980 * @see "Effective Preprocessing in SAT through Variable and Clause Elimination" by Niklas En and Armin Biere
2981 */
2982static
2984 SCIP* scip, /**< SCIP data structure */
2985 SCIP_CONS** conss, /**< array of logicor constraints */
2986 int nconss, /**< number of logicor constraints */
2987 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
2988 * variable */
2989 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
2990 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2991 SCIP_Bool usestrengthening, /**< should we try to strengthen constraints by removing superflous
2992 * non-zeros? */
2993 int* firstchange, /**< pointer to store first changed constraint */
2994 int* nfixedvars, /**< pointer to count number of fixings */
2995 int* ndelconss, /**< pointer to store the number of deleted constraints */
2996 int* nchgcoefs, /**< pointer to store the number of deleted coefficients */
2997 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
2998 )
2999{
3000 SCIP_CONS*** occurlist;
3001 SCIP_CONS** myconss;
3002 SCIP_HASHMAP* varstopos;
3003 SCIP_CONS* cons;
3004 SCIP_CONSDATA* consdata;
3005 int* noccurlistentries;
3006 int* occurlistsizes;
3007 SCIP_Bool redundant;
3008 SCIP_Bool conschanged;
3009 int lastnfixedvars;
3010 int nbinvars;
3011 int occurlistlength;
3012 int occurlistsize;
3013 int nmyconss;
3014 int nmaxvars;
3015 int c;
3016
3017 assert(scip != NULL);
3018 assert(conss != NULL || nconss == 0);
3019 assert(entries != NULL);
3020 assert(*entries != NULL);
3021 assert(nentries != NULL);
3022 assert(eventhdlr != NULL);
3023 assert(firstchange != NULL);
3024 assert(0 <= *firstchange);
3025 assert(nfixedvars != NULL);
3026 assert(ndelconss != NULL);
3027 assert(nchgcoefs != NULL);
3028
3029 if( *firstchange > nconss || nconss < 2 )
3030 return SCIP_OKAY;
3031
3032 SCIPdebugMsg(scip, "starting removeRedundantConssAndNonzeros(), pairwise comparison to detect covered logicor constraints\n");
3033
3034 /* copy constraints to re-order them */
3035 SCIP_CALL( SCIPduplicateBufferArray(scip, &myconss, conss, nconss) );
3036
3037 nmyconss = nconss;
3038 lastnfixedvars = -1;
3039 while( *nfixedvars != lastnfixedvars )
3040 {
3041 lastnfixedvars = *nfixedvars;
3042 for( c = nconss - 1; c >= 0; --c )
3043 {
3044 cons = myconss[c];
3045 assert(cons != NULL);
3046
3047 if( SCIPconsIsDeleted(cons) || SCIPconsIsModifiable(cons) )
3048 {
3049 myconss[c] = myconss[nmyconss - 1];
3050 --nmyconss;
3051
3052 continue;
3053 }
3054
3055 /* prepare constraint by removing fixings and merge it */
3056 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
3057
3058 if( redundant )
3059 {
3061 assert(!(*cutoff));
3062
3063 myconss[c] = myconss[nmyconss - 1];
3064 --nmyconss;
3065
3066 continue;
3067 }
3068
3069 if( *cutoff )
3070 {
3071 SCIPfreeBufferArray(scip, &myconss);
3072
3073 return SCIP_OKAY;
3074 }
3075
3076 consdata = SCIPconsGetData(cons);
3077
3078 /* sort the constraint */
3079 consdataSort(consdata);
3080
3081 assert(consdata->nvars >= 2);
3082 }
3083 }
3084
3085 SCIPsortPtr((void**)myconss, conssLogicorComp, nmyconss);
3086 assert(myconss[0] != NULL && myconss[nmyconss - 1] != NULL);
3087 assert(SCIPconsGetData(myconss[0]) != NULL && SCIPconsGetData(myconss[nmyconss - 1]) != NULL);
3088 assert(SCIPconsGetData(myconss[0])->nvars <= SCIPconsGetData(myconss[nmyconss - 1])->nvars);
3089
3090 /* we can stop if strengthening is disabled and all constraints have the same amount of variables */
3091 if( !usestrengthening && SCIPconsGetData(myconss[0])->nvars == SCIPconsGetData(myconss[nmyconss - 1])->nvars )
3092 {
3093 SCIPfreeBufferArray(scip, &myconss);
3094
3095 return SCIP_OKAY;
3096 }
3097
3098 /* @note: in the following we have at least number of nonzeros in logicor constraints + three times two the number of
3099 * binary variables memory consumption + a map for variables to positions, we need this to get a column base
3100 * representation
3101 */
3102
3103 /* get number of all possible(incl. implicit) binary variables and their negation */
3104 nbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
3105 occurlistsize = 2 * nbinvars;
3106
3107 /* allocate memory for the column representation for each variable */
3108 SCIP_CALL( SCIPallocBufferArray(scip, &occurlist, occurlistsize) );
3109 BMSclearMemoryArray(occurlist, occurlistsize);
3110 SCIP_CALL( SCIPallocBufferArray(scip, &noccurlistentries, occurlistsize) );
3111 BMSclearMemoryArray(noccurlistentries, occurlistsize);
3112 SCIP_CALL( SCIPallocBufferArray(scip, &occurlistsizes, occurlistsize) );
3113 BMSclearMemoryArray(occurlistsizes, occurlistsize);
3114
3115 /* create hashmap to map all occuring variables to a position in the list */
3116 SCIP_CALL( SCIPhashmapCreate(&varstopos, SCIPblkmem(scip), nmyconss) );
3117
3118 /* get maximal number of variables over all logicor constraints */
3119 c = nmyconss - 1;
3120 cons = myconss[c];
3121 assert(cons != NULL);
3122 assert(SCIPconsIsActive(cons));
3123 consdata = SCIPconsGetData(cons);
3124 assert(consdata != NULL);
3125 nmaxvars = consdata->nvars;
3126
3127 occurlistlength = 0;
3128 conschanged = FALSE;
3129
3130 /* determine all constraints with the maximal number of variables and add them to the column representation */
3131 do
3132 {
3133 /* calculate hash-signature */
3134 consdataCalcSignature(consdata);
3135 assert(consdata->validsignature);
3136 conschanged = conschanged || consdata->changed;
3137 consdata->changed = FALSE;
3138
3139 /* add constraint to column data structure */
3140 SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
3141
3142 --c;
3143 if( c < 0 )
3144 break;
3145
3146 cons = myconss[c];
3147 assert(cons != NULL);
3148 assert(SCIPconsIsActive(cons));
3149 consdata = SCIPconsGetData(cons);
3150 assert(consdata != NULL);
3151 }
3152 while( consdata->nvars == nmaxvars );
3153
3154 /* remove covered constraints and left over constraints to the column representation */
3155 while( c >= 0 )
3156 {
3157 cons = myconss[c];
3158 assert(cons != NULL);
3159 assert(SCIPconsIsActive(cons));
3160 consdata = SCIPconsGetData(cons);
3161 assert(consdata != NULL);
3162
3163 /* calculate hash-signature */
3164 consdataCalcSignature(consdata);
3165 assert(consdata->validsignature);
3166
3167 /* search for covered constraints */
3168 if( conschanged || consdata->changed )
3169 {
3170 /* detect covered constraints
3171 *
3172 * e.g.: c1: x1 + x2 + x3 >= 1
3173 * c2: x1 + x2 + x3 + x4 >= 1
3174 *
3175 * => delete c2
3176 */
3177 SCIP_CALL( removeRedundantConss(scip, cons, varstopos, occurlist, noccurlistentries, occurlistlength, ndelconss) );
3178 assert(SCIPconsIsActive(cons));
3179
3180 consdata->changed = FALSE;
3181 conschanged = TRUE;
3182 }
3183
3184 /* add constraint to column data structure */
3185 SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
3186
3187 --c;
3188 }
3189
3190 /* strengthen constraint while removing non-zeros
3191 *
3192 * e.g.: c1: x1 + x2 + x3 >= 1
3193 * c2: x1 + x2 + ~x3 + x4 >= 1
3194 *
3195 * => c2: x1 + x2 + x4 >= 1
3196 *
3197 * special case:
3198 *
3199 * e.g.: c1: x1 + x2 + x3 >= 1
3200 * c2: x1 + x2 + ~x3 >= 1
3201 *
3202 * => delete c1; c2: x1 + x2 >= 1
3203 *
3204 */
3205 SCIP_CALL( strengthenConss(scip, myconss, nmyconss, varstopos, occurlist, noccurlistentries, occurlistlength, eventhdlr, ndelconss, nchgcoefs) );
3206
3207 /* delete temporary memory in occurlist */
3208 for( --occurlistsize ; occurlistsize >= 0; --occurlistsize )
3209 {
3210 assert((occurlistsizes[occurlistsize] == 0) == (occurlist[occurlistsize] == NULL));
3211 SCIPfreeBufferArrayNull(scip, &(occurlist[occurlistsize]));
3212 }
3213
3214 /* delete temporary memory */
3215 SCIPhashmapFree(&varstopos);
3216 SCIPfreeBufferArray(scip, &occurlistsizes);
3217 SCIPfreeBufferArray(scip, &noccurlistentries);
3218 SCIPfreeBufferArray(scip, &occurlist);
3219 SCIPfreeBufferArray(scip, &myconss);
3220
3221 return SCIP_OKAY;
3222}
3223
3224#define MAX_CONSLENGTH 200
3225
3226/** try to tighten constraints by reducing the number of variables in the constraints using implications and cliques,
3227 * also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
3228 */
3229static
3231 SCIP* scip, /**< SCIP data structure */
3232 SCIP_CONSHDLRDATA* conshdlrdata, /**< logic or constraint handler data */
3233 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
3234 SCIP_CONS** conss, /**< all constraints */
3235 int nconss, /**< number of constraints */
3236 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
3237 * variable */
3238 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
3239 int* nfixedvars, /**< pointer to count number of fixings */
3240 int* ndelconss, /**< pointer to count number of deleted constraints */
3241 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
3242 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
3243 )
3244{
3245 SCIP_VAR** probvars;
3246 SCIP_VAR* var;
3247 SCIP_Real* bounds;
3248 SCIP_Bool* boundtypes;
3249 SCIP_Bool* redundants;
3250 int nbinprobvars;
3251 int nredvars;
3252 int c;
3253 int v;
3254
3255 assert(scip != NULL);
3256 assert(eventhdlr != NULL);
3257 assert(conss != NULL || nconss == 0);
3258 assert(entries != NULL);
3259 assert(*entries != NULL);
3260 assert(nentries != NULL);
3261 assert(nfixedvars != NULL);
3262 assert(ndelconss != NULL);
3263 assert(nchgcoefs != NULL);
3264
3265 if( nconss == 0 )
3266 return SCIP_OKAY;
3267
3268 assert(conss != NULL);
3269
3270 if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesshorten
3271 && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsshorten )
3272 return SCIP_OKAY;
3273
3274 conshdlrdata->nlastcliquesshorten = SCIPgetNCliques(scip);
3275 conshdlrdata->nlastimplsshorten = SCIPgetNImplications(scip);
3276
3277 nbinprobvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
3278
3279 /* allocate temporary memory */
3280 SCIP_CALL( SCIPallocBufferArray(scip, &probvars, nbinprobvars) );
3281 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nbinprobvars) );
3282 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nbinprobvars) );
3283 SCIP_CALL( SCIPallocCleanBufferArray(scip, &redundants, nbinprobvars) );
3284
3285 for( c = nconss - 1; c >= 0; --c )
3286 {
3287 SCIP_Bool redundant = FALSE;
3288 SCIP_CONS* cons = conss[c];
3289 SCIP_CONSDATA* consdata;
3290
3291 assert(cons != NULL);
3292
3293 if( SCIPconsIsDeleted(cons) )
3294 continue;
3295
3296 consdata = SCIPconsGetData(cons);
3297 assert(consdata != NULL);
3298
3299 /* prepare constraint by removing fixings and merge it; we invalidate the presolved flag, because the calls to
3300 * SCIPcleanupCliques() in this loop may have lead to fixed variables that are not yet removed */
3301 consdata->presolved = FALSE;
3302 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
3303
3304 if( redundant )
3305 {
3307 continue;
3308 }
3309
3310 if( *cutoff )
3311 goto TERMINATE;
3312
3313 assert(consdata->nvars >= 2);
3314
3315 /* do not try to shorten too long constraints */
3316 if( consdata->nvars > MAX_CONSLENGTH )
3317 continue;
3318
3319 /* form necessary data */
3320 for( v = consdata->nvars - 1; v >= 0; --v)
3321 {
3322 var = consdata->vars[v];
3323 assert(var != NULL);
3325
3326 if( SCIPvarIsActive(var) )
3327 {
3328 probvars[v] = var;
3329 bounds[v] = 1.0;
3330 boundtypes[v] = FALSE;
3331 }
3332 else
3333 {
3334 probvars[v] = SCIPvarGetNegationVar(var);
3335 bounds[v] = 0.0;
3336 boundtypes[v] = TRUE;
3337 }
3338 }
3339
3341
3342 if( *cutoff )
3343 goto TERMINATE;
3344
3345 /* use implications and cliques to derive global fixings and to shrink the number of variables in this constraints */
3346 SCIP_CALL( SCIPshrinkDisjunctiveVarSet(scip, probvars, bounds, boundtypes, redundants, consdata->nvars, &nredvars,
3347 nfixedvars, &redundant, cutoff, TRUE) );
3348
3349 if( *cutoff )
3350 {
3351 /* reset redundants array to FALSE */
3352 BMSclearMemoryArray(redundants, nbinprobvars);
3353 goto TERMINATE;
3354 }
3355
3356 /* remove redundant constraint */
3357 if( redundant )
3358 {
3359 SCIP_CALL( SCIPdelCons(scip, cons) );
3360 ++(*ndelconss);
3361
3362 /* reset redundants array to FALSE */
3363 BMSclearMemoryArray(redundants, consdata->nvars);
3364 continue;
3365 }
3366
3367 /* remove redundant variables */
3368 if( nredvars > 0 )
3369 {
3370 for( v = consdata->nvars - 1; v >= 0; --v )
3371 {
3372 if( redundants[v] )
3373 {
3374 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
3375
3376 /* reset entry to FALSE */
3377 redundants[v] = FALSE;
3378 }
3379 }
3380 *nchgcoefs += nredvars;
3381
3382 /* if only one variable is left over fix it */
3383 if( consdata->nvars == 1 )
3384 {
3385 SCIP_Bool infeasible;
3386 SCIP_Bool fixed;
3387
3388 SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
3389
3390 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
3391 assert(!infeasible);
3392 assert(fixed);
3393 ++(*nfixedvars);
3394
3395 SCIP_CALL( SCIPdelCons(scip, cons) );
3396 ++(*ndelconss);
3397 }
3398 /* @todo might also upgrade a two variable constraint to a set-packing constraint */
3399 }
3400 }
3401
3402 /* invalidate the presolved flags, because the calls to SCIPcleanupCliques() may have lead to fixed variables that
3403 * are not yet removed */
3404 for( c = nconss - 1; c >= 0; --c )
3405 {
3406 SCIP_CONS* cons = conss[c];
3407 SCIP_CONSDATA* consdata;
3408
3409 assert(cons != NULL);
3410
3411 consdata = SCIPconsGetData(cons);
3412 assert(consdata != NULL);
3413
3414 consdata->presolved = FALSE;
3415 }
3416
3417 TERMINATE:
3418 /* free temporary memory */
3419 SCIPfreeCleanBufferArray(scip, &redundants);
3420 SCIPfreeBufferArray(scip, &boundtypes);
3421 SCIPfreeBufferArray(scip, &bounds);
3422 SCIPfreeBufferArray(scip, &probvars);
3423
3424 return SCIP_OKAY;
3425}
3426
3427#define MAXCOMPARISONS 1000000
3428
3429/** try to find a negated clique in a constraint which makes this constraint redundant but we need to keep the negated
3430 * clique information alive, so we create a corresponding set-packing constraint
3431 */
3432static
3434 SCIP* scip, /**< SCIP data structure */
3435 SCIP_CONSHDLR* conshdlr, /**< logicor constraint handler */
3436 SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
3437 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
3438 SCIP_CONS** conss, /**< all constraints */
3439 int nconss, /**< number of constraints */
3440 unsigned char** entries, /**< array to store whether two positions in constraints represent the same
3441 * variable */
3442 int* nentries, /**< pointer for array size, if array will be to small it's corrected */
3443 int* nfixedvars, /**< pointer to count number of fixings */
3444 int* ndelconss, /**< pointer to count number of deleted constraints */
3445 int* nupgdconss, /**< pointer to count number of upgraded constraints */
3446 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
3447 SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
3448 )
3449{
3450 SCIP_CONSHDLRDATA* conshdlrdata;
3451 SCIP_CONS* cons;
3452 SCIP_CONSDATA* consdata;
3453 SCIP_VAR** repvars;
3454 SCIP_Bool* negated;
3455 SCIP_VAR* var1;
3456 SCIP_Bool redundant;
3457 int c;
3458 int size;
3459 int maxcomppercons;
3460 int comppercons;
3461
3462 assert(scip != NULL);
3463 assert(conshdlr != NULL);
3464 assert(eventhdlr != NULL);
3465 assert(conss != NULL || nconss == 0);
3466 assert(entries != NULL);
3467 assert(*entries != NULL);
3468 assert(nentries != NULL);
3469 assert(nfixedvars != NULL);
3470 assert(ndelconss != NULL);
3471 assert(nupgdconss != NULL);
3472 assert(nchgcoefs != NULL);
3473 assert(cutoff != NULL);
3474
3475 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3476 assert(conshdlrdata != NULL);
3477
3478 if( nconss == 0 )
3479 return SCIP_OKAY;
3480
3481 if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesneg && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsneg )
3482 return SCIP_OKAY;
3483
3484 conshdlrdata->nlastcliquesneg = SCIPgetNCliques(scip);
3485 conshdlrdata->nlastimplsneg = SCIPgetNImplications(scip);
3486
3487 /* estimate the maximal number of variables in a logicor constraint */
3489 if( size <= 0 )
3490 return SCIP_OKAY;
3491
3492 /* temporary memory for active/negation of active variables */
3493 SCIP_CALL( SCIPallocBufferArray(scip, &repvars, size) );
3494 SCIP_CALL( SCIPallocBufferArray(scip, &negated, size) );
3495
3496 /* iterate over all constraints and try to find negated cliques in logicors */
3497 for( c = nconss - 1; c >= 0; --c )
3498 {
3499 int v;
3500
3501 assert(conss != NULL); /* for flexelint */
3502
3503 cons = conss[c];
3504 assert(cons != NULL);
3505
3506 if( !SCIPconsIsActive(cons) )
3507 continue;
3508
3509 /* prepare constraint by removing fixings and merge it */
3510 SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
3511
3512 if( redundant )
3513 {
3515 continue;
3516 }
3517
3518 if( *cutoff )
3519 goto TERMINATE;
3520
3521 consdata = SCIPconsGetData(cons);
3522 assert(consdata != NULL);
3523 assert(consdata->nvars >= 2);
3524 assert(consdata->nvars <= size);
3525 assert(consdata->presolved);
3526
3527 if( SCIPconsIsModifiable(cons) && consdata->nvars == 2 )
3528 continue;
3529
3530 if( c % 100 == 0 && SCIPisStopped(scip) )
3531 break;
3532
3533 maxcomppercons = MAXCOMPARISONS / nconss;
3534 comppercons = 0;
3535
3536 BMScopyMemoryArray(repvars, consdata->vars, consdata->nvars);
3537
3538 /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
3539 * called before mergeMultiples()
3540 */
3541 for( v = consdata->nvars - 1; v >= 0; --v )
3542 {
3544 negated[v] = SCIPvarIsNegated(repvars[v]);
3545 }
3546
3547 for( v = consdata->nvars - 1; v > 0; --v )
3548 {
3549 SCIP_Bool breakloop;
3550 SCIP_Bool neg1;
3551 int w;
3552
3553 var1 = repvars[v];
3554
3555 /* if there is no negated variable, there can't be a negated clique */
3556 if( SCIPvarGetNegatedVar(var1) == NULL )
3557 continue;
3558
3559 /* get active counterpart to check for common cliques */
3561 {
3562 var1 = SCIPvarGetNegatedVar(var1);
3563 neg1 = TRUE;
3564 }
3565 else
3566 neg1 = FALSE;
3567
3568 if( !SCIPvarIsActive(var1) )
3569 continue;
3570
3571 /* no cliques available */
3572 if( SCIPvarGetNCliques(var1, neg1) == 0 && SCIPvarGetNImpls(var1, neg1) == 0 )
3573 continue;
3574
3575 comppercons += (v - 1);
3576
3577 breakloop = FALSE;
3578
3579 for( w = v - 1; w >= 0; --w )
3580 {
3581 SCIP_VAR* var2;
3582 SCIP_Bool neg2;
3583
3584 var2 = repvars[w];
3585
3586 /* if there is no negated variable, there can't be a negated clique */
3587 if( SCIPvarGetNegatedVar(var2) == NULL )
3588 continue;
3589
3591 {
3592 var2 = SCIPvarGetNegatedVar(var2);
3593 neg2 = TRUE;
3594 }
3595 else
3596 neg2 = FALSE;
3597
3598 if( !SCIPvarIsActive(var2) )
3599 continue;
3600
3601 /* no cliques available */
3602 if( SCIPvarGetNCliques(var2, neg2) == 0 && SCIPvarGetNImpls(var2, neg2) == 0 )
3603 continue;
3604
3605 /* check if both active variable are the same */
3606 if( var1 == var2 )
3607 {
3608 if( neg1 != neg2 )
3609 {
3610 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant, because variable <%s> and its negation <%s> exist\n",
3611 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
3612
3613 SCIP_CALL( SCIPdelCons(scip, cons) );
3614
3615 breakloop = TRUE;
3616 }
3617 else
3618 {
3619 #ifndef NDEBUG
3620 SCIP_VAR* lastvar = consdata->vars[consdata->nvars - 1];
3621 #endif
3622 SCIPdebugMsg(scip, "in logicor constraint <%s>, active variable of <%s> and active variable of <%s> are the same, removing the first\n",
3623 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
3624
3625 SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
3626
3627 if( v < consdata->nvars )
3628 {
3629 /* delCoefPos replaces the variable on position v with the last one, so w also need to correct the
3630 * negated array the same way, and because of deletion the number of variables is already decreased
3631 */
3632 assert(consdata->vars[v] == lastvar);
3633 negated[v] = negated[consdata->nvars];
3634 }
3635 ++(*nchgcoefs);
3636 }
3637 break;
3638 }
3639
3640 if( conshdlrsetppc != NULL && SCIPconsGetNUpgradeLocks(cons) == 0
3641 && SCIPvarsHaveCommonClique(var1, neg1, var2, neg2, TRUE) )
3642 {
3643 SCIP_CONS* newcons;
3644 SCIP_VAR* vars[2];
3645
3646 /* this negated clique information could be created out of this logicor constraint even if there are more
3647 * than two variables left (, for example by probing), we need to keep this information by creating a
3648 * setppc constraint instead
3649 */
3650
3651 /* get correct variables */
3652 if( !neg1 )
3653 vars[0] = SCIPvarGetNegatedVar(var1);
3654 else
3655 vars[0] = var1;
3656
3657 if( !neg2 )
3658 vars[1] = SCIPvarGetNegatedVar(var2);
3659 else
3660 vars[1] = var2;
3661
3667
3668 SCIPdebugPrintCons(scip, newcons, NULL);
3669 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
3670
3671 SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to negated clique information and will be replaced by a setppc constraint \n",
3672 SCIPconsGetName(cons));
3673 SCIPdebugMsg(scip, "variable <%s> and variable <%s> are in a negated clique\n", SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
3674
3675 SCIP_CALL( SCIPdelCons(scip, cons) );
3676 ++(*nupgdconss);
3677
3678 breakloop = TRUE;
3679 break;
3680 }
3681 }
3682 if( breakloop )
3683 break;
3684
3685 /* do not do to many comparisons */
3686 if( comppercons > maxcomppercons )
3687 break;
3688 }
3689 }
3690
3691 TERMINATE:
3692 /* free temporary memory */
3693 SCIPfreeBufferArray(scip, &negated);
3694 SCIPfreeBufferArray(scip, &repvars);
3695
3696 return SCIP_OKAY;
3697}
3698
3699/** handle all cases with less than three variables in a logicor constraint
3700 *
3701 * in case a constraint has zero variables left, we detected infeasibility
3702 * in case a constraint has one variables left, we will fix it to one
3703 * in case a constraint has two variables left, we will add the implication and upgrade it to a set-packing constraint
3704 */
3705static
3707 SCIP* scip, /**< SCIP data structure */
3708 SCIP_CONS* cons, /**< logic or constraint */
3709 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
3710 SCIP_CONSHDLR* conshdlrlinear, /**< linear constraint handler, or NULL */
3711 SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
3712 int* nfixedvars, /**< pointer to count number of fixings */
3713 int* nchgbds, /**< pointer to count number of tightened bounds */
3714 int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
3715 int* ndelconss, /**< pointer to count number of deleted constraints */
3716 int* naddconss, /**< pointer to count number of added constraints */
3717 int* nupgdconss, /**< pointer to count number of upgraded constraints */
3718 SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
3719 )
3720{
3721 SCIP_CONSDATA* consdata;
3722 SCIP_Bool infeasible;
3723 SCIP_Bool fixed;
3724
3725 assert(scip != NULL);
3726 assert(cons != NULL);
3727 assert(eventhdlr != NULL);
3728 assert(nfixedvars != NULL);
3729 assert(nchgbds != NULL);
3730 assert(nchgcoefs != NULL);
3731 assert(ndelconss != NULL);
3732 assert(naddconss != NULL);
3733 assert(nupgdconss != NULL);
3734 assert(cutoff != NULL);
3735
3736 *cutoff = FALSE;
3737
3738 if( SCIPconsIsModifiable(cons) )
3739 return SCIP_OKAY;
3740
3741 consdata = SCIPconsGetData(cons);
3742 assert(consdata != NULL);
3743
3744 /* if an unmodifiable logicor constraint has only two variables, we can add an implication and we will upgrade this
3745 * constraint to a set-packing constraint
3746 */
3747 if( consdata->nvars == 2 )
3748 {
3749 /* add implication if not yet done */
3750 if( !consdata->impladded )
3751 {
3752 SCIP_Bool implinfeasible;
3753 int nimplbdchgs;
3754 SCIP_Bool values[2];
3755
3756 values[0] = FALSE;
3757 values[1] = FALSE;
3758 /* a two-variable logicor constraint x + y >= 1 yields the implication x == 0 -> y == 1, and is represented
3759 * by the clique inequality ~x + ~y <= 1
3760 */
3761 SCIP_CALL( SCIPaddClique(scip, consdata->vars, values, consdata->nvars, FALSE, &implinfeasible, &nimplbdchgs) );
3762 *nchgbds += nimplbdchgs;
3763 if( implinfeasible )
3764 {
3765 *cutoff = TRUE;
3766 return SCIP_OKAY;
3767 }
3768
3769 /* adding the above implication could lead to fixings, which render the constraint redundant */
3770 if ( nimplbdchgs > 0 )
3771 {
3772 SCIP_Bool redundant;
3773
3774 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
3775 SCIP_CALL( applyFixings(scip, cons, eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
3776 assert(!SCIPconsIsDeleted(cons));
3777
3778 if( redundant )
3779 {
3780 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
3781
3782 SCIP_CALL( SCIPdelCons(scip, cons) );
3783 (*ndelconss)++;
3784
3785 return SCIP_OKAY;
3786 }
3787 }
3788 consdata->impladded = TRUE;
3789 }
3790
3791 /* still we have two variables left, we will upgrade this constraint */
3792 if( conshdlrsetppc != NULL && SCIPconsGetNUpgradeLocks(cons) == 0 && consdata->nvars == 2 )
3793 {
3794 SCIP_CONS* newcons;
3795 SCIP_VAR* vars[2];
3796
3797 /* get correct variables */
3798 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[0], &vars[0]) );
3799 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[1], &vars[1]) );
3800
3806
3807 SCIPdebugPrintCons(scip, newcons, NULL);
3808 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
3809
3810 SCIPdebugMsg(scip, "logicor constraint <%s> was upgraded to a set-packing constraint\n", SCIPconsGetName(cons));
3811
3812 SCIP_CALL( SCIPdelCons(scip, cons) );
3813 ++(*nupgdconss);
3814 }
3815 }
3816
3817 /* if unmodifiable constraint has no variables, it is infeasible,
3818 * if unmodifiable constraint has only one variable, this one can be fixed and the constraint deleted
3819 */
3820 if( consdata->nvars == 0 )
3821 {
3822 SCIPdebugMsg(scip, "logic or constraint <%s> is infeasible\n", SCIPconsGetName(cons));
3823
3824 *cutoff = TRUE;
3825 }
3826 else if( consdata->nvars == 1 )
3827 {
3828 SCIPdebugMsg(scip, "logic or constraint <%s> has only one variable not fixed to 0.0\n",
3829 SCIPconsGetName(cons));
3830
3831 assert(consdata->vars != NULL);
3832 assert(consdata->vars[0] != NULL);
3833
3834 if( SCIPvarGetStatus(consdata->vars[0]) != SCIP_VARSTATUS_MULTAGGR )
3835 {
3836 SCIPdebugMsg(scip, " -> fix variable and delete constraint\n");
3837
3838 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
3839 if( infeasible )
3840 {
3841 SCIPdebugMsg(scip, " -> infeasible fixing\n");
3842
3843 *cutoff = TRUE;
3844 return SCIP_OKAY;
3845 }
3846 if( fixed )
3847 (*nfixedvars)++;
3848
3849 SCIP_CALL( SCIPdelCons(scip, cons) );
3850 (*ndelconss)++;
3851 }
3852 else if( conshdlrlinear != NULL )
3853 {
3854 SCIP_Real coef;
3855 SCIP_CONS* conslinear;
3856 char consname[SCIP_MAXSTRLEN];
3857
3858 SCIPdebugMsg(scip, " -> variable is multi-aggregated, convert to linear constraint <%s> == 1 \n",
3859 SCIPvarGetName(consdata->vars[0]));
3860
3861 coef = 1.0;
3862 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "fixmaggr_%s_%s", SCIPconsGetName(cons),SCIPvarGetName(consdata->vars[0]) );
3863 SCIP_CALL( SCIPcreateConsLinear(scip, &conslinear, consname, 1, consdata->vars, &coef, 1.0, 1.0,
3867 SCIPconsIsStickingAtNode(cons)) );
3868
3869 /* add the downgraded constraint to the problem */
3870 SCIP_CALL( SCIPaddCons(scip, conslinear) );
3871 SCIP_CALL( SCIPreleaseCons(scip, &conslinear) );
3872 SCIP_CALL( SCIPdelCons(scip, cons) );
3873
3874 (*ndelconss)++;
3875 (*naddconss)++;
3876 }
3877 }
3878
3879 return SCIP_OKAY;
3880}
3881
3882
3883/*
3884 * upgrading of linear constraints
3885 */
3886
3887/** creates and captures a normalized (with all coefficients +1) logic or constraint */
3888static
3890 SCIP* scip, /**< SCIP data structure */
3891 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3892 const char* name, /**< name of constraint */
3893 int nvars, /**< number of variables in the constraint */
3894 SCIP_VAR** vars, /**< array with variables of constraint entries */
3895 SCIP_Real* vals, /**< array with coefficients (+1.0 or -1.0) */
3896 int mult, /**< multiplier on the coefficients(+1 or -1) */
3897 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3898 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3899 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3900 * Usually set to TRUE. */
3901 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3902 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3903 SCIP_Bool check, /**< should the constraint be checked for feasibility?
3904 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3905 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3906 * Usually set to TRUE. */
3907 SCIP_Bool local, /**< is constraint only valid locally?
3908 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3909 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3910 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3911 * adds coefficients to this constraint. */
3912 SCIP_Bool dynamic, /**< is constraint subject to aging?
3913 * Usually set to FALSE. Set to TRUE for own cuts which
3914 * are separated as constraints. */
3915 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3916 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3917 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3918 * if it may be moved to a more global node?
3919 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3920 )
3921{
3922 SCIP_VAR** transvars;
3923 int v;
3924
3925 assert(nvars == 0 || vars != NULL);
3926 assert(nvars == 0 || vals != NULL);
3927 assert(mult == +1 || mult == -1);
3928
3929 /* get temporary memory */
3930 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
3931
3932 /* negate positive or negative variables */
3933 for( v = 0; v < nvars; ++v )
3934 {
3935 if( mult * vals[v] > 0.0 )
3936 transvars[v] = vars[v];
3937 else
3938 {
3939 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
3940 }
3941 assert(transvars[v] != NULL);
3942 }
3943
3944 /* create the constraint */
3945 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, transvars,
3946 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3947
3948 /* free temporary memory */
3949 SCIPfreeBufferArray(scip, &transvars);
3950
3951 return SCIP_OKAY;
3952}
3953
3954static
3955SCIP_DECL_LINCONSUPGD(linconsUpgdLogicor)
3956{ /*lint --e{715}*/
3957 assert(upgdcons != NULL);
3958
3959 /* check, if linear constraint can be upgraded to logic or constraint
3960 * - logic or constraints consist only of binary variables with a
3961 * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
3962 * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
3963 * - negating all variables y = (1-Y) with negative coefficients gives:
3964 * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
3965 * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
3966 * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
3967 * - logic or constraints have left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
3968 * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
3969 */
3970 if( nvars > 2 && nposbin + nnegbin + nposimplbin + nnegimplbin == nvars && ncoeffspone + ncoeffsnone == nvars
3971 && ((SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, rhs))
3972 || (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, ncoeffspone - 1.0))) )
3973 {
3974 int mult;
3975
3976 SCIPdebugMsg(scip, "upgrading constraint <%s> to logic or constraint\n", SCIPconsGetName(cons));
3977
3978 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
3979 mult = SCIPisInfinity(scip, rhs) ? +1 : -1;
3980
3981 /* create the logic or constraint (an automatically upgraded constraint is always unmodifiable) */
3983 SCIP_CALL( createNormalizedLogicor(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
3988 }
3989
3990 return SCIP_OKAY;
3991}
3992
3993/** helper function to enforce constraints */
3994static
3996 SCIP* scip, /**< SCIP data structure */
3997 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3998 SCIP_CONS** conss, /**< constraints to process */
3999 int nconss, /**< number of constraints */
4000 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
4001 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
4002 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
4003 )
4004{
4005 SCIP_CONSHDLRDATA* conshdlrdata;
4007 SCIP_Bool separated;
4008 SCIP_Bool reduceddom;
4009 int c;
4010
4011 assert(conshdlr != NULL);
4012 assert(nconss == 0 || conss != NULL);
4013 assert(result != NULL);
4014
4016
4017 SCIPdebugMsg(scip, "Enforcing %d logic or constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
4018
4020
4021 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4022 assert(conshdlrdata != NULL);
4023
4024 cutoff = FALSE;
4025 separated = FALSE;
4026 reduceddom = FALSE;
4027
4028 /* check all useful logic or constraints for feasibility */
4029 for( c = 0; c < nusefulconss && !cutoff && !reduceddom; ++c )
4030 {
4031 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
4032 }
4033
4034 /* check all obsolete logic or constraints for feasibility */
4035 for( c = nusefulconss; c < nconss && !cutoff && !separated && !reduceddom; ++c )
4036 {
4037 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
4038 }
4039
4040 /* return the correct result */
4041 if( cutoff )
4043 else if( separated )
4045 else if( reduceddom )
4047
4048 return SCIP_OKAY;
4049}
4050
4051/** adds symmetry information of constraint to a symmetry detection graph */
4052static
4054 SCIP* scip, /**< SCIP pointer */
4055 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
4056 SCIP_CONS* cons, /**< constraint */
4057 SYM_GRAPH* graph, /**< symmetry detection graph */
4058 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
4059 )
4060{
4061 SCIP_CONSDATA* consdata;
4062 SCIP_VAR** logicorvars;
4063 SCIP_VAR** vars;
4064 SCIP_Real* vals;
4065 SCIP_Real constant = 0.0;
4066 int nlocvars;
4067 int nvars;
4068 int i;
4069
4070 assert(scip != NULL);
4071 assert(cons != NULL);
4072 assert(graph != NULL);
4073 assert(success != NULL);
4074
4075 consdata = SCIPconsGetData(cons);
4076 assert(consdata != NULL);
4077
4078 /* get active variables of the constraint */
4080 nlocvars = SCIPgetNVarsLogicor(scip, cons);
4081
4084
4085 logicorvars = SCIPgetVarsLogicor(scip, cons);
4086 for( i = 0; i < consdata->nvars; ++i )
4087 {
4088 vars[i] = logicorvars[i];
4089 vals[i] = 1.0;
4090 }
4091
4092 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
4093
4095 cons, 1.0 - constant, SCIPinfinity(scip), success) );
4096
4097 SCIPfreeBufferArray(scip, &vals);
4099
4100 return SCIP_OKAY;
4101}
4102
4103/*
4104 * Callback methods of constraint handler
4105 */
4106
4107/** copy method for constraint handler plugins (called when SCIP copies plugins) */
4108static
4109SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLogicor)
4110{ /*lint --e{715}*/
4111 assert(scip != NULL);
4112 assert(conshdlr != NULL);
4113
4115
4116 /* call inclusion method of constraint handler */
4118
4119 *valid = TRUE;
4120
4121 return SCIP_OKAY;
4122}
4123
4124/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
4125static
4126SCIP_DECL_CONSFREE(consFreeLogicor)
4127{ /*lint --e{715}*/
4128 SCIP_CONSHDLRDATA* conshdlrdata;
4129
4130 assert(conshdlr != NULL);
4131 assert(scip != NULL);
4132
4134
4135 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4136 assert(conshdlrdata != NULL);
4137
4138 /* free constraint handler data */
4139 conshdlrdataFree(scip, &conshdlrdata);
4140
4141 SCIPconshdlrSetData(conshdlr, NULL);
4142
4143 return SCIP_OKAY;
4144}
4145
4146
4147/** presolving initialization method of constraint handler (called when presolving is about to begin) */
4148static
4149SCIP_DECL_CONSINITPRE(consInitpreLogicor)
4150{ /*lint --e{715}*/
4151 SCIP_CONSHDLRDATA* conshdlrdata;
4152 SCIP_CONSDATA* consdata;
4153 int c;
4154 int v;
4155
4156 assert(conshdlr != NULL);
4157 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4158 assert(conshdlrdata != NULL);
4159
4160 conshdlrdata->nlastcliquesneg = 0;
4161 conshdlrdata->nlastimplsneg = 0;
4162 conshdlrdata->nlastcliquesshorten = 0;
4163 conshdlrdata->nlastimplsshorten = 0;
4164
4165 /* catch all variable event for deleted variables, which is only used in presolving */
4166 for( c = nconss - 1; c >= 0; --c )
4167 {
4168 consdata = SCIPconsGetData(conss[c]);
4169 assert(consdata != NULL);
4170
4171 for( v = consdata->nvars - 1; v >= 0; --v )
4172 {
4173 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
4174 (SCIP_EVENTDATA*)conss[c], NULL) );
4175 }
4176 }
4177
4178 return SCIP_OKAY;
4179}
4180
4181/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
4182static
4183SCIP_DECL_CONSEXITPRE(consExitpreLogicor)
4184{ /*lint --e{715}*/
4185 SCIP_CONSHDLRDATA* conshdlrdata;
4186 SCIP_CONSDATA* consdata;
4187 int nchgcoefs = 0;
4188 int c;
4189 int v;
4190
4191 assert(conshdlr != NULL);
4192 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4193 assert(conshdlrdata != NULL);
4194
4195 /* drop all variable event for deleted variables, which was only used in presolving */
4196 for( c = 0; c < nconss; ++c )
4197 {
4198 consdata = SCIPconsGetData(conss[c]);
4199 assert(consdata != NULL);
4200
4201 for( v = 0; v < consdata->nvars; ++v )
4202 {
4203 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
4204 (SCIP_EVENTDATA*)conss[c], -1) );
4205 }
4206
4207 if( !SCIPconsIsDeleted(conss[c]) && !consdata->presolved )
4208 {
4209 SCIP_Bool redundant;
4210
4211 /* we are not allowed to detect infeasibility in the exitpre stage */
4212 SCIP_CALL( applyFixings(scip, conss[c], conshdlrdata->eventhdlr, &redundant, &nchgcoefs, NULL, NULL) );
4213
4214 /* it may happen that a constraint still contains variables that are fixed to one; for example, this happens
4215 * when variable fixings have been detected in the last presolving round by some other plugins (see #2941)
4216 */
4217 if( redundant )
4218 {
4219 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant (detected during EXITPRE)\n", SCIPconsGetName(conss[c]));
4220
4221 if( SCIPconsIsAdded(conss[c]) )
4222 {
4223 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
4224 }
4225 else
4226 {
4227 /* we set the presolved flag to FALSE since not all fixing are removed if redundancy is detected */
4228 consdata->presolved = FALSE;
4229 }
4230 }
4231 }
4232 }
4233
4234 return SCIP_OKAY;
4235}
4236
4237/** solving process initialization method of constraint handler */
4238static
4239SCIP_DECL_CONSINITSOL(consInitsolLogicor)
4240{ /*lint --e{715}*/
4241 /* add nlrow representation to NLP, if NLP had been constructed */
4243 {
4244 int c;
4245 for( c = 0; c < nconss; ++c )
4246 {
4247 SCIP_CALL( addNlrow(scip, conss[c]) );
4248 }
4249 }
4250
4251 return SCIP_OKAY;
4252}
4253
4254/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4255static
4256SCIP_DECL_CONSEXITSOL(consExitsolLogicor)
4257{ /*lint --e{715}*/
4258 SCIP_CONSDATA* consdata;
4259 int c;
4260
4261 /* release the rows and nlrows of all constraints */
4262 for( c = 0; c < nconss; ++c )
4263 {
4264 consdata = SCIPconsGetData(conss[c]);
4265 assert(consdata != NULL);
4266
4267 if( consdata->row != NULL )
4268 {
4269 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
4270 }
4271
4272 if( consdata->nlrow != NULL )
4273 {
4274 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
4275 }
4276 }
4277
4278 return SCIP_OKAY;
4279}
4280
4281
4282/** frees specific constraint data */
4283static
4284SCIP_DECL_CONSDELETE(consDeleteLogicor)
4285{ /*lint --e{715}*/
4286 assert(conshdlr != NULL);
4287 assert(consdata != NULL);
4288 assert(*consdata != NULL);
4289
4291
4293 {
4294 SCIP_CONSHDLRDATA* conshdlrdata;
4295 int v;
4296
4297 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4298 assert(conshdlrdata != NULL);
4299
4300 for( v = (*consdata)->nvars - 1; v >= 0; --v )
4301 {
4302 SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
4303 (SCIP_EVENTDATA*)cons, -1) );
4304 }
4305 }
4306
4307 /* free LP row and logic or constraint */
4308 SCIP_CALL( consdataFree(scip, consdata) );
4309
4310 return SCIP_OKAY;
4311}
4312
4313
4314/** transforms constraint data into data belonging to the transformed problem */
4315static
4316SCIP_DECL_CONSTRANS(consTransLogicor)
4317{ /*lint --e{715}*/
4318 SCIP_CONSDATA* sourcedata;
4319 SCIP_CONSDATA* targetdata;
4320
4321 /*debugMsg(scip, "Trans method of logic or constraints\n");*/
4322
4323 assert(conshdlr != NULL);
4325 assert(sourcecons != NULL);
4326 assert(targetcons != NULL);
4327
4329
4330 sourcedata = SCIPconsGetData(sourcecons);
4331 assert(sourcedata != NULL);
4332 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
4333
4334 /* create constraint data for target constraint */
4335 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars) );
4336
4337 /* create target constraint */
4338 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
4339 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
4340 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
4341 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
4342 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
4343
4344 return SCIP_OKAY;
4345}
4346
4347
4348/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
4349static
4350SCIP_DECL_CONSINITLP(consInitlpLogicor)
4351{ /*lint --e{715}*/
4352 int c;
4353
4354 *infeasible = FALSE;
4355
4356 for( c = 0; c < nconss && !(*infeasible); ++c )
4357 {
4358 assert(SCIPconsIsInitial(conss[c]));
4359 SCIP_CALL( addCut(scip, conss[c], infeasible) );
4360 }
4361
4362 return SCIP_OKAY;
4363}
4364
4365
4366/** separation method of constraint handler for LP solutions */
4367static
4368SCIP_DECL_CONSSEPALP(consSepalpLogicor)
4369{ /*lint --e{715}*/
4370 SCIP_CONSHDLRDATA* conshdlrdata;
4372 SCIP_Bool separated;
4373 SCIP_Bool reduceddom;
4374 int c;
4375
4376 assert(conshdlr != NULL);
4377 assert(nconss == 0 || conss != NULL);
4378 assert(result != NULL);
4379
4381
4382 SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
4383
4384 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4385 assert(conshdlrdata != NULL);
4386
4387 cutoff = FALSE;
4388 separated = FALSE;
4389 reduceddom = FALSE;
4390
4391 /* check all useful logic or constraints for feasibility */
4392 for( c = 0; c < nusefulconss && !cutoff; ++c )
4393 {
4394 SCIP_CALL( separateCons(scip, conss[c], NULL, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
4395 }
4396
4397 /* combine logic or constraints to get more cuts */
4398 /**@todo further cuts of logic or constraints */
4399
4400 /* return the correct result */
4401 if( cutoff )
4403 else if( reduceddom )
4405 else if( separated )
4407 else
4409
4410 return SCIP_OKAY;
4411}
4412
4413
4414/** separation method of constraint handler for arbitrary primal solutions */
4415static
4416SCIP_DECL_CONSSEPASOL(consSepasolLogicor)
4417{ /*lint --e{715}*/
4418 SCIP_CONSHDLRDATA* conshdlrdata;
4420 SCIP_Bool separated;
4421 SCIP_Bool reduceddom;
4422 int c;
4423
4424 assert(conshdlr != NULL);
4425 assert(nconss == 0 || conss != NULL);
4426 assert(result != NULL);
4427
4429
4430 SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
4431
4432 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4433 assert(conshdlrdata != NULL);
4434
4435 cutoff = FALSE;
4436 separated = FALSE;
4437 reduceddom = FALSE;
4438
4439 /* check all useful logic or constraints for feasibility */
4440 for( c = 0; c < nusefulconss && !cutoff; ++c )
4441 {
4442 SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
4443 }
4444
4445 /* combine logic or constraints to get more cuts */
4446 /**@todo further cuts of logic or constraints */
4447
4448 /* return the correct result */
4449 if( cutoff )
4451 else if( reduceddom )
4453 else if( separated )
4455 else
4457
4458 return SCIP_OKAY;
4459}
4460
4461
4462/** constraint enforcing method of constraint handler for LP solutions */
4463static
4464SCIP_DECL_CONSENFOLP(consEnfolpLogicor)
4465{ /*lint --e{715}*/
4466 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
4467
4468 return SCIP_OKAY;
4469}
4470
4471
4472/** constraint enforcing method of constraint handler for relaxation solutions */
4473static
4474SCIP_DECL_CONSENFORELAX(consEnforelaxLogicor)
4475{ /*lint --e{715}*/
4476 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
4477
4478 return SCIP_OKAY;
4479}
4480
4481
4482/** constraint enforcing method of constraint handler for pseudo solutions */
4483static
4484SCIP_DECL_CONSENFOPS(consEnfopsLogicor)
4485{ /*lint --e{715}*/
4486 SCIP_CONSHDLRDATA* conshdlrdata;
4488 SCIP_Bool infeasible;
4489 SCIP_Bool reduceddom;
4490 SCIP_Bool solvelp;
4491 int c;
4492
4493 assert(conshdlr != NULL);
4494 assert(nconss == 0 || conss != NULL);
4495 assert(result != NULL);
4496
4498
4499 SCIPdebugMsg(scip, "pseudo enforcing %d logic or constraints\n", nconss);
4500
4502
4503 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4504 assert(conshdlrdata != NULL);
4505
4506 cutoff = FALSE;
4507 infeasible = FALSE;
4508 reduceddom = FALSE;
4509 solvelp = FALSE;
4510
4511 /* check all logic or constraints for feasibility */
4512 for( c = 0; c < nconss && !cutoff && !reduceddom && !solvelp; ++c )
4513 {
4514 SCIP_CALL( enforcePseudo(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &infeasible, &reduceddom, &solvelp) );
4515 }
4516
4517 if( cutoff )
4519 else if( reduceddom )
4521 else if( solvelp )
4523 else if( infeasible )
4525
4526 return SCIP_OKAY;
4527}
4528
4529
4530/** feasibility check method of constraint handler for integral solutions */
4531static
4532SCIP_DECL_CONSCHECK(consCheckLogicor)
4533{ /*lint --e{715}*/
4534 SCIP_CONS* cons;
4535 SCIP_CONSDATA* consdata;
4536 int c;
4537
4538 assert(conshdlr != NULL);
4539 assert(nconss == 0 || conss != NULL);
4540 assert(result != NULL);
4541
4543
4545
4546 /* check all logic or constraints for feasibility */
4547 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
4548 {
4549 cons = conss[c];
4550 consdata = SCIPconsGetData(cons);
4551 assert(consdata != NULL);
4552 if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
4553 {
4554 if( isConsViolated(scip, cons, sol) )
4555 {
4556 /* constraint is violated */
4558
4559 if( printreason )
4560 {
4561#ifndef NDEBUG
4562 int v;
4563 for( v = 0; v < consdata->nvars; ++v )
4564 {
4565 assert( consdata->vars[v] != NULL);
4566 assert( SCIPvarIsBinary(consdata->vars[v]) );
4567 assert( SCIPisFeasLT(scip, SCIPgetSolVal(scip, sol, consdata->vars[v]), 1.0) );
4568 }
4569#endif
4570 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
4571 SCIPinfoMessage(scip, NULL, ";\n");
4572 SCIPinfoMessage(scip, NULL, "violation: all variables are set to zero\n");
4573 }
4574 }
4575 }
4576 }
4577
4578 return SCIP_OKAY;
4579}
4580
4581
4582/** domain propagation method of constraint handler */
4583static
4584SCIP_DECL_CONSPROP(consPropLogicor)
4585{ /*lint --e{715}*/
4586 SCIP_CONSHDLRDATA* conshdlrdata;
4588 SCIP_Bool reduceddom;
4589 SCIP_Bool addcut;
4590 SCIP_Bool mustcheck;
4591 int c;
4592#ifndef NDEBUG
4594#endif
4595
4596 assert(conshdlr != NULL);
4597 assert(nconss == 0 || conss != NULL);
4598 assert(result != NULL);
4599
4601
4602 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4603 assert(conshdlrdata != NULL);
4604
4605 cutoff = FALSE;
4606 reduceddom = FALSE;
4607
4608 /* propagate all useful logic or constraints */
4609 for( c = 0; c < nusefulconss && !cutoff; ++c )
4610 {
4611 assert(inpresolve || !(SCIPconsGetData(conss[c])->existmultaggr));
4612
4613 SCIPdebugMsg(scip, " propagate constraint %s\n", SCIPconsGetName(conss[c]));
4614 SCIP_CALL( processWatchedVars(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &reduceddom, &addcut, &mustcheck) );
4615 }
4616
4617 /* return the correct result */
4618 if( cutoff )
4620 else if( reduceddom )
4622 else
4624
4625 return SCIP_OKAY; /*lint !e438*/
4626}
4627
4628/** presolving method of constraint handler */
4629static
4630SCIP_DECL_CONSPRESOL(consPresolLogicor)
4631{ /*lint --e{715}*/
4632 SCIP_CONSHDLRDATA* conshdlrdata;
4633 SCIP_CONS* cons;
4634 SCIP_CONSDATA* consdata;
4635 unsigned char* entries;
4636 SCIP_Bool redundant;
4637 int c;
4638 int firstchange;
4639 int nentries;
4640 int oldnfixedvars;
4641 int oldnchgbds;
4642 int oldndelconss;
4643 int oldnupgdconss;
4644 int oldnchgcoefs;
4645
4646 assert(conshdlr != NULL);
4647 assert(scip != NULL);
4648 assert(result != NULL);
4649
4651
4653
4654 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4655 assert(conshdlrdata != NULL);
4656
4657 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
4658
4659 oldnfixedvars = *nfixedvars;
4660 oldnchgbds = *nchgbds;
4661 oldndelconss = *ndelconss;
4662 oldnupgdconss = *nupgdconss;
4663 oldnchgcoefs = *nchgcoefs;
4664
4665 firstchange = INT_MAX;
4666
4667 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
4668
4669 /* process constraints */
4670 for( c = 0; c < nconss && *result != SCIP_CUTOFF && !SCIPisStopped(scip); ++c )
4671 {
4672 cons = conss[c];
4673 assert(cons != NULL);
4674 consdata = SCIPconsGetData(cons);
4675 assert(consdata != NULL);
4676
4677 SCIPdebugMsg(scip, "presolving logic or constraint <%s>\n", SCIPconsGetName(cons));
4678
4679 /* force presolving the constraint in the initial round */
4680 if( nrounds == 0 )
4681 {
4683 }
4684
4685 redundant = FALSE;
4686 if( !consdata->presolved )
4687 {
4688 /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
4689 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
4690 }
4691
4692 if( SCIPconsIsDeleted(cons) )
4693 continue;
4694
4695 /* find pairs of negated variables in constraint: constraint is redundant */
4696 /* find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
4697 if( !redundant )
4698 {
4699 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, &redundant, nchgcoefs) );
4700 }
4701
4702 if( redundant )
4703 {
4704 SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
4705 SCIP_CALL( SCIPdelCons(scip, cons) );
4706 (*ndelconss)++;
4708 continue;
4709 }
4710 else if( !SCIPconsIsModifiable(cons) )
4711 {
4712 if( consdata->nvars <= 2 )
4713 {
4715
4716 /* handle all cases with less than three variables in a logicor constraint */
4717 SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
4718 conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
4719
4720 if( cutoff )
4721 {
4723 goto TERMINATE;
4724 }
4725 else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
4726 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
4728
4729 if( SCIPconsIsDeleted(cons) )
4730 continue;
4731 }
4732 }
4733
4734 /* perform dual reductions */
4735 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
4736 {
4737 SCIP_CALL( dualPresolving(scip, cons, conshdlrdata->eventhdlr, nfixedvars, ndelconss, nchgcoefs, naggrvars, result) );
4738
4739 /* if dual reduction deleted the constraint we take the next */
4740 if( !SCIPconsIsActive(cons) )
4741 continue;
4742
4743 /* in dualpresolving we may have removed variables, so we need to take care of special cases */
4744 if( consdata->nvars <= 2 )
4745 {
4747
4748 /* handle all cases with less than three variables in a logicor constraint */
4749 SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
4750 conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
4751
4752 if( cutoff )
4753 {
4755 goto TERMINATE;
4756 }
4757 else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
4758 || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
4760
4761 if( SCIPconsIsDeleted(cons) )
4762 continue;
4763 }
4764 }
4765
4766 /* remember the first changed constraint to begin the next redundancy round with */
4767 if( firstchange == INT_MAX && consdata->changed )
4768 firstchange = c;
4769
4770 assert(consdata->nvars >= 2 || SCIPconsIsModifiable(cons));
4771 }
4772
4774
4775 /* fast preprocessing of pairs of logic or constraints, used for equal constraints */
4776 if( firstchange < nconss && conshdlrdata->presolusehashing )
4777 {
4778 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
4779 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, ndelconss) );
4780 }
4781
4782 /* preprocess pairs of logic or constraints and apply negated clique presolving */
4784 {
4786
4787 /* check constraints for redundancy */
4788 if( conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4789 {
4790 SCIP_CALL( removeRedundantConssAndNonzeros(scip, conss, nconss, &entries, &nentries, conshdlrdata->eventhdlr,
4791 conshdlrdata->usestrengthening, &firstchange, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
4792
4793 if( cutoff )
4794 {
4796 goto TERMINATE;
4797 }
4798 }
4799
4801 {
4802 /* try to tighten constraints by reducing the number of variables in the constraints using implications and
4803 * cliques, also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
4804 */
4805 if( conshdlrdata->useimplications && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4806 {
4807 SCIP_CALL( shortenConss(scip, conshdlrdata, conshdlrdata->eventhdlr, conss, nconss,
4808 &entries, &nentries, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
4809
4810 if( cutoff )
4811 {
4813 goto TERMINATE;
4814 }
4815 }
4816
4817 /* check for redundant constraints due to negated clique information */
4818 if( conshdlrdata->usenegatedclique && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
4819 {
4820 SCIP_CALL( removeConstraintsDueToNegCliques(scip, conshdlr, conshdlrdata->conshdlrsetppc,
4821 conshdlrdata->eventhdlr, conss, nconss, &entries, &nentries, nfixedvars, ndelconss,
4822 nupgdconss, nchgcoefs, &cutoff) );
4823
4824 if( cutoff )
4825 {
4827 goto TERMINATE;
4828 }
4829 }
4830 }
4831 }
4832
4833 TERMINATE:
4834
4835 SCIPfreeBufferArray(scip, &entries);
4836
4837 return SCIP_OKAY;
4838}
4839
4840
4841/** propagation conflict resolving method of constraint handler */
4842static
4843SCIP_DECL_CONSRESPROP(consRespropLogicor)
4844{ /*lint --e{715}*/
4845 SCIP_CONSDATA* consdata;
4846#ifndef NDEBUG
4847 SCIP_Bool infervarfound;
4848#endif
4849 int v;
4850
4851 assert(conshdlr != NULL);
4852 assert(cons != NULL);
4853 assert(infervar != NULL);
4854 assert(result != NULL);
4855
4857
4858 consdata = SCIPconsGetData(cons);
4859 assert(consdata != NULL);
4860
4861 SCIPdebugMsg(scip, "conflict resolving method of logic or constraint handler\n");
4862
4863 /* the only deductions are variables inferred to 1.0 on logic or constraints where all other variables
4864 * are assigned to zero
4865 */
4866 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5); /* the inference variable must be assigned to one */
4867
4868#ifndef NDEBUG
4869 infervarfound = FALSE;
4870#endif
4871 for( v = 0; v < consdata->nvars; ++v )
4872 {
4873 if( consdata->vars[v] != infervar )
4874 {
4875 /* the reason variable must have been assigned to zero */
4876 assert(SCIPgetVarUbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) < 0.5);
4877 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
4878 }
4879#ifndef NDEBUG
4880 else
4881 {
4882 assert(!infervarfound);
4883 infervarfound = TRUE;
4884 }
4885#endif
4886 }
4887 assert(infervarfound);
4888
4890
4891 return SCIP_OKAY;
4892}
4893
4894
4895/** variable rounding lock method of constraint handler */
4896static
4897SCIP_DECL_CONSLOCK(consLockLogicor)
4898{ /*lint --e{715}*/
4899 SCIP_CONSDATA* consdata;
4900 int i;
4901
4902 consdata = SCIPconsGetData(cons);
4903 assert(consdata != NULL);
4904
4905 /* lock every single coefficient */
4906 for( i = 0; i < consdata->nvars; ++i )
4907 {
4908 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
4909 }
4910
4911 return SCIP_OKAY;
4912}
4913
4914
4915/** constraint activation notification method of constraint handler */
4916static
4917SCIP_DECL_CONSACTIVE(consActiveLogicor)
4918{ /*lint --e{715}*/
4919 SCIP_CONSHDLRDATA* conshdlrdata;
4920 SCIP_CONSDATA* consdata;
4921
4922 assert(conshdlr != NULL);
4923 assert(cons != NULL);
4925
4927
4928 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4929 assert(conshdlrdata != NULL);
4930 consdata = SCIPconsGetData(cons);
4931 assert(consdata != NULL);
4932 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
4933
4934 SCIPdebugMsg(scip, "activating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
4935 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
4936
4937 /* catch events on watched variables */
4938 if( consdata->watchedvar1 != -1 )
4939 {
4940 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar1],
4941 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4942 &consdata->filterpos1) );
4943 }
4944 if( consdata->watchedvar2 != -1 )
4945 {
4946 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar2],
4947 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4948 &consdata->filterpos2) );
4949 }
4950
4952 {
4953 SCIP_CALL( addNlrow(scip, cons) );
4954 }
4955
4956 return SCIP_OKAY;
4957}
4958
4959
4960/** constraint deactivation notification method of constraint handler */
4961static
4962SCIP_DECL_CONSDEACTIVE(consDeactiveLogicor)
4963{ /*lint --e{715}*/
4964 SCIP_CONSHDLRDATA* conshdlrdata;
4965 SCIP_CONSDATA* consdata;
4966
4967 assert(conshdlr != NULL);
4968 assert(cons != NULL);
4970
4972
4973 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4974 assert(conshdlrdata != NULL);
4975 consdata = SCIPconsGetData(cons);
4976 assert(consdata != NULL);
4977 assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
4978
4979 SCIPdebugMsg(scip, "deactivating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
4980 SCIPdebug( SCIP_CALL( consdataPrint(scip, consdata, NULL, TRUE) ) );
4981
4982 /* drop events on watched variables */
4983 if( consdata->watchedvar1 != -1 )
4984 {
4985 assert(consdata->filterpos1 != -1);
4986 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1],
4987 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4988 consdata->filterpos1) );
4989 consdata->watchedvar1 = -1;
4990 consdata->filterpos1 = -1;
4991 }
4992 if( consdata->watchedvar2 != -1 )
4993 {
4994 assert(consdata->filterpos2 != -1);
4995 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2],
4996 SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4997 consdata->filterpos2) );
4998 consdata->watchedvar2 = -1;
4999 consdata->filterpos2 = -1;
5000 }
5001
5002 /* remove row from NLP, if still in solving
5003 * if we are in exitsolve, the whole NLP will be freed anyway
5004 */
5005 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
5006 {
5007 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
5008 }
5009
5010 return SCIP_OKAY;
5011}
5012
5013
5014/** constraint display method of constraint handler */
5015static
5016SCIP_DECL_CONSPRINT(consPrintLogicor)
5017{ /*lint --e{715}*/
5018 assert( scip != NULL );
5019 assert( conshdlr != NULL );
5020 assert( cons != NULL );
5021
5023
5024 return SCIP_OKAY;
5025}
5026
5027/** constraint copying method of constraint handler */
5028static
5029SCIP_DECL_CONSCOPY(consCopyLogicor)
5030{ /*lint --e{715}*/
5031 SCIP_CONSHDLRDATA* conshdlrdata;
5032 SCIP_VAR** sourcevars;
5033 const char* consname;
5034 int nvars;
5035
5036 assert(scip != NULL);
5037 assert(sourcescip != NULL);
5038 assert(sourcecons != NULL);
5039 assert(valid != NULL);
5040
5041 conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
5042 assert(conshdlrdata != NULL);
5043
5044 /* get variables of the source constraint */
5045 sourcevars = SCIPgetVarsLogicor(sourcescip, sourcecons);
5046 nvars = SCIPgetNVarsLogicor(sourcescip, sourcecons);
5047
5048 if( conshdlrdata->copytypedcons )
5049 {
5050 SCIP_VAR** targetvars;
5051 int v;
5052
5053 *valid = TRUE;
5054 assert(nvars >= 0);
5055
5056 /* allocate target variable array */
5057 SCIP_CALL( SCIPallocBufferArray(scip, &targetvars, nvars) );
5058
5059 /* map source variables to target variables */
5060 for( v = 0; v < nvars && *valid; ++v )
5061 {
5062 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &targetvars[v], varmap, consmap, global, valid) );
5063 assert(!(*valid) || targetvars[v] != NULL);
5064 }
5065
5066 /* only create the target constraint if all variables were successfully copied */
5067 if( *valid )
5068 {
5069 if( name != NULL )
5070 consname = name;
5071 else
5072 consname = SCIPconsGetName(sourcecons);
5073
5074 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, consname, nvars, targetvars,
5075 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
5076 }
5077
5078 SCIPfreeBufferArray(scip, &targetvars);
5079 }
5080 else
5081 {
5082 if( name != NULL )
5083 consname = name;
5084 else
5085 consname = SCIPconsGetName(sourcecons);
5086
5087 /* copy the logic using the linear constraint copy method */
5088 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, NULL,
5089 1.0, SCIPinfinity(scip), varmap, consmap,
5090 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
5091 assert(cons != NULL);
5092 }
5093
5094 return SCIP_OKAY;
5095}
5096
5097/** constraint parsing method of constraint handler */
5098static
5099SCIP_DECL_CONSPARSE(consParseLogicor)
5100{ /*lint --e{715}*/
5101 SCIP_VAR** vars;
5102 char* strcopy;
5103 char* endptr;
5104 char* startptr;
5105 int requiredsize;
5106 int varssize;
5107 int nvars;
5108
5109 SCIPdebugMsg(scip, "parse <%s> as logicor constraint\n", str);
5110
5111 *success = FALSE;
5112
5113 /* cutoff "logicor" from the constraint string */
5114 startptr = strchr((char*)str, '(');
5115
5116 if( startptr == NULL )
5117 {
5118 SCIPerrorMessage("missing starting character '(' parsing logicor\n");
5119 return SCIP_OKAY;
5120 }
5121
5122 /* skip '(' */
5123 ++startptr;
5124
5125 /* find end character ')' */
5126 endptr = strrchr(startptr, ')');
5127
5128 if( endptr == NULL )
5129 {
5130 SCIPerrorMessage("missing ending character ')' parsing logicor\n");
5131 return SCIP_OKAY;
5132 }
5133 assert(endptr >= startptr);
5134
5135 if( endptr > startptr )
5136 {
5137 /* copy string for parsing; note that SCIPskipSpace() in SCIPparseVarsList() requires that strcopy ends with '\0' */
5138 SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, startptr, (int)(endptr-startptr+1)) );
5139 strcopy[endptr-startptr] = '\0';
5140 varssize = 100;
5141 nvars = 0;
5142
5143 /* allocate buffer array for variables */
5144 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
5145
5146 /* parse string */
5147 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
5148
5149 if( *success )
5150 {
5151 /* check if the size of the variable array was great enough */
5152 if( varssize < requiredsize )
5153 {
5154 /* reallocate memory */
5155 varssize = requiredsize;
5156 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
5157
5158 /* parse string again with the correct size of the variable array */
5159 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
5160 }
5161
5162 assert(*success);
5163 assert(varssize >= requiredsize);
5164
5165 /* create logicor constraint */
5167 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
5168 }
5169
5170 /* free buffers */
5172 SCIPfreeBufferArray(scip, &strcopy);
5173 }
5174 else
5175 {
5176 if( !modifiable )
5177 {
5178 SCIPerrorMessage("cannot create empty logicor constraint\n");
5179 return SCIP_OKAY;
5180 }
5181
5182 /* create empty logicor constraint */
5183 SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, 0, NULL,
5184 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
5185
5186 *success = TRUE;
5187 }
5188
5189 return SCIP_OKAY;
5190}
5191
5192/** constraint method of constraint handler which returns the variables (if possible) */
5193static
5194SCIP_DECL_CONSGETVARS(consGetVarsLogicor)
5195{ /*lint --e{715}*/
5196 SCIP_CONSDATA* consdata;
5197
5198 consdata = SCIPconsGetData(cons);
5199 assert(consdata != NULL);
5200
5201 if( varssize < consdata->nvars )
5202 (*success) = FALSE;
5203 else
5204 {
5205 assert(vars != NULL);
5206
5207 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
5208 (*success) = TRUE;
5209 }
5210
5211 return SCIP_OKAY;
5212}
5213
5214/** constraint method of constraint handler which returns the number of variables (if possible) */
5215static
5216SCIP_DECL_CONSGETNVARS(consGetNVarsLogicor)
5217{ /*lint --e{715}*/
5218 SCIP_CONSDATA* consdata;
5219
5220 consdata = SCIPconsGetData(cons);
5221 assert(consdata != NULL);
5222
5223 (*nvars) = consdata->nvars;
5224 (*success) = TRUE;
5225
5226 return SCIP_OKAY;
5227}
5228
5229/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
5230static
5231SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLogicor)
5232{ /*lint --e{715}*/
5233 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
5234
5235 return SCIP_OKAY;
5236}
5237
5238/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
5239static
5240SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLogicor)
5241{ /*lint --e{715}*/
5242 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
5243
5244 return SCIP_OKAY;
5245}
5246
5247/*
5248 * Callback methods of event handler
5249 */
5250
5251static
5252SCIP_DECL_EVENTEXEC(eventExecLogicor)
5253{ /*lint --e{715}*/
5254 assert(eventhdlr != NULL);
5255 assert(eventdata != NULL);
5256 assert(event != NULL);
5257
5259
5260 SCIPdebugMsg(scip, "exec method of event handler for logic or constraints\n");
5261
5263 {
5264 SCIPdebugMsg(scip, "enabling constraint cons <%s> at depth %d\n", SCIPconsGetName((SCIP_CONS*)eventdata), SCIPgetDepth(scip));
5265
5266 SCIP_CALL( SCIPenableCons(scip, (SCIP_CONS*)eventdata) );
5268 }
5269 else if( SCIPeventGetType(event) == SCIP_EVENTTYPE_UBTIGHTENED )
5270 {
5272 }
5273
5275 {
5276 SCIP_VAR* var = SCIPeventGetVar(event);
5277 SCIP_CONS* cons = (SCIP_CONS*)eventdata;
5278 SCIP_CONSDATA* consdata;
5279
5280 assert(cons != NULL);
5281 consdata = SCIPconsGetData(cons);
5282 assert(consdata != NULL);
5283
5284 /* we only catch this event in presolving stage */
5286 assert(var != NULL);
5287
5288 consdata->presolved = FALSE;
5289
5291 {
5292 if( SCIPconsIsActive(cons) )
5293 {
5294 if( SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
5295 consdata->merged = FALSE;
5296
5297 if( !consdata->existmultaggr )
5298 {
5300 consdata->existmultaggr = TRUE;
5301 }
5302 }
5303 }
5304 }
5305
5306 return SCIP_OKAY;
5307}
5308
5309
5310/*
5311 * Callback methods of conflict handler
5312 */
5313
5314/** conflict processing method of conflict handler (called when conflict was found) */
5315static
5316SCIP_DECL_CONFLICTEXEC(conflictExecLogicor)
5317{ /*lint --e{715}*/
5318 SCIP_VAR** vars;
5319 int i;
5320
5321 assert(conflicthdlr != NULL);
5322 assert(bdchginfos != NULL || nbdchginfos == 0);
5323 assert(result != NULL);
5324
5326
5328
5329 /* don't process already resolved conflicts */
5330 if( resolved )
5331 return SCIP_OKAY;
5332
5333 /* if the conflict consists of only two (binary) variables, it will be handled by the setppc conflict handler */
5334 if( nbdchginfos == 2 )
5335 return SCIP_OKAY;
5336
5338
5339 /* create array of variables in conflict constraint */
5340 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
5341 for( i = 0; i < nbdchginfos; ++i )
5342 {
5343 assert(bdchginfos != NULL); /* for flexelint */
5344 assert(bdchginfos[i] != NULL);
5345
5346 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
5347
5348 /* we can only treat binary variables */
5349 if( !SCIPvarIsBinary(vars[i]) )
5350 break;
5351
5352 /* if the variable is fixed to one in the conflict set, we have to use its negation */
5353 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
5354 {
5356 }
5357 }
5358
5359 if( i == nbdchginfos )
5360 {
5361 SCIP_CONS* cons;
5362 char consname[SCIP_MAXSTRLEN];
5363
5364 /* create a constraint out of the conflict set */
5366 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, consname, nbdchginfos, vars,
5367 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
5368
5369 /* add conflict to SCIP */
5370 SCIP_CALL( SCIPaddConflict(scip, node, &cons, validnode, conftype, cutoffinvolved) );
5371
5373 }
5374
5375 /* free temporary memory */
5377
5378 return SCIP_OKAY;
5379}
5380
5381
5382/*
5383 * constraint specific interface methods
5384 */
5385
5386/** creates the handler for logic or constraints and includes it in SCIP */
5388 SCIP* scip /**< SCIP data structure */
5389 )
5390{
5391 SCIP_CONSHDLRDATA* conshdlrdata;
5392 SCIP_CONSHDLR* conshdlr;
5393 SCIP_CONFLICTHDLR* conflicthdlr;
5394 SCIP_EVENTHDLR* eventhdlr;
5395
5396 /* create event handler for events on watched variables */
5398 eventExecLogicor, NULL) );
5399
5400 /* create conflict handler for logic or constraints */
5402 conflictExecLogicor, NULL) );
5403
5404 /* create constraint handler data */
5405 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
5406
5407 /* include constraint handler */
5410 consEnfolpLogicor, consEnfopsLogicor, consCheckLogicor, consLockLogicor,
5411 conshdlrdata) );
5412 assert(conshdlr != NULL);
5413
5414 /* set non-fundamental callbacks via specific setter functions */
5415 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLogicor) );
5416 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLogicor, consCopyLogicor) );
5417 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLogicor) );
5418 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLogicor) );
5419 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLogicor) );
5420 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLogicor) );
5421 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLogicor) );
5422 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLogicor) );
5423 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLogicor) );
5424 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLogicor) );
5425 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLogicor) );
5426 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLogicor) );
5427 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLogicor) );
5429 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLogicor) );
5432 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLogicor) );
5433 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLogicor, consSepasolLogicor, CONSHDLR_SEPAFREQ,
5435 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLogicor) );
5436 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLogicor) );
5437 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLogicor) );
5438 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLogicor) );
5439
5440 conshdlrdata->conshdlrlinear = SCIPfindConshdlr(scip, "linear");
5441 conshdlrdata->conshdlrsetppc = SCIPfindConshdlr(scip, "setppc");
5442
5443 if( conshdlrdata->conshdlrlinear != NULL )
5444 {
5445 /* include the linear constraint to logicor constraint upgrade in the linear constraint handler */
5447 }
5448
5449 /* logic or constraint handler parameters */
5451 "constraints/logicor/presolpairwise",
5452 "should pairwise constraint comparison be performed in presolving?",
5453 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
5455 "constraints/logicor/presolusehashing",
5456 "should hash table be used for detecting redundant constraints in advance",
5457 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
5459 "constraints/logicor/dualpresolving",
5460 "should dual presolving steps be performed?",
5461 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
5463 "constraints/logicor/negatedclique",
5464 "should negated clique information be used in presolving",
5465 &conshdlrdata->usenegatedclique, TRUE, DEFAULT_NEGATEDCLIQUE, NULL, NULL) );
5467 "constraints/logicor/implications",
5468 "should implications/cliques be used in presolving",
5469 &conshdlrdata->useimplications, TRUE, DEFAULT_IMPLICATIONS, NULL, NULL) );
5471 "constraints/logicor/strengthen",
5472 "should pairwise constraint comparison try to strengthen constraints by removing superflous non-zeros?",
5473 &conshdlrdata->usestrengthening, TRUE, DEFAULT_STRENGTHEN, NULL, NULL) );
5475 "constraints/" CONSHDLR_NAME "/copytypedcons",
5476 "should logicor constraints be copied as logicor instead of as linear constraints?",
5477 &conshdlrdata->copytypedcons, TRUE, DEFAULT_COPYTYPEDCONS, NULL, NULL) );
5478
5479 return SCIP_OKAY;
5480}
5481
5482
5483/** creates and captures a logic or constraint
5484 *
5485 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5486 */
5488 SCIP* scip, /**< SCIP data structure */
5489 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5490 const char* name, /**< name of constraint */
5491 int nvars, /**< number of variables in the constraint */
5492 SCIP_VAR** vars, /**< array with variables of constraint entries */
5493 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
5494 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5495 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
5496 * Usually set to TRUE. */
5497 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
5498 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5499 SCIP_Bool check, /**< should the constraint be checked for feasibility?
5500 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5501 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
5502 * Usually set to TRUE. */
5503 SCIP_Bool local, /**< is constraint only valid locally?
5504 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5505 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
5506 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
5507 * adds coefficients to this constraint. */
5508 SCIP_Bool dynamic, /**< is constraint subject to aging?
5509 * Usually set to FALSE. Set to TRUE for own cuts which
5510 * are separated as constraints. */
5511 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
5512 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5513 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
5514 * if it may be moved to a more global node?
5515 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
5516 )
5517{
5518 SCIP_CONSHDLR* conshdlr;
5519 SCIP_CONSDATA* consdata;
5520 int i;
5521
5522 assert(scip != NULL);
5523
5524 /* find the logicor constraint handler */
5525 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5526 if( conshdlr == NULL )
5527 {
5528 SCIPerrorMessage("logic or constraint handler not found\n");
5529 return SCIP_INVALIDCALL;
5530 }
5531
5532 /* check whether all variables are binary */
5533 assert(vars != NULL || nvars == 0);
5534 for( i = 0; i < nvars; ++i )
5535 {
5536 if( !SCIPvarIsBinary(vars[i]) )
5537 {
5538 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
5539 return SCIP_INVALIDDATA;
5540 }
5541 }
5542
5543 /* create the constraint specific data */
5544 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars) );
5545
5546 /* create constraint */
5547 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5548 local, modifiable, dynamic, removable, stickingatnode) );
5549
5551 {
5552 SCIP_CONSHDLRDATA* conshdlrdata;
5553 int v;
5554
5555 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5556 assert(conshdlrdata != NULL);
5557
5558 for( v = consdata->nvars - 1; v >= 0; --v )
5559 {
5560 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
5561 (SCIP_EVENTDATA*)(*cons), NULL) );
5562 }
5563 }
5564
5565 return SCIP_OKAY;
5566}
5567
5568/** creates and captures a logicor constraint
5569 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
5570 * method SCIPcreateConsLogicor(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
5571 *
5572 * @see SCIPcreateConsLogicor() for information about the basic constraint flag configuration
5573 *
5574 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5575 */
5577 SCIP* scip, /**< SCIP data structure */
5578 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5579 const char* name, /**< name of constraint */
5580 int nvars, /**< number of variables in the constraint */
5581 SCIP_VAR** vars /**< array with variables of constraint entries */
5582 )
5583{
5584 assert(scip != NULL);
5585
5588
5589 return SCIP_OKAY;
5590}
5591
5592/** adds coefficient in logic or constraint */
5594 SCIP* scip, /**< SCIP data structure */
5595 SCIP_CONS* cons, /**< logicor constraint */
5596 SCIP_VAR* var /**< variable to add to the constraint */
5597 )
5598{
5599 assert(var != NULL);
5600
5601 /*debugMsg(scip, "adding variable <%s> to logicor constraint <%s>\n",
5602 SCIPvarGetName(var), SCIPconsGetName(cons));*/
5603
5605
5606 SCIP_CALL( addCoef(scip, cons, var) );
5607
5608 return SCIP_OKAY;
5609}
5610
5611/** gets number of variables in logic or constraint */
5613 SCIP* scip, /**< SCIP data structure */
5614 SCIP_CONS* cons /**< constraint data */
5615 )
5616{
5617 SCIP_CONSDATA* consdata;
5618
5619 assert(scip != NULL);
5620
5622
5623 consdata = SCIPconsGetData(cons);
5624 assert(consdata != NULL);
5625
5626 return consdata->nvars;
5627}
5628
5629/** gets array of variables in logic or constraint */
5631 SCIP* scip, /**< SCIP data structure */
5632 SCIP_CONS* cons /**< constraint data */
5633 )
5634{
5635 SCIP_CONSDATA* consdata;
5636
5637 assert(scip != NULL);
5638
5640
5641 consdata = SCIPconsGetData(cons);
5642 assert(consdata != NULL);
5643
5644 return consdata->vars;
5645}
5646
5647/** gets the dual solution of the logic or constraint in the current LP */
5649 SCIP* scip, /**< SCIP data structure */
5650 SCIP_CONS* cons /**< constraint data */
5651 )
5652{
5653 SCIP_CONSDATA* consdata;
5654
5655 assert(scip != NULL);
5656
5658
5659 consdata = SCIPconsGetData(cons);
5660 assert(consdata != NULL);
5661
5662 if( consdata->row != NULL )
5663 return SCIProwGetDualsol(consdata->row);
5664 else
5665 return 0.0;
5666}
5667
5668/** gets the dual Farkas value of the logic or constraint in the current infeasible LP */
5670 SCIP* scip, /**< SCIP data structure */
5671 SCIP_CONS* cons /**< constraint data */
5672 )
5673{
5674 SCIP_CONSDATA* consdata;
5675
5676 assert(scip != NULL);
5677
5679
5680 consdata = SCIPconsGetData(cons);
5681 assert(consdata != NULL);
5682
5683 if( consdata->row != NULL )
5684 return SCIProwGetDualfarkas(consdata->row);
5685 else
5686 return 0.0;
5687}
5688
5689/** returns the linear relaxation of the given logic or constraint; may return NULL if no LP row was yet created;
5690 * the user must not modify the row!
5691 */
5693 SCIP* scip, /**< SCIP data structure */
5694 SCIP_CONS* cons /**< constraint data */
5695 )
5696{
5697 SCIP_CONSDATA* consdata;
5698
5699 assert(scip != NULL);
5700
5702
5703 consdata = SCIPconsGetData(cons);
5704 assert(consdata != NULL);
5705
5706 return consdata->row;
5707}
5708
5709/** creates and returns the row of the given logicor constraint */
5711 SCIP* scip, /**< SCIP data structure */
5712 SCIP_CONS* cons /**< constraint data */
5713 )
5714{
5715 SCIP_CONSDATA* consdata;
5716
5717 assert(scip != NULL);
5718
5720
5721 consdata = SCIPconsGetData(cons);
5722 assert(consdata != NULL);
5723 assert(consdata->row == NULL);
5724
5725 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), 1.0, SCIPinfinity(scip),
5727
5728 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
5729
5730 return SCIP_OKAY;
5731}
5732
5733/** cleans up (multi-)aggregations and fixings from logicor constraints */
5735 SCIP* scip, /**< SCIP data structure */
5736 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
5737 int* naddconss, /**< pointer to count number of added (linear) constraints */
5738 int* ndelconss, /**< pointer to count number of deleted (logicor) constraints */
5739 int* nchgcoefs /**< pointer to count number of changed coefficients */
5740 )
5741{
5742 SCIP_CONSHDLR* conshdlr;
5743 SCIP_EVENTHDLR* eventhdlr;
5744 SCIP_CONS** conss;
5745 unsigned char* entries;
5746 int nconss;
5747 int nentries;
5748 int i;
5749
5750 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5751 if( conshdlr == NULL )
5752 return SCIP_OKAY;
5753
5754 assert(naddconss != NULL);
5755 assert(ndelconss != NULL);
5756 assert(nchgcoefs != NULL);
5757
5758 eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
5759 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
5760 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
5761
5762 nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
5763 SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
5764
5765 /* loop backwards since then deleted constraints do not interfere with the loop */
5766 for( i = nconss - 1; i >= 0; --i )
5767 {
5768 SCIP_CONS* cons;
5769 SCIP_Bool redundant;
5770
5771 cons = conss[i];
5772 redundant = FALSE;
5773
5774 SCIP_CALL( applyFixings(scip, cons, eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
5775
5776 if( SCIPconsIsDeleted(cons) )
5777 continue;
5778
5779 /* merge constraint */
5780 if( !redundant )
5781 {
5782 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, &entries, &nentries, &redundant, nchgcoefs) );
5783 }
5784
5785 if( redundant )
5786 {
5787 SCIP_CALL( SCIPdelCons(scip, cons) );
5788 ++(*ndelconss);
5789 }
5790 }
5791
5792 SCIPfreeBufferArray(scip, &entries);
5793
5794 return SCIP_OKAY;
5795}
#define EVENTHDLR_NAME
SCIP_VAR * w
#define EVENTHDLR_DESC
#define DEFAULT_DUALPRESOLVING
Definition cons_and.c:109
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:96
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:89
#define CONSHDLR_CHECKPRIORITY
Definition cons_and.c:88
#define CONSHDLR_DESC
Definition cons_and.c:85
#define CONSHDLR_PROP_TIMING
Definition cons_and.c:99
#define CONSHDLR_MAXPREROUNDS
Definition cons_and.c:93
#define DEFAULT_PRESOLPAIRWISE
Definition cons_and.c:104
#define CONSHDLR_SEPAPRIORITY
Definition cons_and.c:86
#define DEFAULT_PRESOLUSEHASHING
Definition cons_and.c:112
#define CONSHDLR_PROPFREQ
Definition cons_and.c:90
#define CONSHDLR_PRESOLTIMING
Definition cons_and.c:98
#define CONSHDLR_EAGERFREQ
Definition cons_and.c:91
#define CONSHDLR_ENFOPRIORITY
Definition cons_and.c:87
#define CONSHDLR_DELAYSEPA
Definition cons_and.c:94
#define CONSHDLR_NAME
Definition cons_and.c:84
#define CONSHDLR_DELAYPROP
Definition cons_and.c:95
#define CONFLICTHDLR_PRIORITY
#define CONFLICTHDLR_NAME
#define CONFLICTHDLR_DESC
#define LINCONSUPGD_PRIORITY
#define DEFAULT_COPYTYPEDCONS
#define DEFAULT_NEGATEDCLIQUE
Constraint handler for linear constraints in their most general form, .
static SCIP_Bool isConsViolated(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
#define MAXCOMPARISONS
#define DEFAULT_IMPLICATIONS
#define AGEINCREASE(n)
static void consdataCalcSignature(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addCut(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE processWatchedVars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *reduceddom, SCIP_Bool *addcut, SCIP_Bool *mustcheck)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE addConsToOccurList(SCIP *scip, SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int *occurlistsizes, int *occurlistlength, int occurlistsize)
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
static SCIP_RETCODE removeConstraintsDueToNegCliques(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLR *conshdlrsetppc, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS **conss, int nconss, unsigned char **entries, int *nentries, int *nfixedvars, int *ndelconss, int *nupgdconss, int *nchgcoefs, SCIP_Bool *cutoff)
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
#define DEFAULT_STRENGTHEN
#define MAX_CONSLENGTH
static SCIP_RETCODE removeRedundantConss(SCIP *scip, SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, int *ndelconss)
static void findShortestOccurlist(SCIP_VAR **vars, int nvars, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, int *nentries, SCIP_CONS ***shortestlist)
static SCIP_RETCODE removeRedundantConssAndNonzeros(SCIP *scip, SCIP_CONS **conss, int nconss, unsigned char **entries, int *nentries, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool usestrengthening, int *firstchange, int *nfixedvars, int *ndelconss, int *nchgcoefs, SCIP_Bool *cutoff)
static SCIP_RETCODE prepareCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *redundant, int *nfixedvars, int *nchgcoefs, int *ndelconss, SCIP_Bool *cutoff)
static SCIP_RETCODE enforcePseudo(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *reduceddom, SCIP_Bool *solvelp)
static SCIP_RETCODE createNormalizedLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, int mult, 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)
static SCIP_RETCODE dualPresolving(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int *nfixedvars, int *ndelconss, int *nchgcoefs, int *naggrvars, SCIP_RESULT *result)
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
static SCIP_RETCODE shortenConss(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS **conss, int nconss, unsigned char **entries, int *nentries, int *nfixedvars, int *ndelconss, int *nchgcoefs, SCIP_Bool *cutoff)
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
static SCIP_RETCODE switchWatchedvars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
static SCIP_RETCODE fixDeleteOrUpgradeCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSHDLR *conshdlrlinear, SCIP_CONSHDLR *conshdlrsetppc, int *nfixedvars, int *nchgbds, int *nchgcoefs, int *ndelconss, int *naddconss, int *nupgdconss, SCIP_Bool *cutoff)
#define HASHSIZE_LOGICORCONS
static unsigned int calcSignature(SCIP_VAR **vars, int nvars)
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, int *ndelconss)
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *separated, SCIP_Bool *reduceddom)
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static void consdataSort(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE strengthenConss(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, SCIP_EVENTHDLR *eventhdlr, int *ndelconss, int *nchgcoefs)
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *redundant, int *nchgcoefs)
static void removeConsFromOccurList(SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *redundant, int *nchgcoefs, int *naddconss, int *ndelconss)
static SCIP_RETCODE disableCons(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE removeRedundantCons(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *ndelconss)
static SCIP_RETCODE removeRedundantNonZeros(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *artvar, int artpos, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, SCIP_EVENTHDLR *eventhdlr, int *nchgcoefs, SCIP_Bool *deleted)
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file, SCIP_Bool endline)
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
Constraint handler for the set partitioning / packing / covering constraints .
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_LONGINT_FORMAT
Definition def.h:157
#define SCIP_LONGINT_MAX
Definition def.h:151
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetDualsolLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_ROW * SCIPgetRowLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcleanupConssLogicor(SCIP *scip, SCIP_Bool onlychecked, int *naddconss, int *ndelconss, int *nchgcoefs)
SCIP_RETCODE SCIPcreateRowLogicor(SCIP *scip, SCIP_CONS *cons)
#define SCIP_DECL_LINCONSUPGD(x)
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, 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_Bool global, SCIP_Bool *valid)
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_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
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_Real SCIPgetDualfarkasLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddCoefLogicor(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
SCIP_RETCODE SCIPincludeConshdlrLogicor(SCIP *scip)
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition scip_copy.c:713
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_Bool SCIPisPresolveFinished(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
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_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
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 SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS **cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition scip_prob.c:3806
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition misc.c:11162
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)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4802
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_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4759
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
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4816
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_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4739
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_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1837
SCIP_Bool SCIPconsIsPropagationEnabled(SCIP_CONS *cons)
Definition cons.c:8511
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition cons.c:8845
SCIP_RETCODE SCIPenableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1951
int SCIPconsGetValidDepth(SCIP_CONS *cons)
Definition cons.c:8476
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8702
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition scip_cons.c:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1871
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1812
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition cons.c:8822
SCIP_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 SCIPdisableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1981
SCIP_RETCODE SCIPaddConsAge(SCIP *scip, SCIP_CONS *cons, SCIP_Real deltaage)
Definition scip_cons.c:1755
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_RETCODE 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
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:413
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition event.c:1217
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition scip_lp.c:87
#define SCIPfreeCleanBufferArray(scip, ptr)
Definition scip_mem.h:146
#define SCIPallocCleanBufferArray(scip, ptr, num)
Definition scip_mem.h:142
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 SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition scip_mem.h:111
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition scip_mem.h:137
#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_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition lp.c:17719
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1974
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17917
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17706
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition scip_sol.c:467
int SCIPgetNImplications(SCIP *scip)
int SCIPgetNRuns(SCIP *scip)
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
SCIP_RETCODE SCIPshrinkDisjunctiveVarSet(SCIP *scip, SCIP_VAR **vars, SCIP_Real *bounds, SCIP_Bool *boundtypes, SCIP_Bool *redundants, int nvars, int *nredvars, int *nglobalred, SCIP_Bool *setredundant, SCIP_Bool *glbinfeas, SCIP_Bool fullshortening)
Definition presolve.c:995
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(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 SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5210
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 SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition scip_var.c:8882
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition scip_var.c:2119
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24600
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
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_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17595
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_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24961
SCIP_RETCODE SCIPcleanupCliques(SCIP *scip, SCIP_Bool *infeasible)
Definition scip_var.c:9469
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition scip_var.c:2378
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition scip_var.c:2166
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition var.c:24674
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition var.c:23910
int SCIPgetNCliques(SCIP *scip)
Definition scip_var.c:9512
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
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_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition var.c:21825
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 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
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition var.c:24951
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 SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
return SCIP_OKAY
int c
SCIP_Bool cutoff
SCIP_Real objval
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_Bool propagate
static SCIP_VAR ** vars
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition memory.h:437
methods commonly used for presolving
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPdebug(x)
Definition pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
public data structures and miscellaneous methods
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 cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
structs for symmetry computations
methods for dealing with symmetry detection graphs
struct SCIP_Conflicthdlr SCIP_CONFLICTHDLR
#define SCIP_DECL_CONFLICTEXEC(x)
@ 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
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition type_event.h:79
#define SCIP_EVENTTYPE_VARFIXED
Definition type_event.h:72
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:259
#define SCIP_EVENTTYPE_LBRELAXED
Definition type_event.h:78
@ SCIP_EXPRCURV_LINEAR
Definition type_expr.h:65
@ SCIP_BRANCHDIR_DOWNWARDS
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:189
#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_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_FEASIBLE
Definition type_result.h:45
@ SCIP_REDUCEDDOM
Definition type_result.h:51
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_CONSADDED
Definition type_result.h:52
@ SCIP_SEPARATED
Definition type_result.h:49
@ SCIP_SOLVELP
Definition type_result.h:55
@ 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_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_INITPRESOLVE
Definition type_set.h:48
@ SCIP_STAGE_PRESOLVING
Definition type_set.h:49
@ SCIP_STAGE_INITSOLVE
Definition type_set.h:52
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
enum SYM_Symtype SYM_SYMTYPE
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
#define SCIP_PRESOLTIMING_MEDIUM
Definition type_timing.h:53
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition type_timing.h:54
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ 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_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141