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