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