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