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-2018 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 500 /**< 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( SCIPallocBlockMemory(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  SCIPfreeBlockMemory(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  SCIPdebugMsg(scip, " -> 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  SCIPdebugMsg(scip, " -> 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  SCIPdebugMsg(scip, " -> 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  SCIPdebugMsg(scip, "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  SCIPdebugMsg(scip, "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 
1104  for( v = 0; v < consdata->nvars; ++v )
1105  {
1106  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
1107  }
1108 
1109  /* analyze the conflict */
1110  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1111 
1112  return SCIP_OKAY;
1113 }
1114 
1115 /** disables or deletes the given constraint, depending on the current depth */
1116 static
1118  SCIP* scip, /**< SCIP data structure */
1119  SCIP_CONS* cons /**< bound disjunction constraint to be disabled */
1120  )
1121 {
1122  assert(SCIPconsGetValidDepth(cons) <= SCIPgetDepth(scip));
1123 
1124  /* in case the logic or constraint is satisfied in the depth where it is also valid, we can delete it */
1125  if( SCIPgetDepth(scip) == SCIPconsGetValidDepth(cons) )
1126  {
1127  SCIP_CALL( SCIPdelCons(scip, cons) );
1128  }
1129  else
1130  {
1131  SCIPdebugMsg(scip, "disabling constraint cons <%s> at depth %d\n", SCIPconsGetName(cons), SCIPgetDepth(scip));
1132  SCIP_CALL( SCIPdisableCons(scip, cons) );
1133  }
1134 
1135  return SCIP_OKAY;
1136 }
1137 
1138 /** find pairs of negated variables in constraint: constraint is redundant */
1139 /** find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
1140 static
1142  SCIP* scip, /**< SCIP data structure */
1143  SCIP_CONS* cons, /**< logic or constraint */
1144  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1145  unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
1146  int* nentries, /**< pointer for array size, if array will be to small it's corrected */
1147  SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
1148  int* nchgcoefs /**< pointer to count number of changed/deleted coefficients */
1149  )
1150 {
1151  SCIP_CONSDATA* consdata;
1152  SCIP_VAR** vars;
1153  int nvars;
1154  SCIP_Bool* negarray;
1155  SCIP_VAR* var;
1156  int v;
1157  int pos;
1158 #ifndef NDEBUG
1159  int nbinvars;
1160  int nintvars;
1161  int nimplvars;
1162 #endif
1163 
1164  assert(scip != NULL);
1165  assert(cons != NULL);
1166  assert(eventhdlr != NULL);
1167  assert(*entries != NULL);
1168  assert(nentries != NULL);
1169  assert(redundant != NULL);
1170  assert(nchgcoefs != NULL);
1171 
1172  consdata = SCIPconsGetData(cons);
1173  assert(consdata != NULL);
1174 
1175  nvars = consdata->nvars;
1176 
1177  *redundant = FALSE;
1178 
1179  if( consdata->merged )
1180  return SCIP_OKAY;
1181 
1182  if( consdata->nvars <= 1 )
1183  {
1184  consdata->merged = TRUE;
1185  return SCIP_OKAY;
1186  }
1187 
1188  assert(consdata->vars != NULL && nvars > 0);
1189 
1190 #ifndef NDEBUG
1191  nbinvars = SCIPgetNBinVars(scip);
1192  nintvars = SCIPgetNIntVars(scip);
1193  nimplvars = SCIPgetNImplVars(scip);
1194  assert(*nentries >= nbinvars + nintvars + nimplvars);
1195 
1196  /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
1197  * called before mergeMultiples()
1198  */
1199  assert(consdata->presolved);
1200 #endif
1201 
1202  /* allocate temporary memory */
1203  SCIP_CALL( SCIPallocBufferArray(scip, &negarray, nvars) );
1204 
1205  vars = consdata->vars;
1206 
1207  /* initialize entries array */
1208  for( v = nvars - 1; v >= 0; --v )
1209  {
1210  /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
1211  * called before mergeMultiples()
1212  */
1213  assert(SCIPvarIsActive(vars[v]) ||
1215  negarray[v] = SCIPvarIsNegated(vars[v]);
1216  var = negarray[v] ? SCIPvarGetNegationVar(vars[v]) : vars[v];
1217  assert(SCIPvarIsActive(var));
1218 
1219  pos = SCIPvarGetProbindex(var);
1220 
1221  /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
1222  assert((pos < nbinvars && SCIPvarGetType(var) == SCIP_VARTYPE_BINARY)
1223  || (SCIPvarIsBinary(var) &&
1224  ((pos >= nbinvars && pos < nbinvars + nintvars && SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER) ||
1225  (pos >= nbinvars + nintvars && pos < nbinvars + nintvars + nimplvars &&
1227 
1228  /* var is not active yet */
1229  (*entries)[pos] = 0;
1230  }
1231 
1232  /* check all vars for multiple entries, do necessary backwards loop because deletion only affect rear items */
1233  for( v = nvars - 1; v >= 0; --v )
1234  {
1235  var = negarray[v] ? SCIPvarGetNegationVar(vars[v]) : vars[v];
1236  assert(SCIPvarIsActive(var));
1237 
1238  pos = SCIPvarGetProbindex(var);
1239 
1240  /* if var occurs first time in constraint init entries array */
1241  if( (*entries)[pos] == 0 )
1242  (*entries)[pos] = negarray[v] ? 2 : 1;
1243  /* if var occurs second time in constraint, first time it was not negated */
1244  else if( (*entries)[pos] == 1 )
1245  {
1246  if( negarray[v] )
1247  {
1248  SCIPdebugMsg(scip, "logicor constraint <%s> redundant: variable <%s> and its negation are present\n",
1249  SCIPconsGetName(cons), SCIPvarGetName(var));
1250 
1251  *redundant = TRUE;
1252  goto TERMINATE;
1253  }
1254  else
1255  {
1256  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1257  ++(*nchgcoefs);
1258  }
1259  }
1260  /* if var occurs second time in constraint, first time it was negated */
1261  else
1262  {
1263  if( !negarray[v] )
1264  {
1265  SCIPdebugMsg(scip, "logicor constraint <%s> redundant: variable <%s> and its negation are present\n",
1266  SCIPconsGetName(cons), SCIPvarGetName(var));
1267 
1268  *redundant = TRUE;
1269  goto TERMINATE;
1270  }
1271  else
1272  {
1273  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1274  ++(*nchgcoefs);
1275  }
1276  }
1277  }
1278 
1279  TERMINATE:
1280  /* free temporary memory */
1281  SCIPfreeBufferArray(scip, &negarray);
1282 
1283  consdata->merged = TRUE;
1284 
1285  return SCIP_OKAY;
1286 }
1287 
1288 /** checks constraint for violation only looking at the watched variables, applies fixings if possible */
1289 static
1291  SCIP* scip, /**< SCIP data structure */
1292  SCIP_CONS* cons, /**< logic or constraint to be processed */
1293  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1294  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1295  SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1296  SCIP_Bool* addcut, /**< pointer to store whether this constraint must be added as a cut */
1297  SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1298  )
1299 {
1300  SCIP_CONSDATA* consdata;
1301  SCIP_VAR** vars;
1302  SCIP_Longint nbranchings1;
1303  SCIP_Longint nbranchings2;
1304  int nvars;
1305  int watchedvar1;
1306  int watchedvar2;
1307 
1308  assert(cons != NULL);
1309  assert(SCIPconsGetHdlr(cons) != NULL);
1310  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1311  assert(cutoff != NULL);
1312  assert(reduceddom != NULL);
1313  assert(addcut != NULL);
1314  assert(mustcheck != NULL);
1315 
1316  consdata = SCIPconsGetData(cons);
1317  assert(consdata != NULL);
1318  assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
1319 
1320  *addcut = FALSE;
1321  *mustcheck = FALSE;
1322 
1323  SCIPdebugMsg(scip, "processing watched variables of constraint <%s>\n", SCIPconsGetName(cons));
1324 
1325  vars = consdata->vars;
1326  nvars = consdata->nvars;
1327  assert(nvars == 0 || vars != NULL);
1328 
1329  /* check watched variables if they are fixed to one */
1330  if( consdata->watchedvar1 >= 0 && SCIPvarGetLbLocal(vars[consdata->watchedvar1]) > 0.5 )
1331  {
1332  /* the variable is fixed to one, making the constraint redundant -> disable the constraint */
1333  SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar1 fixed to 1.0)\n", SCIPconsGetName(cons));
1334  SCIP_CALL( disableCons(scip, cons) );
1335  return SCIP_OKAY;
1336  }
1337  if( consdata->watchedvar2 >= 0 && SCIPvarGetLbLocal(vars[consdata->watchedvar2]) > 0.5 )
1338  {
1339  /* the variable is fixed to one, making the constraint redundant -> disable the constraint */
1340  SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar2 fixed to 1.0)\n", SCIPconsGetName(cons));
1341  SCIP_CALL( disableCons(scip, cons) );
1342  return SCIP_OKAY;
1343  }
1344 
1345  /* check if watched variables are still unfixed */
1346  watchedvar1 = -1;
1347  watchedvar2 = -1;
1348  nbranchings1 = SCIP_LONGINT_MAX;
1349  nbranchings2 = SCIP_LONGINT_MAX;
1350  if( consdata->watchedvar1 >= 0 && SCIPvarGetUbLocal(vars[consdata->watchedvar1]) > 0.5 )
1351  {
1352  watchedvar1 = consdata->watchedvar1;
1353  nbranchings1 = -1; /* prefer keeping the watched variable */
1354  }
1355  if( consdata->watchedvar2 >= 0 && SCIPvarGetUbLocal(vars[consdata->watchedvar2]) > 0.5 )
1356  {
1357  if( watchedvar1 == -1 )
1358  {
1359  watchedvar1 = consdata->watchedvar2;
1360  nbranchings1 = -1; /* prefer keeping the watched variable */
1361  }
1362  else
1363  {
1364  watchedvar2 = consdata->watchedvar2;
1365  nbranchings2 = -1; /* prefer keeping the watched variable */
1366  }
1367  }
1368  assert(watchedvar1 >= 0 || watchedvar2 == -1);
1369  assert(nbranchings1 <= nbranchings2);
1370 
1371  /* search for new watched variables */
1372  if( watchedvar2 == -1 )
1373  {
1374  int v;
1375 
1376  for( v = 0; v < nvars; ++v )
1377  {
1378  SCIP_Longint nbranchings;
1379 
1380  /* don't process the watched variables again */
1381  if( v == consdata->watchedvar1 || v == consdata->watchedvar2 )
1382  continue;
1383 
1384  /* check, if the variable is fixed */
1385  if( SCIPvarGetUbLocal(vars[v]) < 0.5 )
1386  continue;
1387 
1388  /* check, if the literal is satisfied */
1389  if( SCIPvarGetLbLocal(vars[v]) > 0.5 )
1390  {
1391  assert(v != consdata->watchedvar1);
1392  assert(v != consdata->watchedvar2);
1393 
1394  /* the variable is fixed to one, making the constraint redundant;
1395  * make sure, the feasible variable is watched and disable the constraint
1396  */
1397  SCIPdebugMsg(scip, " -> disabling constraint <%s> (variable <%s> fixed to 1.0)\n",
1398  SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
1399  if( consdata->watchedvar1 != -1 )
1400  {
1401  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, v) );
1402  }
1403  else
1404  {
1405  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, v, consdata->watchedvar2) );
1406  }
1407  SCIP_CALL( disableCons(scip, cons) );
1408  return SCIP_OKAY;
1409  }
1410 
1411  /* the variable is unfixed and can be used as watched variable */
1413  assert(nbranchings >= 0);
1414  if( nbranchings < nbranchings2 )
1415  {
1416  if( nbranchings < nbranchings1 )
1417  {
1418  watchedvar2 = watchedvar1;
1419  nbranchings2 = nbranchings1;
1420  watchedvar1 = v;
1421  nbranchings1 = nbranchings;
1422  }
1423  else
1424  {
1425  watchedvar2 = v;
1426  nbranchings2 = nbranchings;
1427  }
1428  }
1429  }
1430  }
1431  assert(nbranchings1 <= nbranchings2);
1432  assert(watchedvar1 >= 0 || watchedvar2 == -1);
1433 
1434  if( watchedvar1 == -1 )
1435  {
1436  /* there is no unfixed variable left -> the constraint is infeasible
1437  * - a modifiable constraint must be added as a cut and further pricing must be performed in the LP solving loop
1438  * - an unmodifiable constraint is infeasible and the node can be cut off
1439  */
1440  assert(watchedvar2 == -1);
1441 
1442  SCIPdebugMsg(scip, " -> constraint <%s> is infeasible\n", SCIPconsGetName(cons));
1443 
1444  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1445  if( SCIPconsIsModifiable(cons) )
1446  *addcut = TRUE;
1447  else
1448  {
1449  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1450  SCIP_CALL( analyzeConflict(scip, cons) );
1451 
1452  /* mark the node to be cut off */
1453  *cutoff = TRUE;
1454  }
1455  }
1456  else if( watchedvar2 == -1 )
1457  {
1458  /* there is only one unfixed variable:
1459  * - a modifiable constraint must be checked manually
1460  * - an unmodifiable constraint is feasible and can be disabled after the remaining variable is fixed to one
1461  */
1462  assert(0 <= watchedvar1 && watchedvar1 < nvars);
1463  assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vars[watchedvar1]), 0.0));
1464  assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(vars[watchedvar1]), 1.0));
1465  if( SCIPconsIsModifiable(cons) )
1466  *mustcheck = TRUE;
1467  else
1468  {
1469  SCIP_Bool infbdchg;
1470 
1471  /* fixed remaining variable to one and disable constraint; make sure, the fixed-to-one variable is watched */
1472  SCIPdebugMsg(scip, " -> single-literal constraint <%s> (fix <%s> to 1.0) at depth %d\n",
1473  SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]), SCIPgetDepth(scip));
1474  SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], TRUE, cons, 0, &infbdchg, NULL) );
1475  assert(!infbdchg);
1476  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1477  if( watchedvar1 != consdata->watchedvar1 ) /* keep one of the watched variables */
1478  {
1479  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, consdata->watchedvar1) );
1480  }
1481  SCIP_CALL( disableCons(scip, cons) );
1482  *reduceddom = TRUE;
1483  }
1484  }
1485  else
1486  {
1487  SCIPdebugMsg(scip, " -> new watched variables <%s> and <%s> of constraint <%s> are still unfixed\n",
1488  SCIPvarGetName(vars[watchedvar1]), SCIPvarGetName(vars[watchedvar2]), SCIPconsGetName(cons));
1489 
1490  /* switch to the new watched variables */
1491  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, watchedvar2) );
1492 
1493  /* there are at least two unfixed variables -> the constraint must be checked manually */
1494  *mustcheck = TRUE;
1495 
1496  /* disable propagation of constraint until a watched variable gets fixed */
1497  SCIP_CALL( SCIPdisableConsPropagation(scip, cons) );
1498 
1499  /* increase aging counter */
1500  SCIP_CALL( SCIPaddConsAge(scip, cons, AGEINCREASE(consdata->nvars)) );
1501  }
1502 
1503  return SCIP_OKAY;
1504 }
1505 
1506 /** checks constraint for violation, returns TRUE iff constraint is feasible */
1507 static
1509  SCIP* scip, /**< SCIP data structure */
1510  SCIP_CONS* cons, /**< logic or constraint to be checked */
1511  SCIP_SOL* sol, /**< primal CIP solution */
1512  SCIP_Bool* violated /**< pointer to store whether the given solution violates the constraint */
1513  )
1514 {
1515  SCIP_CONSDATA* consdata;
1516  SCIP_VAR** vars;
1517  SCIP_Real solval;
1518  SCIP_Real sum;
1519  int nvars;
1520  int v;
1521 
1522  assert(violated != NULL);
1523 
1524  *violated = FALSE;
1525  consdata = SCIPconsGetData(cons);
1526  assert(consdata != NULL);
1527 
1528  vars = consdata->vars;
1529  nvars = consdata->nvars;
1530 
1531  /* calculate the constraint's activity */
1532  sum = 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  /* calculate constraint violation and update it in solution */
1546  if( sol != NULL ){
1547  SCIP_Real absviol = 1.0 - sum;
1548  SCIP_Real relviol = SCIPrelDiff(1.0, sum);
1549  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
1550  }
1551 
1552  return SCIP_OKAY;
1553 }
1554 
1555 /** creates an LP row in a logic or constraint data object */
1556 static
1558  SCIP* scip, /**< SCIP data structure */
1559  SCIP_CONS* cons /**< logic or constraint */
1560  )
1561 {
1562  SCIP_CONSDATA* consdata;
1563 
1564  consdata = SCIPconsGetData(cons);
1565  assert(consdata != NULL);
1566  assert(consdata->row == NULL);
1567 
1568  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), 1.0, SCIPinfinity(scip),
1570 
1571  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
1572 
1573  return SCIP_OKAY;
1574 }
1575 
1576 /** adds logic or constraint as cut to the LP */
1577 static
1579  SCIP* scip, /**< SCIP data structure */
1580  SCIP_CONS* cons, /**< logic or constraint */
1581  SCIP_Bool* cutoff /**< whether a cutoff has been detected */
1582  )
1583 {
1584  SCIP_CONSDATA* consdata;
1585 
1586  assert( cutoff != NULL );
1587  *cutoff = FALSE;
1588 
1589  consdata = SCIPconsGetData(cons);
1590  assert(consdata != NULL);
1591 
1592  if( consdata->row == NULL )
1593  {
1594  /* convert logic or constraint data into LP row */
1595  SCIP_CALL( createRow(scip, cons) );
1596  }
1597  assert(consdata->row != NULL);
1598 
1599  /* insert LP row as cut */
1600  if( !SCIProwIsInLP(consdata->row) )
1601  {
1602  SCIPdebugMsg(scip, "adding constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1603  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
1604  }
1605 
1606  return SCIP_OKAY;
1607 }
1608 
1609 /** checks constraint for violation, and adds it as a cut if possible */
1610 static
1612  SCIP* scip, /**< SCIP data structure */
1613  SCIP_CONS* cons, /**< logic or constraint to be separated */
1614  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1615  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1616  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1617  SCIP_Bool* separated, /**< pointer to store TRUE, if a cut was found */
1618  SCIP_Bool* reduceddom /**< pointer to store TRUE, if a domain reduction was found */
1619  )
1620 {
1621  SCIP_Bool addcut;
1622  SCIP_Bool mustcheck;
1623 
1624  assert(cons != NULL);
1625  assert(SCIPconsGetHdlr(cons) != NULL);
1626  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1627  assert(cutoff != NULL);
1628  assert(separated != NULL);
1629  assert(reduceddom != NULL);
1630 
1631  *cutoff = FALSE;
1632  SCIPdebugMsg(scip, "separating constraint <%s>\n", SCIPconsGetName(cons));
1633 
1634  /* update and check the watched variables, if they were changed since last processing */
1635  if( sol == NULL && SCIPconsIsPropagationEnabled(cons) )
1636  {
1637  SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, reduceddom, &addcut, &mustcheck) );
1638  }
1639  else
1640  {
1641  addcut = FALSE;
1642  mustcheck = TRUE;
1643  }
1644 
1645  if( mustcheck )
1646  {
1647  SCIP_CONSDATA* consdata;
1648 
1649  assert(!addcut);
1650 
1651  consdata = SCIPconsGetData(cons);
1652  assert(consdata != NULL);
1653 
1654  /* variable's fixings didn't give us any information -> we have to check the constraint */
1655  if( sol == NULL && consdata->row != NULL )
1656  {
1657  /* skip constraints already in the LP */
1658  if( SCIProwIsInLP(consdata->row) )
1659  return SCIP_OKAY;
1660  else
1661  {
1662  SCIP_Real feasibility;
1663 
1664  assert(!SCIProwIsInLP(consdata->row));
1665  feasibility = SCIPgetRowLPFeasibility(scip, consdata->row);
1666  addcut = SCIPisFeasNegative(scip, feasibility);
1667  }
1668  }
1669  else
1670  {
1671  SCIP_CALL( checkCons(scip, cons, sol, &addcut) );
1672  }
1673  }
1674 
1675  if( addcut )
1676  {
1677  /* insert LP row as cut */
1678  SCIP_CALL( addCut(scip, cons, cutoff) );
1679  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1680  *separated = TRUE;
1681  }
1682 
1683  return SCIP_OKAY;
1684 }
1685 
1686 /** enforces the pseudo solution on the given constraint */
1687 static
1689  SCIP* scip, /**< SCIP data structure */
1690  SCIP_CONS* cons, /**< logic or constraint to be separated */
1691  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1692  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1693  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
1694  SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1695  SCIP_Bool* solvelp /**< pointer to store TRUE, if the LP has to be solved */
1696  )
1697 {
1698  SCIP_Bool addcut;
1699  SCIP_Bool mustcheck;
1700 
1701  assert(!SCIPhasCurrentNodeLP(scip));
1702  assert(cons != NULL);
1703  assert(SCIPconsGetHdlr(cons) != NULL);
1704  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1705  assert(cutoff != NULL);
1706  assert(infeasible != NULL);
1707  assert(reduceddom != NULL);
1708  assert(solvelp != NULL);
1709 
1710  /* update and check the watched variables, if they were changed since last processing */
1711  if( SCIPconsIsPropagationEnabled(cons) )
1712  {
1713  SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, reduceddom, &addcut, &mustcheck) );
1714  }
1715  else
1716  {
1717  addcut = FALSE;
1718  mustcheck = TRUE;
1719  }
1720 
1721  if( mustcheck )
1722  {
1723  SCIP_Bool violated;
1724 
1725  assert(!addcut);
1726 
1727  SCIP_CALL( checkCons(scip, cons, NULL, &violated) );
1728  if( violated )
1729  {
1730  /* constraint was infeasible -> reset age */
1731  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1732  *infeasible = TRUE;
1733  }
1734  }
1735  else if( addcut )
1736  {
1737  /* a cut must be added to the LP -> we have to solve the LP immediately */
1738  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1739  *solvelp = TRUE;
1740  }
1741 
1742  return SCIP_OKAY;
1743 }
1744 
1745 /** sorts logicor constraint's variables by non-decreasing variable index */
1746 static
1747 void consdataSort(
1748  SCIP_CONSDATA* consdata /**< linear constraint data */
1749  )
1750 {
1751  assert(consdata != NULL);
1752 
1753  if( !consdata->sorted )
1754  {
1755  if( consdata->nvars <= 1 )
1756  consdata->sorted = TRUE;
1757  else
1758  {
1759  SCIP_VAR* var1 = NULL;
1760  SCIP_VAR* var2 = NULL;
1761 
1762  /* remember watch variables */
1763  if( consdata->watchedvar1 != -1 )
1764  {
1765  var1 = consdata->vars[consdata->watchedvar1];
1766  assert(var1 != NULL);
1767  consdata->watchedvar1 = -1;
1768  if( consdata->watchedvar2 != -1 )
1769  {
1770  var2 = consdata->vars[consdata->watchedvar2];
1771  assert(var2 != NULL);
1772  consdata->watchedvar2 = -1;
1773  }
1774  }
1775  assert(consdata->watchedvar1 == -1);
1776  assert(consdata->watchedvar2 == -1);
1777  assert(var1 != NULL || var2 == NULL);
1778 
1779  /* sort variables after index */
1780  SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
1781  consdata->sorted = TRUE;
1782 
1783  /* correct watched variables */
1784  if( var1 != NULL )
1785  {
1786  int pos;
1787 #ifndef NDEBUG
1788  SCIP_Bool found;
1789 
1790  found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
1791  assert(found);
1792 #else
1793  SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
1794 #endif
1795  assert(pos >= 0 && pos < consdata->nvars);
1796  consdata->watchedvar1 = pos;
1797 
1798  if( var2 != NULL )
1799  {
1800 #ifndef NDEBUG
1801  found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
1802  assert(found);
1803 #else
1804  SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
1805 #endif
1806  assert(pos >= 0 && pos < consdata->nvars);
1807  consdata->watchedvar2 = pos;
1808  }
1809  }
1810  }
1811  }
1812 
1813 #ifdef SCIP_DEBUG
1814  /* check sorting */
1815  {
1816  int v;
1817 
1818  for( v = consdata->nvars - 1; v > 0; --v )
1819  {
1820  assert(SCIPvarCompare(consdata->vars[v], consdata->vars[v - 1]) >= 0);
1821  }
1822  }
1823 #endif
1824 }
1825 
1826 /** gets the key of the given element */
1827 static
1828 SCIP_DECL_HASHGETKEY(hashGetKeyLogicorcons)
1829 { /*lint --e{715}*/
1830  /* the key is the element itself */
1831  return elem;
1832 }
1833 
1834 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
1835 static
1836 SCIP_DECL_HASHKEYEQ(hashKeyEqLogicorcons)
1837 {
1838  SCIP_CONSDATA* consdata1;
1839  SCIP_CONSDATA* consdata2;
1840  SCIP_Bool coefsequal;
1841  int i;
1842 #ifndef NDEBUG
1843  SCIP* scip;
1844 
1845  scip = (SCIP*)userptr;
1846  assert(scip != NULL);
1847 #endif
1848 
1849  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
1850  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
1851 
1852  /* checks trivial case */
1853  if( consdata1->nvars != consdata2->nvars )
1854  return FALSE;
1855 
1856  /* sorts the constraints */
1857  consdataSort(consdata1);
1858  consdataSort(consdata2);
1859  assert(consdata1->sorted);
1860  assert(consdata2->sorted);
1861 
1862  coefsequal = TRUE;
1863 
1864  for( i = 0; i < consdata1->nvars ; ++i )
1865  {
1866  /* tests if variables are equal */
1867  if( consdata1->vars[i] != consdata2->vars[i] )
1868  {
1869  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
1870  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
1871  coefsequal = FALSE;
1872  break;
1873  }
1874  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
1875  }
1876 
1877  return coefsequal;
1878 }
1879 
1880 /** returns the hash value of the key */
1881 static
1882 SCIP_DECL_HASHKEYVAL(hashKeyValLogicorcons)
1883 { /*lint --e{715}*/
1884  SCIP_CONSDATA* consdata;
1885  int minidx;
1886  int mididx;
1887  int maxidx;
1888 
1889  consdata = SCIPconsGetData((SCIP_CONS*)key);
1890  assert(consdata != NULL);
1891  assert(consdata->sorted);
1892  assert(consdata->nvars > 0);
1893 
1894  minidx = SCIPvarGetIndex(consdata->vars[0]);
1895  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
1896  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
1897  assert(minidx >= 0 && minidx <= maxidx);
1898 
1899  return SCIPhashTwo(SCIPcombineTwoInt(consdata->nvars, minidx),
1900  SCIPcombineTwoInt(mididx, maxidx));
1901 }
1902 
1903 /** compares each constraint with all other constraints for a possible duplication and removes duplicates using a hash
1904  * table; also @see removeRedundantConssAndNonzeros()
1905  */
1906 static
1908  SCIP* scip, /**< SCIP data structure */
1909  BMS_BLKMEM* blkmem, /**< block memory */
1910  SCIP_CONS** conss, /**< constraint set */
1911  int nconss, /**< number of constraints in constraint set */
1912  int* firstchange, /**< pointer to store first changed constraint */
1913  int* ndelconss /**< pointer to count number of deleted constraints */
1914  )
1915 {
1916  SCIP_HASHTABLE* hashtable;
1917  int hashtablesize;
1918  int c;
1919 
1920  assert(conss != NULL);
1921  assert(ndelconss != NULL);
1922 
1923  /* create a hash table for the constraint set */
1924  hashtablesize = nconss;
1925  hashtablesize = MAX(hashtablesize, HASHSIZE_LOGICORCONS);
1926  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
1927  hashGetKeyLogicorcons, hashKeyEqLogicorcons, hashKeyValLogicorcons, (void*) scip) );
1928 
1929  /* check all constraints in the given set for redundancy */
1930  for( c = 0; c < nconss; ++c )
1931  {
1932  SCIP_CONS* cons0;
1933  SCIP_CONS* cons1;
1934  SCIP_CONSDATA* consdata0;
1935 
1936  cons0 = conss[c];
1937 
1938  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
1939  continue;
1940 
1941  consdata0 = SCIPconsGetData(cons0);
1942  /* sort the constraint */
1943  consdataSort(consdata0);
1944  assert(consdata0->sorted);
1945 
1946  /* get constraint from current hash table with same variables as cons0 */
1947  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
1948 
1949  if( cons1 != NULL )
1950  {
1951 #ifndef NDEBUG
1952  SCIP_CONSDATA* consdata1;
1953 #endif
1954 
1955  assert(SCIPconsIsActive(cons1));
1956  assert(!SCIPconsIsModifiable(cons1));
1957 
1958 #ifndef NDEBUG
1959  consdata1 = SCIPconsGetData(cons1);
1960 #endif
1961  assert(consdata1 != NULL);
1962  assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
1963 
1964  assert(consdata0->sorted && consdata1->sorted);
1965  assert(consdata0->vars[0] == consdata1->vars[0]);
1966 
1967  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
1968  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
1969 
1970  /* delete consdel */
1971  SCIP_CALL( SCIPdelCons(scip, cons0) );
1972  (*ndelconss)++;
1973 
1974  /* update the first changed constraint to begin the next aggregation round with */
1975  if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
1976  *firstchange = SCIPconsGetPos(cons1);
1977 
1978  assert(SCIPconsIsActive(cons1));
1979  }
1980  else
1981  {
1982  /* no such constraint in current hash table: insert cons0 into hash table */
1983  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
1984  }
1985  }
1986 
1987  /* free hash table */
1988  SCIPhashtableFree(&hashtable);
1989 
1990  return SCIP_OKAY;
1991 }
1992 
1993 /** removes the redundant second constraint and updates the flags of the first one */
1994 static
1996  SCIP* scip, /**< SCIP data structure */
1997  SCIP_CONS* cons0, /**< constraint that should stay */
1998  SCIP_CONS* cons1, /**< constraint that should be deleted */
1999  int* ndelconss /**< pointer to count number of deleted constraints */
2000  )
2001 {
2002  assert(ndelconss != NULL);
2003 
2004  SCIPdebugMsg(scip, " -> removing logicor constraint <%s> which is redundant to <%s>\n",
2005  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
2006  SCIPdebugPrintCons(scip, cons0, NULL);
2007  SCIPdebugPrintCons(scip, cons1, NULL);
2008 
2009  /* update flags of cons0 */
2010  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2011 
2012  /* delete cons1 */
2013  SCIP_CALL( SCIPdelCons(scip, cons1) );
2014  (*ndelconss)++;
2015 
2016  return SCIP_OKAY;
2017 }
2018 
2019 
2020 /** compute and return a signature for given variables */
2021 static
2022 unsigned int calcSignature(
2023  SCIP_VAR** vars, /**< variables to calculate the signature for */
2024  int nvars /**< number of variables to calculate the signature for */
2025  )
2026 {
2027  unsigned int signature = 0;
2028  int v;
2029 
2030  assert(vars != NULL);
2031  assert(nvars >= 1);
2032 
2033  for( v = nvars - 1; v >= 0; --v )
2034  {
2035  signature |= ((unsigned int)1 << ((unsigned int)SCIPvarGetIndex(vars[v]) % (sizeof(unsigned int) * 8)));
2036  }
2037 
2038  return signature;
2039 }
2040 
2041 /** compute the constraint signature which is used to detect constraints, that contain potentially the same set of
2042  * variables
2043  */
2044 static
2046  SCIP_CONSDATA* consdata /**< logicor constraint data */
2047  )
2048 {
2049  if( consdata->validsignature )
2050  return;
2051 
2052  consdata->signature = calcSignature(consdata->vars, consdata->nvars);
2053  consdata->validsignature = TRUE;
2054 }
2055 
2056 /** remove a constraint from the column representation */
2057 static
2059  SCIP_CONS* cons, /**< logicor constraint */
2060  SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2061  SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2062  int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2063  int occurlistlength /**< number of columns in the occurlist */
2064  )
2065 {
2066  SCIP_VAR** vars;
2067  SCIP_VAR* var;
2068  SCIP_CONSDATA* consdata;
2069  int nvars;
2070  int pos;
2071  int v;
2072  int l;
2073 
2074  assert(cons != NULL);
2075  assert(SCIPconsIsActive(cons));
2076  assert(varstopos != NULL);
2077  assert(occurlist != NULL);
2078  assert(noccurlistentries != NULL);
2079 
2080  consdata = SCIPconsGetData(cons);
2081  assert(consdata != NULL);
2082 
2083  nvars = consdata->nvars;
2084  assert(nvars >= 1);
2085  vars = consdata->vars;
2086  assert(vars != NULL);
2087 
2088  /* remove constraint from list */
2089  for( v = nvars - 1; v >= 0; --v )
2090  {
2091  var = vars[v];
2092 
2093  assert(SCIPhashmapExists(varstopos, (void*) var));
2094 
2095  pos = (int) (size_t) SCIPhashmapGetImage(varstopos, (void*)var);
2096  assert(0 < pos && pos <= occurlistlength);
2097 
2098  --pos;
2099 
2100  /* remove for each variable one corresponding entry */
2101  for( l = noccurlistentries[pos] - 1; l >= 0; --l )
2102  {
2103  if( occurlist[pos][l] == cons )
2104  {
2105  --noccurlistentries[pos];
2106  assert(noccurlistentries[pos] >= 0);
2107 
2108  occurlist[pos][l] = occurlist[pos][noccurlistentries[pos]];
2109  break;
2110  }
2111  }
2112  assert(l >= 0);
2113  }
2114 }
2115 
2116 /** determine shortest constraint list in column representation */
2117 static
2119  SCIP_VAR** vars, /**< variables to find the shortestlist for */
2120  int nvars, /**< number of variables */
2121  SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2122  SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2123  int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2124  int occurlistlength, /**< number of columns in the occurlist */
2125  int* nentries, /**< pointer to store the number of entries in the shortest list */
2126  SCIP_CONS*** shortestlist /**< pointer to store smallest array with constraints */
2127  )
2128 {
2129  SCIP_VAR* var;
2130  int pos;
2131  int v;
2132 
2133  assert(vars != 0);
2134  assert(nvars >= 1);
2135  assert(varstopos != NULL);
2136  assert(occurlist != NULL);
2137  assert(noccurlistentries != NULL);
2138  assert(nentries != NULL);
2139  assert(shortestlist != NULL);
2140 
2141  *nentries = INT_MAX;
2142  *shortestlist = NULL;
2143 
2144  /* find the shortest list */
2145  for( v = nvars - 1; v >= 0; --v )
2146  {
2147  var = vars[v];
2148  assert(var != NULL);
2149 
2150  /* it might be that a variable is not yet put into the occurlist, then this constraint cannot cover another */
2151  if( !SCIPhashmapExists(varstopos, (void*) var) )
2152  {
2153  *nentries = 0;
2154  return;
2155  }
2156 
2157  pos = (int) (size_t) SCIPhashmapGetImage(varstopos, (void*)var);
2158  assert(0 < pos && pos <= occurlistlength);
2159 
2160  --pos;
2161 
2162  /* remember the shortest list */
2163  if( noccurlistentries[pos] < *nentries )
2164  {
2165  *nentries = noccurlistentries[pos];
2166  *shortestlist = occurlist[pos];
2167  }
2168  }
2169 }
2170 
2171 /** run a pairwise comparison for detecting subset-constraints of other constraint while using a signature */
2172 static
2174  SCIP* scip, /**< SCIP data structure */
2175  SCIP_CONS* cons, /**< logicor constraint to check if it covers another */
2176  SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2177  SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2178  int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2179  int occurlistlength, /**< number of columns in the occurlist */
2180  int* ndelconss /**< pointer to store the number of deleted constraints */
2181  )
2182 {
2183  SCIP_CONS** shortestlist;
2184  SCIP_VAR** vars;
2185  SCIP_CONS* cons1;
2186  SCIP_VAR* var;
2187  SCIP_CONSDATA* consdata;
2188  int nentries;
2189  int c;
2190  int v;
2191 
2192  assert(scip != NULL);
2193  assert(cons != NULL);
2194  assert(SCIPconsIsActive(cons));
2195  assert(!SCIPconsIsModifiable(cons));
2196  assert(varstopos != NULL);
2197  assert(occurlist != NULL);
2198  assert(noccurlistentries != NULL);
2199  assert(ndelconss != NULL);
2200 
2201  consdata = SCIPconsGetData(cons);
2202  assert(consdata != NULL);
2203  assert(consdata->nvars > 1);
2204  assert(consdata->validsignature);
2205  assert(consdata->sorted);
2206 
2207  vars = consdata->vars;
2208  assert(vars != NULL);
2209 
2210  /* determine shortest column */
2211  findShortestOccurlist(vars, consdata->nvars, varstopos, occurlist, noccurlistentries, occurlistlength, &nentries, &shortestlist);
2212 
2213  /* one variable which does not appear in the column representation anymore */
2214  if( nentries == 0 )
2215  return SCIP_OKAY;
2216 
2217  assert(shortestlist != NULL);
2218  assert(0 < nentries);
2219 
2220  /* check all constraints in the shortest list for coverage */
2221  for( c = nentries - 1; c >= 0; --c )
2222  {
2223  cons1 = shortestlist[c];
2224  assert(cons1 != NULL);
2225  assert(!SCIPconsIsModifiable(cons1));
2226  assert(SCIPconsIsActive(cons1));
2227 
2228  if( cons != cons1 )
2229  {
2230  SCIP_CONSDATA* consdata1 = SCIPconsGetData(cons1);
2231  assert(consdata1 != NULL);
2232  assert(consdata1->nvars >= consdata->nvars);
2233 
2234  /* constraints with the same length cannot be covered and same constraints are removed in
2235  * detectRedundantConstraints()
2236  */
2237  if( consdata1->nvars == consdata->nvars )
2238  continue;
2239 
2240  assert(consdata->validsignature);
2241  assert(consdata->sorted);
2242  assert(consdata1->validsignature);
2243  assert(consdata1->sorted);
2244 
2245  if( (consdata->signature & (~consdata1->signature)) == 0 )
2246  {
2247  SCIP_VAR* var1;
2248  int v1;
2249 
2250  v = 0;
2251  v1 = 0;
2252 
2253  while( v < consdata->nvars && v1 < consdata1->nvars )
2254  {
2255  int comp;
2256 
2257  var = vars[v];
2258  var1 = consdata1->vars[v1];
2259 
2260  comp = SCIPvarCompare(var, var1);
2261 
2262  if( comp == 0 )
2263  {
2264  ++v;
2265  ++v1;
2266  }
2267  else if( comp > 0 )
2268  ++v1;
2269  else
2270  break;
2271  }
2272 
2273  /* cons1 is covered by cons */
2274  if( v == consdata->nvars )
2275  {
2276  /* remove cons1 from columns representation */
2277  removeConsFromOccurList(cons1, varstopos, occurlist, noccurlistentries, occurlistlength);
2278 
2279  /* delete redundant constraint and update constraint flags if necessary */
2280  SCIP_CALL( removeRedundantCons(scip, cons, cons1, ndelconss) );
2281  }
2282  }
2283  }
2284  }
2285 
2286  return SCIP_OKAY;
2287 }
2288 
2289 /** compararer for sorting constraints after their number of variables */
2290 static
2291 SCIP_DECL_SORTPTRCOMP(conssLogicorComp)
2292 {
2293  SCIP_CONSDATA* consdata1;
2294  SCIP_CONSDATA* consdata2;
2295 
2296  assert(elem1 != NULL);
2297  assert(elem2 != NULL);
2298 
2299  consdata1 = SCIPconsGetData((SCIP_CONS*) elem1);
2300  consdata2 = SCIPconsGetData((SCIP_CONS*) elem2);
2301 
2302  assert(consdata1 != NULL);
2303  assert(consdata2 != NULL);
2304 
2305  return consdata1->nvars - consdata2->nvars;
2306 }
2307 
2308 /** add a constraint to the column representation */
2309 static
2311  SCIP* scip, /**< SCIP data structure */
2312  SCIP_CONS* cons, /**< logicor constraint */
2313  SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2314  SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2315  int* noccurlistentries, /**< arrray with number of constraints for each variable in the occurlist */
2316  int* occurlistsizes, /**< array of sizes for each variable in the occurlist */
2317  int* occurlistlength, /**< number of columns in the occurlist */
2318  int occurlistsize /**< size of occurlist */
2319  )
2320 {
2321  SCIP_VAR** vars;
2322  SCIP_VAR* var;
2323  SCIP_CONSDATA* consdata;
2324  int pos;
2325  int v;
2326 
2327  assert(scip != NULL);
2328  assert(cons != NULL);
2329  assert(SCIPconsIsActive(cons));
2330  assert(varstopos != NULL);
2331  assert(occurlist != NULL);
2332  assert(noccurlistentries != NULL);
2333  assert(occurlistsizes != NULL);
2334  assert(occurlistlength != NULL);
2335  assert(*occurlistlength <= occurlistsize);
2336 
2337  consdata = SCIPconsGetData(cons);
2338  assert(consdata != NULL);
2339  assert(consdata->nvars > 1);
2340 
2341  vars = consdata->vars;
2342  assert(vars != NULL);
2343 
2344  for( v = consdata->nvars - 1; v >= 0; --v )
2345  {
2346  var = vars[v];
2347  assert(var != NULL);
2348  assert(SCIPvarIsActive(var) || (SCIPvarGetNegatedVar(var) != NULL && SCIPvarIsActive(SCIPvarGetNegatedVar(var))));
2349 
2350  /* check if the variable is not yet put into the occurlist */
2351  if( !SCIPhashmapExists(varstopos, (void*) var) )
2352  {
2353  pos = *occurlistlength;
2354  assert(pos <= occurlistsize);
2355 
2356  /* occurlist values need to be clear */
2357  assert(occurlist[pos] == NULL);
2358  assert(noccurlistentries[pos] == 0);
2359  assert(occurlistsizes[pos] == 0);
2360 
2361  /* allocate memory */
2362  assert(SCIPvarGetNLocksDown(var) > 0 || !SCIPconsIsChecked(cons));
2363  occurlistsizes[pos] = SCIPvarGetNLocksDown(var) + 1;
2364  SCIP_CALL( SCIPallocBufferArray(scip, &(occurlist[pos]), occurlistsizes[pos]) ); /*lint !e866*/
2365 
2366  /* put constraint in list of current variable */
2367  occurlist[pos][noccurlistentries[pos]] = cons;
2368  ++(noccurlistentries[pos]);
2369 
2370  /* add new variable to map */
2371  SCIP_CALL( SCIPhashmapInsert(varstopos, var, (void*) (size_t) (pos + 1)) );
2372 
2373  ++(*occurlistlength);
2374  }
2375  else
2376  {
2377  pos = (int) (size_t) SCIPhashmapGetImage(varstopos, (void*)var);
2378  assert(0 < pos && pos <= *occurlistlength);
2379 
2380  --pos;
2381 
2382  assert(occurlist[pos] != NULL);
2383  assert(occurlistsizes[pos] > 0);
2384 
2385  /* do we need to resize the array */
2386  if( noccurlistentries[pos] == occurlistsizes[pos] )
2387  {
2388  occurlistsizes[pos] = SCIPcalcMemGrowSize(scip, occurlistsizes[pos] + 1);
2389  assert(occurlistsizes[pos] > noccurlistentries[pos] && occurlistsizes[pos] < INT_MAX);
2390 
2391  /* resize occurlist for current variable */
2392  SCIP_CALL( SCIPreallocBufferArray(scip, &(occurlist[pos]), occurlistsizes[pos]) ); /*lint !e866*/
2393  }
2394  assert(noccurlistentries[pos] < occurlistsizes[pos]);
2395 
2396  /* put constraint in list of current variable */
2397  occurlist[pos][noccurlistentries[pos]] = cons;
2398  ++(noccurlistentries[pos]);
2399  }
2400  }
2401 
2402  return SCIP_OKAY;
2403 }
2404 
2405 /** run a pairwise comparison for the given variables against all constraits to detect redundant non-zeros in these
2406  * constraints
2407  */
2408 static
2410  SCIP* scip, /**< SCIP data structure */
2411  SCIP_CONS* cons, /**< logicor constraint to check if it covers another */
2412  SCIP_VAR* artvar, /**< artificial negated variable of constraint */
2413  int artpos, /**< position to replace constraint variable with artvar */
2414  SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2415  SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2416  int* noccurlistentries, /**< number of constraints for each variable in the occurlist */
2417  int occurlistlength, /**< number of columns in the occurlist */
2418  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
2419  int* nchgcoefs, /**< pointer to store the number of deleted non-zeros */
2420  SCIP_Bool* deleted /**< pointer to store if cons will be deleted */
2421  )
2422 {
2423  SCIP_CONS** shortestlist;
2424  SCIP_VAR** vars;
2425  SCIP_CONS* cons1;
2426  SCIP_VAR* oldvar;
2427  SCIP_VAR* var;
2428  SCIP_CONSDATA* consdata;
2429  unsigned int signature;
2430  int nentries;
2431  int nvars;
2432  int c;
2433  int v;
2434  int pos;
2435 
2436  assert(scip != NULL);
2437  assert(cons != NULL);
2438  assert(artvar != NULL);
2439  assert(SCIPconsIsActive(cons));
2440  assert(!SCIPconsIsModifiable(cons));
2441  assert(varstopos != NULL);
2442  assert(SCIPhashmapExists(varstopos, (void*) artvar));
2443  assert(occurlist != NULL);
2444  assert(noccurlistentries != NULL);
2445  assert(nchgcoefs != NULL);
2446  assert(deleted != NULL);
2447 
2448  consdata = SCIPconsGetData(cons);
2449  assert(consdata != NULL);
2450  assert(consdata->sorted);
2451 
2452  nvars = consdata->nvars;
2453  assert(nvars > 1);
2454  assert(0 <= artpos && artpos < nvars);
2455 
2456  vars = consdata->vars;
2457  assert(vars != NULL);
2458 
2459  *deleted = FALSE;
2460 
2461  /* temporary exchange the variable for finding the shortest list */
2462  oldvar = vars[artpos];
2463  assert(oldvar == SCIPvarGetNegatedVar(artvar));
2464  vars[artpos] = artvar;
2465 
2466  /* determine shortest column */
2467  findShortestOccurlist(vars, nvars, varstopos, occurlist, noccurlistentries, occurlistlength, &nentries, &shortestlist);
2468 
2469  /* correct exchanged variable with constraint variables */
2470  vars[artpos] = oldvar;
2471 
2472  /* one variable which does not appear in the column representation anymore */
2473  if( nentries == 0 )
2474  return SCIP_OKAY;
2475 
2476  assert(shortestlist != NULL);
2477  assert(0 < nentries);
2478 
2479  /* temporary exchange the variable for calculating a valid signature */
2480  oldvar = vars[artpos];
2481  vars[artpos] = artvar;
2482  signature = calcSignature(vars, nvars);
2483 
2484  /* correct exchanged variable with constraint variables */
2485  vars[artpos] = oldvar;
2486 
2487  /* check all constraints in the shortest list for coverage */
2488  for( c = nentries - 1; c >= 0; --c )
2489  {
2490  cons1 = shortestlist[c];
2491  assert(cons1 != NULL);
2492  assert(!SCIPconsIsModifiable(cons1));
2493 
2494  if( !SCIPconsIsActive(cons1) )
2495  continue;
2496 
2497  if( cons != cons1 )
2498  {
2499  SCIP_CONSDATA* consdata1 = SCIPconsGetData(cons1);
2500  assert(consdata1 != NULL);
2501 
2502  /* constraints with the less variables cannot be covered */
2503  if( consdata1->nvars < nvars )
2504  continue;
2505 
2506  pos = -1;
2507 
2508  assert(consdata->sorted);
2509  assert(consdata->merged);
2510  assert(consdata1->validsignature);
2511  assert(consdata1->sorted);
2512  assert(consdata1->merged);
2513 
2514  if( (signature & (~consdata1->signature)) == 0 )
2515  {
2516  SCIP_VAR* var1;
2517  int v1;
2518 
2519  v = 0;
2520  v1 = 0;
2521 
2522  while( v < nvars && v1 < consdata1->nvars )
2523  {
2524  int comp;
2525 
2526  /* skip position of artificial variable */
2527  if( artpos == v )
2528  {
2529  ++v;
2530  continue;
2531  }
2532 
2533  var1 = consdata1->vars[v1];
2534 
2535  /* did we find the artificial variable in cons1 */
2536  if( artvar == var1 )
2537  {
2538  /* remember of possible redundant variable */
2539  assert(pos == -1);
2540  pos = v1;
2541 
2542  ++v1;
2543  continue;
2544  }
2545 
2546  var = vars[v];
2547  comp = SCIPvarCompare(var, var1);
2548 
2549  /* check if the cons1 can still be covered */
2550  if( comp == 0 )
2551  {
2552  ++v;
2553  ++v1;
2554  }
2555  else if( comp > 0 )
2556  ++v1;
2557  else
2558  break;
2559  }
2560 
2561  /* cons1 is might be covered by the changed constraints cons, meaning that we might remove the artvar from
2562  * cons1
2563  */
2564  if( v == nvars )
2565  {
2566  int l;
2567 
2568  /* if the artificial variable was not yet found, search over the rear variables in constraint cons1 */
2569  if( pos == -1 )
2570  {
2571  while( v1 < consdata1->nvars )
2572  {
2573  if( artvar == consdata1->vars[v1] )
2574  {
2575  /* remember of possible redundant variable */
2576  pos = v1;
2577  break;
2578  }
2579  ++v1;
2580  }
2581  }
2582 
2583  if( pos >= 0 )
2584  {
2585  int conspos;
2586 
2587  assert(pos < consdata1->nvars);
2588  assert(artvar == consdata1->vars[pos]);
2589 
2590  /* remove redudant entry in cons1 */
2591  SCIPdebugMsg(scip, "variable %s in logicor constraint <%s> is redundant and will be removed (used constraint %s)\n",
2592  SCIPvarGetName(artvar), SCIPconsGetName(cons1), SCIPconsGetName(cons));
2593  SCIPdebugPrintCons(scip, cons1, NULL);
2594  conspos = pos;
2595 
2596  if( consdata1->nvars > nvars )
2597  {
2598  pos = (int) (size_t) SCIPhashmapGetImage(varstopos, (void*)artvar);
2599  assert(0 < pos && pos <= occurlistlength);
2600 
2601  --pos;
2602 
2603  /* remove corresponding entry in column representation */
2604  for( l = noccurlistentries[pos] - 1; l >= 0; --l )
2605  {
2606  if( occurlist[pos][l] == cons1 )
2607  {
2608  --noccurlistentries[pos];
2609  assert(noccurlistentries[pos] >= 0);
2610 
2611  occurlist[pos][l] = occurlist[pos][noccurlistentries[pos]];
2612  break;
2613  }
2614  }
2615  assert(l >= 0);
2616  }
2617  else
2618  {
2619  assert(consdata1->nvars == nvars);
2620 
2621  /* delete cons */
2622  SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to constraint <%s> after removing variable <%s>\n",
2623  SCIPconsGetName(cons), SCIPconsGetName(cons1), SCIPvarGetName(artvar));
2624 
2625  /* remove cons from columns representation */
2626  removeConsFromOccurList(cons, varstopos, occurlist, noccurlistentries, occurlistlength);
2627 
2628  /* update flags of cons1 */
2629  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
2630 
2631  SCIP_CALL( SCIPdelCons(scip, cons) );
2632  *deleted = TRUE;
2633  }
2634 
2635  /* remove variable */
2636  SCIP_CALL( delCoefPos(scip, cons1, eventhdlr, conspos) );
2637  ++(*nchgcoefs);
2638  consdataSort(consdata1);
2639  consdataCalcSignature(consdata1);
2640 
2641  if( *deleted )
2642  return SCIP_OKAY;
2643  }
2644  }
2645  }
2646  }
2647  }
2648 
2649  return SCIP_OKAY;
2650 }
2651 
2652 /** find and remove redundant non-zero entries */
2653 static
2655  SCIP* scip, /**< SCIP data structure */
2656  SCIP_CONS** conss, /**< sorted array of logicor constraint */
2657  int nconss, /**< number of sorted constraints */
2658  SCIP_HASHMAP* varstopos, /**< map for mapping variables to positions in the occurlist */
2659  SCIP_CONS*** occurlist, /**< column representation of logicor constraints */
2660  int* noccurlistentries, /**< number of constraints for each variable in the occurlist */
2661  int occurlistlength, /**< number of columns in the occurlist */
2662  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2663  int* ndelconss, /**< pointer to store the number of deleted constraints */
2664  int* nchgcoefs /**< pointer to store the number of remove coefficients */
2665  )
2666 {
2667  SCIP_VAR** vars;
2668  SCIP_CONSDATA* consdata;
2669  SCIP_CONS* cons;
2670  SCIP_VAR* artvar;
2671  int nvars;
2672  int c;
2673  int v;
2674 
2675  assert(scip != NULL);
2676  assert(conss != NULL || nconss == 0);
2677  assert(varstopos != NULL);
2678  assert(occurlist != NULL);
2679  assert(noccurlistentries != NULL);
2680  assert(eventhdlr != NULL);
2681  assert(ndelconss != NULL);
2682  assert(nchgcoefs != NULL);
2683 
2684  if( nconss == 0 )
2685  return SCIP_OKAY;
2686 
2687  assert(conss != NULL);
2688 
2689  for( c = 0; c < nconss; ++c )
2690  {
2691  cons = conss[c];
2692  assert(cons != NULL);
2693  assert(!SCIPconsIsModifiable(cons));
2694 
2695  if( !SCIPconsIsActive(cons) )
2696  continue;
2697 
2698  consdata = SCIPconsGetData(cons);
2699  assert(consdata != NULL);
2700 
2701  nvars = consdata->nvars;
2702  assert(nvars >= 1);
2703 
2704  if( nvars == 1 )
2705  continue;
2706 
2707  vars = consdata->vars;
2708  assert(vars != NULL);
2709 
2710  for( v = nvars - 1; v >= 0; --v )
2711  {
2712  artvar = SCIPvarGetNegatedVar(vars[v]);
2713 
2714  if( artvar != NULL && SCIPhashmapExists(varstopos, (void*) artvar) )
2715  {
2716  SCIP_Bool deleted;
2717 
2718  /* detect and remove redundant non-zero entries */
2719  /* @todo: improve this algorithm by using the information that a constraint variables does not appaer in any
2720  * other constraint, which means that only this variable needs to be negated to check for redundant
2721  * non-zeros, therefor change also findShortestOccurlist() to return the corresponding
2722  * variable/position
2723  */
2724  SCIP_CALL( removeRedundantNonZeros(scip, cons, artvar, v, varstopos, occurlist, noccurlistentries,
2725  occurlistlength, eventhdlr, nchgcoefs, &deleted) );
2726 
2727  if( deleted )
2728  {
2729  assert(SCIPconsIsDeleted(cons));
2730  ++(*ndelconss);
2731  break;
2732  }
2733  else
2734  assert(SCIPconsIsActive(cons));
2735  }
2736  }
2737  }
2738 
2739  return SCIP_OKAY;
2740 }
2741 
2742 
2743 /** prepares a constraint by removing fixings and merge it */
2744 static
2746  SCIP* scip, /**< SCIP data structure */
2747  SCIP_CONS* cons, /**< logic or constraint */
2748  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2749  unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
2750  int* nentries, /**< pointer for array size, if array will be to small it's corrected */
2751  SCIP_Bool* redundant, /**< returns whether a variable fixed to one exists in the constraint */
2752  int* nfixedvars, /**< pointer to count number of fixings */
2753  int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
2754  int* ndelconss, /**< pointer to count number of deleted constraints */
2755  SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
2756  )
2757 {
2758  SCIP_CONSDATA* consdata;
2759 
2760  assert(scip != NULL);
2761  assert(cons != NULL);
2762  assert(!SCIPconsIsDeleted(cons));
2763  assert(eventhdlr != NULL);
2764  assert(*entries != NULL);
2765  assert(nentries != NULL);
2766  assert(redundant != NULL);
2767  assert(nfixedvars != NULL);
2768  assert(nchgcoefs != NULL);
2769  assert(ndelconss != NULL);
2770  assert(redundant != NULL);
2771 
2772  consdata = SCIPconsGetData(cons);
2773  assert(consdata != NULL);
2774  assert(consdata->nvars > 0);
2775 
2776  *redundant = FALSE;
2777 
2778  /* remove old fixings */
2779  if( !consdata->presolved )
2780  {
2781  /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
2782  SCIP_CALL( applyFixings(scip, cons, eventhdlr, redundant, nchgcoefs, NULL, NULL) );
2783  }
2784 
2785  if( !*redundant )
2786  {
2787  /* merge constraint */
2788  SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, redundant, nchgcoefs) );
2789  }
2790 
2791  if( *redundant )
2792  {
2793  SCIP_CALL( SCIPdelCons(scip, cons) );
2794  ++(*ndelconss);
2795 
2796  return SCIP_OKAY;
2797  }
2798 
2799  if( consdata->nvars == 0 )
2800  {
2801  *cutoff = TRUE;
2802  }
2803  else if( consdata->nvars == 1 )
2804  {
2805  SCIP_Bool infeasible;
2806  SCIP_Bool fixed;
2807 
2808  SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
2809 
2810  SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
2811  assert(!infeasible);
2812  assert(fixed);
2813  ++(*nfixedvars);
2814 
2815  SCIP_CALL( SCIPdelCons(scip, cons) );
2816  ++(*ndelconss);
2817 
2818  *redundant = TRUE;
2819  }
2820  consdata->presolved = TRUE;
2821 
2822  return SCIP_OKAY;
2823 }
2824 
2825 
2826 /** find covered/subsumed constraints and redundant non-zero entries
2827  *
2828  * covered:
2829  * e.g.: c1: x1 + x2 + x3 >= 1
2830  * c2: x1 + x2 + x3 + x4 >= 1
2831  *
2832  * strengthen:
2833  * e.g.: c1: x1 + x2 + x3 >= 1
2834  * c2: x1 + x2 + ~x3 + x4 >= 1
2835  *
2836  * => c2: x1 + x2 + x4 >= 1
2837  *
2838  * @see "Effective Preprocessing in SAT through Variable and Clause Elimination" by Niklas En and Armin Biere
2839  */
2840 static
2842  SCIP* scip, /**< SCIP data structure */
2843  SCIP_CONS** conss, /**< array of logicor constraints */
2844  int nconss, /**< number of logicor constraints */
2845  unsigned char** entries, /**< array to store whether two positions in constraints represent the same
2846  * variable */
2847  int* nentries, /**< pointer for array size, if array will be to small it's corrected */
2848  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2849  SCIP_Bool usestrengthening, /**< should we try to strengthen constraints by removing superflous
2850  * non-zeros? */
2851  int* firstchange, /**< pointer to store first changed constraint */
2852  int* nfixedvars, /**< pointer to count number of fixings */
2853  int* ndelconss, /**< pointer to store the number of deleted constraints */
2854  int* nchgcoefs, /**< pointer to store the number of deleted coefficients */
2855  SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
2856  )
2857 {
2858  SCIP_CONS*** occurlist;
2859  SCIP_CONS** myconss;
2860  SCIP_HASHMAP* varstopos;
2861  SCIP_CONS* cons;
2862  SCIP_CONSDATA* consdata;
2863  int* noccurlistentries;
2864  int* occurlistsizes;
2865  SCIP_Bool redundant;
2866  SCIP_Bool conschanged;
2867  int nbinvars;
2868  int occurlistlength;
2869  int occurlistsize;
2870  int nmyconss;
2871  int nmaxvars;
2872  int c;
2873 
2874  assert(scip != NULL);
2875  assert(conss != NULL || nconss == 0);
2876  assert(entries != NULL);
2877  assert(*entries != NULL);
2878  assert(nentries != NULL);
2879  assert(eventhdlr != NULL);
2880  assert(firstchange != NULL);
2881  assert(0 <= *firstchange);
2882  assert(nfixedvars != NULL);
2883  assert(ndelconss != NULL);
2884  assert(nchgcoefs != NULL);
2885 
2886  if( *firstchange > nconss || nconss < 2 )
2887  return SCIP_OKAY;
2888 
2889  SCIPdebugMsg(scip, "starting removeRedundantConssAndNonzeros(), pairwise comparison to detect covered logicor constraints\n");
2890 
2891  /* copy constraints to re-order them */
2892  SCIP_CALL( SCIPduplicateBufferArray(scip, &myconss, conss, nconss) );
2893 
2894  nmyconss = nconss;
2895  for( c = nconss - 1; c >= 0; --c )
2896  {
2897  cons = myconss[c];
2898  assert(cons != NULL);
2899 
2900  if( SCIPconsIsDeleted(cons) || SCIPconsIsModifiable(cons) )
2901  {
2902  myconss[c] = myconss[nmyconss - 1];
2903  --nmyconss;
2904 
2905  continue;
2906  }
2907 
2908  /* prepare constraint by removing fixings and merge it */
2909  SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
2910 
2911  if( redundant )
2912  {
2913  assert(SCIPconsIsDeleted(cons));
2914 
2915  myconss[c] = myconss[nmyconss - 1];
2916  --nmyconss;
2917  }
2918 
2919  if( *cutoff )
2920  {
2921  SCIPfreeBufferArray(scip, &myconss);
2922 
2923  return SCIP_OKAY;
2924  }
2925 
2926  consdata = SCIPconsGetData(cons);
2927 
2928  /* sort the constraint */
2929  consdataSort(consdata);
2930 
2931  assert(consdata->nvars >= 2);
2932  }
2933 
2934  SCIPsortPtr((void**)myconss, conssLogicorComp, nmyconss);
2935  assert(myconss[0] != NULL && myconss[nmyconss - 1] != NULL);
2936  assert(SCIPconsGetData(myconss[0]) != NULL && SCIPconsGetData(myconss[nmyconss - 1]) != NULL);
2937  assert(SCIPconsGetData(myconss[0])->nvars <= SCIPconsGetData(myconss[nmyconss - 1])->nvars);
2938 
2939  /* we can stop if strengthening is disabled and all constraints have the same amount of variables */
2940  if( !usestrengthening && SCIPconsGetData(myconss[0])->nvars == SCIPconsGetData(myconss[nmyconss - 1])->nvars )
2941  {
2942  SCIPfreeBufferArray(scip, &myconss);
2943 
2944  return SCIP_OKAY;
2945  }
2946 
2947  /* @note: in the following we have at least number of nonzeros in logicor constraints + three times two the number of
2948  * binary variables memory consumption + a map for variables to positions, we need this to get a column base
2949  * representation
2950  */
2951 
2952  /* get number of all possible(incl. implcit) binary variables and their negation */
2953  nbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
2954  occurlistsize = 2 * nbinvars;
2955 
2956  /* allocate memory for the column representation for each variable */
2957  SCIP_CALL( SCIPallocBufferArray(scip, &occurlist, occurlistsize) );
2958  BMSclearMemoryArray(occurlist, occurlistsize);
2959  SCIP_CALL( SCIPallocBufferArray(scip, &noccurlistentries, occurlistsize) );
2960  BMSclearMemoryArray(noccurlistentries, occurlistsize);
2961  SCIP_CALL( SCIPallocBufferArray(scip, &occurlistsizes, occurlistsize) );
2962  BMSclearMemoryArray(occurlistsizes, occurlistsize);
2963 
2964  /* create hashmap to map all occuring variables to a position in the list */
2965  SCIP_CALL( SCIPhashmapCreate(&varstopos, SCIPblkmem(scip), nmyconss) );
2966 
2967  /* get maximal number of variables over all logicor constraints */
2968  c = nmyconss - 1;
2969  cons = myconss[c];
2970  assert(cons != NULL);
2971  assert(SCIPconsIsActive(cons));
2972  consdata = SCIPconsGetData(cons);
2973  assert(consdata != NULL);
2974  nmaxvars = consdata->nvars;
2975 
2976  occurlistlength = 0;
2977  conschanged = FALSE;
2978 
2979  /* determine all constraints with the maximal number of variables and add them to the column representation */
2980  do
2981  {
2982  /* calculate hash-signature */
2983  consdataCalcSignature(consdata);
2984  assert(consdata->validsignature);
2985  conschanged = conschanged || consdata->changed;
2986  consdata->changed = FALSE;
2987 
2988  /* add constraint to column data structure */
2989  SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
2990 
2991  --c;
2992  if( c < 0 )
2993  break;
2994 
2995  cons = myconss[c];
2996  assert(cons != NULL);
2997  assert(SCIPconsIsActive(cons));
2998  consdata = SCIPconsGetData(cons);
2999  assert(consdata != NULL);
3000  }
3001  while( consdata->nvars == nmaxvars );
3002 
3003  /* remove covered constraints and left over constraints to the column representation */
3004  while( c >= 0 )
3005  {
3006  cons = myconss[c];
3007  assert(cons != NULL);
3008  assert(SCIPconsIsActive(cons));
3009  consdata = SCIPconsGetData(cons);
3010  assert(consdata != NULL);
3011 
3012  /* calculate hash-signature */
3013  consdataCalcSignature(consdata);
3014  assert(consdata->validsignature);
3015 
3016  /* search for covered constraints */
3017  if( conschanged || consdata->changed )
3018  {
3019  /* detect covered constraints
3020  *
3021  * e.g.: c1: x1 + x2 + x3 >= 1
3022  * c2: x1 + x2 + x3 + x4 >= 1
3023  *
3024  * => delete c2
3025  */
3026  SCIP_CALL( removeRedundantConss(scip, cons, varstopos, occurlist, noccurlistentries, occurlistlength, ndelconss) );
3027  assert(SCIPconsIsActive(cons));
3028 
3029  consdata->changed = FALSE;
3030  conschanged = TRUE;
3031  }
3032 
3033  /* add constraint to column data structure */
3034  SCIP_CALL( addConsToOccurList(scip, cons, varstopos, occurlist, noccurlistentries, occurlistsizes, &occurlistlength, occurlistsize) );
3035 
3036  --c;
3037  }
3038 
3039  /* strengthen constraint while removing non-zeros
3040  *
3041  * e.g.: c1: x1 + x2 + x3 >= 1
3042  * c2: x1 + x2 + ~x3 + x4 >= 1
3043  *
3044  * => c2: x1 + x2 + x4 >= 1
3045  *
3046  * special case:
3047  *
3048  * e.g.: c1: x1 + x2 + x3 >= 1
3049  * c2: x1 + x2 + ~x3 >= 1
3050  *
3051  * => delete c1; c2: x1 + x2 >= 1
3052  *
3053  */
3054  SCIP_CALL( strengthenConss(scip, myconss, nmyconss, varstopos, occurlist, noccurlistentries, occurlistlength, eventhdlr, ndelconss, nchgcoefs) );
3055 
3056  /* delete temporary memory in occurlist */
3057  for( --occurlistsize ; occurlistsize >= 0; --occurlistsize )
3058  {
3059  assert((occurlistsizes[occurlistsize] == 0) == (occurlist[occurlistsize] == NULL));
3060  SCIPfreeBufferArrayNull(scip, &(occurlist[occurlistsize]));
3061  }
3062 
3063  /* delete temporary memory */
3064  SCIPhashmapFree(&varstopos);
3065  SCIPfreeBufferArray(scip, &occurlistsizes);
3066  SCIPfreeBufferArray(scip, &noccurlistentries);
3067  SCIPfreeBufferArray(scip, &occurlist);
3068  SCIPfreeBufferArray(scip, &myconss);
3069 
3070  return SCIP_OKAY;
3071 }
3072 
3073 #define MAX_CONSLENGTH 200
3074 
3075 /** try to tighten constraints by reducing the number of variables in the constraints using implications and cliques,
3076  * also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
3077  */
3078 static
3080  SCIP* scip, /**< SCIP data structure */
3081  SCIP_CONSHDLRDATA* conshdlrdata, /**< logic or constraint handler data */
3082  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
3083  SCIP_CONS** conss, /**< all constraints */
3084  int nconss, /**< number of constraints */
3085  unsigned char** entries, /**< array to store whether two positions in constraints represent the same
3086  * variable */
3087  int* nentries, /**< pointer for array size, if array will be to small it's corrected */
3088  int* nfixedvars, /**< pointer to count number of fixings */
3089  int* ndelconss, /**< pointer to count number of deleted constraints */
3090  int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
3091  SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
3092  )
3093 {
3094  SCIP_VAR** probvars;
3095  SCIP_VAR* var;
3096  SCIP_Real* bounds;
3097  SCIP_Bool* boundtypes;
3098  SCIP_Bool* redundants;
3099  int nbinprobvars;
3100  int nredvars;
3101  int c;
3102  int v;
3103 
3104  assert(scip != NULL);
3105  assert(eventhdlr != NULL);
3106  assert(conss != NULL || nconss == 0);
3107  assert(entries != NULL);
3108  assert(*entries != NULL);
3109  assert(nentries != NULL);
3110  assert(nfixedvars != NULL);
3111  assert(ndelconss != NULL);
3112  assert(nchgcoefs != NULL);
3113 
3114  if( nconss == 0 )
3115  return SCIP_OKAY;
3116 
3117  assert(conss != NULL);
3118 
3119  if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesshorten
3120  && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsshorten )
3121  return SCIP_OKAY;
3122 
3123  conshdlrdata->nlastcliquesshorten = SCIPgetNCliques(scip);
3124  conshdlrdata->nlastimplsshorten = SCIPgetNImplications(scip);
3125 
3126  nbinprobvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
3127 
3128  /* allocate temporary memory */
3129  SCIP_CALL( SCIPallocBufferArray(scip, &probvars, nbinprobvars) );
3130  SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nbinprobvars) );
3131  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nbinprobvars) );
3132  SCIP_CALL( SCIPallocCleanBufferArray(scip, &redundants, nbinprobvars) );
3133 
3134  for( c = nconss - 1; c >= 0; --c )
3135  {
3136  SCIP_Bool redundant = FALSE;
3137  SCIP_Bool glbinfeas = FALSE;
3138  SCIP_CONS* cons = conss[c];
3139  SCIP_CONSDATA* consdata;
3140 
3141  assert(cons != NULL);
3142 
3143  if( SCIPconsIsDeleted(cons) )
3144  continue;
3145 
3146  consdata = SCIPconsGetData(cons);
3147  assert(consdata != NULL);
3148 
3149  /* prepare constraint by removing fixings and merge it */
3150  SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
3151 
3152  if( redundant )
3153  {
3154  assert(SCIPconsIsDeleted(cons));
3155  continue;
3156  }
3157 
3158  if( *cutoff )
3159  goto TERMINATE;
3160 
3161  assert(consdata->nvars >= 2);
3162 
3163  /* do not try to shorten too long constraints */
3164  if( consdata->nvars > MAX_CONSLENGTH )
3165  continue;
3166 
3167  /* form necessary data */
3168  for( v = consdata->nvars - 1; v >= 0; --v)
3169  {
3170  var = consdata->vars[v];
3171  assert(var != NULL);
3173 
3174  if( SCIPvarIsActive(var) )
3175  {
3176  probvars[v] = var;
3177  bounds[v] = 1.0;
3178  boundtypes[v] = FALSE;
3179  }
3180  else
3181  {
3182  probvars[v] = SCIPvarGetNegationVar(var);
3183  bounds[v] = 0.0;
3184  boundtypes[v] = TRUE;
3185  }
3186  }
3187 
3188  SCIP_CALL( SCIPcleanupCliques(scip, cutoff) );
3189 
3190  if( *cutoff )
3191  goto TERMINATE;
3192 
3193  /* use implications and cliques to derive global fixings and to shrink the number of variables in this constraints */
3194  SCIP_CALL( SCIPshrinkDisjunctiveVarSet(scip, probvars, bounds, boundtypes, redundants, consdata->nvars, &nredvars,
3195  nfixedvars, &redundant, &glbinfeas, TRUE) );
3196 
3197  if( glbinfeas )
3198  goto TERMINATE;
3199 
3200  /* remove redundant constraint */
3201  if( redundant )
3202  {
3203  SCIP_CALL( SCIPdelCons(scip, cons) );
3204  ++(*ndelconss);
3205 
3206  /* reset redundants array to FALSE */
3207 #if 1
3208  BMSclearMemoryArray(redundants, consdata->nvars);
3209 #else
3210  if( nredvars > 0 )
3211  {
3212  for( v = consdata->nvars - 1; v >= 0; --v )
3213  {
3214  if( redundants[v] )
3215  {
3216  redundants[v] = FALSE;
3217  }
3218  }
3219  }
3220 #endif
3221  continue;
3222  }
3223 
3224  /* remove redundant variables */
3225  if( nredvars > 0 )
3226  {
3227  for( v = consdata->nvars - 1; v >= 0; --v )
3228  {
3229  if( redundants[v] )
3230  {
3231  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
3232 
3233  /* reset entry to FALSE */
3234  redundants[v] = FALSE;
3235  }
3236  }
3237  *nchgcoefs += nredvars;
3238 
3239  /* if only one variable is left over fix it */
3240  if( consdata->nvars == 1 )
3241  {
3242  SCIP_Bool infeasible;
3243  SCIP_Bool fixed;
3244 
3245  SCIPdebugMsg(scip, " -> fix last remaining variable and delete constraint\n");
3246 
3247  SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
3248  assert(!infeasible);
3249  assert(fixed);
3250  ++(*nfixedvars);
3251 
3252  SCIP_CALL( SCIPdelCons(scip, cons) );
3253  ++(*ndelconss);
3254  }
3255  /* @todo might also upgrade a two variable constraint to a set-packing constraint */
3256  }
3257  }
3258 
3259  TERMINATE:
3260  /* free temporary memory */
3261  SCIPfreeCleanBufferArray(scip, &redundants);
3262  SCIPfreeBufferArray(scip, &boundtypes);
3263  SCIPfreeBufferArray(scip, &bounds);
3264  SCIPfreeBufferArray(scip, &probvars);
3265 
3266  return SCIP_OKAY;
3267 }
3268 
3269 #define MAXCOMPARISONS 1000000
3270 
3271 /** try to find a negated clique in a constraint which makes this constraint redundant but we need to keep the negated
3272  * clique information alive, so we create a corresponding set-packing constraint
3273  */
3274 static
3276  SCIP* scip, /**< SCIP data structure */
3277  SCIP_CONSHDLR* conshdlr, /**< logicor constraint handler */
3278  SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
3279  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
3280  SCIP_CONS** conss, /**< all constraints */
3281  int nconss, /**< number of constraints */
3282  unsigned char** entries, /**< array to store whether two positions in constraints represent the same
3283  * variable */
3284  int* nentries, /**< pointer for array size, if array will be to small it's corrected */
3285  int* nfixedvars, /**< pointer to count number of fixings */
3286  int* ndelconss, /**< pointer to count number of deleted constraints */
3287  int* nupgdconss, /**< pointer to count number of upgraded constraints */
3288  int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
3289  SCIP_Bool* cutoff /**< pointer to store, if cut off appeared */
3290  )
3291 {
3292  SCIP_CONSHDLRDATA* conshdlrdata;
3293  SCIP_CONS* cons;
3294  SCIP_CONSDATA* consdata;
3295  SCIP_VAR** repvars;
3296  SCIP_Bool* negated;
3297  SCIP_VAR* var1;
3298  SCIP_Bool redundant;
3299  int c;
3300  int size;
3301  int maxcomppercons;
3302  int comppercons;
3303 
3304  assert(scip != NULL);
3305  assert(conshdlr != NULL);
3306  assert(eventhdlr != NULL);
3307  assert(conss != NULL || nconss == 0);
3308  assert(entries != NULL);
3309  assert(*entries != NULL);
3310  assert(nentries != NULL);
3311  assert(nfixedvars != NULL);
3312  assert(ndelconss != NULL);
3313  assert(nupgdconss != NULL);
3314  assert(nchgcoefs != NULL);
3315  assert(cutoff != NULL);
3316 
3317  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3318  assert(conshdlrdata != NULL);
3319 
3320  if( nconss == 0 )
3321  return SCIP_OKAY;
3322 
3323  if( SCIPgetNCliques(scip) == conshdlrdata->nlastcliquesneg && SCIPgetNImplications(scip) == conshdlrdata->nlastimplsneg )
3324  return SCIP_OKAY;
3325 
3326  conshdlrdata->nlastcliquesneg = SCIPgetNCliques(scip);
3327  conshdlrdata->nlastimplsneg = SCIPgetNImplications(scip);
3328 
3329  /* estimate the maximal number of variables in a logicor constraint */
3330  size = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
3331  if( size <= 0 )
3332  return SCIP_OKAY;
3333 
3334  /* temporary memory for active/negation of active variables */
3335  SCIP_CALL( SCIPallocBufferArray(scip, &repvars, size) );
3336  SCIP_CALL( SCIPallocBufferArray(scip, &negated, size) );
3337 
3338  /* iterate over all constraints and try to find negated cliques in logicors */
3339  for( c = nconss - 1; c >= 0; --c )
3340  {
3341  int v;
3342 
3343  assert(conss != NULL); /* for flexelint */
3344 
3345  cons = conss[c];
3346  assert(cons != NULL);
3347 
3348  if( !SCIPconsIsActive(cons) )
3349  continue;
3350 
3351  /* prepare constraint by removing fixings and merge it */
3352  SCIP_CALL( prepareCons(scip, cons, eventhdlr, entries, nentries, &redundant, nfixedvars, nchgcoefs, ndelconss, cutoff) );
3353 
3354  if( redundant )
3355  {
3356  assert(SCIPconsIsDeleted(cons));
3357  continue;
3358  }
3359 
3360  if( *cutoff )
3361  goto TERMINATE;
3362 
3363  consdata = SCIPconsGetData(cons);
3364  assert(consdata != NULL);
3365  assert(consdata->nvars >= 2);
3366  assert(consdata->nvars <= size);
3367  assert(consdata->presolved);
3368 
3369  if( SCIPconsIsModifiable(cons) && consdata->nvars == 2 )
3370  continue;
3371 
3372  if( c % 100 == 0 && SCIPisStopped(scip) )
3373  break;
3374 
3375  maxcomppercons = MAXCOMPARISONS / nconss;
3376  comppercons = 0;
3377 
3378  BMScopyMemoryArray(repvars, consdata->vars, consdata->nvars);
3379 
3380  /* all variables should be active or negative active variables, otherwise something went wrong with applyFixings()
3381  * called before mergeMultiples()
3382  */
3383  for( v = consdata->nvars - 1; v >= 0; --v )
3384  {
3385  assert(SCIPvarIsActive(repvars[v]) || (SCIPvarGetStatus(repvars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
3386  negated[v] = SCIPvarIsNegated(repvars[v]);
3387  }
3388 
3389  for( v = consdata->nvars - 1; v > 0; --v )
3390  {
3391  SCIP_Bool breakloop;
3392  SCIP_Bool neg1;
3393  int w;
3394 
3395  var1 = repvars[v];
3396 
3397  /* if there is no negated variable, there can't be a negated clique */
3398  if( SCIPvarGetNegatedVar(var1) == NULL )
3399  continue;
3400 
3401  /* get active counterpart to check for common cliques */
3403  {
3404  var1 = SCIPvarGetNegatedVar(var1);
3405  neg1 = TRUE;
3406  }
3407  else
3408  neg1 = FALSE;
3409 
3410  if( !SCIPvarIsActive(var1) )
3411  continue;
3412 
3413  /* no cliques available */
3414  if( SCIPvarGetNCliques(var1, neg1) == 0 && SCIPvarGetNImpls(var1, neg1) == 0 )
3415  continue;
3416 
3417  comppercons += (v - 1);
3418 
3419  breakloop = FALSE;
3420 
3421  for( w = v - 1; w >= 0; --w )
3422  {
3423  SCIP_VAR* var2;
3424  SCIP_Bool neg2;
3425 
3426  var2 = repvars[w];
3427 
3428  /* if there is no negated variable, there can't be a negated clique */
3429  if( SCIPvarGetNegatedVar(var2) == NULL )
3430  continue;
3431 
3433  {
3434  var2 = SCIPvarGetNegatedVar(var2);
3435  neg2 = TRUE;
3436  }
3437  else
3438  neg2 = FALSE;
3439 
3440  if( !SCIPvarIsActive(var2) )
3441  continue;
3442 
3443  /* no cliques available */
3444  if( SCIPvarGetNCliques(var2, neg2) == 0 && SCIPvarGetNImpls(var2, neg2) == 0 )
3445  continue;
3446 
3447  /* check if both active variable are the same */
3448  if( var1 == var2 )
3449  {
3450  if( neg1 != neg2 )
3451  {
3452  SCIPdebugMsg(scip, "logicor constraint <%s> is redundant, because variable <%s> and its negation <%s> exist\n",
3453  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
3454 
3455  SCIP_CALL( SCIPdelCons(scip, cons) );
3456 
3457  breakloop = TRUE;
3458  }
3459  else
3460  {
3461  #ifndef NDEBUG
3462  SCIP_VAR* lastvar = consdata->vars[consdata->nvars - 1];
3463  #endif
3464  SCIPdebugMsg(scip, "in logicor constraint <%s>, active variable of <%s> and active variable of <%s> are the same, removing the first\n",
3465  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
3466 
3467  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
3468 
3469  if( v < consdata->nvars )
3470  {
3471  /* delCoefPos replaces the variable on position v with the last one, so w also need to correct the
3472  * negated array the same way, and because of deletion the number of variables is already decreased
3473  */
3474  assert(consdata->vars[v] == lastvar);
3475  negated[v] = negated[consdata->nvars];
3476  }
3477  ++(*nchgcoefs);
3478  }
3479  break;
3480  }
3481 
3482  if( SCIPvarsHaveCommonClique(var1, neg1, var2, neg2, TRUE) && conshdlrsetppc != NULL )
3483  {
3484  SCIP_CONS* newcons;
3485  SCIP_VAR* vars[2];
3486 
3487  /* this negated clique information could be created out of this logicor constraint even if there are more
3488  * than two variables left (, for example by probing), we need to keep this information by creating a
3489  * setppc constraint instead
3490  */
3491 
3492  /* get correct variables */
3493  if( !neg1 )
3494  vars[0] = SCIPvarGetNegatedVar(var1);
3495  else
3496  vars[0] = var1;
3497 
3498  if( !neg2 )
3499  vars[1] = SCIPvarGetNegatedVar(var2);
3500  else
3501  vars[1] = var2;
3502 
3503  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
3506  SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons),
3508 
3509  SCIP_CALL( SCIPaddCons(scip, newcons) );
3510  SCIPdebugPrintCons(scip, newcons, NULL);
3511 
3512  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3513 
3514  SCIPdebugMsg(scip, "logicor constraint <%s> is redundant due to negated clique information and will be replaced by a setppc constraint \n",
3515  SCIPconsGetName(cons));
3516  SCIPdebugMsg(scip, "variable <%s> and variable <%s> are in a negated clique\n", SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[w]));
3517 
3518  SCIP_CALL( SCIPdelCons(scip, cons) );
3519  ++(*nupgdconss);
3520 
3521  breakloop = TRUE;
3522  break;
3523  }
3524  }
3525  if( breakloop )
3526  break;
3527 
3528  /* do not do to many comparisons */
3529  if( comppercons > maxcomppercons )
3530  break;
3531  }
3532  }
3533 
3534  TERMINATE:
3535  /* free temporary memory */
3536  SCIPfreeBufferArray(scip, &negated);
3537  SCIPfreeBufferArray(scip, &repvars);
3538 
3539  return SCIP_OKAY;
3540 }
3541 
3542 /** handle all cases with less than three variables in a logicor constraint
3543  *
3544  * in case a constraint has zero variables left, we detected infeasibility
3545  * in case a constraint has one variables left, we will fix it to one
3546  * in case a constraint has two variables left, we will add the implication and upgrade it to a set-packing constraint
3547  */
3548 static
3550  SCIP* scip, /**< SCIP data structure */
3551  SCIP_CONS* cons, /**< logic or constraint */
3552  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
3553  SCIP_CONSHDLR* conshdlrlinear, /**< linear constraint handler, or NULL */
3554  SCIP_CONSHDLR* conshdlrsetppc, /**< setppc constraint handler, or NULL */
3555  int* nfixedvars, /**< pointer to count number of fixings */
3556  int* nchgbds, /**< pointer to count number of tightened bounds */
3557  int* nchgcoefs, /**< pointer to count number of changed/deleted coefficients */
3558  int* ndelconss, /**< pointer to count number of deleted constraints */
3559  int* naddconss, /**< pointer to count number of added constraints */
3560  int* nupgdconss, /**< pointer to count number of upgraded constraints */
3561  SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
3562  )
3563 {
3564  SCIP_CONSDATA* consdata;
3565  SCIP_Bool infeasible;
3566  SCIP_Bool fixed;
3567 
3568  assert(scip != NULL);
3569  assert(cons != NULL);
3570  assert(eventhdlr != NULL);
3571  assert(nfixedvars != NULL);
3572  assert(nchgbds != NULL);
3573  assert(nchgcoefs != NULL);
3574  assert(ndelconss != NULL);
3575  assert(naddconss != NULL);
3576  assert(nupgdconss != NULL);
3577  assert(cutoff != NULL);
3578 
3579  *cutoff = FALSE;
3580 
3581  if( SCIPconsIsModifiable(cons) )
3582  return SCIP_OKAY;
3583 
3584  consdata = SCIPconsGetData(cons);
3585  assert(consdata != NULL);
3586 
3587  /* if an unmodifiable logicor constraint has only two variables, we can add an implication and we will upgrade this
3588  * constraint to a set-packing constraint
3589  */
3590  if( consdata->nvars == 2 )
3591  {
3592  /* add implication if not yet done */
3593  if( !consdata->impladded )
3594  {
3595  SCIP_Bool implinfeasible;
3596  int nimplbdchgs;
3597  SCIP_Bool values[2];
3598 
3599  values[0] = FALSE;
3600  values[1] = FALSE;
3601  /* a two-variable logicor constraint x + y >= 1 yields the implication x == 0 -> y == 1, and is represented
3602  * by the clique inequality ~x + ~y <= 1
3603  */
3604  SCIP_CALL( SCIPaddClique(scip, consdata->vars, values, consdata->nvars, FALSE, &implinfeasible, &nimplbdchgs) );
3605  *nchgbds += nimplbdchgs;
3606  if( implinfeasible )
3607  {
3608  *cutoff = TRUE;
3609  return SCIP_OKAY;
3610  }
3611 
3612  /* adding the above implication could lead to fixings, which render the constraint redundant */
3613  if ( nimplbdchgs > 0 )
3614  {
3615  SCIP_Bool redundant;
3616 
3617  /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
3618  SCIP_CALL( applyFixings(scip, cons, eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
3619  assert(!SCIPconsIsDeleted(cons));
3620 
3621  if( redundant )
3622  {
3623  SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
3624 
3625  SCIP_CALL( SCIPdelCons(scip, cons) );
3626  (*ndelconss)++;
3627 
3628  return SCIP_OKAY;
3629  }
3630  }
3631  consdata->impladded = TRUE;
3632  }
3633 
3634  /* still we have two variables left, we will upgrade this constraint */
3635  if( consdata->nvars == 2 && conshdlrsetppc != NULL )
3636  {
3637  SCIP_CONS* newcons;
3638  SCIP_VAR* vars[2];
3639 
3640 
3641  /* get correct variables */
3642  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[0], &vars[0]) );
3643  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[1], &vars[1]) );
3644 
3645  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
3650 
3651  SCIP_CALL( SCIPaddCons(scip, newcons) );
3652  SCIPdebugPrintCons(scip, newcons, NULL);
3653 
3654  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3655 
3656  SCIPdebugMsg(scip, "logicor constraint <%s> was upgraded to a set-packing constraint\n", SCIPconsGetName(cons));
3657 
3658  SCIP_CALL( SCIPdelCons(scip, cons) );
3659  ++(*nupgdconss);
3660  }
3661  }
3662 
3663  /* if unmodifiable constraint has no variables, it is infeasible,
3664  * if unmodifiable constraint has only one variable, this one can be fixed and the constraint deleted
3665  */
3666  if( consdata->nvars == 0 )
3667  {
3668  SCIPdebugMsg(scip, "logic or constraint <%s> is infeasible\n", SCIPconsGetName(cons));
3669 
3670  *cutoff = TRUE;
3671  }
3672  else if( consdata->nvars == 1 )
3673  {
3674  SCIPdebugMsg(scip, "logic or constraint <%s> has only one variable not fixed to 0.0\n",
3675  SCIPconsGetName(cons));
3676 
3677  assert(consdata->vars != NULL);
3678  assert(consdata->vars[0] != NULL);
3679 
3680  if( SCIPvarGetStatus(consdata->vars[0]) != SCIP_VARSTATUS_MULTAGGR )
3681  {
3682  SCIPdebugMsg(scip, " -> fix variable and delete constraint\n");
3683 
3684  SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
3685  if( infeasible )
3686  {
3687  SCIPdebugMsg(scip, " -> infeasible fixing\n");
3688 
3689  *cutoff = TRUE;
3690  return SCIP_OKAY;
3691  }
3692  if( fixed )
3693  (*nfixedvars)++;
3694 
3695  SCIP_CALL( SCIPdelCons(scip, cons) );
3696  (*ndelconss)++;
3697  }
3698  else if( conshdlrlinear != NULL )
3699  {
3700  SCIP_Real coef;
3701  SCIP_CONS* conslinear;
3702  char consname[SCIP_MAXSTRLEN];
3703 
3704  SCIPdebugMsg(scip, " -> variable is multi-aggregated, upgrade to linear constraint <%s> == 1 \n",
3705  SCIPvarGetName(consdata->vars[0]));
3706 
3707  coef = 1.0;
3708  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "fixmaggr_%s_%s", SCIPconsGetName(cons),SCIPvarGetName(consdata->vars[0]) );
3709  SCIP_CALL( SCIPcreateConsLinear(scip, &conslinear, consname, 1, consdata->vars, &coef, 1.0, 1.0,
3713  SCIPconsIsStickingAtNode(cons)) );
3714 
3715  /* add constraint */
3716  SCIP_CALL( SCIPaddCons(scip, conslinear) );
3717  SCIP_CALL( SCIPreleaseCons(scip, &conslinear) );
3718  SCIP_CALL( SCIPdelCons(scip, cons) );
3719 
3720  (*ndelconss)++;
3721  (*naddconss)++;
3722  }
3723  }
3724 
3725  return SCIP_OKAY;
3726 }
3727 
3728 
3729 /*
3730  * upgrading of linear constraints
3731  */
3732 
3733 /** creates and captures a normalized (with all coefficients +1) logic or constraint */
3734 static
3736  SCIP* scip, /**< SCIP data structure */
3737  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3738  const char* name, /**< name of constraint */
3739  int nvars, /**< number of variables in the constraint */
3740  SCIP_VAR** vars, /**< array with variables of constraint entries */
3741  SCIP_Real* vals, /**< array with coefficients (+1.0 or -1.0) */
3742  int mult, /**< multiplier on the coefficients(+1 or -1) */
3743  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3744  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3745  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3746  * Usually set to TRUE. */
3747  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3748  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3749  SCIP_Bool check, /**< should the constraint be checked for feasibility?
3750  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3751  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3752  * Usually set to TRUE. */
3753  SCIP_Bool local, /**< is constraint only valid locally?
3754  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3755  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3756  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3757  * adds coefficients to this constraint. */
3758  SCIP_Bool dynamic, /**< is constraint subject to aging?
3759  * Usually set to FALSE. Set to TRUE for own cuts which
3760  * are separated as constraints. */
3761  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3762  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3763  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3764  * if it may be moved to a more global node?
3765  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3766  )
3767 {
3768  SCIP_VAR** transvars;
3769  int v;
3770 
3771  assert(nvars == 0 || vars != NULL);
3772  assert(nvars == 0 || vals != NULL);
3773  assert(mult == +1 || mult == -1);
3774 
3775  /* get temporary memory */
3776  SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
3777 
3778  /* negate positive or negative variables */
3779  for( v = 0; v < nvars; ++v )
3780  {
3781  if( mult * vals[v] > 0.0 )
3782  transvars[v] = vars[v];
3783  else
3784  {
3785  SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
3786  }
3787  assert(transvars[v] != NULL);
3788  }
3789 
3790  /* create the constraint */
3791  SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, transvars,
3792  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3793 
3794  /* free temporary memory */
3795  SCIPfreeBufferArray(scip, &transvars);
3796 
3797  return SCIP_OKAY;
3798 }
3799 
3800 static
3801 SCIP_DECL_LINCONSUPGD(linconsUpgdLogicor)
3802 { /*lint --e{715}*/
3803  assert(upgdcons != NULL);
3804 
3805  /* check, if linear constraint can be upgraded to logic or constraint
3806  * - logic or constraints consist only of binary variables with a
3807  * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
3808  * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
3809  * - negating all variables y = (1-Y) with negative coefficients gives:
3810  * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
3811  * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
3812  * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
3813  * - logic or constraints have left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
3814  * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
3815  */
3816  if( nvars > 2 && nposbin + nnegbin + nposimplbin + nnegimplbin == nvars && ncoeffspone + ncoeffsnone == nvars
3817  && ((SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, rhs))
3818  || (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, ncoeffspone - 1.0))) )
3819  {
3820  int mult;
3821 
3822  SCIPdebugMsg(scip, "upgrading constraint <%s> to logic or constraint\n", SCIPconsGetName(cons));
3823 
3824  /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
3825  mult = SCIPisInfinity(scip, rhs) ? +1 : -1;
3826 
3827  /* create the logic or constraint (an automatically upgraded constraint is always unmodifiable) */
3828  assert(!SCIPconsIsModifiable(cons));
3829  SCIP_CALL( createNormalizedLogicor(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
3834  }
3835 
3836  return SCIP_OKAY;
3837 }
3838 
3839 /** helper function to enforce constraints */
3840 static
3842  SCIP* scip, /**< SCIP data structure */
3843  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3844  SCIP_CONS** conss, /**< constraints to process */
3845  int nconss, /**< number of constraints */
3846  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
3847  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
3848  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
3849  )
3850 {
3851  SCIP_CONSHDLRDATA* conshdlrdata;
3852  SCIP_Bool cutoff;
3853  SCIP_Bool separated;
3854  SCIP_Bool reduceddom;
3855  int c;
3856 
3857  assert(conshdlr != NULL);
3858  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3859  assert(nconss == 0 || conss != NULL);
3860  assert(result != NULL);
3861 
3862  SCIPdebugMsg(scip, "Enforcing %d logic or constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
3863 
3864  *result = SCIP_FEASIBLE;
3865 
3866  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3867  assert(conshdlrdata != NULL);
3868 
3869  cutoff = FALSE;
3870  separated = FALSE;
3871  reduceddom = FALSE;
3872 
3873  /* check all useful logic or constraints for feasibility */
3874  for( c = 0; c < nusefulconss && !cutoff && !reduceddom; ++c )
3875  {
3876  SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
3877  }
3878 
3879  /* check all obsolete logic or constraints for feasibility */
3880  for( c = nusefulconss; c < nconss && !cutoff && !separated && !reduceddom; ++c )
3881  {
3882  SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
3883  }
3884 
3885  /* return the correct result */
3886  if( cutoff )
3887  *result = SCIP_CUTOFF;
3888  else if( separated )
3889  *result = SCIP_SEPARATED;
3890  else if( reduceddom )
3891  *result = SCIP_REDUCEDDOM;
3892 
3893  return SCIP_OKAY;
3894 }
3895 
3896 
3897 /*
3898  * Callback methods of constraint handler
3899  */
3900 
3901 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
3902 static
3903 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLogicor)
3904 { /*lint --e{715}*/
3905  assert(scip != NULL);
3906  assert(conshdlr != NULL);
3907  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3908 
3909  /* call inclusion method of constraint handler */
3911 
3912  *valid = TRUE;
3913 
3914  return SCIP_OKAY;
3915 }
3916 
3917 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
3918 static
3919 SCIP_DECL_CONSFREE(consFreeLogicor)
3920 { /*lint --e{715}*/
3921  SCIP_CONSHDLRDATA* conshdlrdata;
3922 
3923  assert(conshdlr != NULL);
3924  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3925  assert(scip != NULL);
3926 
3927  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3928  assert(conshdlrdata != NULL);
3929 
3930  /* free constraint handler data */
3931  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
3932 
3933  SCIPconshdlrSetData(conshdlr, NULL);
3934 
3935  return SCIP_OKAY;
3936 }
3937 
3938 
3939 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
3940 static
3941 SCIP_DECL_CONSINITPRE(consInitpreLogicor)
3942 { /*lint --e{715}*/
3943  SCIP_CONSHDLRDATA* conshdlrdata;
3944  SCIP_CONSDATA* consdata;
3945  int c;
3946  int v;
3947 
3948  assert(conshdlr != NULL);
3949  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3950  assert(conshdlrdata != NULL);
3951 
3952  conshdlrdata->nlastcliquesneg = 0;
3953  conshdlrdata->nlastimplsneg = 0;
3954  conshdlrdata->nlastcliquesshorten = 0;
3955  conshdlrdata->nlastimplsshorten = 0;
3956 
3957  /* catch all variable event for deleted variables, which is only used in presolving */
3958  for( c = nconss - 1; c >= 0; --c )
3959  {
3960  consdata = SCIPconsGetData(conss[c]);
3961  assert(consdata != NULL);
3962 
3963  for( v = consdata->nvars - 1; v >= 0; --v )
3964  {
3965  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
3966  (SCIP_EVENTDATA*)conss[c], NULL) );
3967  }
3968  }
3969 
3970  return SCIP_OKAY;
3971 }
3972 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
3973 static
3974 SCIP_DECL_CONSEXITPRE(consExitpreLogicor)
3975 { /*lint --e{715}*/
3976  SCIP_CONSHDLRDATA* conshdlrdata;
3977  SCIP_CONSDATA* consdata;
3978  SCIP_Bool redundant;
3979  int nchgcoefs = 0;
3980  int c;
3981  int v;
3982 
3983  assert(conshdlr != NULL);
3984  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3985  assert(conshdlrdata != NULL);
3986 
3987  /* drop all variable event for deleted variables, which was only used in presolving */
3988  for( c = 0; c < nconss; ++c )
3989  {
3990  consdata = SCIPconsGetData(conss[c]);
3991  assert(consdata != NULL);
3992 
3993  for( v = 0; v < consdata->nvars; ++v )
3994  {
3995  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
3996  (SCIP_EVENTDATA*)conss[c], -1) );
3997  }
3998 
3999  if( !SCIPconsIsDeleted(conss[c]) && !consdata->presolved )
4000  {
4001  /* we are not allowed to detect infeasibility in the exitpre stage */
4002  SCIP_CALL( applyFixings(scip, conss[c], conshdlrdata->eventhdlr, &redundant, &nchgcoefs, NULL, NULL) );
4003  }
4004  }
4005 
4006  return SCIP_OKAY;
4007 }
4008 
4009 
4010 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4011 static
4012 SCIP_DECL_CONSEXITSOL(consExitsolLogicor)
4013 { /*lint --e{715}*/
4014  SCIP_CONSDATA* consdata;
4015  int c;
4016 
4017  /* release the rows of all constraints */
4018  for( c = 0; c < nconss; ++c )
4019  {
4020  consdata = SCIPconsGetData(conss[c]);
4021  assert(consdata != NULL);
4022 
4023  if( consdata->row != NULL )
4024  {
4025  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
4026  }
4027  }
4028 
4029  return SCIP_OKAY;
4030 }
4031 
4032 
4033 /** frees specific constraint data */
4034 static
4035 SCIP_DECL_CONSDELETE(consDeleteLogicor)
4036 { /*lint --e{715}*/
4037  assert(conshdlr != NULL);
4038  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4039  assert(consdata != NULL);
4040  assert(*consdata != NULL);
4041 
4043  {
4044  SCIP_CONSHDLRDATA* conshdlrdata;
4045  int v;
4046 
4047  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4048  assert(conshdlrdata != NULL);
4049 
4050  for( v = (*consdata)->nvars - 1; v >= 0; --v )
4051  {
4052  SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
4053  (SCIP_EVENTDATA*)cons, -1) );
4054  }
4055  }
4056 
4057  /* free LP row and logic or constraint */
4058  SCIP_CALL( consdataFree(scip, consdata) );
4059 
4060  return SCIP_OKAY;
4061 }
4062 
4063 
4064 /** transforms constraint data into data belonging to the transformed problem */
4065 static
4066 SCIP_DECL_CONSTRANS(consTransLogicor)
4067 { /*lint --e{715}*/
4068  SCIP_CONSDATA* sourcedata;
4069  SCIP_CONSDATA* targetdata;
4070 
4071  /*debugMsg(scip, "Trans method of logic or constraints\n");*/
4072 
4073  assert(conshdlr != NULL);
4074  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4075  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
4076  assert(sourcecons != NULL);
4077  assert(targetcons != NULL);
4078 
4079  sourcedata = SCIPconsGetData(sourcecons);
4080  assert(sourcedata != NULL);
4081  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
4082 
4083  /* create constraint data for target constraint */
4084  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars) );
4085 
4086  /* create target constraint */
4087  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
4088  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
4089  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
4090  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
4091  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
4092 
4093  return SCIP_OKAY;
4094 }
4095 
4096 
4097 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
4098 static
4099 SCIP_DECL_CONSINITLP(consInitlpLogicor)
4100 { /*lint --e{715}*/
4101  int c;
4102 
4103  *infeasible = FALSE;
4104 
4105  for( c = 0; c < nconss && !(*infeasible); ++c )
4106  {
4107  assert(SCIPconsIsInitial(conss[c]));
4108  SCIP_CALL( addCut(scip, conss[c], infeasible) );
4109  }
4110 
4111  return SCIP_OKAY;
4112 }
4113 
4114 
4115 /** separation method of constraint handler for LP solutions */
4116 static
4117 SCIP_DECL_CONSSEPALP(consSepalpLogicor)
4118 { /*lint --e{715}*/
4119  SCIP_CONSHDLRDATA* conshdlrdata;
4120  SCIP_Bool cutoff;
4121  SCIP_Bool separated;
4122  SCIP_Bool reduceddom;
4123  int c;
4124 
4125  assert(conshdlr != NULL);
4126  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4127  assert(nconss == 0 || conss != NULL);
4128  assert(result != NULL);
4129 
4130  SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
4131 
4132  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4133  assert(conshdlrdata != NULL);
4134 
4135  cutoff = FALSE;
4136  separated = FALSE;
4137  reduceddom = FALSE;
4138 
4139  /* check all useful logic or constraints for feasibility */
4140  for( c = 0; c < nusefulconss && !cutoff; ++c )
4141  {
4142  SCIP_CALL( separateCons(scip, conss[c], NULL, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
4143  }
4144 
4145  /* combine logic or constraints to get more cuts */
4146  /**@todo further cuts of logic or constraints */
4147 
4148  /* return the correct result */
4149  if( cutoff )
4150  *result = SCIP_CUTOFF;
4151  else if( reduceddom )
4152  *result = SCIP_REDUCEDDOM;
4153  else if( separated )
4154  *result = SCIP_SEPARATED;
4155  else
4156  *result = SCIP_DIDNOTFIND;
4157 
4158  return SCIP_OKAY;
4159 }
4160 
4161 
4162 /** separation method of constraint handler for arbitrary primal solutions */
4163 static
4164 SCIP_DECL_CONSSEPASOL(consSepasolLogicor)
4165 { /*lint --e{715}*/
4166  SCIP_CONSHDLRDATA* conshdlrdata;
4167  SCIP_Bool cutoff;
4168  SCIP_Bool separated;
4169  SCIP_Bool reduceddom;
4170  int c;
4171 
4172  assert(conshdlr != NULL);
4173  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4174  assert(nconss == 0 || conss != NULL);
4175  assert(result != NULL);
4176 
4177  SCIPdebugMsg(scip, "separating %d/%d logic or constraints\n", nusefulconss, nconss);
4178 
4179  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4180  assert(conshdlrdata != NULL);
4181 
4182  cutoff = FALSE;
4183  separated = FALSE;
4184  reduceddom = FALSE;
4185 
4186  /* check all useful logic or constraints for feasibility */
4187  for( c = 0; c < nusefulconss && !cutoff; ++c )
4188  {
4189  SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &separated, &reduceddom) );
4190  }
4191 
4192  /* combine logic or constraints to get more cuts */
4193  /**@todo further cuts of logic or constraints */
4194 
4195  /* return the correct result */
4196  if( cutoff )
4197  *result = SCIP_CUTOFF;
4198  else if( reduceddom )
4199  *result = SCIP_REDUCEDDOM;
4200  else if( separated )
4201  *result = SCIP_SEPARATED;
4202  else
4203  *result = SCIP_DIDNOTFIND;
4204 
4205  return SCIP_OKAY;
4206 }
4207 
4208 
4209 /** constraint enforcing method of constraint handler for LP solutions */
4210 static
4211 SCIP_DECL_CONSENFOLP(consEnfolpLogicor)
4212 { /*lint --e{715}*/
4213  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
4214 
4215  return SCIP_OKAY;
4216 }
4217 
4218 
4219 /** constraint enforcing method of constraint handler for relaxation solutions */
4220 static
4221 SCIP_DECL_CONSENFORELAX(consEnforelaxLogicor)
4222 { /*lint --e{715}*/
4223  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
4224 
4225  return SCIP_OKAY;
4226 }
4227 
4228 
4229 /** constraint enforcing method of constraint handler for pseudo solutions */
4230 static
4231 SCIP_DECL_CONSENFOPS(consEnfopsLogicor)
4232 { /*lint --e{715}*/
4233  SCIP_CONSHDLRDATA* conshdlrdata;
4234  SCIP_Bool cutoff;
4235  SCIP_Bool infeasible;
4236  SCIP_Bool reduceddom;
4237  SCIP_Bool solvelp;
4238  int c;
4239 
4240  assert(conshdlr != NULL);
4241  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4242  assert(nconss == 0 || conss != NULL);
4243  assert(result != NULL);
4244 
4245  SCIPdebugMsg(scip, "pseudo enforcing %d logic or constraints\n", nconss);
4246 
4247  *result = SCIP_FEASIBLE;
4248 
4249  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4250  assert(conshdlrdata != NULL);
4251 
4252  cutoff = FALSE;
4253  infeasible = FALSE;
4254  reduceddom = FALSE;
4255  solvelp = FALSE;
4256 
4257  /* check all logic or constraints for feasibility */
4258  for( c = 0; c < nconss && !cutoff && !reduceddom && !solvelp; ++c )
4259  {
4260  SCIP_CALL( enforcePseudo(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &infeasible, &reduceddom, &solvelp) );
4261  }
4262 
4263  if( cutoff )
4264  *result = SCIP_CUTOFF;
4265  else if( reduceddom )
4266  *result = SCIP_REDUCEDDOM;
4267  else if( solvelp )
4268  *result = SCIP_SOLVELP;
4269  else if( infeasible )
4270  *result = SCIP_INFEASIBLE;
4271 
4272  return SCIP_OKAY;
4273 }
4274 
4275 
4276 /** feasibility check method of constraint handler for integral solutions */
4277 static
4278 SCIP_DECL_CONSCHECK(consCheckLogicor)
4279 { /*lint --e{715}*/
4280  SCIP_CONS* cons;
4281  SCIP_CONSDATA* consdata;
4282  int c;
4283 
4284  assert(conshdlr != NULL);
4285  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4286  assert(nconss == 0 || conss != NULL);
4287  assert(result != NULL);
4288 
4289  *result = SCIP_FEASIBLE;
4290 
4291  /* check all logic or constraints for feasibility */
4292  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
4293  {
4294  cons = conss[c];
4295  consdata = SCIPconsGetData(cons);
4296  assert(consdata != NULL);
4297  if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
4298  {
4299  SCIP_Bool violated;
4300 
4301  SCIP_CALL( checkCons(scip, cons, sol, &violated) );
4302  if( violated )
4303  {
4304  /* constraint is violated */
4305  *result = SCIP_INFEASIBLE;
4306 
4307  if( printreason )
4308  {
4309 #ifndef NDEBUG
4310  int v;
4311  for( v = 0; v < consdata->nvars; ++v )
4312  {
4313  assert( consdata->vars[v] != NULL);
4314  assert( SCIPvarIsBinary(consdata->vars[v]) );
4315  assert( SCIPisFeasLT(scip, SCIPgetSolVal(scip, sol, consdata->vars[v]), 1.0) );
4316  }
4317 #endif
4318  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
4319  SCIPinfoMessage(scip, NULL, ";\n");
4320  SCIPinfoMessage(scip, NULL, "violation: all variables are set to zero\n");
4321  }
4322  }
4323  }
4324  }
4325 
4326  return SCIP_OKAY;
4327 }
4328 
4329 
4330 /** domain propagation method of constraint handler */
4331 static
4332 SCIP_DECL_CONSPROP(consPropLogicor)
4333 { /*lint --e{715}*/
4334  SCIP_CONSHDLRDATA* conshdlrdata;
4335  SCIP_Bool cutoff;
4336  SCIP_Bool reduceddom;
4337  SCIP_Bool addcut;
4338  SCIP_Bool mustcheck;
4339  int c;
4340 #ifndef NDEBUG
4341  SCIP_Bool inpresolve = (SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE);
4342 #endif
4343 
4344  assert(conshdlr != NULL);
4345  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4346  assert(nconss == 0 || conss != NULL);
4347  assert(result != NULL);
4348 
4349  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4350  assert(conshdlrdata != NULL);
4351 
4352  cutoff = FALSE;
4353  reduceddom = FALSE;
4354 
4355  /* propagate all useful logic or constraints */
4356  for( c = 0; c < nusefulconss && !cutoff; ++c )
4357  {
4358  assert(inpresolve || !(SCIPconsGetData(conss[c])->existmultaggr));
4359 
4360  SCIPdebugMsg(scip, " propagate constraint %s\n", SCIPconsGetName(conss[c]));
4361  SCIP_CALL( processWatchedVars(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &reduceddom, &addcut, &mustcheck) );
4362  }
4363 
4364  /* return the correct result */
4365  if( cutoff )
4366  *result = SCIP_CUTOFF;
4367  else if( reduceddom )
4368  *result = SCIP_REDUCEDDOM;
4369  else
4370  *result = SCIP_DIDNOTFIND;
4371 
4372  return SCIP_OKAY;
4373 }
4374 
4375 /** presolving method of constraint handler */
4376 static
4377 SCIP_DECL_CONSPRESOL(consPresolLogicor)
4378 { /*lint --e{715}*/
4379  SCIP_CONSHDLRDATA* conshdlrdata;
4380  SCIP_CONS* cons;
4381  SCIP_CONSDATA* consdata;
4382  unsigned char* entries;
4383  SCIP_Bool redundant;
4384  int c;
4385  int firstchange;
4386  int nentries;
4387  int oldnfixedvars;
4388  int oldnchgbds;
4389  int oldndelconss;
4390  int oldnupgdconss;
4391  int oldnchgcoefs;
4392 
4393  assert(conshdlr != NULL);
4394  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4395  assert(scip != NULL);
4396  assert(result != NULL);
4397 
4398  *result = SCIP_DIDNOTFIND;
4399 
4400  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4401  assert(conshdlrdata != NULL);
4402 
4403  nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
4404 
4405  oldnfixedvars = *nfixedvars;
4406  oldnchgbds = *nchgbds;
4407  oldndelconss = *ndelconss;
4408  oldnupgdconss = *nupgdconss;
4409  oldnchgcoefs = *nchgcoefs;
4410 
4411  firstchange = INT_MAX;
4412 
4413  SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
4414 
4415  /* process constraints */
4416  for( c = 0; c < nconss && *result != SCIP_CUTOFF && !SCIPisStopped(scip); ++c )
4417  {
4418  cons = conss[c];
4419  assert(cons != NULL);
4420  consdata = SCIPconsGetData(cons);
4421  assert(consdata != NULL);
4422 
4423  SCIPdebugMsg(scip, "presolving logic or constraint <%s>\n", SCIPconsGetName(cons));
4424 
4425  /* force presolving the constraint in the initial round */
4426  if( nrounds == 0 )
4427  {
4428  SCIP_CALL( SCIPenableConsPropagation(scip, cons) );
4429  }
4430 
4431  redundant = FALSE;
4432  if( !consdata->presolved )
4433  {
4434  /* remove all variables that are fixed to zero, check redundancy due to fixed-to-one variable */
4435  SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &redundant, nchgcoefs, naddconss, ndelconss) );
4436  }
4437 
4438  if( SCIPconsIsDeleted(cons) )
4439  continue;
4440 
4441  /* find pairs of negated variables in constraint: constraint is redundant */
4442  /* find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
4443  if( !redundant )
4444  {
4445  SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, &redundant, nchgcoefs) );
4446  }
4447 
4448  if( redundant )
4449  {
4450  SCIPdebugMsg(scip, "logic or constraint <%s> is redundant\n", SCIPconsGetName(cons));
4451  SCIP_CALL( SCIPdelCons(scip, cons) );
4452  (*ndelconss)++;
4453  *result = SCIP_SUCCESS;
4454  continue;
4455  }
4456  else if( !SCIPconsIsModifiable(cons) )
4457  {
4458  if( consdata->nvars <= 2 )
4459  {
4460  SCIP_Bool cutoff;
4461 
4462  /* handle all cases with less than three variables in a logicor constraint */
4463  SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
4464  conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
4465 
4466  if( cutoff )
4467  {
4468  *result = SCIP_CUTOFF;
4469  goto TERMINATE;
4470  }
4471  else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
4472  || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
4473  *result = SCIP_SUCCESS;
4474 
4475  if( SCIPconsIsDeleted(cons) )
4476  continue;
4477  }
4478  }
4479 
4480  /* perform dual reductions */
4481  if( conshdlrdata->dualpresolving && SCIPallowDualReds(scip) )
4482  {
4483  SCIP_CALL( dualPresolving(scip, cons, conshdlrdata->eventhdlr, nfixedvars, ndelconss, nchgcoefs, result) );
4484 
4485  /* if dual reduction deleted the constraint we take the next */
4486  if( !SCIPconsIsActive(cons) )
4487  continue;
4488 
4489  /* in dualpresolving we may have removed variables, so we need to take care of special cases */
4490  if( consdata->nvars <= 2 )
4491  {
4492  SCIP_Bool cutoff;
4493 
4494  /* handle all cases with less than three variables in a logicor constraint */
4495  SCIP_CALL( fixDeleteOrUpgradeCons(scip, cons, conshdlrdata->eventhdlr, conshdlrdata->conshdlrlinear,
4496  conshdlrdata->conshdlrsetppc, nfixedvars, nchgbds, nchgcoefs, ndelconss, naddconss, nupgdconss, &cutoff) );
4497 
4498  if( cutoff )
4499  {
4500  *result = SCIP_CUTOFF;
4501  goto TERMINATE;
4502  }
4503  else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *nchgcoefs > oldnchgcoefs
4504  || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
4505  *result = SCIP_SUCCESS;
4506 
4507  if( SCIPconsIsDeleted(cons) )
4508  continue;
4509  }
4510  }
4511 
4512  /* remember the first changed constraint to begin the next redundancy round with */
4513  if( firstchange == INT_MAX && consdata->changed )
4514  firstchange = c;
4515 
4516  assert(consdata->nvars >= 2 || SCIPconsIsModifiable(cons));
4517  }
4518 
4519  assert(*result != SCIP_CUTOFF);
4520 
4521  /* fast preprocessing of pairs of logic or constraints, used for equal constraints */
4522  if( firstchange < nconss && conshdlrdata->presolusehashing )
4523  {
4524  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
4525  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, ndelconss) );
4526  }
4527 
4528  /* preprocess pairs of logic or constraints and apply negated clique presolving */
4529  if( SCIPisPresolveFinished(scip) )
4530  {
4531  SCIP_Bool cutoff = FALSE;
4532 
4533  /* check constraints for redundancy */
4534  if( conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4535  {
4536  SCIP_CALL( removeRedundantConssAndNonzeros(scip, conss, nconss, &entries, &nentries, conshdlrdata->eventhdlr,
4537  conshdlrdata->usestrengthening, &firstchange, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
4538 
4539  if( cutoff )
4540  {
4541  *result = SCIP_CUTOFF;
4542  goto TERMINATE;
4543  }
4544  }
4545 
4546  if( SCIPisPresolveFinished(scip) )
4547  {
4548  /* try to tighten constraints by reducing the number of variables in the constraints using implications and
4549  * cliques, also derive fixations through them, @see SCIPshrinkDisjunctiveVarSet()
4550  */
4551  if( conshdlrdata->useimplications && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4552  {
4553  SCIP_CALL( shortenConss(scip, conshdlrdata, conshdlrdata->eventhdlr, conss, nconss,
4554  &entries, &nentries, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
4555 
4556  if( cutoff )
4557  {
4558  *result = SCIP_CUTOFF;
4559  goto TERMINATE;
4560  }
4561  }
4562 
4563  /* check for redundant constraints due to negated clique information */
4564  if( conshdlrdata->usenegatedclique && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
4565  {
4566  SCIP_CALL( removeConstraintsDueToNegCliques(scip, conshdlr, conshdlrdata->conshdlrsetppc,
4567  conshdlrdata->eventhdlr, conss, nconss, &entries, &nentries, nfixedvars, ndelconss,
4568  nupgdconss, nchgcoefs, &cutoff) );
4569 
4570  if( cutoff )
4571  {
4572  *result = SCIP_CUTOFF;
4573  goto TERMINATE;
4574  }
4575  }
4576  }
4577  }
4578 
4579  TERMINATE:
4580 
4581  SCIPfreeBufferArray(scip, &entries);
4582 
4583  return SCIP_OKAY;
4584 }
4585 
4586 
4587 /** propagation conflict resolving method of constraint handler */
4588 static
4589 SCIP_DECL_CONSRESPROP(consRespropLogicor)
4590 { /*lint --e{715}*/
4591  SCIP_CONSDATA* consdata;
4592 #ifndef NDEBUG
4593  SCIP_Bool infervarfound;
4594 #endif
4595  int v;
4596 
4597  assert(conshdlr != NULL);
4598  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4599  assert(cons != NULL);
4600  assert(infervar != NULL);
4601  assert(result != NULL);
4602 
4603  consdata = SCIPconsGetData(cons);
4604  assert(consdata != NULL);
4605 
4606  SCIPdebugMsg(scip, "conflict resolving method of logic or constraint handler\n");
4607 
4608  /* the only deductions are variables infered to 1.0 on logic or constraints where all other variables
4609  * are assigned to zero
4610  */
4611  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5); /* the inference variable must be assigned to one */
4612 
4613 #ifndef NDEBUG
4614  infervarfound = FALSE;
4615 #endif
4616  for( v = 0; v < consdata->nvars; ++v )
4617  {
4618  if( consdata->vars[v] != infervar )
4619  {
4620  /* the reason variable must have been assigned to zero */
4621  assert(SCIPgetVarUbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) < 0.5);
4622  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
4623  }
4624 #ifndef NDEBUG
4625  else
4626  {
4627  assert(!infervarfound);
4628  infervarfound = TRUE;
4629  }
4630 #endif
4631  }
4632  assert(infervarfound);
4633 
4634  *result = SCIP_SUCCESS;
4635 
4636  return SCIP_OKAY;
4637 }
4638 
4639 
4640 /** variable rounding lock method of constraint handler */
4641 static
4642 SCIP_DECL_CONSLOCK(consLockLogicor)
4643 { /*lint --e{715}*/
4644  SCIP_CONSDATA* consdata;
4645  int i;
4646 
4647  consdata = SCIPconsGetData(cons);
4648  assert(consdata != NULL);
4649 
4650  /* lock every single coefficient */
4651  for( i = 0; i < consdata->nvars; ++i )
4652  {
4653  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
4654  }
4655 
4656  return SCIP_OKAY;
4657 }
4658 
4659 
4660 /** constraint activation notification method of constraint handler */
4661 static
4662 SCIP_DECL_CONSACTIVE(consActiveLogicor)
4663 { /*lint --e{715}*/
4664  SCIP_CONSHDLRDATA* conshdlrdata;
4665  SCIP_CONSDATA* consdata;
4666 
4667  assert(conshdlr != NULL);
4668  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4669  assert(cons != NULL);
4670  assert(SCIPconsIsTransformed(cons));
4671 
4672  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4673  assert(conshdlrdata != NULL);
4674  consdata = SCIPconsGetData(cons);
4675  assert(consdata != NULL);
4676  assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
4677 
4678  SCIPdebugMsg(scip, "activating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
4679  SCIPdebug( SCIP_CALL(consdataPrint(scip, consdata, NULL, TRUE)) );
4680 
4681  /* catch events on watched variables */
4682  if( consdata->watchedvar1 != -1 )
4683  {
4684  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar1],
4685  SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4686  &consdata->filterpos1) );
4687  }
4688  if( consdata->watchedvar2 != -1 )
4689  {
4690  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[consdata->watchedvar2],
4691  SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4692  &consdata->filterpos2) );
4693  }
4694 
4695  return SCIP_OKAY;
4696 }
4697 
4698 
4699 /** constraint deactivation notification method of constraint handler */
4700 static
4701 SCIP_DECL_CONSDEACTIVE(consDeactiveLogicor)
4702 { /*lint --e{715}*/
4703  SCIP_CONSHDLRDATA* conshdlrdata;
4704  SCIP_CONSDATA* consdata;
4705 
4706  assert(conshdlr != NULL);
4707  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4708  assert(cons != NULL);
4709  assert(SCIPconsIsTransformed(cons));
4710 
4711  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4712  assert(conshdlrdata != NULL);
4713  consdata = SCIPconsGetData(cons);
4714  assert(consdata != NULL);
4715  assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
4716 
4717  SCIPdebugMsg(scip, "deactivating information for logic or constraint <%s>\n", SCIPconsGetName(cons));
4718  SCIPdebug( SCIP_CALL(consdataPrint(scip, consdata, NULL, TRUE)) );
4719 
4720  /* drop events on watched variables */
4721  if( consdata->watchedvar1 != -1 )
4722  {
4723  assert(consdata->filterpos1 != -1);
4724  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1],
4725  SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4726  consdata->filterpos1) );
4727  }
4728  if( consdata->watchedvar2 != -1 )
4729  {
4730  assert(consdata->filterpos2 != -1);
4731  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2],
4732  SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED, conshdlrdata->eventhdlr, (SCIP_EVENTDATA*)cons,
4733  consdata->filterpos2) );
4734  }
4735 
4736  return SCIP_OKAY;
4737 }
4738 
4739 
4740 /** constraint display method of constraint handler */
4741 static
4742 SCIP_DECL_CONSPRINT(consPrintLogicor)
4743 { /*lint --e{715}*/
4745  assert( scip != NULL );
4746  assert( conshdlr != NULL );
4747  assert( cons != NULL );
4748 
4749  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file, FALSE) );
4750 
4751  return SCIP_OKAY;
4752 }
4753 
4754 /** constraint copying method of constraint handler */
4755 static
4756 SCIP_DECL_CONSCOPY(consCopyLogicor)
4757 { /*lint --e{715}*/
4758  SCIP_VAR** sourcevars;
4759  const char* consname;
4760  int nvars;
4761 
4762  /* get variables and coefficients of the source constraint */
4763  sourcevars = SCIPgetVarsLogicor(sourcescip, sourcecons);
4764  nvars = SCIPgetNVarsLogicor(sourcescip, sourcecons);
4765 
4766  if( name != NULL )
4767  consname = name;
4768  else
4769  consname = SCIPconsGetName(sourcecons);
4770 
4771  /* copy the logic using the linear constraint copy method */
4772  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, NULL,
4773  1.0, SCIPinfinity(scip), varmap, consmap,
4774  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
4775  assert(cons != NULL);
4776 
4777  return SCIP_OKAY;
4778 }
4779 
4780 /** constraint parsing method of constraint handler */
4781 static
4782 SCIP_DECL_CONSPARSE(consParseLogicor)
4783 { /*lint --e{715}*/
4784  SCIP_VAR** vars;
4785  char* strcopy;
4786  char* endptr;
4787  char* startptr;
4788  int requiredsize;
4789  int varssize;
4790  int nvars;
4791 
4792  SCIPdebugMsg(scip, "parse <%s> as logicor constraint\n", str);
4793 
4794  *success = FALSE;
4795 
4796  /* cutoff "logicor" from the constraint string */
4797  startptr = strchr((char*)str, '(');
4798 
4799  if( startptr == NULL )
4800  {
4801  SCIPerrorMessage("missing starting character '(' parsing logicor\n");
4802  return SCIP_OKAY;
4803  }
4804 
4805  /* skip '(' */
4806  ++startptr;
4807 
4808  /* find end character ')' */
4809  endptr = strrchr(startptr, ')');
4810 
4811  if( endptr == NULL )
4812  {
4813  SCIPerrorMessage("missing ending character ')' parsing logicor\n");
4814  return SCIP_OKAY;
4815  }
4816  assert(endptr >= startptr);
4817 
4818  if( endptr > startptr )
4819  {
4820  /* copy string for parsing */
4821  SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, startptr, (int)(endptr-startptr)) );
4822 
4823  varssize = 100;
4824  nvars = 0;
4825 
4826  /* allocate buffer array for variables */
4827  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
4828 
4829  /* parse string */
4830  SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4831 
4832  if( *success )
4833  {
4834  /* check if the size of the variable array was great enough */
4835  if( varssize < requiredsize )
4836  {
4837  /* reallocate memory */
4838  varssize = requiredsize;
4839  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
4840 
4841  /* parse string again with the correct size of the variable array */
4842  SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4843  }
4844 
4845  assert(*success);
4846  assert(varssize >= requiredsize);
4847 
4848  /* create logicor constraint */
4849  SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, vars,
4850  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4851  }
4852 
4853  /* free buffers */
4854  SCIPfreeBufferArray(scip, &vars);
4855  SCIPfreeBufferArray(scip, &strcopy);
4856  }
4857  else
4858  {
4859  if( !modifiable )
4860  {
4861  SCIPerrorMessage("cannot create empty logicor constraint\n");
4862  return SCIP_OKAY;
4863  }
4864 
4865  /* create empty logicor constraint */
4866  SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, 0, NULL,
4867  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4868 
4869  *success = TRUE;
4870  }
4871 
4872  return SCIP_OKAY;
4873 }
4874 
4875 /** constraint method of constraint handler which returns the variables (if possible) */
4876 static
4877 SCIP_DECL_CONSGETVARS(consGetVarsLogicor)
4878 { /*lint --e{715}*/
4879  SCIP_CONSDATA* consdata;
4880 
4881  consdata = SCIPconsGetData(cons);
4882  assert(consdata != NULL);
4883 
4884  if( varssize < consdata->nvars )
4885  (*success) = FALSE;
4886  else
4887  {
4888  assert(vars != NULL);
4889 
4890  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
4891  (*success) = TRUE;
4892  }
4893 
4894  return SCIP_OKAY;
4895 }
4896 
4897 /** constraint method of constraint handler which returns the number of variables (if possible) */
4898 static
4899 SCIP_DECL_CONSGETNVARS(consGetNVarsLogicor)
4900 { /*lint --e{715}*/
4901  SCIP_CONSDATA* consdata;
4902 
4903  consdata = SCIPconsGetData(cons);
4904  assert(consdata != NULL);
4905 
4906  (*nvars) = consdata->nvars;
4907  (*success) = TRUE;
4908 
4909  return SCIP_OKAY;
4910 }
4911 
4912 /*
4913  * Callback methods of event handler
4914  */
4915 
4916 static
4917 SCIP_DECL_EVENTEXEC(eventExecLogicor)
4918 { /*lint --e{715}*/
4919  assert(eventhdlr != NULL);
4920  assert(eventdata != NULL);
4921  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
4922  assert(event != NULL);
4923 
4924  SCIPdebugMsg(scip, "exec method of event handler for logic or constraints\n");
4925 
4927  {
4928  SCIPdebugMsg(scip, "enabling constraint cons <%s> at depth %d\n", SCIPconsGetName((SCIP_CONS*)eventdata), SCIPgetDepth(scip));
4929 
4930  SCIP_CALL( SCIPenableCons(scip, (SCIP_CONS*)eventdata) );
4931  SCIP_CALL( SCIPenableConsPropagation(scip, (SCIP_CONS*)eventdata) );
4932  }
4933  else if( SCIPeventGetType(event) == SCIP_EVENTTYPE_UBTIGHTENED )
4934  {
4935  SCIP_CALL( SCIPenableConsPropagation(scip, (SCIP_CONS*)eventdata) );
4936  }
4937 
4939  {
4940  SCIP_VAR* var = SCIPeventGetVar(event);
4941  SCIP_CONS* cons = (SCIP_CONS*)eventdata;
4942  SCIP_CONSDATA* consdata;
4943 
4944  assert(cons != NULL);
4945  consdata = SCIPconsGetData(cons);
4946  assert(consdata != NULL);
4947 
4948  /* we only catch this event in presolving stage */
4949  assert(SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING);
4950  assert(var != NULL);
4951 
4952  consdata->presolved = FALSE;
4953 
4955  {
4956  if( SCIPconsIsActive(cons) )
4957  {
4958  if( SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
4959  consdata->merged = FALSE;
4960 
4961  if( !consdata->existmultaggr )
4962  {
4964  consdata->existmultaggr = TRUE;
4965  }
4966  }
4967  }
4968  }
4969 
4970  return SCIP_OKAY;
4971 }
4972 
4973 
4974 /*
4975  * Callback methods of conflict handler
4976  */
4977 
4978 static
4979 SCIP_DECL_CONFLICTEXEC(conflictExecLogicor)
4980 { /*lint --e{715}*/
4981  SCIP_VAR** vars;
4982  int i;
4983 
4984  assert(conflicthdlr != NULL);
4985  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
4986  assert(bdchginfos != NULL || nbdchginfos == 0);
4987  assert(result != NULL);
4988 
4989  *result = SCIP_DIDNOTRUN;
4990 
4991  /* don't process already resolved conflicts */
4992  if( resolved )
4993  return SCIP_OKAY;
4994 
4995  /* if the conflict consists of only two (binary) variables, it will be handled by the setppc conflict handler */
4996  if( nbdchginfos == 2 )
4997  return SCIP_OKAY;
4998 
4999  *result = SCIP_DIDNOTFIND;
5000 
5001  /* create array of variables in conflict constraint */
5002  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
5003  for( i = 0; i < nbdchginfos; ++i )
5004  {
5005  assert(bdchginfos != NULL); /* for flexelint */
5006  assert(bdchginfos[i] != NULL);
5007 
5008  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
5009 
5010  /* we can only treat binary variables */
5011  if( !SCIPvarIsBinary(vars[i]) )
5012  break;
5013 
5014  /* if the variable is fixed to one in the conflict set, we have to use its negation */
5015  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
5016  {
5017  SCIP_CALL( SCIPgetNegatedVar(scip, vars[i], &vars[i]) );
5018  }
5019  }
5020 
5021  if( i == nbdchginfos )
5022  {
5023  SCIP_CONS* cons;
5024  char consname[SCIP_MAXSTRLEN];
5025 
5026  /* create a constraint out of the conflict set */
5027  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%d_%" SCIP_LONGINT_FORMAT, SCIPgetNRuns(scip), SCIPgetNConflictConssApplied(scip));
5028  SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, consname, nbdchginfos, vars,
5029  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
5030 
5031  /* add conflict to SCIP */
5032  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
5033 
5034  *result = SCIP_CONSADDED;
5035  }
5036 
5037  /* free temporary memory */
5038  SCIPfreeBufferArray(scip, &vars);
5039 
5040  return SCIP_OKAY;
5041 }
5042 
5043 
5044 /*
5045  * constraint specific interface methods
5046  */
5047 
5048 /** creates the handler for logic or constraints and includes it in SCIP */
5050  SCIP* scip /**< SCIP data structure */
5051  )
5052 {
5053  SCIP_CONSHDLRDATA* conshdlrdata;
5054  SCIP_CONSHDLR* conshdlr;
5055  SCIP_CONFLICTHDLR* conflicthdlr;
5056  SCIP_EVENTHDLR* eventhdlr;
5057 
5058  /* create event handler for events on watched variables */
5060  eventExecLogicor, NULL) );
5061 
5062  /* create conflict handler for logic or constraints */
5064  conflictExecLogicor, NULL) );
5065 
5066  /* create constraint handler data */
5067  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
5068 
5069  /* include constraint handler */
5072  consEnfolpLogicor, consEnfopsLogicor, consCheckLogicor, consLockLogicor,
5073  conshdlrdata) );
5074  assert(conshdlr != NULL);
5075 
5076  /* set non-fundamental callbacks via specific setter functions */
5077  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLogicor) );
5078  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLogicor, consCopyLogicor) );
5079  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLogicor) );
5080  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLogicor) );
5081  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLogicor) );
5082  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLogicor) );
5083  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLogicor) );
5084  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLogicor) );
5085  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLogicor) );
5086  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLogicor) );
5087  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLogicor) );
5088  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLogicor) );
5089  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLogicor,CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
5090  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLogicor) );
5091  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLogicor, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
5093  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLogicor) );
5094  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLogicor, consSepasolLogicor, CONSHDLR_SEPAFREQ,
5096  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLogicor) );
5097  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLogicor) );
5098 
5099  conshdlrdata->conshdlrlinear = SCIPfindConshdlr(scip, "linear");
5100  conshdlrdata->conshdlrsetppc = SCIPfindConshdlr(scip, "setppc");
5101 
5102  if( conshdlrdata->conshdlrlinear != NULL )
5103  {
5104  /* include the linear constraint to logicor constraint upgrade in the linear constraint handler */
5106  }
5107 
5108  /* logic or constraint handler parameters */
5110  "constraints/logicor/presolpairwise",
5111  "should pairwise constraint comparison be performed in presolving?",
5112  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
5114  "constraints/logicor/presolusehashing",
5115  "should hash table be used for detecting redundant constraints in advance",
5116  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
5118  "constraints/logicor/dualpresolving",
5119  "should dual presolving steps be performed?",
5120  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
5122  "constraints/logicor/negatedclique",
5123  "should negated clique information be used in presolving",
5124  &conshdlrdata->usenegatedclique, TRUE, DEFAULT_NEGATEDCLIQUE, NULL, NULL) );
5126  "constraints/logicor/implications",
5127  "should implications/cliques be used in presolving",
5128  &conshdlrdata->useimplications, TRUE, DEFAULT_IMPLICATIONS, NULL, NULL) );
5130  "constraints/logicor/strengthen",
5131  "should pairwise constraint comparison try to strengthen constraints by removing superflous non-zeros?",
5132  &conshdlrdata->usestrengthening, TRUE, DEFAULT_STRENGTHEN, NULL, NULL) );
5133 
5134  return SCIP_OKAY;
5135 }
5136 
5137 
5138 /** creates and captures a logic or constraint
5139  *
5140  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5141  */
5143  SCIP* scip, /**< SCIP data structure */
5144  SCIP_CONS** cons, /**< pointer to hold the created constraint */
5145  const char* name, /**< name of constraint */
5146  int nvars, /**< number of variables in the constraint */
5147  SCIP_VAR** vars, /**< array with variables of constraint entries */
5148  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
5149  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5150  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
5151  * Usually set to TRUE. */
5152  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
5153  * TRUE for model constraints, FALSE for additional, redundant constraints. */
5154  SCIP_Bool check, /**< should the constraint be checked for feasibility?
5155  * TRUE for model constraints, FALSE for additional, redundant constraints. */
5156  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
5157  * Usually set to TRUE. */
5158  SCIP_Bool local, /**< is constraint only valid locally?
5159  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5160  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
5161  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
5162  * adds coefficients to this constraint. */
5163  SCIP_Bool dynamic, /**< is constraint subject to aging?
5164  * Usually set to FALSE. Set to TRUE for own cuts which
5165  * are separated as constraints. */
5166  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
5167  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5168  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
5169  * if it may be moved to a more global node?
5170  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
5171  )
5172 {
5173  SCIP_CONSHDLR* conshdlr;
5174  SCIP_CONSDATA* consdata;
5175 
5176  assert(scip != NULL);
5177 
5178  /* find the logicor constraint handler */
5179  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5180  if( conshdlr == NULL )
5181  {
5182  SCIPerrorMessage("logic or constraint handler not found\n");
5183  return SCIP_INVALIDCALL;
5184  }
5185 
5186  /* create the constraint specific data */
5187  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars) );
5188 
5189  /* create constraint */
5190  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5191  local, modifiable, dynamic, removable, stickingatnode) );
5192 
5193  if( SCIPisTransformed(scip) && SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING )
5194  {
5195  SCIP_CONSHDLRDATA* conshdlrdata;
5196  int v;
5197 
5198  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5199  assert(conshdlrdata != NULL);
5200 
5201  for( v = consdata->nvars - 1; v >= 0; --v )
5202  {
5203  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[v], SCIP_EVENTTYPE_VARFIXED, conshdlrdata->eventhdlr,
5204  (SCIP_EVENTDATA*)(*cons), NULL) );
5205  }
5206  }
5207 
5208  return SCIP_OKAY;
5209 }
5210 
5211 /** creates and captures a logicor constraint
5212  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
5213  * method SCIPcreateConsLogicor(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
5214  *
5215  * @see SCIPcreateConsLogicor() for information about the basic constraint flag configuration
5216  *
5217  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5218  */
5220  SCIP* scip, /**< SCIP data structure */
5221  SCIP_CONS** cons, /**< pointer to hold the created constraint */
5222  const char* name, /**< name of constraint */
5223  int nvars, /**< number of variables in the constraint */
5224  SCIP_VAR** vars /**< array with variables of constraint entries */
5225  )
5226 {
5227  assert(scip != NULL);
5228 
5229  SCIP_CALL( SCIPcreateConsLogicor(scip, cons, name, nvars, vars,
5230  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5231 
5232  return SCIP_OKAY;
5233 }
5234 
5235 /** adds coefficient in logic or constraint */
5237  SCIP* scip, /**< SCIP data structure */
5238  SCIP_CONS* cons, /**< logicor constraint */
5239  SCIP_VAR* var /**< variable to add to the constraint */
5240  )
5241 {
5242  assert(var != NULL);
5243 
5244  /*debugMsg(scip, "adding variable <%s> to logicor constraint <%s>\n",
5245  SCIPvarGetName(var), SCIPconsGetName(cons));*/
5246 
5247  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5248  {
5249  SCIPerrorMessage("constraint is not a logic or constraint\n");
5250  return SCIP_INVALIDDATA;
5251  }
5252 
5253  SCIP_CALL( addCoef(scip, cons, var) );
5254 
5255  return SCIP_OKAY;
5256 }
5257 
5258 /** gets number of variables in logic or constraint */
5260  SCIP* scip, /**< SCIP data structure */
5261  SCIP_CONS* cons /**< constraint data */
5262  )
5263 {
5264  SCIP_CONSDATA* consdata;
5265 
5266  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5267  {
5268  SCIPerrorMessage("constraint is not a logic or constraint\n");
5269  SCIPABORT();
5270  return -1; /*lint !e527*/
5271  }
5272 
5273  consdata = SCIPconsGetData(cons);
5274  assert(consdata != NULL);
5275 
5276  return consdata->nvars;
5277 }
5278 
5279 /** gets array of variables in logic or constraint */
5281  SCIP* scip, /**< SCIP data structure */
5282  SCIP_CONS* cons /**< constraint data */
5283  )
5284 {
5285  SCIP_CONSDATA* consdata;
5286 
5287  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5288  {
5289  SCIPerrorMessage("constraint is not a logic or constraint\n");
5290  SCIPABORT();
5291  return NULL; /*lint !e527*/
5292  }
5293 
5294  consdata = SCIPconsGetData(cons);
5295  assert(consdata != NULL);
5296 
5297  return consdata->vars;
5298 }
5299 
5300 /** gets the dual solution of the logic or constraint in the current LP */
5302  SCIP* scip, /**< SCIP data structure */
5303  SCIP_CONS* cons /**< constraint data */
5304  )
5305 {
5306  SCIP_CONSDATA* consdata;
5307 
5308  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5309  {
5310  SCIPerrorMessage("constraint is not a logic or constraint\n");
5311  SCIPABORT();
5312  return SCIP_INVALID; /*lint !e527*/
5313  }
5314 
5315  consdata = SCIPconsGetData(cons);
5316  assert(consdata != NULL);
5317 
5318  if( consdata->row != NULL )
5319  return SCIProwGetDualsol(consdata->row);
5320  else
5321  return 0.0;
5322 }
5323 
5324 /** gets the dual Farkas value of the logic or constraint in the current infeasible LP */
5326  SCIP* scip, /**< SCIP data structure */
5327  SCIP_CONS* cons /**< constraint data */
5328  )
5329 {
5330  SCIP_CONSDATA* consdata;
5331 
5332  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5333  {
5334  SCIPerrorMessage("constraint is not a logic or constraint\n");
5335  SCIPABORT();
5336  return SCIP_INVALID; /*lint !e527*/
5337  }
5338 
5339  consdata = SCIPconsGetData(cons);
5340  assert(consdata != NULL);
5341 
5342  if( consdata->row != NULL )
5343  return SCIProwGetDualfarkas(consdata->row);
5344  else
5345  return 0.0;
5346 }
5347 
5348 /** returns the linear relaxation of the given logic or constraint; may return NULL if no LP row was yet created;
5349  * the user must not modify the row!
5350  */
5352  SCIP* scip, /**< SCIP data structure */
5353  SCIP_CONS* cons /**< constraint data */
5354  )
5355 {
5356  SCIP_CONSDATA* consdata;
5357 
5358  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5359  {
5360  SCIPerrorMessage("constraint is not a logic or constraint\n");
5361  SCIPABORT();
5362  return NULL; /*lint !e527*/
5363  }
5364 
5365  consdata = SCIPconsGetData(cons);
5366  assert(consdata != NULL);
5367 
5368  return consdata->row;
5369 }
5370 
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition: scip.c:30740
SCIP_RETCODE SCIPaddCoefLogicor(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4143
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11902
static SCIP_DECL_CONSCHECK(consCheckLogicor)
SCIP_RETCODE SCIPaddConsAge(SCIP *scip, SCIP_CONS *cons, SCIP_Real deltaage)
Definition: scip.c:28343
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:22593
static SCIP_DECL_CONSPRESOL(consPresolLogicor)
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6291
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_logicor.c:66
static SCIP_RETCODE removeRedundantCons(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *ndelconss)
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10889
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_logicor.c:62
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19649
#define CONSHDLR_DELAYSEPA
Definition: cons_logicor.c:46
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:821
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:58
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8245
static SCIP_DECL_CONSINITLP(consInitlpLogicor)
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6314
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47311
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 CONSHDLR_NEEDSCONS
Definition: cons_logicor.c:48
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19509
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2265
int SCIPconsGetValidDepth(SCIP_CONS *cons)
Definition: cons.c:8069
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41226
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17878
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6544
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)
int SCIPgetNVarsLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11720
#define SCIP_MAXSTRLEN
Definition: def.h:259
static SCIP_DECL_CONSEXITPRE(consExitpreLogicor)
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6036
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28400
static SCIP_DECL_CONSPRINT(consPrintLogicor)
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12663
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:46813
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30668
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_logicor.c:304
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:27388
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47015
static SCIP_DECL_CONFLICTEXEC(conflictExecLogicor)
SCIP_RETCODE SCIPdisableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28569
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip.c:6406
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:8355
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
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 SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18957
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:28112
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
Definition: scip.c:6205
static SCIP_RETCODE disableCons(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47387
static SCIP_DECL_CONSDEACTIVE(consDeactiveLogicor)
static SCIP_DECL_EVENTEXEC(eventExecLogicor)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47350
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_logicor.c:502
#define CONSHDLR_DELAYPROP
Definition: cons_logicor.c:47
#define FALSE
Definition: def.h:64
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:7996
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10289
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:5894
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47100
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21660
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8265
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:45
#define LINCONSUPGD_PRIORITY
Definition: cons_logicor.c:53
static unsigned int calcSignature(SCIP_VAR **vars, int nvars)
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
static SCIP_DECL_CONSEXITSOL(consExitsolLogicor)
static SCIP_DECL_CONSSEPALP(consSepalpLogicor)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8295
#define CONSHDLR_SEPAFREQ
Definition: cons_logicor.c:40
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *violated)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:27155
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
SCIP_RETCODE SCIPenableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28539
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:5948
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
#define CONSHDLR_NAME
Definition: cons_logicor.c:35
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
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:135
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15150
Constraint handler for the set partitioning / packing / covering constraints .
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:6688
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17102
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8255
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6337
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:16504
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1267
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18998
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6521
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8047
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17628
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:11992
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:27584
static SCIP_DECL_HASHGETKEY(hashGetKeyLogicorcons)
static SCIP_RETCODE switchWatchedvars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
Definition: cons_logicor.c:361
static SCIP_RETCODE addCut(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
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:2014
static SCIP_RETCODE conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_logicor.c:197
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17092
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16695
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3025
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:64
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)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:27133
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons)
#define SCIPallocCleanBufferArray(scip, ptr, num)
Definition: scip.h:22638
SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28425
SCIP_Real SCIPgetDualsolLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:24222
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11628
static void removeConsFromOccurList(SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:22599
static SCIP_DECL_HASHKEYVAL(hashKeyValLogicorcons)
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:18115
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip.c:1054
#define DEFAULT_DUALPRESOLVING
Definition: cons_logicor.c:67
static SCIP_DECL_CONSACTIVE(consActiveLogicor)
#define SCIP_PRESOLTIMING_MEDIUM
Definition: type_timing.h:44
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:6060
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)
static SCIP_DECL_LINCONSUPGD(linconsUpgdLogicor)
SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
Definition: scip.c:19162
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
#define CONSHDLR_ENFOPRIORITY
Definition: cons_logicor.c:38
static SCIP_DECL_CONSTRANS(consTransLogicor)
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
static SCIP_DECL_CONSRESPROP(consRespropLogicor)
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:22633
static SCIP_DECL_HASHKEYEQ(hashKeyEqLogicorcons)
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:46731
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21788
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8205
SCIP_VAR ** SCIPgetVarsLogicor(SCIP *scip, SCIP_CONS *cons)
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
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)
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6085
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
#define EVENTHDLR_NAME
Definition: cons_logicor.c:55
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_logicor.c:158
static SCIP_RETCODE addConsToOccurList(SCIP *scip, SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int *occurlistsizes, int *occurlistlength, int occurlistsize)
SCIP_RETCODE SCIPcreateConsBasicLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:17146
#define SCIP_CALL(x)
Definition: def.h:350
#define SCIPhashTwo(a, b)
Definition: pub_misc.h:473
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:19255
#define CONFLICTHDLR_NAME
Definition: cons_logicor.c:58
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip.c:13802
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47324
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27535
SCIP_ROW * SCIPgetRowLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8225
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
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6360
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28459
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:29208
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:9092
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file, SCIP_Bool endline)
Definition: cons_logicor.c:335
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
public data structures and miscellaneous methods
static SCIP_DECL_CONSGETVARS(consGetVarsLogicor)
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:982
#define CONFLICTHDLR_DESC
Definition: cons_logicor.c:59
#define SCIP_Bool
Definition: def.h:61
int SCIPgetNImplVars(SCIP *scip)
Definition: scip.c:11947
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
static SCIP_DECL_CONSENFOLP(consEnfolpLogicor)
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_Bool SCIPconsIsPropagationEnabled(SCIP_CONS *cons)
Definition: cons.c:8104
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:30402
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43045
static void consdataSort(SCIP_CONSDATA *consdata)
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17554
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:29091
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
#define MAX(x, y)
Definition: tclique_def.h:75
#define CONSHDLR_MAXPREROUNDS
Definition: cons_logicor.c:45
#define MAX_CONSLENGTH
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11353
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8115
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8155
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17868
#define MAXCOMPARISONS
static SCIP_DECL_CONSCOPY(consCopyLogicor)
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:25575
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:42050
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:16517
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21714
SCIP_Real SCIPgetDualfarkasLogicor(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6498
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
Definition: scip.c:43019
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2326
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
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)
static SCIP_RETCODE strengthenConss(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, SCIP_EVENTHDLR *eventhdlr, int *ndelconss, int *nchgcoefs)
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_logicor.c:172
static SCIP_DECL_CONSFREE(consFreeLogicor)
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:35836
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2064
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
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
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars)
Definition: cons_logicor.c:236
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 SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:6229
static SCIP_DECL_CONSENFORELAX(consEnforelaxLogicor)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
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_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
Definition: scip.c:17797
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLogicor)
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
#define CONSHDLR_DESC
Definition: cons_logicor.c:36
#define CONSHDLR_PROPFREQ
Definition: cons_logicor.c:41
static SCIP_DECL_CONSPARSE(consParseLogicor)
#define CONSHDLR_EAGERFREQ
Definition: cons_logicor.c:42
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8016
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_logicor.c:144
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:25885
static SCIP_DECL_CONSINITPRE(consInitpreLogicor)
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:712
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6253
static SCIP_RETCODE removeRedundantConss(SCIP *scip, SCIP_CONS *cons, SCIP_HASHMAP *varstopos, SCIP_CONS ***occurlist, int *noccurlistentries, int occurlistlength, int *ndelconss)
int SCIPgetNCliques(SCIP *scip)
Definition: scip.c:24879
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30977
int SCIPgetNImplications(SCIP *scip)
Definition: scip.c:45911
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16781
SCIP_RETCODE SCIPincludeConshdlrLogicor(SCIP *scip)
static SCIP_DECL_CONSPROP(consPropLogicor)
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18732
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8235
#define SCIPfreeCleanBufferArray(scip, ptr)
Definition: scip.h:22642
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6567
static SCIP_DECL_CONSGETNVARS(consGetNVarsLogicor)
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8175
#define CONSHDLR_SEPAPRIORITY
Definition: cons_logicor.c:37
#define SCIP_INVALID
Definition: def.h:169
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8165
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
#define SCIP_Longint
Definition: def.h:134
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16959
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
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:969
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47076
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
#define CONSHDLR_PROP_TIMING
Definition: cons_logicor.c:51
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:22605
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16804
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
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2874
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip.c:6383
#define CONSHDLR_CHECKPRIORITY
Definition: cons_logicor.c:39
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:13049
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_logicor.c:432
static SCIP_DECL_CONSSEPASOL(consSepasolLogicor)
SCIP_RETCODE SCIPcleanupCliques(SCIP *scip, SCIP_Bool *infeasible)
Definition: scip.c:24836
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6181
#define SCIPcombineTwoInt(a, b)
Definition: pub_misc.h:479
#define SCIPABORT()
Definition: def.h:322
#define CONFLICTHDLR_PRIORITY
Definition: cons_logicor.c:60
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
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:23039
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)
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:19045
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)
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:4239
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16949
#define DEFAULT_STRENGTHEN
Definition: cons_logicor.c:63
#define DEFAULT_IMPLICATIONS
Definition: cons_logicor.c:69
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16817
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *redundant, int *nchgcoefs)
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:22624
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5994