Scippy

SCIP

Solving Constraint Integer Programs

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