Scippy

SCIP

Solving Constraint Integer Programs

cons_setppc.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_setppc.c
17  * @brief Constraint handler for the set partitioning / packing / covering constraints \f$1^T x\ \{=, \le, \ge\}\ 1\f$.
18  * @author Tobias Achterberg
19  * @author Michael Winkler
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <assert.h>
25 #include <string.h>
26 #include <limits.h>
27 #include <stdio.h>
28 #include <ctype.h>
29 
30 #include "scip/cons_setppc.h"
31 #include "scip/cons_linear.h"
32 #include "scip/cons_quadratic.h"
33 #include "scip/pub_misc.h"
34 
35 
36 #define CONSHDLR_NAME "setppc"
37 #define CONSHDLR_DESC "set partitioning / packing / covering constraints"
38 #define CONSHDLR_SEPAPRIORITY +700000 /**< priority of the constraint handler for separation */
39 #define CONSHDLR_ENFOPRIORITY -700000 /**< priority of the constraint handler for constraint enforcing */
40 #define CONSHDLR_CHECKPRIORITY -700000 /**< priority of the constraint handler for checking feasibility */
41 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
42 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
43 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
44  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
45 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
46 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
47 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
48 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
49 
50 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_ALWAYS
51 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
52 
53 #define LINCONSUPGD_PRIORITY +700000 /**< priority of the constraint handler for upgrading of linear constraints */
54 #define QUADCONSUPGD_PRIORITY +700000 /**< priority of the constraint handler for upgrading of linear constraints */
55 
56 #define EVENTHDLR_NAME "setppc"
57 #define EVENTHDLR_DESC "bound change event handler for set partitioning / packing / covering constraints"
58 
59 #define CONFLICTHDLR_NAME "setppc"
60 #define CONFLICTHDLR_DESC "conflict handler creating set covering constraints"
61 #define CONFLICTHDLR_PRIORITY LINCONSUPGD_PRIORITY
62 
63 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
64 
65 #define HASHSIZE_SETPPCCONS 131101 /**< minimal size of hash table in setppc constraint tables */
66 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
67 #define NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
68 #define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
69 
70 /*#define VARUSES*/ /* activate variable usage counting, that is necessary for LP and pseudo branching */
71 /*#define BRANCHLP*/ /* BRANCHLP is only useful if the ENFOPRIORITY is set to a positive value */
72 #ifdef BRANCHLP
73 #define MINBRANCHWEIGHT 0.3 /**< minimum weight of both sets in binary set branching */
74 #define MAXBRANCHWEIGHT 0.7 /**< maximum weight of both sets in binary set branching */
75 #endif
76 #define DEFAULT_NPSEUDOBRANCHES 2 /**< number of children created in pseudo branching (0: disable branching) */
77 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
78 
79 #define DEFAULT_CLIQUELIFTING FALSE /**< should we try to lift variables into other clique constraints, fix
80  * variables, aggregate them, and also shrink the amount of variables in
81  * clique constraints
82  */
83 #define DEFAULT_ADDVARIABLESASCLIQUES FALSE/**< should we try to generate extra clique constraint out of all binary
84  * variables to hopefully fasten the detection of redundant clique
85  * constraints */
86 #define DEFAULT_CLIQUESHRINKING TRUE /**< should we try to shrink the number of variables in a clique constraints, by
87  * replacing more than one variable by only one
88  */
89 
90 /* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
91 
92 /*
93  * Data structures
94  */
95 
96 /** constraint handler data */
97 struct SCIP_ConshdlrData
98 {
99  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
100  SCIP_CONSHDLR* conshdlrlinear; /**< pointer to linear constraint handler or NULL if not included */
101 #ifdef VARUSES
102  SCIP_INTARRAY* varuses; /**< number of times a var is used in the active setppc constraints */
103 #endif
104  SCIP_Longint nsetpart; /**< number of set partitioning constraints in transformed problem */
105  int npseudobranches; /**< number of children created in pseudo branching (0 to disable branching) */
106  int noldfixedvars; /**< number of fixed variables after last clique lifting run */
107  int noldimpls; /**< number of implication before last clique lifting run */
108  int noldcliques; /**< number of cliques before last clique lifting run */
109  int noldupgrs; /**< number of setppc constraints since the last clique lifting run */
110  int nclqpresolve; /**< number of setppc clique lifting runs */
111  SCIP_Bool updatedsetppctype; /**< remember whether we upgraded a constraint type */
112  SCIP_Bool cliquelifting; /**< should we perform the clique lifting procedure */
113  SCIP_Bool enablecliquelifting;/**< check whether we have enough changes to run the lifting procedure again */
114  SCIP_Bool cliqueshrinking; /**< should we try to shrink the number of variables in a clique
115  * constraints, by replacing more than one variable by only one
116  */
117  SCIP_Bool addvariablesascliques;/**< should we try to generate extra clique constraint out of all binary
118  * variables to hopefully fasten the detection of redundant clique
119  * constraints */
120  unsigned int randseed; /**< start value for randomly permutate binary variable array to create
121  * extra cliques, iff addvariablesascliques is set to TRUE */
122  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
123  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
124  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
125 };
126 
127 /** constraint data for set partitioning / packing / covering constraints */
128 struct SCIP_ConsData
129 {
130  SCIP_Longint signature; /**< bit signature of vars array */
131  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
132  SCIP_VAR** vars; /**< variables of the constraint */
133  int varssize; /**< size of vars array */
134  int nvars; /**< number of variables in the constraint */
135  int nfixedzeros; /**< current number of variables fixed to zero in the constraint */
136  int nfixedones; /**< current number of variables fixed to one in the constraint */
137  unsigned int setppctype:2; /**< type of constraint: set partitioning, packing or covering */
138  unsigned int sorted:1; /**< are the constraint's variables sorted? */
139  unsigned int cliqueadded:1; /**< was the set partitioning / packing constraint already added as clique? */
140  unsigned int validsignature:1; /**< is the bit signature valid? */
141  unsigned int changed:1; /**< was constraint changed since last redundancy round in preprocessing? */
142  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
143  unsigned int merged:1; /**< are the constraint's equal/negated variables already merged? */
144  unsigned int propagated:1; /**< does this constraint need to be propagated? */
145  unsigned int existmultaggr:1; /**< does this constraint contain aggregations */
146 };
147 
148 
149 
150 
151 /*
152  * Local methods
153  */
154 
155 /** compares two active constraints of type set partitioning or set packing such that a "-1" is return if
156  * 1. the first constraint is a set partitioning constraint and the second is a set packing or
157  * 2. both constraints are set partitioning constraints and the second has more! variables than the first or
158  * 3. both constraints are set packing constraints and the second has less! variables than the first
159  * a "0" is return if
160  * 1. both constraint are of the same type and have the amount of variables or
161  * and a "1" is returned otherwise
162  */
163 static
164 int setppcCompare(
165  SCIP_CONS*const cons1, /**< first problem variable */
166  SCIP_CONS*const cons2 /**< second problem variable */
167  )
168 {
169  SCIP_CONSDATA* consdata1;
170  SCIP_CONSDATA* consdata2;
171 
172  assert(cons1 != NULL);
173  assert(cons2 != NULL);
174  assert(SCIPconsIsActive(cons1));
175  assert(SCIPconsIsActive(cons2));
176 
177  /* the partitioning type should be the smallest value and the packing the second smallest */
179 
180  consdata1 = SCIPconsGetData(cons1);
181  assert(consdata1 != NULL);
182  assert(consdata1->setppctype != SCIP_SETPPCTYPE_COVERING); /*lint !e641*/
183  consdata2 = SCIPconsGetData(cons2);
184  assert(consdata2 != NULL);
185  assert(consdata2->setppctype != SCIP_SETPPCTYPE_COVERING); /*lint !e641*/
186 
187  if( consdata1->setppctype < consdata2->setppctype ||
188  (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nvars < consdata2->nvars) || /*lint !e641*/
189  (consdata2->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->nvars > consdata2->nvars) ) /*lint !e641*/
190  return -1;
191  else if( (consdata1->setppctype == consdata2->setppctype && consdata1->nvars == consdata2->nvars) ) /*lint !e641*/
192  return 0;
193  else
194  {
195  assert(consdata1->setppctype > consdata2->setppctype || (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->setppctype == consdata2->setppctype && consdata1->nvars > consdata2->nvars) || (consdata1->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->setppctype == consdata2->setppctype && consdata1->nvars < consdata2->nvars)); /*lint !e641*/
196  return +1;
197  }
198 }
199 
200 /** sort constraints first after type (partitioning before packing before covering) and second after number of
201  * variables such that the partitioning constraints have increasing number of variables and the packing constraints
202  * have decreasing number of variables */
203 static
204 SCIP_DECL_SORTPTRCOMP(setppcConssSort)
205 {
206  return setppcCompare((SCIP_CONS*)elem1, (SCIP_CONS*)elem2);
207 }
208 
209 /** compares two setppc constraints such that a "-1" is return if the first constraint is active and
210  * 1. the second constraint is deleted
211  * 2. the first constraint is a set partitioning constraint and the second is a set packing or
212  * 3. both constraints are set partitioning constraints and the second has more! variables than the first or
213  * 4. both constraints are set packing constraints and the second has less! variables than the first
214  * a "0" is return if
215  * 1. both constraint are set-covering constraints
216  * 2. both constraint are of the same type and have the amount of variables or
217  * and a "1" is returned otherwise
218  */
219 static
220 int setppcCompare2(
221  SCIP_CONS*const cons1, /**< first problem variable */
222  SCIP_CONS*const cons2 /**< second problem variable */
223  )
224 {
225  SCIP_CONSDATA* consdata1;
226  SCIP_CONSDATA* consdata2;
227 
228  assert(cons1 != NULL);
229  assert(cons2 != NULL);
230 
231  if( SCIPconsIsDeleted(cons1) )
232  {
233  if( SCIPconsIsDeleted(cons2) )
234  return 0;
235  else
236  return +1;
237  }
238  else if( SCIPconsIsDeleted(cons2) )
239  return -1;
240 
241  consdata1 = SCIPconsGetData(cons1);
242  assert(consdata1 != NULL);
243  consdata2 = SCIPconsGetData(cons2);
244  assert(consdata2 != NULL);
245 
246  /* the partitioning type should be the smallest value and the packing the second smallest */
248 
249  if( consdata1->setppctype < consdata2->setppctype ||
250  ((SCIP_SETPPCTYPE)consdata1->setppctype != SCIP_SETPPCTYPE_COVERING &&
251  (((SCIP_SETPPCTYPE)consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nvars < consdata2->nvars) ||
252  ((SCIP_SETPPCTYPE)consdata2->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->nvars > consdata2->nvars))) )
253  return -1;
254  else if( ((SCIP_SETPPCTYPE)consdata2->setppctype == SCIP_SETPPCTYPE_COVERING || (consdata1->setppctype == consdata2->setppctype && consdata1->nvars == consdata2->nvars)) )
255  return 0;
256  else
257  {
258  assert(consdata1->setppctype > consdata2->setppctype || ((consdata1->setppctype == consdata2->setppctype) &&
259  ((consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nvars > consdata2->nvars)
260  || (consdata1->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->nvars < consdata2->nvars)))); /*lint !e641*/
261  return +1;
262  }
263 }
264 
265 /** sort constraints first after type (partitioning before packing before covering) and second after number of
266  * variables such that the partitioning constraints have increasing number of variables and the packing constraints
267  * have decreasing number of variables */
268 static
269 SCIP_DECL_SORTPTRCOMP(setppcConssSort2)
270 {
271  return setppcCompare2((SCIP_CONS*)elem1, (SCIP_CONS*)elem2);
272 }
273 
274 
275 /** installs rounding locks for the given variable in the given setppc constraint */
276 static
278  SCIP* scip, /**< SCIP data structure */
279  SCIP_CONS* cons, /**< setppc constraint */
280  SCIP_VAR* var /**< variable of constraint entry */
281  )
282 {
283  SCIP_CONSDATA* consdata;
284 
285  consdata = SCIPconsGetData(cons);
286  assert(consdata != NULL);
287 
288  switch( consdata->setppctype )
289  {
291  /* rounding in both directions may violate the constraint */
292  SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
293  break;
295  /* rounding up may violate the constraint */
296  SCIP_CALL( SCIPlockVarCons(scip, var, cons, FALSE, TRUE) );
297  break;
299  /* rounding down may violate the constraint */
300  SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, FALSE) );
301  break;
302  default:
303  SCIPerrorMessage("unknown setppc type\n");
304  return SCIP_INVALIDDATA;
305  }
306 
307  return SCIP_OKAY;
308 }
309 
310 /** removes rounding locks for the given variable in the given setppc constraint */
311 static
313  SCIP* scip, /**< SCIP data structure */
314  SCIP_CONS* cons, /**< setppc constraint */
315  SCIP_VAR* var /**< variable of constraint entry */
316  )
317 {
318  SCIP_CONSDATA* consdata;
319 
320  consdata = SCIPconsGetData(cons);
321  assert(consdata != NULL);
322 
323  switch( consdata->setppctype )
324  {
326  /* rounding in both directions may violate the constraint */
327  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
328  break;
330  /* rounding up may violate the constraint */
331  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, FALSE, TRUE) );
332  break;
334  /* rounding down may violate the constraint */
335  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, FALSE) );
336  break;
337  default:
338  SCIPerrorMessage("unknown setppc type\n");
339  return SCIP_INVALIDDATA;
340  }
341 
342  return SCIP_OKAY;
343 }
344 
345 /** creates constraint handler data for set partitioning / packing / covering constraint handler */
346 static
348  SCIP* scip, /**< SCIP data structure */
349  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
350  SCIP_EVENTHDLR* eventhdlr /**< event handler */
351  )
352 {
353  assert(scip != NULL);
354  assert(conshdlrdata != NULL);
355  assert(eventhdlr != NULL);
356 
357  SCIP_CALL( SCIPallocMemory(scip, conshdlrdata) );
358 #ifdef VARUSES
359  SCIP_CALL( SCIPcreateIntarray(scip, &(*conshdlrdata)->varuses) );
360 #endif
361  (*conshdlrdata)->npseudobranches = DEFAULT_NPSEUDOBRANCHES;
362 
363  /* set event handler for bound change events */
364  (*conshdlrdata)->eventhdlr = eventhdlr;
365  (*conshdlrdata)->nsetpart = 0;
366 
367  return SCIP_OKAY;
368 }
369 
370 /** frees constraint handler data for set partitioning / packing / covering constraint handler */
371 static
373  SCIP* scip, /**< SCIP data structure */
374  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
375  )
376 {
377  assert(conshdlrdata != NULL);
378  assert(*conshdlrdata != NULL);
379 
380 #ifdef VARUSES
381  SCIP_CALL( SCIPfreeIntarray(scip, &(*conshdlrdata)->varuses) );
382 #endif
383  SCIPfreeMemory(scip, conshdlrdata);
384 
385  return SCIP_OKAY;
386 }
387 
388 #ifdef VARUSES
389 /** adds the given value to the usage counter of the given variable */
390 static
391 SCIP_RETCODE conshdlrdataAddVaruses(
392  SCIP* scip, /**< SCIP data structure */
393  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
394  SCIP_VAR* var, /**< variable to increase usage counter for */
395  int addval /**< value to add to the usage counter */
396  )
397 {
398  SCIP_INTARRAY* varuses;
399 
400  assert(conshdlrdata != NULL);
401  assert(var != NULL);
402 
403  varuses = conshdlrdata->varuses;
404  assert(varuses != NULL);
405 
406  /* if the variable is the negation of a problem variable, count the varuses in the problem variable */
407  if( SCIPvarIsNegated(var) )
408  {
409  SCIP_VAR* negvar;
410  int varindex;
411 
412  /* move the varuses value of the negated variable to the active problem variable */
413  varindex = SCIPvarGetIndex(var);
414  addval += SCIPgetIntarrayVal(scip, varuses, varindex);
415  SCIP_CALL( SCIPsetIntarrayVal(scip, varuses, varindex, 0) );
416  SCIP_CALL( SCIPgetNegatedVar(scip, var, &negvar) );
417  var = negvar;
418  }
419 
420  /* increase varuses counter */
421  SCIP_CALL( SCIPincIntarrayVal(scip, varuses, SCIPvarGetIndex(var), addval) );
422 
423  SCIPdebugMessage("added %d to varuses of <%s>: %d\n",
424  addval, SCIPvarGetName(var), SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var)));
425 
426  return SCIP_OKAY;
427 }
428 
429 /** increases the usage counter of the given variable */
430 static
431 SCIP_RETCODE conshdlrdataIncVaruses(
432  SCIP* scip, /**< SCIP data structure */
433  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
434  SCIP_VAR* var /**< variable to increase usage counter for */
435  )
436 {
437  assert(conshdlrdata != NULL);
438 
439  SCIPdebugMessage("increasing varuses of <%s>: %d\n",
440  SCIPvarGetName(var), SCIPgetIntarrayVal(scip, conshdlrdata->varuses, SCIPvarGetIndex(var)));
441 
442  SCIP_CALL( conshdlrdataAddVaruses(scip, conshdlrdata, var, +1) );
443 
444  return SCIP_OKAY;
445 }
446 
447 /** decreases the usage counter of the given variable */
448 static
449 SCIP_RETCODE conshdlrdataDecVaruses(
450  SCIP* scip, /**< SCIP data structure */
451  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
452  SCIP_VAR* var /**< variable to increase usage counter for */
453  )
454 {
455  assert(conshdlrdata != NULL);
456 
457  SCIPdebugMessage("decreasing varuses of <%s>: %d\n",
458  SCIPvarGetName(var), SCIPgetIntarrayVal(scip, conshdlrdata->varuses, SCIPvarGetIndex(var)));
459 
460  SCIP_CALL( conshdlrdataAddVaruses(scip, conshdlrdata, var, -1) );
461 
462  return SCIP_OKAY;
463 }
464 
465 /** increases the usage counter of all variable in the constraint */
466 static
467 SCIP_RETCODE consdataIncVaruses(
468  SCIP* scip, /**< SCIP data structure */
469  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
470  SCIP_CONSDATA* consdata /**< setppc constraint data */
471  )
472 {
473  int v;
474 
475  assert(consdata != NULL);
476 
477  for( v = 0; v < consdata->nvars; ++v )
478  {
479  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, consdata->vars[v]) );
480  }
481 
482  return SCIP_OKAY;
483 }
484 
485 /** decreases the usage counter of all variable in the constraint */
486 static
487 SCIP_RETCODE consdataDecVaruses(
488  SCIP* scip, /**< SCIP data structure */
489  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
490  SCIP_CONSDATA* consdata /**< setppc constraint data */
491  )
492 {
493  int v;
494 
495  assert(consdata != NULL);
496 
497  for( v = 0; v < consdata->nvars; ++v )
498  {
499  SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, consdata->vars[v]) );
500  }
501 
502  return SCIP_OKAY;
503 }
504 #endif
505 
506 /** ensures, that the vars array can store at least num entries */
507 static
509  SCIP* scip, /**< SCIP data structure */
510  SCIP_CONSDATA* consdata, /**< setppc constraint data */
511  int num /**< minimum number of entries to store */
512  )
513 {
514  assert(consdata != NULL);
515  assert(consdata->nvars <= consdata->varssize);
517  if( num > consdata->varssize )
518  {
519  int newsize;
520 
521  newsize = SCIPcalcMemGrowSize(scip, num);
522  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
523  consdata->varssize = newsize;
524  }
525  assert(num <= consdata->varssize);
526 
527  return SCIP_OKAY;
528 }
529 
530 /** creates a set partitioning / packing / covering constraint data object */
531 static
533  SCIP* scip, /**< SCIP data structure */
534  SCIP_CONSDATA** consdata, /**< pointer to store the set partitioning / packing / covering constraint */
535  int nvars, /**< number of variables in the constraint */
536  SCIP_VAR** vars, /**< variables of the constraint */
537  SCIP_SETPPCTYPE setppctype /**< type of constraint: set partitioning, packing, or covering constraint */
538  )
539 {
540  assert(consdata != NULL);
541  assert(nvars == 0 || vars != NULL);
542 
543  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
544 
545  (*consdata)->signature = 0;
546  (*consdata)->row = NULL;
547  (*consdata)->existmultaggr = FALSE;
548 
549  if( nvars > 0 )
550  {
551  int v;
552 
553  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
554  (*consdata)->varssize = nvars;
555  (*consdata)->nvars = nvars;
556 
557  if( SCIPisTransformed(scip) )
558  {
559  /* get transformed variables */
560  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
561 
562  /* check for multi-aggregations and capture variables */
563  for( v = 0; v < (*consdata)->nvars; v++ )
564  {
565  SCIP_VAR* var = SCIPvarGetProbvar((*consdata)->vars[v]);
566  assert(var != NULL);
567  (*consdata)->existmultaggr = (*consdata)->existmultaggr || (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
568  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
569  }
570  }
571  else
572  {
573  /* capture variables */
574  for( v = 0; v < (*consdata)->nvars; v++ )
575  {
576  assert((*consdata)->vars[v] != NULL);
577  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
578  }
579  }
580 
581  }
582  else
583  {
584  (*consdata)->vars = NULL;
585  (*consdata)->varssize = 0;
586  (*consdata)->nvars = 0;
587  }
588  (*consdata)->nfixedzeros = 0;
589  (*consdata)->nfixedones = 0;
590  (*consdata)->setppctype = setppctype; /*lint !e641*/
591  (*consdata)->sorted = (nvars <= 1);
592  (*consdata)->cliqueadded = FALSE;
593  (*consdata)->validsignature = FALSE;
594  (*consdata)->changed = TRUE;
595  (*consdata)->varsdeleted = FALSE;
596  (*consdata)->merged = FALSE;
597  (*consdata)->propagated = FALSE;
598 
599  return SCIP_OKAY;
600 }
601 
602 /** creates a transformed set partitioning / packing / covering constraint data object */
603 static
605  SCIP* scip, /**< SCIP data structure */
606  SCIP_CONSDATA** consdata, /**< pointer to store the set partitioning / packing / covering constraint */
607  int nvars, /**< number of variables in the constraint */
608  SCIP_VAR** vars, /**< variables of the constraint */
609  SCIP_SETPPCTYPE setppctype /**< type of constraint: set partitioning, packing, or covering constraint */
610  )
611 {
612  assert(consdata != NULL);
613  assert(nvars == 0 || vars != NULL);
614 
615  /* create constraint data */
616  SCIP_CALL( consdataCreate(scip, consdata, nvars, vars, setppctype) );
617 
618  /* transform the variables */
619  SCIP_CALL( SCIPgetTransformedVars(scip, nvars, (*consdata)->vars, (*consdata)->vars) );
620 
621  return SCIP_OKAY;
622 }
623 
624 /** frees a set partitioning / packing / covering constraint data */
625 static
627  SCIP* scip, /**< SCIP data structure */
628  SCIP_CONSDATA** consdata /**< pointer to store the set partitioning / packing / covering constraint */
629  )
630 {
631  int v;
632 
633  assert(consdata != NULL);
634  assert(*consdata != NULL);
635 
636  /* release the row */
637  if( (*consdata)->row != NULL )
638  {
639  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
640  }
641 
642  /* release variables */
643  for( v = 0; v < (*consdata)->nvars; v++ )
644  {
645  assert((*consdata)->vars[v] != NULL);
646  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
647  }
648 
649  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
650  SCIPfreeBlockMemory(scip, consdata);
651 
652  return SCIP_OKAY;
653 }
654 
655 /** prints set partitioning / packing / covering constraint to file stream */
656 static
658  SCIP* scip, /**< SCIP data structure */
659  SCIP_CONSDATA* consdata, /**< set partitioning / packing / covering constraint data */
660  FILE* file /**< output file (or NULL for standard output) */
661  )
662 {
663  assert(consdata != NULL);
664 
665  /* print coefficients */
666  if( consdata->nvars == 0 )
667  SCIPinfoMessage(scip, file, "0 ");
668 
669  /* write linear sum */
670  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, NULL, consdata->nvars, TRUE) );
671 
672  /* print right hand side */
673  switch( consdata->setppctype )
674  {
676  SCIPinfoMessage(scip, file, " == 1");
677  break;
679  SCIPinfoMessage(scip, file, " <= 1");
680  break;
682  SCIPinfoMessage(scip, file, " >= 1");
683  break;
684  default:
685  SCIPerrorMessage("unknown setppc type\n");
686  return SCIP_ERROR;
687  }
688 
689  return SCIP_OKAY;
690 }
691 
692 /** returns the signature bitmask for the given variable */
693 static
695  SCIP_VAR* var /**< variable */
696  )
697 {
698  int sigidx;
699 
700  sigidx = SCIPvarGetIndex(var) % (int)(8*sizeof(SCIP_Longint));
701  return ((SCIP_Longint)1) << sigidx; /*lint !e703*/
702 }
703 
704 /** returns the bit signature of the given constraint data */
705 static
707  SCIP_CONSDATA* consdata /**< set partitioning / packing / covering constraint data */
708  )
709 {
710  assert(consdata != NULL);
711 
712  if( !consdata->validsignature )
713  {
714  int i;
715 
716  consdata->signature = 0;
717  for( i = 0; i < consdata->nvars; ++i )
718  consdata->signature |= getVarSignature(consdata->vars[i]);
719  consdata->validsignature = TRUE;
720  }
721 
722  return consdata->signature;
723 }
724 
725 /** sorts setppc constraint's variables by non-decreasing variable index */
726 static
727 void consdataSort(
728  SCIP_CONSDATA* consdata /**< linear constraint data */
729  )
730 {
731  assert(consdata != NULL);
732 
733  if( !consdata->sorted )
734  {
735  if( consdata->nvars <= 1 )
736  consdata->sorted = TRUE;
737  else
738  {
739  SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
740  consdata->sorted = TRUE;
741  }
742  }
743  assert(consdata->sorted);
744 #ifdef SCIP_DEBUG
745  /* check sorting */
746  {
747  int v;
748 
749  for( v = 0; v < consdata->nvars; ++v )
750  {
751  assert(v == consdata->nvars-1 || SCIPvarCompare(consdata->vars[v], consdata->vars[v+1]) <= 0);
752  }
753  }
754 #endif
755 }
756 
757 /** changes the type of a setppc constraint */
758 static
760  SCIP* scip, /**< SCIP data structure */
761  SCIP_CONS* cons, /**< setppc constraint */
762  SCIP_SETPPCTYPE setppctype /**< new type of constraint */
763  )
764 {
765  SCIP_CONSHDLR* conshdlr;
766  SCIP_CONSHDLRDATA* conshdlrdata;
767  SCIP_CONSDATA* consdata;
768 
769  consdata = SCIPconsGetData(cons);
770  assert(consdata != NULL);
771 
772  if( (SCIP_SETPPCTYPE)consdata->setppctype == setppctype )
773  return SCIP_OKAY;
774 
775  SCIPdebugMessage(" -> converting <%s> into setppc type %d\n", SCIPconsGetName(cons), setppctype);
776 
777  /* remove rounding locks */
778  if( SCIPconsIsLocked(cons) )
779  {
780  int v;
781 
782  for( v = 0; v < consdata->nvars; ++v )
783  {
784  SCIP_CALL( unlockRounding(scip, cons, consdata->vars[v]) );
785  }
786  }
787 
788  conshdlr = SCIPconsGetHdlr(cons);
789  assert(conshdlr != NULL);
790  conshdlrdata = SCIPconshdlrGetData(conshdlr);
791  assert(conshdlrdata != NULL);
792 
793  if( SCIPisTransformed(scip) )
794  {
795  if( setppctype == SCIP_SETPPCTYPE_PARTITIONING )
796  {
797  ++(conshdlrdata->nsetpart);
798  assert(conshdlrdata->nsetpart >= 0);
799  }
800  else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
801  {
802  --(conshdlrdata->nsetpart);
803  assert(conshdlrdata->nsetpart >= 0);
804  }
805  }
806 
807  /* change the constraint type */
808  consdata->setppctype = setppctype; /*lint !e641*/
809 
810  /* reinstall rounding locks again */
811  if( SCIPconsIsLocked(cons) )
812  {
813  int v;
814 
815  for( v = 0; v < consdata->nvars; ++v )
816  {
817  SCIP_CALL( lockRounding(scip, cons, consdata->vars[v]) );
818  }
819  }
820 
821  /* remember that we changed a constraint type for clique lifting procedure */
822  if( setppctype != SCIP_SETPPCTYPE_COVERING )
823  conshdlrdata->updatedsetppctype = TRUE;
824 
825  return SCIP_OKAY;
826 }
827 
828 /** catches events for variable at given position */
829 static
831  SCIP* scip, /**< SCIP data structure */
832  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
833  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
834  int pos /**< array position of variable to catch bound change events for */
835  )
836 {
837  SCIP_CONSDATA* consdata;
838  SCIP_EVENTTYPE eventtype;
839  SCIP_VAR* var;
840 
841  consdata = SCIPconsGetData(cons);
842  assert(consdata != NULL);
843  assert(eventhdlr != NULL);
844  assert(0 <= pos && pos < consdata->nvars);
845  assert(consdata->vars != NULL);
846 
847  var = consdata->vars[pos];
848  assert(var != NULL);
849 
850  /* we are catching the following events:
851  *
852  * - SCIP_EVENTTYPE_BOUNDCHANGED: Is used to count the number of variable fixed locally to zero and one. That helps
853  * to speed up the propagation
854  *
855  * - SCIP_EVENTTYPE_VARDELETED: Is caught to remove a deleted variable from the constraint
856  *
857  * - SCIP_EVENTTYPE_VARFIXED: Is used to get informed if a variable of the constraint was aggregated which means was
858  * detected to be equal or a negated variable of on other variable. in case of a negation
859  * this could lead to a redundant constraint if the (other) active variable is also part
860  * of the constraint.
861  */
863 
864  /* catch bound change events on variable */
865  SCIP_CALL( SCIPcatchVarEvent(scip, var, eventtype, eventhdlr, (SCIP_EVENTDATA*)cons, NULL) );
866 
867  /* update the fixed variables counters for this variable */
868  if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
869  {
870  consdata->nfixedzeros++;
871  consdata->propagated = FALSE;
872 
873  if( SCIPconsIsActive(cons) && consdata->nfixedzeros >= consdata->nvars - 1 )
874  {
875  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
876  }
877  }
878  else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
879  {
880  consdata->nfixedones++;
881  consdata->propagated = FALSE;
882 
883  if( SCIPconsIsActive(cons) )
884  {
885  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
886  }
887  }
888 
889  return SCIP_OKAY;
890 }
891 
892 /** drops events for variable at given position */
893 static
895  SCIP* scip, /**< SCIP data structure */
896  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
897  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
898  int pos /**< array position of variable to catch bound change events for */
899  )
900 {
901  SCIP_CONSDATA* consdata;
902  SCIP_EVENTTYPE eventtype;
903  SCIP_VAR* var;
904 
905  consdata = SCIPconsGetData(cons);
906  assert(consdata != NULL);
907  assert(eventhdlr != NULL);
908  assert(0 <= pos && pos < consdata->nvars);
909  assert(consdata->vars != NULL);
910 
911  var = consdata->vars[pos];
912  assert(var != NULL);
913 
915 
916  /* drop events on variable */
917  SCIP_CALL( SCIPdropVarEvent(scip, var, eventtype, eventhdlr, (SCIP_EVENTDATA*)cons, -1) );
918 
919  /* update the fixed variables counters for this variable */
920  if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
921  consdata->nfixedzeros--;
922  else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
923  consdata->nfixedones--;
924 
925  return SCIP_OKAY;
926 }
927 
928 /** catches bound change events for all variables in transformed setppc constraint */
929 static
931  SCIP* scip, /**< SCIP data structure */
932  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
933  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
934  )
935 {
936  SCIP_CONSDATA* consdata;
937  int i;
939  consdata = SCIPconsGetData(cons);
940  assert(consdata != NULL);
941 
942  /* catch event for every single variable */
943  for( i = 0; i < consdata->nvars; ++i )
944  {
945  SCIP_CALL( catchEvent(scip, cons, eventhdlr, i) );
946  }
947 
948  return SCIP_OKAY;
949 }
950 
951 /** drops bound change events for all variables in transformed setppc constraint */
952 static
954  SCIP* scip, /**< SCIP data structure */
955  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
956  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
957  )
958 {
959  SCIP_CONSDATA* consdata;
960  int i;
962  consdata = SCIPconsGetData(cons);
963  assert(consdata != NULL);
964 
965  /* drop event of every single variable */
966  for( i = 0; i < consdata->nvars; ++i )
967  {
968  SCIP_CALL( dropEvent(scip, cons, eventhdlr, i) );
969  }
970 
971  return SCIP_OKAY;
972 }
973 
974 /** adds coefficient in setppc constraint */
975 static
977  SCIP* scip, /**< SCIP data structure */
978  SCIP_CONS* cons, /**< setppc constraint */
979  SCIP_VAR* var /**< variable to add to the constraint */
980  )
981 {
982  SCIP_CONSDATA* consdata;
983  SCIP_Bool transformed;
985  assert(var != NULL);
986 
987  consdata = SCIPconsGetData(cons);
988  assert(consdata != NULL);
989 
990  /* are we in the transformed problem? */
991  transformed = SCIPconsIsTransformed(cons);
992 
993  /* always use transformed variables in transformed constraints */
994  if( transformed )
995  {
996  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
997  }
998  assert(var != NULL);
999  assert(transformed == SCIPvarIsTransformed(var));
1000 
1001  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
1002  consdata->vars[consdata->nvars] = var;
1003  consdata->nvars++;
1004  if( consdata->validsignature )
1005  consdata->signature |= getVarSignature(var);
1006  consdata->sorted = (consdata->nvars == 1);
1007  consdata->changed = TRUE;
1008 
1009  /* capture the variable */
1010  SCIP_CALL( SCIPcaptureVar(scip, var) );
1011 
1012  /* if we are in transformed problem, catch the variable's events */
1013  if( transformed )
1014  {
1015  SCIP_CONSHDLR* conshdlr;
1016  SCIP_CONSHDLRDATA* conshdlrdata;
1017 
1018  /* get event handler */
1019  conshdlr = SCIPconsGetHdlr(cons);
1020  assert(conshdlr != NULL);
1021  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1022  assert(conshdlrdata != NULL);
1023  assert(conshdlrdata->eventhdlr != NULL);
1024 
1025  /* catch bound change events of variable */
1026  SCIP_CALL( catchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
1027 
1028  if( !consdata->existmultaggr && SCIPvarGetStatus(SCIPvarGetProbvar(var)) == SCIP_VARSTATUS_MULTAGGR )
1029  consdata->existmultaggr = TRUE;
1030 
1031 #ifdef VARUSES
1032  /* if the constraint is currently active, increase the variable usage counter */
1033  if( SCIPconsIsActive(cons) )
1034  {
1035  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var) );
1036  }
1037 #endif
1038  }
1039 
1040  /* install the rounding locks for the new variable */
1041  SCIP_CALL( lockRounding(scip, cons, var) );
1042 
1043  /* add the new coefficient to the LP row */
1044  if( consdata->row != NULL )
1045  {
1046  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, 1.0) );
1047  }
1048 
1049  consdata->merged = FALSE;
1050  consdata->cliqueadded = FALSE;
1051 
1052  return SCIP_OKAY;
1053 }
1054 
1055 /** deletes coefficient at given position from setppc constraint data */
1056 static
1058  SCIP* scip, /**< SCIP data structure */
1059  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
1060  int pos /**< position of coefficient to delete */
1061  )
1062 {
1063  SCIP_CONSDATA* consdata;
1064  SCIP_VAR* var;
1066  assert(scip != NULL);
1067  assert(cons != NULL);
1068 
1069  consdata = SCIPconsGetData(cons);
1070  assert(consdata != NULL);
1071  assert(0 <= pos && pos < consdata->nvars);
1072 
1073  var = consdata->vars[pos];
1074  assert(var != NULL);
1075  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
1076 
1077  /* remove the rounding locks for the deleted variable */
1078  SCIP_CALL( unlockRounding(scip, cons, var) );
1079 
1080  /* if we are in transformed problem, delete the event data of the variable */
1081  if( SCIPconsIsTransformed(cons) )
1082  {
1083  SCIP_CONSHDLR* conshdlr;
1084  SCIP_CONSHDLRDATA* conshdlrdata;
1085 
1086  /* get event handler */
1087  conshdlr = SCIPconsGetHdlr(cons);
1088  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1089  assert(conshdlrdata != NULL);
1090  assert(conshdlrdata->eventhdlr != NULL);
1091 
1092  /* drop bound change events of variable */
1093  SCIP_CALL( dropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
1094  }
1095 
1096  /* delete coefficient from the LP row */
1097  if( consdata->row != NULL )
1098  {
1099  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -1.0) );
1100  }
1101 
1102  /* move the last variable to the free slot */
1103  if( pos != consdata->nvars - 1 )
1104  {
1105  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
1106  consdata->sorted = FALSE;
1107  }
1108  consdata->nvars--;
1109  consdata->validsignature = FALSE;
1110  consdata->changed = TRUE;
1111 
1112  /* release variable */
1113  SCIP_CALL( SCIPreleaseVar(scip, &var) );
1114 
1115  return SCIP_OKAY;
1116 }
1117 
1118 /** in case a part (more than one variable) in the setppc constraint is independent of every else (is locked only by
1119  * this constraint), we can perform dual reductions;
1120  *
1121  * (1) set covering
1122  *
1123  * - fix all independant variables with negative object coefficient to one
1124  * - fix all remaining independant variables to zero
1125  *
1126  * (i) all variables are independent and the constraint is not modifiable
1127  *
1128  * - fix the variable with the smallest object coefficient to one
1129  *
1130  * (ii) a variable x has exactly 0 uplocks and arbitrary downlocks and a variable y has exactly 1 downlock and
1131  * arbitrary uplocks and obj(x) <= obj(y) and obj(y) >= 0
1132  *
1133  * - fix y to 0, because it is dominated by x
1134  *
1135  * (2) set partitioning
1136  *
1137  * (i) all variables are independent and the constraint is not modifiable
1138  *
1139  * - fix the variable with the smallest object coefficient to one
1140  * - fix all remaining independant variables to zero
1141  *
1142  * (ii) a variable x has exactly 1 uplock and arbitrary downlocks and a variable y has exactly 1 downlock and
1143  * arbitrary uplocks and obj(x) <= obj(y)
1144  *
1145  * - fix y to 0, because it is dominated by x
1146  *
1147  * (3) set packing
1148  *
1149  * (i) all variables are independent and the constraint is not modifiable
1150  *
1151  * - fix the variable with the smallest object coefficient to one if the object coefficient is negative or zero
1152  * - fix all remaining independant variables to zero
1153  *
1154  * (ii) a variable x has exactly 1 uplock and arbitrary downlocks and a variable y has exactly 0 downlocks and
1155  * arbitrary uplocks and obj(x) <= obj(y)
1156  *
1157  * - fix y to 0, because it is dominated by x
1158  *
1159  *
1160  * Note: the following dual reduction for set covering and set packing constraints is already performed by the presolver
1161  * "dualfix"
1162  * (1) in case of a set covering constraint the following dual reduction can be performed:
1163  * - if a variable in a set covering constraint is only locked by that constraint and has negative or zero
1164  * objective coefficient than it can be fixed to one
1165  * (2) in case of a set packing constraint the following dual reduction can be performed:
1166  * - if a variable in a set packing constraint is only locked by that constraint and has positive or zero
1167  * objective coefficient than it can be fixed to zero
1168  *
1169  * Note: all dual reduction (ii) could also be performed by the "domcol" presolver, but cause the pairwise comparison of
1170  * columns is only done heuristically (and here it should be even cheaper) we perform them here (too)
1171  *
1172  */
1173 static
1175  SCIP* scip, /**< SCIP data structure */
1176  SCIP_CONS* cons, /**< setppc constraint */
1177  int* nfixedvars, /**< pointer to count number of fixings */
1178  int* ndelconss, /**< pointer to count number of deleted constraints */
1179  SCIP_RESULT* result /**< pointer to store the result SCIP_SUCCESS, if presolving was performed */
1180  )
1181 {
1182  SCIP_CONSDATA* consdata;
1183  SCIP_SETPPCTYPE setppctype;
1184  SCIP_VAR** vars;
1185  SCIP_VAR* activevar;
1186  SCIP_VAR* var;
1187  SCIP_Real bestobjval;
1188  SCIP_Real objval;
1189  SCIP_Real fixval;
1190  SCIP_Bool infeasible;
1191  SCIP_Bool fixed;
1192  SCIP_Bool negated;
1193  int noldfixed;
1194  int nposfixings;
1195  int nlockdowns;
1196  int nlockups;
1197  int nvars;
1198  int idx;
1199  int v;
1200 
1201  assert(scip != NULL);
1202  assert(cons != NULL);
1203  assert(nfixedvars != NULL);
1204  assert(ndelconss != NULL);
1205  assert(result != NULL);
1206 
1207  /* constraints for which the check flag is set to FALSE, did not contribute to the lock numbers; therefore, we cannot
1208  * use the locks to decide for a dual reduction using this constraint; for example after a restart the cuts which are
1209  * added to the problems have the check flag set to FALSE
1210  */
1211  if( !SCIPconsIsChecked(cons) )
1212  return SCIP_OKAY;
1213 
1214  assert(SCIPconsIsActive(cons));
1215 
1216  consdata = SCIPconsGetData(cons);
1217  assert(consdata != NULL);
1218 
1219  /* modifiable non-covering constraints cannot be deleted if one variable is fixed to one, because the propagation for
1220  * newly inserted variables must be considered later
1221  */
1222  if( consdata->nfixedones == 1 && SCIPconsIsModifiable(cons) )
1223  return SCIP_OKAY;
1224 
1225  /* all fixed variables should be removed at that point */
1226  assert(consdata->nfixedones == 0);
1227  assert(consdata->nfixedzeros == 0);
1228 
1229  nvars = consdata->nvars;
1230 
1231  /* we don't want to consider small constraints (note that the constraints can be modifiable, so we can't delete this
1232  * constraint)
1233  */
1234  if( nvars < 2 )
1235  return SCIP_OKAY;
1236 
1237  setppctype = (SCIP_SETPPCTYPE)consdata->setppctype;
1238  vars = consdata->vars;
1239  idx = -1;
1240  bestobjval = SCIP_INVALID;
1241 
1242  /* collect the rounding locks depending on the setppc type */
1243  switch( setppctype )
1244  {
1246  nlockdowns = 1;
1247  nlockups = 1;
1248  break;
1250  nlockdowns = 0;
1251  nlockups = 1;
1252  break;
1254  nlockdowns = 1;
1255  nlockups = 0;
1256  break;
1257  default:
1258  SCIPerrorMessage("unknown setppc type\n");
1259  SCIPABORT();
1260  return SCIP_INVALIDDATA; /*lint !e527*/
1261  }
1262 
1263  nposfixings = 0;
1264 
1265  /* check if we can apply the dual reduction; therefore count the number of variables where the setppc has the only
1266  * locks on this constraint
1267  */
1268  for( v = 0; v < nvars; ++v )
1269  {
1270  var = vars[v];
1271  assert(var != NULL);
1272 
1273  /* the variable should not be (globally) fixed */
1274  assert(SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5);
1275 
1276  if( SCIPvarGetNLocksDown(var) >= nlockdowns && SCIPvarGetNLocksUp(var) == nlockups )
1277  {
1278  activevar = var;
1279  negated = FALSE;
1280 
1281  /* get the active variable */
1282  SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
1283  assert(SCIPvarIsActive(activevar));
1284 
1285  if( negated )
1286  objval = -SCIPvarGetObj(activevar);
1287  else
1288  objval = SCIPvarGetObj(activevar);
1289 
1290  /* check if the current variable has a smaller objective coefficient */
1291  if( idx == -1 || objval < bestobjval )
1292  {
1293  idx = v;
1294  bestobjval = objval;
1295  }
1296  }
1297 
1298  /* in case another constraint has also downlocks on that variable we cannot perform a dual reduction on these
1299  * variables
1300  */
1301  if( SCIPvarGetNLocksDown(var) == nlockdowns && SCIPvarGetNLocksUp(var) >= nlockups )
1302  ++nposfixings;
1303  }
1304 
1305  if( idx == -1 || nposfixings == 0 )
1306  return SCIP_OKAY;
1307 
1308  SCIPdebugMessage("dual fixing constraint: \n");
1309  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
1310  SCIPdebug( SCIPinfoMessage(scip, NULL, "\n") );
1311 
1312  assert(idx >= 0 && idx < nvars);
1313  assert(bestobjval < SCIPinfinity(scip));
1314 
1315  noldfixed = *nfixedvars;
1316 
1317  /* in case of set packing and set partitioning we fix the dominated variables to zero */
1318  if( setppctype != SCIP_SETPPCTYPE_COVERING )
1319  {
1320  /* first part of all variables */
1321  for( v = nvars - 1; v >= 0; --v )
1322  {
1323  if( v == idx )
1324  continue;
1325 
1326  var = vars[v];
1327  assert(var != NULL);
1328 
1329  /* in case another constraint has also downlocks on that variable we cannot perform a dual reduction on these
1330  * variables
1331  */
1332  if( SCIPvarGetNLocksDown(var) == nlockdowns && SCIPvarGetNLocksUp(var) >= nlockups )
1333  {
1334  activevar = var;
1335  negated = FALSE;
1336 
1337  /* get the active variable */
1338  SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
1339  assert(SCIPvarIsActive(activevar));
1340 
1341  if( negated )
1342  objval = -SCIPvarGetObj(activevar);
1343  else
1344  objval = SCIPvarGetObj(activevar);
1345 
1346  if( objval >= bestobjval )
1347  {
1348  SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
1349  assert(!infeasible);
1350  assert(fixed);
1351 
1352  SCIPdebugMessage(" -> dual-fixed dominated variable <%s> == 0.0\n", SCIPvarGetName(var));
1353  ++(*nfixedvars);
1354  }
1355  }
1356  }
1357  }
1358  /* if we got a set covering constraint and not all variables are locked from this constraint it might not get
1359  * redundant (which is case if it is not possible to fix at least one variable to one), we fix all redundant
1360  * variables to their best bound
1361  */
1362  else
1363  {
1364  /* first part of all variables */
1365  for( v = nvars - 1; v >= 0; --v )
1366  {
1367  if( v == idx )
1368  continue;
1369 
1370  var = vars[v];
1371  assert(var != NULL);
1372 
1373  /* in case another constraint has also downlocks on that variable we cannot perform a dual reduction on these
1374  * variables
1375  */
1376  if( SCIPvarGetNLocksDown(var) == nlockdowns && SCIPvarGetNLocksUp(var) >= nlockups )
1377  {
1378  activevar = var;
1379  negated = FALSE;
1380 
1381  /* get the active variable */
1382  SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
1383  assert(SCIPvarIsActive(activevar));
1384  assert(SCIPvarGetNLocksDown(var) == SCIPvarGetNLocksDown(activevar) && SCIPvarGetNLocksUp(var) == SCIPvarGetNLocksUp(activevar));
1385 
1386  if( negated )
1387  objval = -SCIPvarGetObj(activevar);
1388  else
1389  objval = SCIPvarGetObj(activevar);
1390 
1391  if( objval > 0.0 )
1392  fixval = 0.0;
1393  else
1394  fixval = 1.0;
1395 
1396  /* if variables has a negative objective contribution, and is uplocked by another constraint we cannot fix
1397  * the variables to 1
1398  */
1399  if( (fixval == 1.0 && SCIPvarGetNLocksUp(var) > nlockups) || objval < bestobjval )
1400  continue;
1401 
1402  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
1403  assert(!infeasible);
1404  assert(fixed);
1405 
1406  SCIPdebugMessage(" -> dual-fixed dominated variable <%s> == %g\n", SCIPvarGetName(var), fixval);
1407  ++(*nfixedvars);
1408  }
1409  }
1410  }
1411 
1412  /* if all variables but the domination variable is fixed and the constraint is not modifiables or the constraint is a
1413  * covering constraint and the bestobjval is less than or equal to zero, we can fix the domination variable (with best
1414  * objective coefficient) and the constraint gets redundant
1415  */
1416  if( ((*nfixedvars - noldfixed == nvars - 1) && !SCIPconsIsModifiable(cons)) || (setppctype == SCIP_SETPPCTYPE_COVERING && bestobjval <= 0.0) )
1417  {
1418  /* in case of a set packing constraint with positive objective values, all variables can be fixed to zero; in all
1419  * other cases the variable with the smallest objective values is fixed to one
1420  */
1421  if( (setppctype == SCIP_SETPPCTYPE_PACKING && bestobjval > 0.0 && SCIPvarGetNLocksDown(vars[idx]) == 0) || setppctype != SCIP_SETPPCTYPE_PACKING || bestobjval <= 0.0 )
1422  {
1423  if( setppctype == SCIP_SETPPCTYPE_PACKING && bestobjval > 0.0 )
1424  fixval = 0.0;
1425  else
1426  fixval = 1.0;
1427 
1428  SCIP_CALL( SCIPfixVar(scip, vars[idx], fixval, &infeasible, &fixed) );
1429  assert(!infeasible);
1430  assert(fixed);
1431 
1432  SCIPdebugMessage(" -> dual-fixed best variable <%s> == %g\n", SCIPvarGetName(vars[idx]), fixval);
1433  ++(*nfixedvars);
1434  }
1435 
1436  /* check that we really have a non-violated constraint in hand before deleting */
1437  assert((setppctype == SCIP_SETPPCTYPE_PACKING && consdata->nfixedones <= 1) ||
1438  (setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata->nfixedones == 1) ||
1439  (setppctype == SCIP_SETPPCTYPE_COVERING && consdata->nfixedones >= 1));
1440 
1441  /* remove constraint since it is redundant */
1442  SCIP_CALL( SCIPdelCons(scip, cons) );
1443  ++(*ndelconss);
1444  }
1445 
1446  assert(*nfixedvars >= noldfixed);
1447 
1448  /* set result pointer to SCIP_SUCCESS, if variables could be fixed */
1449  if( *nfixedvars != noldfixed )
1450  *result = SCIP_SUCCESS;
1451 
1452 
1453  return SCIP_OKAY;
1454 }
1455 
1456 /** find pairs of negated variables in constraint:
1457  * partitioning/packing: all other variables must be zero, constraint is redundant
1458  * covering: constraint is redundant
1459  *
1460  * find sets of equal variables in constraint:
1461  * partitioning/packing: variable must be zero
1462  * covering: multiple entries of variable can be replaced by single entry
1463  */
1464 static
1466  SCIP* scip, /**< SCIP data structure */
1467  SCIP_CONS* cons, /**< knapsack constraint */
1468  int* nfixedvars, /**< pointer to store number of fixed variables */
1469  int* ndelconss, /**< pointer to store number of deleted constraints */
1470  int* nchgcoefs, /**< pointer to store number of changed coefficients */
1471  SCIP_Bool* cutoff /**< pointer to store whether a fixing leads to a cutoff */
1472  )
1474  SCIP_CONSDATA* consdata;
1475  int v;
1476 
1477  assert(scip != NULL);
1478  assert(cons != NULL);
1479  assert(nfixedvars != NULL);
1480  assert(ndelconss != NULL);
1481  assert(nchgcoefs != NULL);
1482  assert(cutoff != NULL);
1483 
1484  consdata = SCIPconsGetData(cons);
1485  assert(consdata != NULL);
1486 
1487  if( consdata->merged || SCIPconsIsDeleted(cons) )
1488  return SCIP_OKAY;
1489 
1490  if( consdata->nvars <= 1 )
1491  {
1492  consdata->merged = TRUE;
1493  return SCIP_OKAY;
1494  }
1495 
1496  assert(consdata->vars != NULL || consdata->nvars == 0);
1497 
1498  /* sorting array after indices of variables, that's only for faster merging */
1499  SCIPsortPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, consdata->nvars);
1500  /* setppc sorting now lost */
1501  consdata->sorted = FALSE;
1502 
1503  /* loop backwards through the items: deletion only affects rear items */
1504  for( v = consdata->nvars - 1; v > 0; --v )
1505  {
1506  SCIP_VAR* var1;
1507  SCIP_VAR* var2;
1508  SCIP_Bool negated1;
1509  SCIP_Bool negated2;
1510 
1511  negated1 = FALSE;
1512  negated2 = FALSE;
1513 
1514  var1 = consdata->vars[v];
1515  assert(SCIPvarIsBinary(var1));
1518  {
1519  var1 = SCIPvarGetNegatedVar(var1);
1520  negated1 = TRUE;
1521  }
1522  assert(var1 != NULL);
1523 
1524  var2 = consdata->vars[v-1];
1525  assert(SCIPvarIsBinary(var2));
1528  {
1529  var2 = SCIPvarGetNegatedVar(var2);
1530  negated2 = TRUE;
1531  }
1532  assert(var2 != NULL);
1533 
1534  if( var1 == var2 )
1535  {
1536  SCIP_Bool infeasible;
1537  SCIP_Bool fixed;
1538 
1539  /* one variables is active and the other is the same negated variable */
1540  if( negated1 != negated2 )
1541  {
1542  /* all other variable have to be zero if it's a partitioning or packing constraint */
1543  if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
1544  {
1545  int i;
1546 
1547  assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
1548  || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
1549 
1550  for( i = consdata->nvars - 1; i >= 0; --i )
1551  if( i != v && i != (v-1) )
1552  {
1553  SCIP_CALL( SCIPfixVar(scip, consdata->vars[i], 0.0, &infeasible, &fixed) );
1554  if( infeasible )
1555  {
1556  SCIPdebugMessage("setppc constraint <%s>: infeasible fixing <%s> == 0\n",
1557  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
1558  *cutoff = TRUE;
1559  return SCIP_OKAY;
1560  }
1561 
1562  if( fixed )
1563  ++(*nfixedvars);
1564  }
1565  }
1566  /* all setppc-type constraints are redundant */
1567  SCIP_CALL( SCIPdelCons(scip, cons) );
1568  ++(*ndelconss);
1569  return SCIP_OKAY;
1570  }
1571  /* both variables are either active or negated */
1572  else
1573  {
1574  /* this variable can be fixed to zero if it's a partitioning or packing constraint */
1575  if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
1576  {
1577  assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
1578  || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
1579 
1580  SCIP_CALL( SCIPfixVar(scip, var1, negated1 ? 1.0 : 0.0, &infeasible, &fixed) );
1581  if( infeasible )
1582  {
1583  SCIPdebugMessage("setppc constraint <%s>: infeasible fixing <%s> == %g\n",
1584  SCIPconsGetName(cons), SCIPvarGetName(var1), negated1 ? 1.0 : 0.0);
1585  *cutoff = TRUE;
1586  return SCIP_OKAY;
1587  }
1588 
1589  if( fixed )
1590  ++(*nfixedvars);
1591  }
1592  /* multiple entries of variable can be replaced by single entry */
1593  else
1594  {
1595  SCIP_CALL( delCoefPos(scip, cons, v) ); /* only some changed behind position v-1, so it's okay */
1596  ++(*nchgcoefs);
1597  }
1598  }
1599  consdata->changed = TRUE;
1600  }
1601  }
1602  consdata->merged = TRUE;
1603 
1604  return SCIP_OKAY;
1605 }
1606 
1607 /** deletes all zero-fixed variables and replace aggregated variables */
1608 static
1610  SCIP* scip, /**< SCIP data structure */
1611  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
1612  int* naddconss, /**< pointer to count number of added constraints, or NULL indicating we
1613  * can not resolve multi-aggregations
1614  */
1615  int* ndelconss, /**< pointer to count number of deleted constraints, or NULL indicating we
1616  * can not resolve multi-aggregations
1617  */
1618  int* nfixedvars, /**< pointer to store number of fixed variables, or NULL indicating we can
1619  * not resolve multi-aggregations
1620  */
1621  SCIP_Bool* cutoff /**< pointer to store whether a fixing leads to a cutoff, or NULL
1622  * indicating we can not resolve multi-aggregations
1623  */
1624  )
1625 {
1626  SCIP_CONSDATA* consdata;
1627  int v;
1628 
1629  assert(scip != NULL);
1630  assert(cons != NULL);
1631 
1632  consdata = SCIPconsGetData(cons);
1633  assert(consdata != NULL);
1634 
1635  /* all multi-aggregations should be resolved */
1636  consdata->existmultaggr = FALSE;
1637 
1638  v = 0;
1639  while( v < consdata->nvars )
1640  {
1641  SCIP_VAR* var;
1642 
1643  var = consdata->vars[v];
1644  assert(SCIPvarIsBinary(var));
1645 
1646  if( SCIPvarGetUbGlobal(var) < 0.5 )
1647  {
1648  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
1649  SCIP_CALL( delCoefPos(scip, cons, v) );
1650  }
1651  else
1652  {
1653  SCIP_VAR* repvar;
1654  SCIP_Bool negated;
1655 
1656  /* get binary representative of variable */
1657  SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
1658 
1659  /* resolve multi-aggregation */
1661  {
1662  SCIP_VAR** consvars;
1663  SCIP_Real* consvals;
1664  SCIP_Real constant = 0.0;
1665  SCIP_Bool easycase;
1666  int nconsvars;
1667  int requiredsize;
1668  int v2;
1669 
1670  nconsvars = 1;
1671  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 1) );
1672  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 1) );
1673  consvars[0] = repvar;
1674  consvals[0] = 1.0;
1675 
1676  /* get active variables for new constraint */
1677  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
1678  /* if space was not enough we need to resize the buffers */
1679  if( requiredsize > nconsvars )
1680  {
1681  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
1682  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
1683 
1684  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
1685  assert(requiredsize <= nconsvars);
1686  }
1687 
1688  easycase = FALSE;
1689 
1690  if( SCIPisZero(scip, constant) )
1691  {
1692  /* add active representation */
1693  for( v2 = nconsvars - 1; v2 >= 0; --v2 )
1694  {
1695  if( !SCIPvarIsBinary(consvars[v2]) )
1696  {
1697  break;
1698 #if 0
1699  SCIPerrorMessage("try to resolve a multi-aggregation with a non-binary variable <%s>\n", consvars[v2]);
1700  return SCIP_ERROR;
1701 #endif
1702  }
1703 
1704  if( !SCIPisEQ(scip, consvals[v2], 1.0) )
1705  break;
1706  }
1707 
1708  if( v2 < 0 )
1709  easycase = TRUE;
1710  }
1711  else if( SCIPisFeasEQ(scip, constant, 1.0) )
1712  {
1713  /* check for another multi-aggregation */
1714  for( v2 = consdata->nvars - 1; v2 > v; --v2 )
1715  {
1716  if( SCIPvarGetStatus(SCIPvarGetProbvar(consdata->vars[v])) == SCIP_VARSTATUS_MULTAGGR )
1717  break;
1718  }
1719 
1720  /* constraint is redundant */
1721  if( v2 == v && nconsvars == 0 )
1722  {
1723  /* we can fix */
1724  if( consdata->nvars > 1 && (SCIP_SETPPCTYPE)consdata->setppctype != SCIP_SETPPCTYPE_COVERING )
1725  {
1726  if( nfixedvars != NULL )
1727  {
1728  SCIP_Bool fixed;
1729 
1730  assert(cutoff != NULL);
1731 
1732  for( v2 = consdata->nvars - 1; v2 >= 0; --v2 )
1733  {
1734  if( consdata->vars[v2] != var )
1735  {
1736  SCIPdebugMessage("trying to fix <%s> to 0 due to at least one variable is already fixed to 1\n", SCIPvarGetName(consdata->vars[v2]));
1737 
1738  /* fix all remaining variables to zero, constraint is already feasible or infeasible */
1739  SCIP_CALL( SCIPfixVar(scip, consdata->vars[v2], 0.0, cutoff, &fixed) );
1740  if( *cutoff )
1741  {
1742  SCIPdebugMessage("setppc constraint <%s>: infeasible fixing <%s> == 0\n",
1743  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v2]));
1744 
1745  SCIPfreeBufferArray(scip, &consvals);
1746  SCIPfreeBufferArray(scip, &consvars);
1747 
1748  /* all multi-aggregations should be resolved */
1749  consdata->existmultaggr = FALSE;
1750 
1751  return SCIP_OKAY;
1752  }
1753 
1754  if( fixed )
1755  ++(*nfixedvars);
1756  }
1757  }
1758  }
1759  }
1760 
1761  if( ndelconss != NULL && (nfixedvars != NULL || consdata->nvars == 1 || (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING) )
1762  {
1763  /* delete old constraint */
1764  SCIP_CALL( SCIPdelCons(scip, cons) );
1765  ++(*ndelconss);
1766  }
1767  SCIPfreeBufferArray(scip, &consvals);
1768  SCIPfreeBufferArray(scip, &consvars);
1769 
1770  /* all multi-aggregations should be resolved */
1771  consdata->existmultaggr = FALSE;
1772 
1773  return SCIP_OKAY;
1774  }
1775  }
1776 
1777  /* we can easily add the coefficients and still have a setppc constraint */
1778  if( easycase )
1779  {
1780  /* delete old (multi-aggregated) variable */
1781  SCIP_CALL( delCoefPos(scip, cons, v) );
1782 
1783  /* add active representation */
1784  for( v2 = nconsvars - 1; v2 >= 0; --v2 )
1785  {
1786  assert(SCIPvarIsBinary(consvars[v2]));
1787  assert(SCIPvarIsActive(consvars[v2]) || (SCIPvarGetStatus(consvars[v2]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(consvars[v2]))));
1788 
1789  SCIP_CALL( addCoef(scip, cons, consvars[v2]) );
1790  }
1791  }
1792  /* we need to degrade this setppc constraint to a linear constraint */
1793  else if( (ndelconss != NULL && naddconss != NULL) || SCIPconsIsAdded(cons) )
1794  {
1795  char name[SCIP_MAXSTRLEN];
1796  SCIP_CONS* newcons;
1797  SCIP_Real lhs;
1798  SCIP_Real rhs;
1799  int size;
1800  int k;
1801 
1802  /* it might happen that there are more than one multi-aggregated variable, so we need to get the whole
1803  * probvar sum over all variables
1804  */
1805 
1806  size = MAX(nconsvars, 1) + consdata->nvars - 1;
1807 
1808  /* memory needed is at least old number of variables - 1 + number of variables in first multi-aggregation */
1809  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, size) );
1810  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, size) );
1811 
1812  nconsvars = consdata->nvars;
1813 
1814  /* add constraint variables to new linear variables */
1815  for( k = consdata->nvars - 1; k >= 0; --k )
1816  {
1817  consvars[k] = consdata->vars[k];
1818  consvals[k] = 1.0;
1819  }
1820 
1821  constant = 0.0;
1822 
1823  /* get active variables for new constraint */
1824  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize, TRUE) );
1825 
1826  /* if space was not enough (we found another multi-aggregation), we need to resize the buffers */
1827  if( requiredsize > nconsvars )
1828  {
1829  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
1830  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
1831 
1832  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
1833  assert(requiredsize <= nconsvars);
1834  }
1835 
1836  /* compute sides */
1837  if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
1838  {
1839  lhs = -SCIPinfinity(scip);
1840  rhs = 1.0 - constant;
1841  }
1842  else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
1843  {
1844  lhs = 1.0 - constant;
1845  rhs = 1.0 - constant;
1846  }
1847  else
1848  {
1849  assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING);
1850  lhs = 1.0 - constant;
1851  rhs = SCIPinfinity(scip);
1852  }
1853 
1854  /* create linear constraint */
1855  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPconsGetName(cons));
1856  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, nconsvars, consvars, consvals, lhs, rhs,
1857  SCIPconsIsInitial(cons),
1861  SCIP_CALL( SCIPaddCons(scip, newcons) );
1862 
1863  SCIPdebugMessage("added linear constraint: ");
1864  SCIPdebugPrintCons(scip, newcons, NULL);
1865  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1866 
1867  SCIPfreeBufferArray(scip, &consvals);
1868  SCIPfreeBufferArray(scip, &consvars);
1869 
1870  /* delete old constraint */
1871  SCIP_CALL( SCIPdelCons(scip, cons) );
1872  if( ndelconss != NULL && naddconss != NULL )
1873  {
1874  ++(*ndelconss);
1875  ++(*naddconss);
1876  }
1877 
1878  /* all multi-aggregations should be resolved */
1879  consdata->existmultaggr = FALSE;
1880 
1881  return SCIP_OKAY;
1882  }
1883  /* we need to degrade this setppc constraint to a linear constraint*/
1884  else
1885  {
1886  /* check, if the variable should be replaced with the representative */
1887  if( repvar != var )
1888  {
1889  /* delete old (aggregated) variable */
1890  SCIP_CALL( delCoefPos(scip, cons, v) );
1891 
1892  /* add representative instead */
1893  SCIP_CALL( addCoef(scip, cons, repvar) );
1894  }
1895 
1896  SCIPwarningMessage(scip, "setppc constraint <%s> has a multi-aggregated variable, which was not resolved and therefore could lead to aborts\n", SCIPconsGetName(cons));
1897  ++v;
1898  }
1899 
1900  SCIPfreeBufferArray(scip, &consvals);
1901  SCIPfreeBufferArray(scip, &consvars);
1902  }
1903  else
1904  {
1905  /* check, if the variable should be replaced with the representative */
1906  if( repvar != var )
1907  {
1908  /* delete old (aggregated) variable */
1909  SCIP_CALL( delCoefPos(scip, cons, v) );
1910 
1911  /* add representative instead */
1912  SCIP_CALL( addCoef(scip, cons, repvar) );
1913  }
1914  else
1915  ++v;
1916  }
1917  }
1918  }
1919 
1920  /* all multi-aggregations should be resolved */
1921  consdata->existmultaggr = FALSE;
1922 
1923  return SCIP_OKAY;
1924 }
1925 
1926 /** analyzes conflicting assignment on given constraint where all of the variables where assigned to zero,
1927  * and adds conflict constraint to problem
1928  */
1929 static
1931  SCIP* scip, /**< SCIP data structure */
1932  SCIP_CONS* cons /**< set partitioning / packing / covering constraint that detected the conflict */
1933  )
1934 {
1935  SCIP_CONSDATA* consdata;
1936  int v;
1937 
1938  /* conflict analysis can only be applied in solving stage and if it is applicable */
1940  return SCIP_OKAY;
1941 
1942  consdata = SCIPconsGetData(cons);
1943  assert(consdata != NULL);
1944  assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
1945  || consdata->setppctype == SCIP_SETPPCTYPE_COVERING); /*lint !e641*/
1946 
1947  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
1949  for( v = 0; v < consdata->nvars; ++v )
1950  {
1951  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
1952  }
1953 
1954  /* analyze the conflict */
1955  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1956 
1957  return SCIP_OKAY;
1958 }
1959 
1960 /** analyzes conflicting assignment on given constraint where two of the variables where assigned to one,
1961  * and adds conflict constraint to problem
1962  */
1963 static
1965  SCIP* scip, /**< SCIP data structure */
1966  SCIP_CONS* cons /**< set partitioning / packing / covering constraint that detected the conflict */
1967  )
1968 {
1969  SCIP_CONSDATA* consdata;
1970  int v;
1971  int n;
1973  /* conflict analysis can only be applied in solving stage and if it is applicable */
1975  return SCIP_OKAY;
1976 
1977  consdata = SCIPconsGetData(cons);
1978  assert(consdata != NULL);
1979  assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
1980  || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
1981 
1982  /* initialize conflict analysis, and add the two variables assigned to one to conflict candidate queue */
1984  n = 0;
1985  for( v = 0; v < consdata->nvars && n < 2; ++v )
1986  {
1987  if( SCIPvarGetLbLocal(consdata->vars[v]) > 0.5 )
1988  {
1989  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
1990  n++;
1991  }
1992  }
1993  assert(n == 2);
1994 
1995  /* analyze the conflict */
1996  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1997 
1998  return SCIP_OKAY;
1999 }
2000 
2001 /** checks constraint for violation only looking at the fixed variables, applies further fixings if possible */
2002 static
2004  SCIP* scip, /**< SCIP data structure */
2005  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint to be processed */
2006  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2007  int* nfixedvars, /**< pointer to count number of deleted variables */
2008  SCIP_Bool* addcut, /**< pointer to store whether this constraint must be added as a cut */
2009  SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
2010  )
2012  SCIP_CONSDATA* consdata;
2013 #ifndef NDEBUG
2014  int oldnfixedvars = *nfixedvars;
2015 #endif
2016 
2017  assert(cons != NULL);
2018  assert(SCIPconsGetHdlr(cons) != NULL);
2019  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2020  assert(cutoff != NULL);
2021  assert(nfixedvars != NULL);
2022  assert(addcut != NULL);
2023  assert(mustcheck != NULL);
2024 
2025  consdata = SCIPconsGetData(cons);
2026  assert(consdata != NULL);
2027  assert(consdata->nvars == 0 || consdata->vars != NULL);
2028  assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nvars);
2029  assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nvars);
2030 
2031  *addcut = FALSE;
2032  *mustcheck = TRUE;
2033 
2034  /*SCIPdebugMessage("processing constraint <%s> with respect to fixed variables (%d fixed to 0.0, %d fixed to 1.0)\n",
2035  SCIPconsGetName(cons), consdata->nfixedzeros, consdata->nfixedones);*/
2036 
2037  if( consdata->nfixedones == 1 )
2038  {
2039  /* exactly one variable is fixed to 1:
2040  * - a set covering constraint is feasible anyway and can be disabled
2041  * - all other variables in a set partitioning or packing constraint must be zero
2042  */
2043  if( consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
2044  {
2045  SCIPdebugMessage(" -> disabling set covering constraint <%s>\n", SCIPconsGetName(cons));
2046  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2047  }
2048  else
2049  {
2050  if( consdata->nfixedzeros < consdata->nvars - 1 )
2051  {
2052  SCIP_VAR** vars;
2053  SCIP_VAR* var;
2054 #ifndef NDEBUG
2055  SCIP_Bool fixedonefound;
2056 #endif
2057  SCIP_Bool infeasible;
2058  SCIP_Bool tightened;
2059  int nvars;
2060  int v;
2061  int oneidx = -1;
2062 
2063  SCIPdebugMessage(" -> fixing all other variables to zero in set packing/partitioning constraint <%s>\n",
2064  SCIPconsGetName(cons));
2065 
2066  /* unfixed variables exist: fix them to zero;
2067  * this could result in additional variables fixed to one due to aggregations; in this case, the
2068  * constraint is infeasible in local bounds
2069  */
2070  vars = consdata->vars;
2071  nvars = consdata->nvars;
2072 #ifndef NDEBUG
2073  fixedonefound = FALSE;
2074 #endif
2075  for( v = 0; v < nvars && consdata->nfixedones == 1; ++v )
2076  {
2077  var = vars[v];
2078  assert(SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), 1.0));
2079  if( SCIPvarGetLbLocal(var) < 0.5 )
2080  {
2081  SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, oneidx, &infeasible, &tightened) );
2082  assert(!infeasible);
2083 
2084  if( tightened )
2085  ++(*nfixedvars);
2086 
2087  SCIPdebugMessage(" -> fixed <%s> to zero (tightened=%u)\n", SCIPvarGetName(var), tightened);
2088  }
2089  else
2090  {
2091 #ifndef NDEBUG
2092  fixedonefound = TRUE;
2093 #endif
2094  oneidx = v;
2095  }
2096  }
2097  /* the fixed to one variable must have been found, and at least one variable must have been fixed */
2098  assert(consdata->nfixedones >= 2 || (fixedonefound && *nfixedvars > oldnfixedvars));
2099 
2100  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2101  }
2102 
2103  /* now all other variables are fixed to zero:
2104  * the constraint is feasible, and if it's not modifiable, it is redundant
2105  */
2106  if( !SCIPconsIsModifiable(cons) && consdata->nfixedones == 1 )
2107  {
2108  SCIPdebugMessage(" -> disabling set packing/partitioning constraint <%s>\n", SCIPconsGetName(cons));
2109  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2110  }
2111  }
2112  *mustcheck = FALSE;
2113  }
2114 
2115  if( consdata->nfixedones >= 2 )
2116  {
2117  /* at least two variables are fixed to 1:
2118  * - a set covering constraint is feasible anyway and can be disabled
2119  * - a set partitioning or packing constraint is infeasible
2120  */
2121  if( consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
2122  {
2123  SCIPdebugMessage(" -> disabling set covering constraint <%s>\n", SCIPconsGetName(cons));
2124  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2125  }
2126  else
2127  {
2128  SCIPdebugMessage(" -> conflict on set packing/partitioning constraint <%s>\n", SCIPconsGetName(cons));
2129 
2130  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2131 
2132  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
2133  SCIP_CALL( analyzeConflictOne(scip, cons) );
2134 
2135  *cutoff = TRUE;
2136  }
2137  *mustcheck = FALSE;
2138  }
2139  else if( consdata->nfixedzeros == consdata->nvars )
2140  {
2141  /* all variables are fixed to zero:
2142  * - a set packing constraint is feasible anyway, and if it's unmodifiable, it can be disabled
2143  * - a set partitioning or covering constraint is infeasible, and if it's unmodifiable, the node
2144  * can be cut off -- otherwise, the constraint must be added as a cut and further pricing must
2145  * be performed
2146  */
2147  assert(consdata->nfixedones == 0);
2148 
2149  if( consdata->setppctype == SCIP_SETPPCTYPE_PACKING ) /*lint !e641*/
2150  {
2151  if( !SCIPconsIsModifiable(cons) )
2152  {
2153  SCIPdebugMessage(" -> disabling set packing constraint <%s>\n", SCIPconsGetName(cons));
2154  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2155  }
2156  }
2157  else
2158  {
2159  SCIPdebugMessage(" -> set covering/partitioning constraint <%s> is infeasible\n", SCIPconsGetName(cons));
2160 
2161  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2162  if( SCIPconsIsModifiable(cons) )
2163  *addcut = TRUE;
2164  else
2165  {
2166  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
2167  SCIP_CALL( analyzeConflictZero(scip, cons) );
2168 
2169  *cutoff = TRUE;
2170  }
2171  }
2172  *mustcheck = FALSE;
2173  }
2174  else if( consdata->nfixedzeros == consdata->nvars - 1 && consdata->nfixedones == 0 )
2175  {
2176  /* all variables except one are fixed to zero:
2177  * - a set packing constraint is feasible anyway, and if it's unmodifiable, it can be disabled
2178  * - an unmodifiable set partitioning or covering constraint is feasible and can be disabled after the
2179  * remaining variable is fixed to one
2180  * - a modifiable set partitioning or covering constraint must be checked manually
2181  */
2182  if( consdata->setppctype == SCIP_SETPPCTYPE_PACKING ) /*lint !e641*/
2183  {
2184  if( !SCIPconsIsModifiable(cons) )
2185  {
2186  SCIPdebugMessage(" -> disabling set packing constraint <%s>\n", SCIPconsGetName(cons));
2187  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2188  }
2189  *mustcheck = FALSE;
2190  }
2191  else if( !SCIPconsIsModifiable(cons) )
2192  {
2193  SCIP_VAR** vars;
2194  SCIP_VAR* var;
2195  SCIP_Bool infeasible;
2196  SCIP_Bool tightened;
2197  int nvars;
2198  int v;
2199 
2200  /* search the single variable that can be fixed */
2201  vars = consdata->vars;
2202  nvars = consdata->nvars;
2203  for( v = 0; v < nvars; ++v )
2204  {
2205  var = vars[v];
2206  assert(SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)));
2207  assert(SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), 1.0));
2208  if( SCIPvarGetUbLocal(var) > 0.5 )
2209  {
2210  SCIPdebugMessage(" -> fixing remaining variable <%s> to one in set covering/partitioning constraint <%s>\n",
2211  SCIPvarGetName(var), SCIPconsGetName(cons));
2212  SCIP_CALL( SCIPinferBinvarCons(scip, var, TRUE, cons, 0, &infeasible, &tightened) );
2213  assert(!infeasible);
2214  assert(tightened);
2215 
2216  ++(*nfixedvars);
2217  break;
2218  }
2219  }
2220  assert(v < nvars);
2221  assert(consdata->nfixedzeros == consdata->nvars - 1);
2222  assert(consdata->nfixedones == 1);
2223 
2224  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2225  *mustcheck = FALSE;
2226  }
2227  }
2228  assert(consdata->nfixedzeros + consdata->nfixedones <= consdata->nvars);
2229 
2230  return SCIP_OKAY;
2231 }
2232 
2233 /** checks constraint for violation, returns TRUE iff constraint is feasible */
2234 static
2236  SCIP* scip, /**< SCIP data structure */
2237  SCIP_CONSDATA* consdata, /**< set partitioning / packing / covering constraint to be checked */
2238  SCIP_SOL* sol /**< primal CIP solution */
2239  )
2240 {
2241  SCIP_VAR** vars;
2242  SCIP_Real solval;
2244  SCIP_Real sumbound;
2245  int nvars;
2246  int v;
2247 
2248  /* calculate the constraint's activity */
2249  vars = consdata->vars;
2250  nvars = consdata->nvars;
2251  sum = 0.0;
2252  sumbound = ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING ? 1.0 : 1.0 + 2*SCIPfeastol(scip));
2253  for( v = 0; v < nvars && sum < sumbound; ++v ) /* if sum >= sumbound, the feasibility is clearly decided */
2254  {
2255  assert(SCIPvarIsBinary(vars[v]));
2256 
2257  solval = SCIPgetSolVal(scip, sol, vars[v]);
2258  assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
2259 
2260  sum += solval;
2261  }
2262 
2263  switch( consdata->setppctype )
2264  {
2266  return SCIPisFeasEQ(scip, sum, 1.0);
2268  return SCIPisFeasLE(scip, sum, 1.0);
2270  return SCIPisFeasGE(scip, sum, 1.0);
2271  default:
2272  SCIPerrorMessage("unknown setppc type\n");
2273  SCIPABORT();
2274  return FALSE; /*lint !e527*/
2275  }
2276 }
2277 
2278 /** creates an LP row in a set partitioning / packing / covering constraint data object */
2279 static
2281  SCIP* scip, /**< SCIP data structure */
2282  SCIP_CONS* cons /**< set partitioning / packing / covering constraint */
2283  )
2284 {
2285  SCIP_CONSDATA* consdata;
2286  SCIP_Real lhs;
2287  SCIP_Real rhs;
2289  consdata = SCIPconsGetData(cons);
2290  assert(consdata != NULL);
2291  assert(consdata->row == NULL);
2292 
2293  switch( consdata->setppctype )
2294  {
2296  lhs = 1.0;
2297  rhs = 1.0;
2298  break;
2300  lhs = -SCIPinfinity(scip);
2301  rhs = 1.0;
2302  break;
2304  lhs = 1.0;
2305  rhs = SCIPinfinity(scip);
2306  break;
2307  default:
2308  SCIPerrorMessage("unknown setppc type\n");
2309  return SCIP_INVALIDDATA;
2310  }
2311 
2312  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), lhs, rhs,
2314 
2315  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
2316 
2317  return SCIP_OKAY;
2318 }
2319 
2320 /** adds setppc constraint as cut to the LP */
2321 static
2323  SCIP* scip, /**< SCIP data structure */
2324  SCIP_CONS* cons, /**< setppc constraint */
2325  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
2326  SCIP_Bool* cutoff /**< whether a cutoff has been detected */
2327  )
2328 {
2329  SCIP_CONSDATA* consdata;
2331  assert( cutoff != NULL );
2332  *cutoff = FALSE;
2333 
2334  consdata = SCIPconsGetData(cons);
2335  assert(consdata != NULL);
2336 
2337  if( consdata->row == NULL )
2338  {
2339  /* convert set partitioning constraint data into LP row */
2340  SCIP_CALL( createRow(scip, cons) );
2341  }
2342  assert(consdata->row != NULL);
2343 
2344  /* insert LP row as cut */
2345  if( !SCIProwIsInLP(consdata->row) )
2346  {
2347  SCIPdebugMessage("adding constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
2348  SCIP_CALL( SCIPaddCut(scip, sol, consdata->row, FALSE, cutoff) );
2349  }
2350 
2351  return SCIP_OKAY;
2352 }
2353 
2354 /** checks constraint for violation, and adds it as a cut if possible */
2355 static
2357  SCIP* scip, /**< SCIP data structure */
2358  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint to be separated */
2359  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
2360  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2361  SCIP_Bool* separated, /**< pointer to store TRUE, if a cut was found */
2362  SCIP_Bool* reduceddom /**< pointer to store TRUE, if a domain reduction was found */
2363  )
2365  SCIP_CONSDATA* consdata;
2366  SCIP_Bool addcut;
2367  SCIP_Bool mustcheck;
2368 
2369  assert(cons != NULL);
2370  assert(SCIPconsGetHdlr(cons) != NULL);
2371  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2372  assert(cutoff != NULL);
2373  assert(separated != NULL);
2374  assert(reduceddom != NULL);
2375 
2376  *cutoff = FALSE;
2377 
2378  consdata = SCIPconsGetData(cons);
2379  assert(consdata != NULL);
2380  assert(consdata->nvars == 0 || consdata->vars != NULL);
2381  assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nvars);
2382  assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nvars);
2383 
2384  /* skip constraints already in the LP */
2385  if( sol == NULL && consdata->row != NULL && SCIProwIsInLP(consdata->row) )
2386  return SCIP_OKAY;
2387 
2388  SCIPdebugMessage("separating constraint <%s>\n", SCIPconsGetName(cons));
2389 
2390  /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
2391  if( sol == NULL )
2392  {
2393  int nfixedvars = 0;
2394 
2395  SCIP_CALL( processFixings(scip, cons, cutoff, &nfixedvars, &addcut, &mustcheck) );
2396 
2397  *reduceddom = (nfixedvars > 0);
2398  }
2399  else
2400  {
2401  mustcheck = TRUE;
2402  addcut = FALSE;
2403  }
2404 
2405  if( mustcheck )
2406  {
2407  assert(!addcut);
2408 
2409  /* variable's fixings didn't give us any information -> we have to check the constraint */
2410  if( sol == NULL && consdata->row != NULL )
2411  {
2412  SCIP_Real feasibility;
2413 
2414  assert(!SCIProwIsInLP(consdata->row));
2415  feasibility = SCIPgetRowLPFeasibility(scip, consdata->row);
2416  addcut = SCIPisFeasNegative(scip, feasibility);
2417  }
2418  else
2419  addcut = !checkCons(scip, consdata, sol);
2420 
2421  if( !addcut )
2422  {
2423  /* constraint was feasible -> increase age */
2424  SCIP_CALL( SCIPincConsAge(scip, cons) );
2425  }
2426  }
2427 
2428  if( addcut )
2429  {
2430  /* insert LP row as cut */
2431  SCIP_CALL( addCut(scip, cons, sol, cutoff) );
2432  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2433  *separated = TRUE;
2434  }
2435 
2436  return SCIP_OKAY;
2437 }
2438 
2439 /** enforces the pseudo solution on the given constraint */
2440 static
2442  SCIP* scip, /**< SCIP data structure */
2443  SCIP_CONS* cons, /**< set partitioning / packing / covering constraint to be separated */
2444  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2445  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
2446  SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
2447  SCIP_Bool* solvelp /**< pointer to store TRUE, if the LP has to be solved */
2448  )
2450  SCIP_Bool addcut;
2451  SCIP_Bool mustcheck;
2452  int nfixedvars = 0;
2453 
2454  assert(!SCIPhasCurrentNodeLP(scip));
2455  assert(cons != NULL);
2456  assert(SCIPconsGetHdlr(cons) != NULL);
2457  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2458  assert(cutoff != NULL);
2459  assert(infeasible != NULL);
2460  assert(reduceddom != NULL);
2461  assert(solvelp != NULL);
2462 
2463  /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
2464  SCIP_CALL( processFixings(scip, cons, cutoff, &nfixedvars, &addcut, &mustcheck) );
2465 
2466  *reduceddom = (nfixedvars > 0);
2467 
2468  if( mustcheck )
2469  {
2470  SCIP_CONSDATA* consdata;
2471 
2472  assert(!addcut);
2473 
2474  consdata = SCIPconsGetData(cons);
2475  assert(consdata != NULL);
2476 
2477  if( checkCons(scip, consdata, NULL) )
2478  {
2479  /* constraint was feasible -> increase age */
2480  SCIP_CALL( SCIPincConsAge(scip, cons) );
2481  }
2482  else
2483  {
2484  /* constraint was infeasible -> reset age */
2485  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2486  *infeasible = TRUE;
2487  }
2488  }
2489 
2490  if( addcut )
2491  {
2492  /* a cut must be added to the LP -> we have to solve the LP immediately */
2493  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2494  *solvelp = TRUE;
2495  }
2496 
2497  return SCIP_OKAY;
2498 }
2499 
2500 /** gets the key of the given element */
2501 static
2502 SCIP_DECL_HASHGETKEY(hashGetKeySetppccons)
2503 { /*lint --e{715}*/
2504  /* the key is the element itself */
2505  return elem;
2506 }
2507 
2508 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
2509 static
2510 SCIP_DECL_HASHKEYEQ(hashKeyEqSetppccons)
2511 {
2512 #ifndef NDEBUG
2513  SCIP* scip;
2514 #endif
2515  SCIP_CONSDATA* consdata1;
2516  SCIP_CONSDATA* consdata2;
2517  SCIP_Bool coefsequal;
2518  int i;
2519 
2520  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
2521  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
2522  assert(consdata1->sorted);
2523  assert(consdata2->sorted);
2524 #ifndef NDEBUG
2525  scip = (SCIP*)userptr;
2526  assert(scip != NULL);
2527 #endif
2528 
2529  /* checks trivial case */
2530  if( consdata1->nvars != consdata2->nvars )
2531  return FALSE;
2532 
2533  coefsequal = TRUE;
2534 
2535  for( i = 0; i < consdata1->nvars; ++i )
2536  {
2537  /* tests if variables are equal */
2538  if( consdata1->vars[i] != consdata2->vars[i] )
2539  {
2540  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
2541  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
2542  coefsequal = FALSE;
2543  break;
2544  }
2545  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
2546  }
2547 
2548  return coefsequal;
2549 }
2550 
2551 /** returns the hash value of the key */
2552 static
2553 SCIP_DECL_HASHKEYVAL(hashKeyValSetppccons)
2554 {
2555  SCIP_CONSDATA* consdata;
2556  unsigned int hashval;
2557  int minidx;
2558  int mididx;
2559  int maxidx;
2560 #ifndef NDEBUG
2561  SCIP* scip;
2562 
2563  scip = (SCIP*)userptr;
2564  assert(scip != NULL);
2565 #endif
2566 
2567  consdata = SCIPconsGetData((SCIP_CONS*)key);
2568  assert(consdata != NULL);
2569  assert(consdata->nvars > 0);
2570 
2571  /* sorts the constraints */
2572  consdataSort(consdata);
2573 
2574  minidx = SCIPvarGetIndex(consdata->vars[0]);
2575  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
2576  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
2577  assert(minidx >= 0 && minidx <= maxidx);
2578 
2579  hashval = (consdata->nvars << 29) + (minidx << 22) + (mididx << 11) + maxidx; /*lint !e701*/
2580 
2581  return hashval;
2582 }
2583 
2584 /** add extra clique-constraints resulting from a given cliquepartition to SCIP */
2585 static
2587  SCIP*const scip, /**< SCIP data structure */
2588  SCIP_VAR**const binvars, /**< binary variables to create clique constraints */
2589  int const nbinvars, /**< number of binary variables to create clique constraints */
2590  int*const cliquepartition, /**< clique partition of binary variables */
2591  int const ncliques, /**< number of cliques in cliquepartition */
2592  SCIP_CONS**const usefulconss, /**< storage for created constraints */
2593  int*const nusefulconss, /**< pointer to store number of useful created constraints */
2594  int const nrounds, /**< actual presolving round */
2595  int*const nfixedvars, /**< pointer to count number of deleted variables */
2596  int*const naddconss, /**< pointer to count number of added constraints */
2597  int*const ndelconss, /**< pointer to count number of deleted constraints */
2598  int*const nchgcoefs, /**< pointer to count number of deleted coefficients */
2599  SCIP_Bool*const cutoff /**< pointer to store if the problem is infeasible due to a fixing */
2600  )
2601 {
2602  SCIP_CONS* cliquecons;
2603  char name[SCIP_MAXSTRLEN];
2604  int lastclqidx;
2605  int nadded;
2606  int c;
2607  int v;
2608 
2609  assert(scip != NULL);
2610  assert(binvars != NULL || nbinvars == 0);
2611  assert(cliquepartition != NULL || nbinvars == 0);
2612  assert(ncliques >= 0 && ncliques <= nbinvars);
2613  assert(usefulconss != NULL);
2614  assert(nusefulconss != NULL);
2615  assert(nfixedvars != NULL);
2616  assert(naddconss != NULL);
2617  assert(ndelconss != NULL);
2618  assert(nchgcoefs != NULL);
2619  assert(cutoff != NULL);
2620 
2621  /* no given binary variables */
2622  if( nbinvars == 0 || ncliques == 0 )
2623  return SCIP_OKAY;
2624 
2625  assert(binvars != NULL);
2626  assert(cliquepartition != NULL);
2627 
2628  /* no useful clique information */
2629  if( ncliques == nbinvars )
2630  return SCIP_OKAY;
2631 
2632  lastclqidx = 0;
2633 
2634  /* @todo: maybe sort cliques and accordingly the variables so it will be faster to add the constraints */
2635  for( c = 0; c < ncliques - 1; ++c )
2636  {
2637  if( lastclqidx >= cliquepartition[c] )
2638  continue;
2639 
2640  nadded = 0;
2641 
2642  /* name the clique constraint */
2643  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "extra_clq_%d_round_%d", cliquepartition[c], nrounds);
2644  SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 0, NULL,
2646 
2647  /* add variables to clique constraint */
2648  for( v = c; v < nbinvars - 1; ++v )
2649  {
2650  if( cliquepartition[c] == cliquepartition[v] )
2651  {
2652  SCIP_CALL( addCoef(scip, cliquecons, binvars[v]) );
2653  ++nadded;
2654  }
2655  }
2656 
2657  /* @todo: try to find a good value for what are enough variables to create this constraint, maybe at least
2658  * (nmaxvars(over all conss)-nminvars(over all conss))/2 */
2659  if( nadded >= 2 )
2660  {
2661  SCIP_CONSDATA* cliqueconsdata;
2662 
2663  SCIPdebugMessage(" -> adding clique constraint: ");
2664  SCIPdebugPrintCons(scip, cliquecons, NULL);
2665  SCIP_CALL( SCIPaddCons(scip, cliquecons) );
2666  ++(*naddconss);
2667 
2668  /* we only want to consider merged constraints */
2669  SCIP_CALL( mergeMultiples(scip, cliquecons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
2670  if( *cutoff )
2671  {
2672  SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2673 
2674  return SCIP_OKAY;
2675  }
2676 
2677  cliqueconsdata = SCIPconsGetData(cliquecons);
2678  assert(cliqueconsdata != NULL);
2679 
2680  /* the artificial constraints could be deleled while merging */
2681  if( !SCIPconsIsDeleted(cliquecons) && nadded - cliqueconsdata->nfixedzeros >= 2 )
2682  {
2683  assert(cliqueconsdata->nfixedones == 0);
2684 
2685  /* save the type and constraint */
2686  usefulconss[*nusefulconss] = cliquecons;
2687  ++(*nusefulconss);
2688  }
2689  SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2690  }
2691  else
2692  {
2693  SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2694  }
2695  lastclqidx = cliquepartition[c];
2696  }
2697 
2698  return SCIP_OKAY;
2699 }
2700 
2701 
2702 /** start to collect setpartitioning and setpacking constraints, and try to remove fixed variables and merged these
2703  * constraints
2704  */
2705 static
2707  SCIP*const scip, /**< SCIP data structure */
2708  SCIP_CONS**const conss, /**< constraint set */
2709  int const nconss, /**< number of constraints in constraint set */
2710  SCIP_CONS**const usefulconss, /**< storage for created constraints */
2711  int*const nusefulconss, /**< pointer to store number of useful created constraints */
2712  int*const nfixedvars, /**< pointer to count number of deleted variables */
2713  int*const ndelconss, /**< pointer to count number of deleted constraints */
2714  int*const nchgcoefs, /**< pointer to count number of deleted coefficients */
2715  SCIP_Bool*const cutoff /**< pointer to store if the problem is infeasible due to a fixing */
2716  )
2717 {
2718  SCIP_CONS* cons;
2719  SCIP_CONSDATA* consdata;
2720  SCIP_Bool addcut;
2721  SCIP_Bool mustcheck;
2722  int nlocaladdconss = 0;
2723  int c;
2724 
2725  assert(scip != NULL);
2726  assert(conss != NULL || nconss == 0);
2727  assert(usefulconss != NULL);
2728  assert(nusefulconss != NULL);
2729  assert(nfixedvars != NULL);
2730  assert(ndelconss != NULL);
2731  assert(nchgcoefs != NULL);
2732  assert(cutoff != NULL);
2733 
2734  if( nconss == 0 )
2735  return SCIP_OKAY;
2736 
2737  assert(conss != NULL);
2738 
2739  for( c = nconss - 1; c >= 0; --c )
2740  {
2741  cons = conss[c];
2742 
2743  /* we only want to consider constraints with either active or negated of active variables, applyfixings removes
2744  * aggregated and fixed variables to zero, processFixings removes fixings to one but no aggregation
2745  *
2746  * @todo: maybe write a new method for deleting aggregations and all fixings
2747  */
2748  SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
2749  if( *cutoff )
2750  return SCIP_OKAY;
2751 
2752  if( SCIPconsIsDeleted(cons) )
2753  {
2754  /* reset nlocaladdconss and continue */
2755  nlocaladdconss = 0;
2756  continue;
2757  }
2758  assert(nlocaladdconss == 0);
2759 
2760  SCIP_CALL( processFixings(scip, cons, cutoff, nfixedvars, &addcut, &mustcheck) );
2761  if( *cutoff )
2762  return SCIP_OKAY;
2763 
2764  consdata = SCIPconsGetData(cons);
2765  assert(consdata != NULL);
2766 
2767  /* we only want to consider merged constraints */
2768  SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
2769  if( *cutoff )
2770  return SCIP_OKAY;
2771 
2772  if( SCIPconsIsModifiable(cons) || !SCIPconsIsActive(cons) )
2773  continue;
2774 
2775  assert(consdata->nfixedones == 0);
2776 
2777  if( consdata->nvars == 0 )
2778  continue;
2779 
2780  /* @todo: check for covering constraints with only two variables which are equal to a packing constraint with
2781  * negated variables */
2782  if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
2783  {
2784  assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
2785 
2786  usefulconss[*nusefulconss] = cons;
2787  ++(*nusefulconss);
2788  }
2789  }
2790 
2791  return SCIP_OKAY;
2792 }
2793 
2794 /** creating all necessary data in array structure, collect all clique constraint variables and occurances,
2795  * @note works only with merged and active not set-covering constraints
2796  */
2797 static
2799  SCIP*const scip, /**< SCIP data structure */
2800  SCIP_CONS**const usefulconss, /**< clique constraints */
2801  int const nusefulconss, /**< number of clique constraints */
2802  SCIP_VAR**const usefulvars, /**< storage for all found variables */
2803  int*const nusefulvars, /**< pointer to store number of added variables */
2804  SCIP_HASHMAP*const vartoindex, /**< hashmap mapping variables to indices */
2805  int*const varnconss, /**< storage for remembering the number of constraints a variable occurs */
2806  int*const maxnvarconsidx, /**< storage for the maximal number of occurances of a variable */
2807  int**const varconsidxs, /**< storage for constraint indices in which the corresponding variable exists */
2808  int*const maxnvars /**< pointer to store maximal number of variables of a constraint */
2809  )
2810 {
2811  SCIP_CONS* cons;
2812  SCIP_CONSDATA* consdata;
2813  int varindex;
2814  int c;
2815  int v;
2816 
2817  assert(scip != NULL);
2818  assert(usefulconss != NULL || nusefulconss == 0);
2819  assert(usefulvars != NULL);
2820  assert(nusefulvars != NULL);
2821  assert(vartoindex != NULL);
2822  assert(varnconss != NULL);
2823  assert(maxnvarconsidx != NULL);
2824  assert(varconsidxs != NULL);
2825  assert(maxnvars != NULL);
2826 
2827  if( nusefulconss == 0 )
2828  return SCIP_OKAY;
2829 
2830  assert(usefulconss != NULL);
2831 
2832  for( c = nusefulconss - 1; c >= 0; --c )
2833  {
2834  cons = usefulconss[c];
2835 
2836  assert(SCIPconsIsActive(cons));
2837 
2838  consdata = SCIPconsGetData(cons);
2839  assert(consdata != NULL);
2840 
2841  /* here we should have no covering constraints anymore and the constraint data should be merged */
2842  assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
2843  assert(consdata->merged);
2844 
2845  /* save maximal number of vars */
2846  if( consdata->nvars > *maxnvars )
2847  *maxnvars = consdata->nvars;
2848 
2849  /* adding variables and information about occurances to local data structure */
2850  for( v = consdata->nvars - 1; v >= 0; --v )
2851  {
2852  SCIP_VAR* var;
2853 
2854  var = consdata->vars[v];
2855  assert(var != NULL);
2856 
2857  /* don't remember fixed vars */
2858  if( SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetUbLocal(var) < 0.5 )
2859  continue;
2860 
2861  /* only collect active or negated active varibels */
2863 
2864  if( !SCIPhashmapExists(vartoindex, (void*) var) )
2865  {
2866  SCIP_VAR* tmpvar;
2867 
2868  usefulvars[*nusefulvars] = var;
2869  ++(*nusefulvars);
2870  varindex = *nusefulvars;
2871  SCIP_CALL( SCIPhashmapInsert(vartoindex, (void*) var, (void*) (size_t) varindex) );
2872 
2873  /* get the maximal number of occurances of this variable, if this variables */
2874  tmpvar = SCIPvarIsNegated(var) ? SCIPvarGetNegatedVar(var) : var;
2875  maxnvarconsidx[varindex] = SCIPvarGetNLocksDown(tmpvar) + SCIPvarGetNLocksUp(tmpvar);
2876  SCIP_CALL( SCIPallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) ); /*lint !e866*/
2877  }
2878  else
2879  {
2880  assert(SCIPhashmapGetImage(vartoindex, (void*) var) != NULL);
2881  varindex = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) var);
2882  }
2883 
2884  /* the number of occurances of a variable is not limited by the locks (so maybe we have to increase memory),
2885  * because for examples converted cuts are not check and therefore they have no locks on their variables */
2886  if( varnconss[varindex] == maxnvarconsidx[varindex] )
2887  {
2888  maxnvarconsidx[varindex] = SCIPcalcMemGrowSize(scip, maxnvarconsidx[varindex] + 1);
2889  SCIP_CALL( SCIPreallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) ); /*lint !e866*/
2890  }
2891 
2892  assert(varnconss[varindex] < maxnvarconsidx[varindex]);
2893  /* add the constraint number to the variable list */
2894  varconsidxs[varindex][varnconss[varindex]] = c;
2895  /* increase number of occurances for variables */
2896  ++(varnconss[varindex]);
2897  }
2898  } /* data structure created */
2899 
2900  return SCIP_OKAY;
2901 }
2902 
2903 /** correct clique data due to an aggregation */
2904 static
2906  SCIP_VAR*const var, /**< variable which appears less */
2907  int const considx, /**< constraint index which to remove */
2908  SCIP_HASHMAP*const vartoindex, /**< hashmap mapping variables to indices */
2909  int*const varnconss, /**< storage for remembering the number of constraints a variable occurs */
2910  int**const varconsidxs /**< storage for constraint indices in which the corresponding variable exists */
2911  )
2912 {
2913  int varindex;
2914  int i;
2915 #ifndef NDEBUG
2916  SCIP_Bool found = FALSE;
2917 #endif
2918 
2919  assert(var != NULL);
2920  assert(SCIPvarGetLbLocal(var) < 0.5 && SCIPvarGetUbLocal(var) > 0.5);
2921  assert(considx >= 0);
2922  assert(vartoindex != NULL);
2923  assert(varnconss != NULL);
2924  assert(varconsidxs != NULL);
2925 
2926  assert(SCIPhashmapGetImage(vartoindex, (void*) var) != NULL);
2927  varindex = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) var);
2928 
2929  /* remove entry of variable at the given position */
2930  for( i = 0; i < varnconss[varindex]; ++i )
2931  {
2932  if( varconsidxs[varindex][i] == considx )
2933  {
2934  varconsidxs[varindex][i] = varconsidxs[varindex][varnconss[varindex] - 1];
2935 #ifndef NDEBUG
2936  found = TRUE;
2937 #endif
2938  --(varnconss[varindex]);
2939  break;
2940  }
2941  }
2942  assert(found);
2943 }
2944 
2945 /* correct local data structure, add constraint entry to variable data */
2946 static
2948  SCIP*const scip, /**< SCIP data structure */
2949  SCIP_VAR*const addvar, /**< variable which was added */
2950  int const considx, /**< constraint index which to add */
2951  SCIP_Bool const maybenew, /**< could be a new variables, a negated of an already existing */
2952  SCIP_VAR**const usefulvars, /**< storage for all found variables */
2953  int*const nusefulvars, /**< pointer to store number of added variables */
2954  SCIP_HASHMAP*const vartoindex, /**< hashmap mapping variables to indices */
2955  int*const varnconss, /**< storage for remembering the number of constraints a variable occurs */
2956  int*const maxnvarconsidx, /**< storage for the maximal number of occurances of a variable */
2957  int**const varconsidxs /**< storage for constraint indices in which the corresponding variable exists */
2958  )
2959 {
2960  int varindex;
2961 
2962  assert(scip != NULL);
2963  assert(addvar != NULL);
2964  assert(SCIPvarGetLbLocal(addvar) < 0.5 && SCIPvarGetUbLocal(addvar) > 0.5);
2965  assert(usefulvars != NULL);
2966  assert(nusefulvars != NULL);
2967  assert(vartoindex != NULL);
2968  assert(varnconss != NULL);
2969  assert(maxnvarconsidx != NULL);
2970  assert(varconsidxs != NULL);
2971 
2972  /* we add the variable to the hashmap if its new */
2973  if( maybenew && !SCIPhashmapExists(vartoindex, (void*) addvar) )
2974  {
2975  assert(SCIPvarIsActive(addvar) || SCIPvarIsNegated(addvar));
2976  assert(SCIPvarGetNegatedVar(addvar) != NULL && SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(addvar)));
2977 
2978  /* @note because we can only have created a negated variable, and we already alloacted enough memory for
2979  * all (even not existing) negated variables the usefulvars array should be big enough
2980  */
2981  SCIPsortedvecInsertDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, addvar, nusefulvars, NULL);
2982  varindex = *nusefulvars;
2983  SCIP_CALL( SCIPhashmapInsert(vartoindex, (void*) addvar, (void*) (size_t) varindex) );
2984 
2985  assert(varconsidxs[varindex] == NULL);
2986 
2987  maxnvarconsidx[varindex] = 1;
2988  SCIP_CALL( SCIPallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) ); /*lint !e866*/
2989  varnconss[varindex] = 0;
2990  }
2991  else
2992  {
2993  varindex = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) addvar);
2994 
2995  /* grow the needed memory if we added a variable */
2996  if( varnconss[varindex] == maxnvarconsidx[varindex] )
2997  {
2998  maxnvarconsidx[varindex] = SCIPcalcMemGrowSize(scip, maxnvarconsidx[varindex] + 1);
2999  SCIP_CALL( SCIPreallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) ); /*lint !e866*/
3000  }
3001  }
3002  assert(varnconss[varindex] < maxnvarconsidx[varindex]);
3003  varconsidxs[varindex][varnconss[varindex]] = considx;
3004 
3005  /* increase number of occurances for variables */
3006  ++(varnconss[varindex]);
3007 
3008  return SCIP_OKAY;
3009 }
3010 
3011 
3012 /** check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
3013  * possible
3014  */
3015 static
3017  SCIP*const scip, /**< SCIP data structure */
3018  SCIP_CONS*const cons, /**< constraint */
3019  SCIP_Bool const aggregate, /**< try to aggregate if possible */
3020  SCIP_VAR** undoneaggrvars, /**< array to store aggregation variables, if aggregation is not performed
3021  * yet; both variables are standing next to each other; or NULL if
3022  * aggregate == TRUE
3023  */
3024  SCIP_Bool* undoneaggrtypes, /**< array to store aggregation type, if aggregation is not performed yet;
3025  * type FALSE means the aggregation is of the form x + y = 1; type TRUE means
3026  * the aggregation is of the form x = y; or NULL if aggregate == TRUE
3027  */
3028  int*const naggregations, /**< pointer to store number of aggregations which are not yet performed;
3029  * or NULL if aggregate == TRUE
3030  */
3031  int*const saggregations, /**< pointer to store size of the array for aggregation type and two times
3032  * the value is the size of the array for the aggregation variables which
3033  * are not yet performed; or NULL if aggregate == TRUE
3034  */
3035  int*const nfixedvars, /**< pointer to count number of deleted variables */
3036  int*const naggrvars, /**< pointer to count number of aggregated variables */
3037  int*const ndelconss, /**< pointer to count number of deleted constraints */
3038  SCIP_Bool*const cutoff /**< pointer to store if the problem is infeasible due to a fixing */
3039  )
3040 {
3041  SCIP_CONSDATA* consdata;
3042  SCIP_VAR** vars;
3043  int nvars;
3044  int v;
3045  SCIP_Bool fixed;
3046 
3047  assert(scip != NULL);
3048  assert(cons != NULL);
3049  assert(nfixedvars != NULL);
3050  assert(naggrvars != NULL);
3051  assert(ndelconss != NULL);
3052  assert(cutoff != NULL);
3053 
3054  if( !SCIPconsIsActive(cons) )
3055  return SCIP_OKAY;
3056 
3057  consdata = SCIPconsGetData(cons);
3058  assert(consdata != NULL);
3059 
3060  if( consdata->propagated )
3061  return SCIP_OKAY;
3062 
3063  consdata->propagated = TRUE;
3064 
3065  vars = consdata->vars;
3066  nvars = consdata->nvars;
3067 
3068  /* no variables left */
3069  if( nvars == 0 && !SCIPconsIsModifiable(cons) )
3070  {
3071  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3072  {
3073  SCIPdebugMessage("empty set-partition/-covering constraint <%s> found -> cutoff\n", SCIPconsGetName(cons));
3074  *cutoff = TRUE;
3075 
3076  return SCIP_OKAY;
3077  }
3078  else
3079  {
3080  assert(consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
3081 
3082  /* delete constraint */
3083  SCIPdebugMessage(" -> deleting constraint <%s>, no variables left\n", SCIPconsGetName(cons));
3084  SCIP_CALL( SCIPdelCons(scip, cons) );
3085  ++(*ndelconss);
3086 
3087  return SCIP_OKAY;
3088  }
3089  }
3090 
3091  /* more then two variables are fixed */
3092  if( consdata->nfixedones > 1 )
3093  {
3094  /* at least two variables are fixed to 1:
3095  * - a set covering constraint is feasible anyway and can be deleted
3096  * - a set partitioning or packing constraint is infeasible
3097  */
3098  if( consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3099  {
3100  /* delete constraint */
3101  SCIPdebugMessage(" -> deleting set-covering constraint <%s>, at least two variables are fixed to 1\n", SCIPconsGetName(cons));
3102  SCIP_CALL( SCIPdelCons(scip, cons) );
3103  ++(*ndelconss);
3104 
3105  return SCIP_OKAY;
3106  }
3107 
3108  SCIPdebugMessage("set partitioning / packing constraint <%s> is infeasible, %d variables fixed to one\n", SCIPconsGetName(cons), consdata->nfixedones);
3109  *cutoff = TRUE;
3110 
3111  return SCIP_OKAY;
3112  }
3113 
3114  if( consdata->nfixedones == 1 )
3115  {
3116  /* exactly one variable is fixed to 1:
3117  * - a set covering constraint is feasible anyway and can be disabled
3118  * - all other variables in a set partitioning or packing constraint must be zero
3119  */
3120  if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING && consdata->nfixedzeros < nvars - 1 ) /*lint !e641*/
3121  {
3122  assert(vars != NULL);
3123 
3124  for( v = nvars - 1; v >= 0; --v )
3125  {
3126  if( SCIPvarGetLbLocal(vars[v]) + 0.5 < SCIPvarGetUbLocal(vars[v]) )
3127  {
3128  SCIPdebugMessage("trying to fix <%s> to 0 due to at least one variable is already fixed to 1\n", SCIPvarGetName(vars[v]));
3129 
3130  /* fix all remaining variables to zero, constraint is already feasible or infeasible */
3131  SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, cutoff, &fixed) );
3132  if( *cutoff )
3133  {
3134  SCIPdebugMessage("setppc constraint <%s>: infeasible fixing <%s> == 0\n",
3135  SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
3136 
3137  return SCIP_OKAY;
3138  }
3139 
3140  assert(fixed);
3141  ++(*nfixedvars);
3142  }
3143  }
3144  }
3145 
3146  if( !SCIPconsIsModifiable(cons) || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3147  {
3148  /* delete constraint */
3149  SCIPdebugMessage(" -> deleting constraint <%s>, all variables are fixed\n", SCIPconsGetName(cons));
3150  assert(SCIPconsIsActive(cons));
3151  SCIP_CALL( SCIPdelCons(scip, cons) );
3152  ++(*ndelconss);
3153  }
3154 
3155  return SCIP_OKAY;
3156  }
3157 
3158  /* other propagations can only be done on not modifiable constraints */
3159  if( SCIPconsIsModifiable(cons) )
3160  return SCIP_OKAY;
3161 
3162  assert(vars != NULL);
3163 
3164  /* all variables were fixed to zero then either delete the constraint or stop with infeasibility */
3165  if( consdata->nfixedzeros == nvars )
3166  {
3167  assert(consdata->nfixedones == 0);
3168 
3169  /* all variables are fixed to zero:
3170  * - a set packing constraint is feasible anyway and can be deleted
3171  * - a set partitioning or covering constraint is infeasible, and so is the whole problem
3172  */
3173  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3174  {
3175  SCIPdebugMessage("set partitioning / covering constraint <%s> is infeasible\n", SCIPconsGetName(cons));
3176  *cutoff = TRUE;
3177 
3178  return SCIP_OKAY;
3179  }
3180 
3181  /* delete constraint */
3182  SCIPdebugMessage(" -> deleting set-packing constraint <%s>, all variables are fixed to zero\n", SCIPconsGetName(cons));
3183  assert(SCIPconsIsActive(cons));
3184  SCIP_CALL( SCIPdelCons(scip, cons) );
3185  ++(*ndelconss);
3186 
3187  return SCIP_OKAY;
3188  }
3189 
3190  /* all but one variable were fixed to zero then delete the constraint and for setpartition fix the remaining variable to 1 */
3191  if( consdata->nfixedzeros + 1 == nvars )
3192  {
3193  assert(consdata->nfixedones == 0);
3194 
3195  /* all variables except one are fixed to zero:
3196  * - a set packing constraint is feasible anyway, and can be deleted
3197  * - a set partitioning or covering constraint is feasible and can be deleted after the
3198  * remaining variable is fixed to one
3199  */
3200  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3201  {
3202  fixed = FALSE;
3203  for( v = nvars - 1; v >= 0; --v )
3204  {
3205  assert(SCIPvarGetLbLocal(vars[v]) < 0.5);
3206  if( SCIPvarGetUbLocal(vars[v]) > 0.5 )
3207  {
3208  SCIPdebugMessage("trying to fix <%s> to 1 due to it's the last unfixed variable is the set-partitioning/covering constraint\n", SCIPvarGetName(vars[v]));
3209 
3210  /* fix the remaining set partition variable */
3211  SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, cutoff, &fixed) );
3212  if( *cutoff )
3213  {
3214  SCIPdebugMessage("setppc constraint <%s>: infeasible fixing <%s> == 1\n",
3215  SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
3216 
3217  return SCIP_OKAY;
3218  }
3219 
3220  assert(fixed);
3221  ++(*nfixedvars);
3222  break;
3223  }
3224  }
3225  assert(fixed);
3226  }
3227 
3228  /* delete constraint */
3229  SCIPdebugMessage(" -> deleting constraint <%s>, all %svariables are fixed\n", SCIPconsGetName(cons), consdata->setppctype == (int) SCIP_SETPPCTYPE_PACKING ? "but one " : "");
3230  assert(SCIPconsIsActive(cons));
3231  SCIP_CALL( SCIPdelCons(scip, cons) );
3232  ++(*ndelconss);
3233 
3234  return SCIP_OKAY;
3235  }
3236 
3237  /* all but two variable were fixed to zero in a setpartitioning constraint then delete the constraint and
3238  * aggregate the remaining two variables
3239  */
3240  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata->nfixedzeros + 2 == nvars ) /*lint !e641*/
3241  {
3242  SCIP_VAR* var;
3243 
3244  var = NULL;
3245  for( v = nvars - 1; v >= 0; --v )
3246  {
3247  assert(SCIPvarGetLbLocal(vars[v]) < 0.5);
3248 
3249  if( SCIPvarGetUbLocal(vars[v]) > 0.5 )
3250  {
3251  if( var == NULL )
3252  var = vars[v];
3253  else
3254  {
3255  SCIP_Bool redundant;
3256  SCIP_Bool aggregated;
3257 #ifdef VARUSES
3258  SCIP_CONSHDLR* conshdlr;
3259  SCIP_CONSHDLRDATA* conshdlrdata;
3260 
3261  /* get event handler and event handler data */
3262  conshdlr = SCIPconsGetHdlr(cons);
3263  assert(conshdlr != NULL);
3264  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3265  assert(conshdlrdata != NULL);
3266 #endif
3267  if( aggregate )
3268  {
3269  SCIPdebugMessage("trying to aggregate <%s> and <%s> due to they are the last two unfixed variables in the set partitionning constraint <%s>\n", SCIPvarGetName(var), SCIPvarGetName(vars[v]), SCIPconsGetName(cons));
3270 
3271 #ifdef VARUSES
3272  /* in order to not mess up the variable usage counting, we have to decrease usage counting, aggregate,
3273  * and increase usage counting again
3274  */
3275  SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, var) );
3276  SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, vars[v]) );
3277 #endif
3278 
3279  /* aggregate last remaining variables in the set partitioning constraint */
3280  SCIP_CALL( SCIPaggregateVars(scip, var, vars[v], 1.0, 1.0, 1.0, cutoff, &redundant, &aggregated) );
3281  if( *cutoff )
3282  {
3283  SCIPdebugMessage("set partitioning constraint <%s>: aggregate <%s> + <%s> == 1\n",
3284  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(vars[v]));
3285 
3286  return SCIP_OKAY;
3287  }
3288 
3289 #ifdef VARUSES
3290  /* increase variable usage counting again */
3291  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var) );
3292  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, vars[v]) );
3293 #endif
3294 
3295  if( aggregated )
3296  ++(*naggrvars);
3297 
3298  if( redundant )
3299  {
3300  /* delete constraint */
3301  SCIPdebugMessage(" -> deleting constraint <%s>, all variables are fixed\n", SCIPconsGetName(cons));
3302  assert(SCIPconsIsActive(cons));
3303  SCIP_CALL( SCIPdelCons(scip, cons) );
3304  ++(*ndelconss);
3305  }
3306  }
3307  else
3308  {
3309  assert(undoneaggrvars != NULL);
3310  assert(undoneaggrtypes != NULL);
3311  assert(naggregations != NULL);
3312  assert(saggregations != NULL);
3313 
3314  SCIPdebugMessage("memorize the aggregation of <%s> + <%s> = 1, because they are the last two unfixed variable in the set partitioning constraints <%s>\n", SCIPvarGetName(var), SCIPvarGetName(vars[v]), SCIPconsGetName(cons));
3315 
3316  /* resize the aggregation arrays if necessary */
3317  if( *saggregations == *naggregations )
3318  {
3319  *saggregations = SCIPcalcMemGrowSize(scip, *naggregations + 1);
3320  assert(*saggregations > *naggregations);
3321  SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrtypes, *saggregations) );
3322  SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrvars, 2 * (*saggregations)) );
3323 
3324  /* clear the aggregation type array to set the default to the aggregation of the form x + y = 1 */
3325  BMSclearMemoryArray(&(undoneaggrtypes[*naggregations]), *saggregations - *naggregations); /*lint !e866*/
3326  }
3327 
3328  /* memorize aagregation variables*/
3329  assert(undoneaggrtypes[*naggregations] == FALSE);
3330  undoneaggrvars[2 * (*naggregations)] = var;
3331  undoneaggrvars[2 * (*naggregations) + 1] = vars[v];
3332  ++(*naggregations);
3333 
3334  if( !SCIPdoNotAggr(scip) )
3335  {
3336  /* delete constraint */
3337  SCIPdebugMessage(" -> deleting constraint <%s>, all variables are fixed\n", SCIPconsGetName(cons));
3338  assert(SCIPconsIsActive(cons));
3339  SCIP_CALL( SCIPdelCons(scip, cons) );
3340  ++(*ndelconss);
3341  }
3342  }
3343 
3344  return SCIP_OKAY;
3345  }
3346  }
3347  }
3348  /* we should never be here, because the last to unfixed variables should have been either aggregated or a cutoff
3349  * should be applied
3350  */
3351  assert(FALSE);
3352  }
3353 
3354  return SCIP_OKAY;
3355 }
3356 
3357 /** check for overlapping constraint */
3358 static
3360  SCIP*const scip, /**< SCIP data structure */
3361  SCIP_CONS*const cons, /**< constraint which may overlap */
3362  int const considx, /**< constriant index to avoid checking against itself */
3363  int const endidx, /**< end index to check against given constraint */
3364  SCIP_CONS**const usefulconss, /**< clique constraints */
3365  int const nusefulconss, /**< number of clique constraints */
3366  SCIP_VAR**const usefulvars, /**< storage for all found variables */
3367  int*const nusefulvars, /**< pointer to store number of added variables */
3368  SCIP_HASHMAP*const vartoindex, /**< hashmap mapping variables to indices */
3369  int*const varnconss, /**< storage for remembering the number of constraints a variable occurs */
3370  int*const maxnvarconsidx, /**< storage for the maximal number of occurances of a variable */
3371  int**const varconsidxs, /**< storage for constraint indices in which the corresponding variable exists */
3372  int*const countofoverlapping, /**< the amount of variables of cons which overlap in all other constraint */
3373  SCIP_Bool const shrinking, /**< try to replace some variables with one variable */
3374  SCIP_Bool*const chgcons, /**< pointer to store if the given constraint was changed, due to
3375  * added/deleted variables
3376  */
3377  SCIP_VAR** undoneaggrvars, /**< array to store aggregation variables, if aggregation is not performed
3378  * yet; both variables are standing next to each other;
3379  */
3380  SCIP_Bool* undoneaggrtypes, /**< array to store aggregation type, if aggregation is not performed yet;
3381  * type FALSE means the aggregation is of the form x + y = 1; type TRUE means
3382  * the aggregation is of the form x = y;
3383  */
3384  int*const naggregations, /**< pointer to store number of aggregations which are not yet performed; */
3385  int*const saggregations, /**< pointer to store size of the array for aggregation type and two times
3386  * the value is the size of the array for the aggregation variables which
3387  * are not yet performed;
3388  */
3389  int*const nfixedvars, /**< pointer to count number of deleted variables */
3390  int*const naggrvars, /**< pointer to count number of aggregated variables */
3391  int*const nchgcoefs, /**< pointer to count number of changed coefficients */
3392  int*const ndelconss, /**< pointer to count number of deleted constraints */
3393  SCIP_Bool*const cutoff /**< pointer to store if the problem is infeasible due to a fixing */
3394  )
3395 {
3396  SCIP_CONS* cons1;
3397  SCIP_CONSDATA* consdata1;
3398  SCIP_CONSDATA* consdata;
3399  SCIP_VAR** vars;
3400  SCIP_VAR** vars1;
3401  SCIP_VAR* var;
3402  SCIP_VAR* var1;
3403  SCIP_Bool fixed;
3404  SCIP_Bool overlapdestroyed;
3405  int nvars;
3406  int nvars1;
3407  int oldnfixedzeros;
3408  int c;
3409  int v;
3410  int v1;
3411 #ifndef NDEBUG
3412  int oldnaggrvars;
3413 #endif
3414 
3415  assert(scip != NULL);
3416  assert(cons != NULL);
3417  assert(usefulconss != NULL && nusefulconss > 0);
3418  assert(0 <= considx && considx < nusefulconss);
3419  assert(usefulconss[considx] == cons);
3420  assert(0 <= endidx && endidx <= nusefulconss);
3421  assert(countofoverlapping != NULL);
3422  assert(chgcons != NULL);
3423  assert(undoneaggrvars != NULL);
3424  assert(undoneaggrtypes != NULL);
3425  assert(naggregations != NULL);
3426  assert(saggregations != NULL);
3427  assert(nfixedvars != NULL);
3428  assert(naggrvars != NULL);
3429  assert(nchgcoefs != NULL);
3430  assert(ndelconss != NULL);
3431  assert(cutoff != NULL);
3432 
3433  if( !SCIPconsIsActive(cons) )
3434  return SCIP_OKAY;
3435 
3436  consdata = SCIPconsGetData(cons);
3437  assert(consdata != NULL);
3438 
3439  nvars = consdata->nvars;
3440 
3441  if( nvars == 0 )
3442  return SCIP_OKAY;
3443 
3444  vars = consdata->vars;
3445  assert(vars != NULL);
3446 
3447  oldnfixedzeros = consdata->nfixedzeros;
3448  overlapdestroyed = FALSE;
3449 
3450  /* first check for redundancy for all unprocessed constraints with cons */
3451  for( c = endidx - 1; c >= 0; --c )
3452  {
3453  cons1 = usefulconss[c];
3454 
3455  if( !SCIPconsIsActive(cons1) )
3456  continue;
3457 
3458  /* avoid checking constraint against itself */
3459  if( considx == c )
3460  continue;
3461 
3462  assert(usefulconss[c] != cons);
3463 
3464 #ifndef NDEBUG
3465  oldnaggrvars = *naggrvars;
3466 #endif
3467 
3468  /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
3469  * possible
3470  */
3471  SCIP_CALL( presolvePropagateCons(scip, cons1, FALSE, undoneaggrvars, undoneaggrtypes, naggregations, saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
3472 
3473  if( *cutoff )
3474  return SCIP_OKAY;
3475 
3476  /* we can't handle aggregated variables later on so we should have saved them for later */
3477  assert(*naggrvars == oldnaggrvars);
3478 
3479  if( !SCIPconsIsActive(cons1) )
3480  continue;
3481 
3482  consdata1 = SCIPconsGetData(cons1);
3483  assert(consdata1 != NULL);
3484 
3485  nvars1 = consdata1->nvars;
3486 
3487  if( nvars1 == 0 )
3488  continue;
3489 
3490  /* no more variables from cons as nvars1 can overlap */
3491  assert(countofoverlapping[c] <= nvars1);
3492 
3493  /* constraint should not be redundant or infeasible */
3494  assert(consdata1->nfixedones == 0);
3495 
3496  SCIPdebugMessage("constraint <%s> overlaps with constraint <%s> by %d variables\n", SCIPconsGetName(cons), SCIPconsGetName(cons1), countofoverlapping[c]);
3497 
3498  /* cons1 includes cons */
3499  if( !overlapdestroyed && countofoverlapping[c] == nvars - consdata->nfixedzeros )
3500  {
3501  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
3502  {
3503  if( nvars - consdata->nfixedzeros < nvars1 )
3504  {
3505 #ifndef NDEBUG
3506  SCIP_Bool negated0;
3507  SCIP_Bool negated1;
3508 #endif
3509 
3510  /* both constraints should stay merged */
3511  assert(consdata->merged);
3512  assert(consdata1->merged);
3513 
3514  vars1 = consdata1->vars;
3515  assert(vars1 != NULL);
3516 
3517  /* sorting array after indices of variables, negated and active counterparts would stand side by side */
3518  SCIPsortDownPtr((void**)vars1, SCIPvarCompActiveAndNegated, nvars1);
3519  /* standard setppc-sorting now lost */
3520  consdata1->sorted = FALSE;
3521 
3522  /* iterate over the both cliques variables the "same" time */
3523  for( v = nvars - 1, v1 = nvars1 - 1; v >= 0 && v1 >= 0; )
3524  {
3525  if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3526  {
3527  --v1;
3528  continue;
3529  }
3530  if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
3531  {
3532  --v;
3533  continue;
3534  }
3535 
3536  /* all variables inside the second clique constraint should be either active or negated of an active one */
3537  assert(SCIPvarIsActive(vars1[v1]) || (SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1]))));
3538 
3539  /* get not negated variable and clique value in cons */
3540  if( SCIPvarGetStatus(vars[v]) != SCIP_VARSTATUS_NEGATED )
3541  {
3542  var = vars[v];
3543 #ifndef NDEBUG
3544  negated0 = FALSE;
3545 #endif
3546  }
3547  else
3548  {
3549  var = SCIPvarGetNegationVar(vars[v]);
3550 #ifndef NDEBUG
3551  negated0 = TRUE;
3552 #endif
3553  }
3554 
3555  /* get active variable and clique value of next variable */
3556  if( SCIPvarIsActive(vars1[v1]) )
3557  {
3558  var1 = vars1[v1];
3559 #ifndef NDEBUG
3560  negated1 = FALSE;
3561 #endif
3562  }
3563  else
3564  {
3566  var1 = SCIPvarGetNegationVar(vars1[v1]);
3567 #ifndef NDEBUG
3568  negated1 = TRUE;
3569 #endif
3570  }
3571 
3572  /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
3573  if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1) )
3574  --v;
3575  /* variable index in the constraint is greater than the other one, so fix this variable */
3576  else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1) )
3577  {
3578  SCIPdebugMessage("trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(vars1[v1]));
3579 
3580  /* fix all variables except the one which has the negated var in the clique to zero */
3581  SCIP_CALL( SCIPfixVar(scip, vars1[v1], 0.0, cutoff, &fixed) );
3582  if( *cutoff )
3583  {
3584  SCIPdebugMessage("fixing led to cutoff\n");
3585 
3586  return SCIP_OKAY;
3587  }
3588 
3589  assert(fixed);
3590  ++(*nfixedvars);
3591  --v1;
3592  }
3593  else
3594  {
3595  /* because the constraint's are merged it is not possible that one constraint contains a negated
3596  * variable of another and because all variables in cons are in cons1 this should be really the
3597  * same variable here; so we can decrease v and v1
3598  */
3599  assert(negated0 == negated1);
3600 
3601  --v;
3602  --v1;
3603  }
3604  }
3605  /* maybe we ended because of cons(v reached -1) so try to add rest of cons1 to cons */
3606  for( ; v1 >= 0; --v1)
3607  {
3608  if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3609  continue;
3610 
3611  SCIPdebugMessage("trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(vars1[v1]));
3612 
3613  /* fix all variables except the one which has the negated var in the clique to zero */
3614  SCIP_CALL( SCIPfixVar(scip, vars1[v1], 0.0, cutoff, &fixed) );
3615  if( *cutoff )
3616  {
3617  SCIPdebugMessage("fixing led to cutoff\n");
3618 
3619  return SCIP_OKAY;
3620  }
3621 
3622  assert(fixed);
3623  ++(*nfixedvars);
3624  }
3625  }
3626 
3627  /* if caused by all fixings now this set partitioning constraint doesn't have any variable which was
3628  * fixed to one, it's infeasible */
3629  if( consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nfixedzeros == nvars1 && consdata1->nfixedones != 1 ) /*lint !e641*/
3630  {
3631  SCIPdebugMessage("all variables in the set-partitioning constraint <%s> are fixed to zero, this leads to a cutoff\n", SCIPconsGetName(cons1));
3632  *cutoff = TRUE;
3633 
3634  return SCIP_OKAY;
3635  }
3636 
3637  assert(SCIPconsIsActive(cons1));
3638  /* delete second constraint */
3639  SCIPdebugMessage(" -> deleting constraint <%s> number <%d> because it includes the setpartitioning constraint <%s> number <%d>\n", SCIPconsGetName(cons1), c, SCIPconsGetName(cons), considx);
3640 
3641  SCIP_CALL( SCIPupdateConsFlags(scip, cons, cons1) );
3642  SCIP_CALL( SCIPdelCons(scip, cons1) );
3643  ++(*ndelconss);
3644  }
3645  /* could already be deleted because the constraint was included in another set partition constraint */
3646  else if( SCIPconsIsActive(cons) )
3647  {
3648  /* delete cons due to redundancy to cons1 */
3649  SCIPdebugMessage(" -> deleting constraint <%s> number <%d> due to inclusion in constraint <%s> number <%d>\n", SCIPconsGetName(cons), considx, SCIPconsGetName(cons1), c);
3650 
3651  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
3652  SCIP_CALL( SCIPdelCons(scip, cons) );
3653  ++(*ndelconss);
3654  }
3655  }
3656  /* cons includes cons1
3657  *
3658  * @note that zero fixations from above can only appear through a set-partitioning constraint, this means if
3659  * cons was the set-partitioning constraint only variables which are not in this constraint could be fixed
3660  * to zero, and this also means that the overlapping variables in this particular case are still active or
3661  * fixed to 1
3662  * later on it could be possible that even variables in cons are fixed to zero, which can lead to wrong
3663  * results when checking if countofoverlapping[c] + consdata1->nfixedzeros == nvars1, because a fixed
3664  * variable could be counted twice
3665  */
3666  else if( (!overlapdestroyed && countofoverlapping[c] + consdata1->nfixedzeros == nvars1) || countofoverlapping[c] == nvars1 )
3667  {
3668  /* even in deleted constraints we may fix unfixed variables */
3669  if( consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
3670  {
3671  const int oldnfixedvars = *nfixedvars;
3672 #ifndef NDEBUG
3673  SCIP_Bool negated0;
3674  SCIP_Bool negated1;
3675 #endif
3676  /* both constraints should stay merged */
3677  assert(consdata->merged);
3678  assert(consdata1->merged);
3679 
3680  vars1 = consdata1->vars;
3681 
3682  /* sorting array after indices of variables, negated and active counterparts would stand side by side */
3683  SCIPsortDownPtr((void**)vars1, SCIPvarCompActiveAndNegated, nvars1);
3684  /* standard setppc-sorting now lost */
3685  consdata1->sorted = FALSE;
3686 
3687  /* iterate over the both cliques variables the "same" time */
3688  for( v = nvars - 1, v1 = nvars1 - 1; v >= 0 && v1 >= 0; )
3689  {
3690  if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3691  {
3692  --v1;
3693  continue;
3694  }
3695  if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
3696  {
3697  --v;
3698  continue;
3699  }
3700 
3701  /* all variables inside the second clique constraint should be either active or negated of an active one */
3702  assert(SCIPvarIsActive(vars1[v1]) || (SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1]))));
3703  /* all variables inside the first clique constraint should be either active or negated of an active one */
3704  assert(SCIPvarIsActive(vars[v]) || (SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v]))));
3705 
3706  /* get not negated variable and clique value in cons */
3707  if( SCIPvarIsActive(vars[v]) )
3708  {
3709  var = vars[v];
3710 #ifndef NDEBUG
3711  negated0 = FALSE;
3712 #endif
3713  }
3714  else
3715  {
3717  var = SCIPvarGetNegationVar(vars[v]);
3718 #ifndef NDEBUG
3719  negated0 = TRUE;
3720 #endif
3721  }
3722 
3723  /* get active variable and clique value of next variable */
3724  if( SCIPvarIsActive(vars1[v1]) )
3725  {
3726  var1 = vars1[v1];
3727 #ifndef NDEBUG
3728  negated1 = FALSE;
3729 #endif
3730  }
3731  else
3732  {
3734  var1 = SCIPvarGetNegationVar(vars1[v1]);
3735 #ifndef NDEBUG
3736  negated1 = TRUE;
3737 #endif
3738  }
3739 
3740  /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
3741  if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1) )
3742  {
3743  SCIPdebugMessage("trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(var));
3744 
3745  /* fix all variables except the one which has the negated var in the clique to zero */
3746  SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, cutoff, &fixed) );
3747  if( *cutoff )
3748  {
3749  SCIPdebugMessage("fixing led to cutoff\n");
3750 
3751  return SCIP_OKAY;
3752  }
3753 
3754  assert(fixed);
3755  ++(*nfixedvars);
3756 
3757  --v;
3758  }
3759  /* variable index in the constraint is greater than the other one, so fix this variable */
3760  else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1) )
3761  --v1;
3762  else
3763  {
3764  /* because the constraint's are merged it is not possible that one constraint contains a negated
3765  * variable of another and because all variables in cons1 are in cons this should be really the same
3766  * variable here; so we can decrease v and v1
3767  */
3768  assert(negated0 == negated1);
3769 
3770  --v;
3771  --v1;
3772  }
3773  }
3774 
3775  /* maybe we ended because of cons1(v1 reached -1) so try to add rest of cons to cons1 */
3776  for( ; v >= 0; --v)
3777  {
3778  if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
3779  continue;
3780 
3781  SCIPdebugMessage("trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(vars[v]));
3782 
3783  /* fix all variables except the one which has the negated var in the clique to zero */
3784  SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, cutoff, &fixed) );
3785  if( *cutoff )
3786  {
3787  SCIPdebugMessage("fixing led to cutoff\n");
3788 
3789  return SCIP_OKAY;
3790  }
3791 
3792  assert(fixed);
3793  ++(*nfixedvars);
3794  }
3795 
3796  /* if caused by all fixings now this set partitioning constraint doesn't have any variable which was
3797  * fixed to one, it's infeasible */
3798  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata->nfixedzeros == nvars && consdata->nfixedones != 1 ) /*lint !e641*/
3799  {
3800  SCIPdebugMessage("all variables in the set-partitioning constraint <%s> are fixed to zero, this leads to a cutoff\n", SCIPconsGetName(cons1));
3801  *cutoff = TRUE;
3802 
3803  return SCIP_OKAY;
3804  }
3805 
3806  /* could already be deleted because the constraint was included in another set partition constraint */
3807  if( SCIPconsIsActive(cons) )
3808  {
3809  /* delete cons because it include another set partitioning constraint */
3810  SCIPdebugMessage(" -> deleting constraint <%s> number <%d> because it includes the setpartitioning constraint <%s> number <%d>\n", SCIPconsGetName(cons), considx, SCIPconsGetName(cons1), c);
3811  assert(SCIPconsIsActive(cons));
3812 
3813  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
3814  SCIP_CALL( SCIPdelCons(scip, cons) );
3815  ++(*ndelconss);
3816  }
3817 
3818  /* due to fixings in cons0 mark overlapping invalid for checking with fixedzero variables together */
3819  if( oldnfixedvars < *nfixedvars )
3820  overlapdestroyed = TRUE;
3821  }
3822  else
3823  {
3824  assert(consdata1->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
3825 
3826  /* delete cons1 due to redundancy to cons */
3827  SCIPdebugMessage(" -> deleting constraint <%s> number <%d> due to inclusion in constraint <%s> number <%d>\n", SCIPconsGetName(cons1), c, SCIPconsGetName(cons), considx);
3828  assert(SCIPconsIsActive(cons1));
3829 
3830  SCIP_CALL( SCIPupdateConsFlags(scip, cons, cons1) );
3831  SCIP_CALL( SCIPdelCons(scip, cons1) );
3832  ++(*ndelconss);
3833  }
3834  }
3835  /* if cons has only one unfixed variable which is not in cons1 and cons1 has one variable which does not appaer in
3836  * cons and both constraints are setpartitioning constraints we might aggregate both not overlapping variables and
3837  * delete one constraint
3838  */
3839  else if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars - oldnfixedzeros - 1 && countofoverlapping[c] == nvars1 - 1 ) /*lint !e641*/
3840  {
3841  SCIP_VAR* aggvar1;
3842  SCIP_VAR* aggvar2;
3843  SCIP_Bool negated0;
3844  SCIP_Bool negated1;
3845 
3846  aggvar1 = NULL;
3847  aggvar2 = NULL;
3848 
3849  /* both constraints should stay merged */
3850  assert(consdata->merged);
3851  assert(consdata1->merged);
3852 
3853  vars1 = consdata1->vars;
3854 
3855  /* sorting array after indices of variables, negated and active counterparts would stand side by side */
3856  SCIPsortDownPtr((void**)vars1, SCIPvarCompActiveAndNegated, nvars1);
3857  /* standard setppc-sorting now lost */
3858  consdata1->sorted = FALSE;
3859 
3860  /* iterate over the both cliques variables the "same" time */
3861  for( v = nvars - 1, v1 = nvars1 - 1; v >= 0 && v1 >= 0; )
3862  {
3863  if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3864  {
3865  --v1;
3866  continue;
3867  }
3868  if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
3869  {
3870  --v;
3871  continue;
3872  }
3873 
3874  /* all variables inside the second clique constraint should be either active or negated of an active one */
3875  assert(SCIPvarIsActive(vars1[v1]) || (SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1]))));
3876  /* all variables inside the first clique constraint should be either active or negated of an active one */
3877  assert(SCIPvarIsActive(vars[v]) || (SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v]))));
3878 
3879  /* get not negated variable and clique value in cons */
3880  if( SCIPvarIsActive(vars[v]) )
3881  {
3882  var = vars[v];
3883  negated0 = FALSE;
3884  }
3885  else
3886  {
3888  var = SCIPvarGetNegationVar(vars[v]);
3889  negated0 = TRUE;
3890  }
3891 
3892  /* get active variable and clique value of next variable */
3893  if( SCIPvarIsActive(vars1[v1]) )
3894  {
3895  var1 = vars1[v1];
3896  negated1 = FALSE;
3897  }
3898  else
3899  {
3901  var1 = SCIPvarGetNegationVar(vars1[v1]);
3902  negated1 = TRUE;
3903  }
3904 
3905  /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
3906  if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1) )
3907  {
3908  assert(aggvar1 == NULL);
3909  aggvar1 = vars[v];
3910 
3911  if( aggvar2 != NULL )
3912  break;
3913 
3914  --v;
3915  }
3916  /* variable index in the constraint is greater than the other one, so fix this variable */
3917  else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1) )
3918  {
3919  assert(aggvar2 == NULL);
3920  aggvar2 = vars1[v1];
3921 
3922  if( aggvar1 != NULL )
3923  break;
3924 
3925  --v1;
3926  }
3927  else
3928  {
3929  /* because the constraint's are merged it is not possible that one constraint contains a negated variable
3930  * of another, but both variables in both constraints still can be negated to each other
3931  */
3932  if( negated0 != negated1 )
3933  {
3934  /* cons is except for one variable equal to cons1 and the unequal variable in cons is negated
3935  * to the one in cons1, so the problem is infeasible
3936  */
3937  SCIPdebugMessage("two set-partitioning constraint <%s> and <%s> have only one variable not in common, but this variable <%s> appears in one constraint as the negated version as in the other constraint\n", SCIPconsGetName(cons), SCIPconsGetName(cons1), SCIPvarGetName(vars[v]));
3938  *cutoff = TRUE;
3939 
3940  return SCIP_OKAY;
3941  }
3942  --v;
3943  --v1;
3944  }
3945  }
3946 
3947  /* due to fixings, it is possible that there are no active variables left, we we did not recognize which variables we could aggregate */
3948  if( aggvar1 == NULL && aggvar2 == NULL )
3949  continue;
3950 
3951  /* determine second aggregation var, if not yet done */
3952  if( aggvar2 == NULL )
3953  {
3954  for( ; v1 >= 0; --v1)
3955  {
3956  if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3957  continue;
3958 
3959  aggvar2 = vars1[v1];
3960  break;
3961  }
3962  }
3963  /* determine first aggregation var, if not yet done */
3964  else if( aggvar1 == NULL )
3965  {
3966  /* maybe we ended because of cons1(v1 reached -1) so find the aggvar1 in cons */
3967  for( ; v >= 0; --v)
3968  {
3969  if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
3970  continue;
3971 
3972  aggvar1 = vars[v];
3973  break;
3974  }
3975  }
3976 
3977  /* due to fixings, it is possible that there are no active variables left, we we did not recognize which variables we could aggregate */
3978  if( aggvar1 == NULL || aggvar2 == NULL )
3979  continue;
3980 
3981  SCIPdebugMessage("memorize the aggregation of <%s> == <%s>, because they are the last two variable which are different in these two set partitioning constraints <%s> <%s>\n", SCIPvarGetName(aggvar1), SCIPvarGetName(aggvar2), SCIPconsGetName(cons), SCIPconsGetName(cons1));
3982 
3983  /* resize the aggregation arrays if necessary */
3984  if( *saggregations == *naggregations )
3985  {
3986  *saggregations = SCIPcalcMemGrowSize(scip, *naggregations + 1);
3987  assert(*saggregations > *naggregations);
3988  SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrtypes, *saggregations) );
3989  SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrvars, 2 * (*saggregations)) );
3990 
3991  /* clear the aggregation type array to set the default to the aggregation of the form x + y = 1 */
3992  BMSclearMemoryArray(&(undoneaggrtypes[*naggregations]), *saggregations - *naggregations); /*lint !e866*/
3993  }
3994 
3995  /* memorize aagregation variables*/
3996  undoneaggrtypes[*naggregations] = TRUE;
3997  undoneaggrvars[2 * (*naggregations)] = aggvar1;
3998  undoneaggrvars[2 * (*naggregations) + 1] = aggvar2;
3999  ++(*naggregations);
4000 
4001  if( !SCIPdoNotAggr(scip) )
4002  {
4003  /* delete constraint */
4004  SCIPdebugMessage(" -> deleting constraint <%s> number <%d> because it is dominated by constraint <%s>\n", SCIPconsGetName(cons1), c, SCIPconsGetName(cons));
4005  assert(SCIPconsIsActive(cons1));
4006 
4007  SCIP_CALL( SCIPupdateConsFlags(scip, cons, cons1) );
4008  SCIP_CALL( SCIPdelCons(scip, cons1) );
4009  ++(*ndelconss);
4010  }
4011  }
4012  /* w.l.o.g. cons is a setpartitioning constraint and countofoverlapping == nvars - oldnfixedzeros - 1 we can
4013  * delete all overlapping variables in cons1 and add the negated variable of the not overlapped variable to cons
4014  * 1; the result should be a shorter constraint with the same impact
4015  */
4016  else if( shrinking && !overlapdestroyed && countofoverlapping[c] > 1 && ((consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars - oldnfixedzeros - 1) || (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars1 - 1)) ) /*lint !e641*/
4017  {
4018  SCIP_CONSDATA* consdatachange;
4019  SCIP_VAR** varstostay;
4020  SCIP_VAR** varstochange;
4021  SCIP_CONS* constochange;
4022  SCIP_CONS* constostay;
4023  SCIP_VAR* addvar;
4024  SCIP_Bool negated0;
4025  SCIP_Bool negated1;
4026  int nvarstostay;
4027  int nvarstochange;
4028  int constochangeidx;
4029 #ifndef NDEBUG
4030  const int oldnchgcoefs = *nchgcoefs;
4031 #endif
4032 
4033  addvar = NULL;
4034 
4035  assert((consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING) != (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING) || countofoverlapping[c] != nvars - 1 || countofoverlapping[c] != nvars1 - 1); /*lint !e641*/
4036 
4037  /* both constraints should stay merged */
4038  assert(consdata->merged);
4039  assert(consdata1->merged);
4040 
4041  /* sorting array after indices of variables, negated and active counterparts would stand side by side */
4042  SCIPsortDownPtr((void**)(consdata1->vars), SCIPvarCompActiveAndNegated, nvars1);
4043  /* standard setppc-sorting now lost */
4044  consdata1->sorted = FALSE;
4045 
4046  /* initialize variables */
4047  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars - oldnfixedzeros - 1) /*lint !e641*/
4048  {
4049  varstostay = vars;
4050  varstochange = consdata1->vars;
4051  nvarstostay = nvars;
4052  nvarstochange = nvars1;
4053  constostay = cons;
4054  constochange = cons1;
4055  consdatachange = consdata1;
4056  constochangeidx = c;
4057  }
4058  else
4059  {
4060  varstostay = consdata1->vars;
4061  varstochange = vars;
4062  nvarstostay = nvars1;
4063  nvarstochange = nvars;
4064  constostay = cons1;
4065  constochange = cons;
4066  consdatachange = consdata;
4067  constochangeidx = considx;
4068 
4069  *chgcons = TRUE;
4070  }
4071 
4072  /* iterate over the both cliques variables the "same" time, here we need the backward loop, because we
4073  * delete some variables and we don not want to loose order
4074  */
4075  for( v = nvarstostay - 1, v1 = nvarstochange - 1; v >= 0 && v1 >= 0; )
4076  {
4077  if( SCIPvarGetLbLocal(varstochange[v1]) > 0.5 || SCIPvarGetUbLocal(varstochange[v1]) < 0.5 )
4078  {
4079  --v1;
4080  continue;
4081  }
4082  if( SCIPvarGetLbLocal(varstostay[v]) > 0.5 || SCIPvarGetUbLocal(varstostay[v]) < 0.5 )
4083  {
4084  --v;
4085  continue;
4086  }
4087 
4088  /* all variables inside the second clique constraint should be either active or negated of an active one */
4089  assert(SCIPvarIsActive(varstochange[v1]) || (SCIPvarGetStatus(varstochange[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstochange[v1]))));
4090  /* all variables inside the first clique constraint should be either active or negated of an active one */
4091  assert(SCIPvarIsActive(varstostay[v]) || (SCIPvarGetStatus(varstostay[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstostay[v]))));
4092 
4093  /* get not negated variable and clique value in constostay */
4094  if( SCIPvarIsActive(varstostay[v]) )
4095  {
4096  var = varstostay[v];
4097  negated0 = FALSE;
4098  }
4099  else
4100  {
4101  assert(SCIPvarGetStatus(varstostay[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstostay[v])));
4102  var = SCIPvarGetNegationVar(varstostay[v]);
4103  negated0 = TRUE;
4104  }
4105 
4106  /* get active variable and clique value of in constochange*/
4107  if( SCIPvarIsActive(varstochange[v1]) )
4108  {
4109  var1 = varstochange[v1];
4110  negated1 = FALSE;
4111  }
4112  else
4113  {
4114  assert(SCIPvarGetStatus(varstochange[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstochange[v1])));
4115  var1 = SCIPvarGetNegationVar(varstochange[v1]);
4116  negated1 = TRUE;
4117  }
4118 
4119  /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
4120  if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1) )
4121  {
4122  assert(addvar == NULL);
4123  addvar = varstostay[v];
4124  --v;
4125  }
4126  /* variable index in the constraint is greater than the other one, so fix this variable */
4127  else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1) )
4128  {
4129  --v1;
4130  }
4131  else
4132  {
4133  /* because the constraint's are merged it is not possible that one constraint contains a negated variable
4134  * of another, but both constraint might have a variable in neagted form of the other
4135  */
4136  if( negated0 != negated1 )
4137  {
4138  assert(addvar == NULL);
4139 
4140  SCIPdebugMessage("-> trying to fix <%s> to 0 because it would exist twice in a constraint\n", SCIPvarGetName(varstochange[v1]));
4141 
4142  /* fix variable to zero */
4143  SCIP_CALL( SCIPfixVar(scip, varstochange[v1], 0.0, cutoff, &fixed) );
4144  if( *cutoff )
4145  {
4146  SCIPdebugMessage("fixing led to cutoff\n");
4147 
4148  return SCIP_OKAY;
4149  }
4150 
4151  assert(fixed);
4152  ++(*nfixedvars);
4153 
4154  /* the above fixing is equal to the fixation of varstostay[v] to 1, so we can call presolvePropagateCons() for consstay */
4155  SCIP_CALL( presolvePropagateCons(scip, constostay, FALSE, NULL, NULL, NULL, NULL, nfixedvars, naggrvars, ndelconss, cutoff) );
4156 
4157  return SCIP_OKAY;
4158  }
4159  else
4160  {
4161  /* correct local data structure, remove variable from constraint entry where it will be removed */
4162  deleteCliqueDataEntry(varstochange[v1], constochangeidx, vartoindex, varnconss, varconsidxs);
4163 
4164  SCIPdebugMessage(" -> deleting variable <%s> in constraint <%s> number %d, because it will be replaced\n", SCIPvarGetName(varstochange[v1]), SCIPconsGetName(constochange), constochangeidx);
4165  /* delete overlapping variabes in constochange */
4166  SCIP_CALL( delCoefPos(scip, constochange, v1) );
4167  ++(*nchgcoefs);
4168  }
4169 
4170  --v;
4171  --v1;
4172  }
4173  }
4174  assert(addvar != NULL || v >= 0);
4175  /* we should have removed exactly countofoverlapping[c] variables from the constochange */
4176  assert(*nchgcoefs - oldnchgcoefs == countofoverlapping[c]);
4177 
4178  /* determine addvar if not yet found */
4179  if( addvar == NULL )
4180  {
4181  for( ; v >= 0; --v)
4182  {
4183  if( SCIPvarGetLbLocal(varstostay[v]) > 0.5 || SCIPvarGetUbLocal(varstostay[v]) < 0.5 )
4184  continue;
4185 
4186  /* all variables inside the first clique constraint should be either active or negated of an active one */
4187  assert(SCIPvarIsActive(varstostay[v]) || (SCIPvarGetStatus(varstostay[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstostay[v]))));
4188 
4189  addvar = varstostay[v];
4190  break;
4191  }
4192  }
4193  assert(addvar != NULL);
4194 
4195  /* get representative variable for all deleted variables */
4196  SCIP_CALL( SCIPgetNegatedVar(scip, addvar, &addvar) );
4197  assert(addvar != NULL);
4198 
4199  SCIPdebugMessage(" -> adding variable <%s> to constraint <%s> number %d\n", SCIPvarGetName(addvar), SCIPconsGetName(constochange), constochangeidx);
4200  /* add representative for overlapping instead */
4201  SCIP_CALL( addCoef(scip, constochange, addvar) );
4202  ++(*nchgcoefs);
4203 
4204  /* constraint should be still merged because this added variable is new in this constraint */
4205  consdatachange->merged = TRUE;
4206  assert(constochangeidx == (cons == constochange ? considx : c));
4207 
4208  /* correct local data structure, add constraint entry to variable data */
4209  SCIP_CALL( addCliqueDataEntry(scip, addvar, constochangeidx, TRUE, usefulvars, nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs) );
4210 
4211  /* cons changed so much, that it cannot be used for more overlapping checks */
4212  if( *chgcons )
4213  return SCIP_OKAY;
4214  }
4215  }
4216 
4217  return SCIP_OKAY;
4218 }
4219 
4220 /** try to lift variables to given constraint */
4221 /** @todo try another variant by determine lifting variables as the intersection of all cliques variables of the
4222  * constraint variables, note that the insection changes after one variable was added
4223  */
4224 static
4226  SCIP*const scip, /**< SCIP data structure */
4227  SCIP_CONS*const cons, /**< constraint which may overlap */
4228  int const arraypos, /**< position of constraint in global array */
4229  SCIP_VAR**const usefulvars, /**< possible variables to lift */
4230  int*const nusefulvars, /**< pointer to store number of added variables */
4231  int const endidx, /**< end index for possible lifting variables */
4232  SCIP_Bool** cliquevalues, /**< pointer to clique values of constraint-variables, either one if the
4233  * varibale is active or zero if the variable is negated
4234  * @note this array can be resized in this method
4235  */
4236  SCIP_HASHMAP*const vartoindex, /**< hashmap mapping variables to indices */
4237  int*const varnconss, /**< array with number of constraints a variable occurs */
4238  int*const maxnvarconsidx, /**< array with the maximal number of occurances of a variable */
4239  int**const varconsidxs, /**< array with constraint indices in which the corresponding variable
4240  * exists
4241  */
4242  int*const maxnvars, /**< pointer to store maximal number of variables of a constraint */
4243  int*const nadded, /**< pointer to store number of possible added variables */
4244  SCIP_Bool*const chgcons, /**< pointer to store if the constraint was changed, due to added
4245  * variables
4246  */
4247  int*const nfixedvars, /**< pointer to count number of deleted variables */
4248  int*const ndelconss, /**< pointer to count number of deleted constraints */
4249  SCIP_Bool*const cutoff /**< pointer to store if the problem is infeasible due to a fixing */
4250  )
4251 {
4252  SCIP_CONSDATA* consdata;
4253  SCIP_VAR** vars;
4254  SCIP_VAR* var;
4255  SCIP_VAR* var1;
4256  SCIP_Bool fixed;
4257  SCIP_Bool value;
4258  int nvars;
4259  int nottocheck; /* will be the position for a variable in cons0 which is in negated form in the same clique */
4260  int v;
4261  int v1;
4262  int k;
4263 
4264  assert(scip != NULL);
4265  assert(cons != NULL);
4266  assert(usefulvars != NULL);
4267  assert(cliquevalues != NULL);
4268  assert(*cliquevalues != NULL);
4269  assert(vartoindex != NULL);
4270  assert(varnconss != NULL);
4271  assert(maxnvarconsidx != NULL);
4272  assert(varconsidxs != NULL);
4273  assert(maxnvars != NULL);
4274  assert(nadded != NULL);
4275  assert(chgcons != NULL);
4276  assert(nfixedvars != NULL);
4277  assert(ndelconss != NULL);
4278  assert(cutoff != NULL);
4279 
4280  if( !SCIPconsIsActive(cons) )
4281  return SCIP_OKAY;
4282 
4283  consdata = SCIPconsGetData(cons);
4284  assert(consdata != NULL);
4285 
4286  nvars = consdata->nvars;
4287 
4288  if( nvars == 0 )
4289  return SCIP_OKAY;
4290 
4291  assert(nvars <= *maxnvars);
4292 
4293  vars = consdata->vars;
4294  assert(vars != NULL);
4295 
4296  v1 = endidx;
4297 
4298  /* now we try to add variables with index prior to endidx to cons */
4299  for( v = nvars - 1; v >= 0 && v1 >= 0; )
4300  {
4301  if( SCIPvarGetLbLocal(usefulvars[v1]) > 0.5 || SCIPvarGetUbLocal(usefulvars[v1]) < 0.5 )
4302  {
4303  --v1;
4304  continue;
4305  }
4306  if( SCIPvarGetUbLocal(vars[v]) < 0.5 )
4307  {
4308  --v;
4309  continue;
4310  }
4311 
4312  /* check that constraint variables are still correctly sorted, indices of active variables should be decreasing */
4313  assert(v == 0 || SCIPvarCompareActiveAndNegated(vars[v], vars[v - 1]) <= 0);
4314 
4315  /* there should no variables fixed to one occur in our constraint */
4316  assert(SCIPvarGetLbLocal(vars[v]) < 0.5 && SCIPvarGetUbLocal(vars[v]) > 0.5);
4317  assert(SCIPvarGetLbLocal(usefulvars[v1]) < 0.5 && SCIPvarGetUbLocal(usefulvars[v1]) > 0.5);
4318 
4319  /* all variables which we have inside the clique constraint and which can possibly be added should be either active or negated */
4320  assert(SCIPvarIsActive(vars[v]) || (SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v]))));
4321  assert(SCIPvarIsActive(usefulvars[v1]) || (SCIPvarGetStatus(usefulvars[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(usefulvars[v1]))));
4322 
4323  /* constraint should during adding of variables stay merged, because for each variable which is added holds that
4324  * the index of this corresponding active variable is pairwise different to all indices of all active
4325  * corresponding variables inside the constraint
4326  * @note it should not happen that we add one variable and the corresponding counterpart to the same constraint */
4327  assert(consdata->merged);
4328 
4329  /* get active variable and clique value in cons */
4330  if( (*cliquevalues)[v] )
4331  var = vars[v];
4332  else
4333  {
4335  var = SCIPvarGetNegationVar(vars[v]);
4336  }
4337 
4338  /* get active variable and clique value of next variable */
4339  if( SCIPvarIsActive(usefulvars[v1]) )
4340  {
4341  var1 = usefulvars[v1];
4342  value = TRUE;
4343  }
4344  else
4345  {
4346  assert(SCIPvarGetStatus(usefulvars[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(usefulvars[v1])));
4347  var1 = SCIPvarGetNegationVar(usefulvars[v1]);
4348  value = FALSE;
4349  }
4350 
4351  nottocheck = -1;
4352  k = 0;
4353 
4354  /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
4355  if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1) )
4356  {
4357  --v;
4358  continue;
4359  }
4360  /* variable index in the constraint is greater than the other one, so check for possible inclusion of the variable */
4361  else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1) )
4362  {
4363  assert(consdata == SCIPconsGetData(cons));
4364 
4365  /* check if every variable in the actual clique is in clique with the new variable */
4366  for( k = nvars - 1; k >= 0; --k )
4367  {
4368  if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4369  {
4370  /* there should no variables fixed to one occur in our constraint */
4371  assert(SCIPvarGetLbLocal(vars[k]) < 0.5);
4372  assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4373 
4374  if( (*cliquevalues)[k] )
4375  {
4376  assert(SCIPvarIsActive(vars[k]));
4377  var = vars[k];
4378  }
4379  else
4380  {
4382  var = SCIPvarGetNegationVar(vars[k]);
4383  }
4384  if( !SCIPhaveVarsCommonClique(scip, var1, value, var, (*cliquevalues)[k], TRUE) )
4385  break;
4386  }
4387  }
4388  --v1;
4389  }
4390  /* variable index in the constraint is equal to the index of the other variable, check if these variables are
4391  * negated of each other so memorize the position and check for possible inclusion of the new variable and if
4392  * possible decrease indices
4393  */
4394  else
4395  {
4396  /* one clique contains the negated and the other clique the corresponding active var */
4397  if( value != (*cliquevalues)[v] )
4398  {
4399  nottocheck = v;
4400 
4401  assert(consdata == SCIPconsGetData(cons));
4402  assert(nvars <= consdata->nvars);
4403 
4404  /* check if every variable in the actual clique is in clique with the new variable */
4405  for( k = nvars - 1; k >= 0; --k )
4406  {
4407  if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4408  {
4409  /* there should no variables fixed to one occur in our constraint */
4410  assert(SCIPvarGetLbLocal(vars[k]) < 0.5);
4411 
4412  assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4413 
4414  if( k == nottocheck )
4415  continue;
4416 
4417  if( (*cliquevalues)[k] )
4418  {
4419  assert(SCIPvarIsActive(vars[k]));
4420  var = vars[k];
4421  }
4422  else
4423  {
4425  var = SCIPvarGetNegationVar(vars[k]);
4426  }
4427 
4428  if( !SCIPhaveVarsCommonClique(scip, var1, value, var, (*cliquevalues)[k], TRUE) )
4429  break;
4430  }
4431  }
4432  }
4433  /* don't decrease v because it might happen that the corresponding negated variable of var is next in
4434  * usefulvars
4435  */
4436  --v1;
4437  }
4438 
4439  /* if k is smaller than 0 than the possible new variables is in the same clique with all variables of cons,
4440  * so we add the new variable to clique constraint or fix some variables */
4441  if( k < 0 )
4442  {
4443  ++(*nadded);
4444 
4445  /* we found a variable which is the negated variable of another one in this clique so we can fix all
4446  * other variable to zero and if it's a partitioning constraint we can also fix the variable of the
4447  * negated to one and we can delete the constraint too */
4448  if( nottocheck >= 0 )
4449  {
4450  assert(consdata == SCIPconsGetData(cons));
4451  assert(nvars <= consdata->nvars);
4452  assert(consdata->merged);
4453 
4454  /* process all vars for possible fixing */
4455  for( k = consdata->nvars - 1; k >= 0; --k )
4456  {
4457  if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4458  {
4459  /* there should no variables fixed to one occur in our constraint */
4460  assert(SCIPvarGetLbLocal(vars[v]) < 0.5);
4461 
4462  assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4463 
4464  if( k != nottocheck )
4465  {
4466  SCIPdebugMessage("trying to fix <%s> to 0 because we could lift a negated variable of another constraint variable\n", SCIPvarGetName(vars[k]));
4467  /* fix variable to zero */
4468  SCIP_CALL( SCIPfixVar(scip, vars[k], 0.0, cutoff, &fixed) );
4469 
4470  if( *cutoff )
4471  {
4472  SCIPdebugMessage("fixing led to cutoff\n");
4473 
4474  return SCIP_OKAY;
4475  }
4476 
4477  assert(fixed);
4478 
4479  ++(*nfixedvars);
4480  }
4481  }
4482  }
4483  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
4484  {
4485  assert(SCIPvarIsActive(vars[nottocheck]) || (SCIPvarGetStatus(vars[nottocheck]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[nottocheck]))));
4486 
4487  SCIPdebugMessage("trying to fix <%s> to 1 due to this setpartitioning variable is with its negated in the same clique\n", SCIPvarGetName(vars[nottocheck]));
4488  /* fix the remaining variable to one, due to it's the only one left to satisfy the constraint */
4489  SCIP_CALL( SCIPfixVar(scip, vars[nottocheck], 1.0, cutoff, &fixed) );
4490  if( *cutoff )
4491  {
4492  SCIPdebugMessage("fixing led to cutoff\n");
4493 
4494  return SCIP_OKAY;
4495  }
4496 
4497  assert(fixed);
4498  ++(*nfixedvars);
4499  }
4500 
4501  /* delete constraint */
4502  SCIPdebugMessage(" -> deleting constraint <%s> number <%d> due to active and negated variable in the same clique constraint\n", SCIPconsGetName(cons), arraypos);
4503  assert(SCIPconsIsActive(cons));
4504  SCIP_CALL( SCIPdelCons(scip, cons) );
4505  ++(*ndelconss);
4506 
4507  break;
4508  }
4509  /* we found a variable which could be added to a partitioning constraint so we can fix it to zero */
4510  else if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
4511  {
4512  SCIPdebugMessage("trying to fix <%s> to 0 because this variable is in the same clique with a set partition\n", SCIPvarGetName(usefulvars[v1 + 1]));
4513  /* fix variable to zero */
4514  SCIP_CALL( SCIPfixVar(scip, usefulvars[v1 + 1], 0.0, cutoff, &fixed) );
4515 
4516  if( *cutoff )
4517  {
4518  SCIPdebugMessage("fixing led to cutoff\n");
4519 
4520  return SCIP_OKAY;
4521  }
4522 
4523  assert(fixed);
4524 
4525  ++(*nfixedvars);
4526  }
4527  /* we have found a new variable for a set packing constraint cons, so add the found variable to the first constraint */
4528  else
4529  {
4530  SCIP_VAR* addvar;
4531 
4532  assert(SCIPconsIsActive(cons));
4533 
4534  addvar = usefulvars[v1 + 1];
4535 
4536  assert(SCIPvarGetLbLocal(addvar) < 0.5 && SCIPvarGetUbLocal(addvar) > 0.5);
4537 
4538  /* add representative instead */
4539  SCIPdebugMessage(" -> adding variable <%s> to constraint <%s> number %d\n", SCIPvarGetName(usefulvars[v1 + 1]), SCIPconsGetName(cons), arraypos);
4540  SCIP_CALL( addCoef(scip, cons, addvar) );
4541  assert(consdata == SCIPconsGetData(cons));
4542  /* we know that this constraint stays merged but later on we have to resort */
4543  consdata->merged = TRUE;
4544 
4545  /* second we add the constraint index to the list of indices where this variable occurs */
4546  assert(SCIPhashmapExists(vartoindex, (void*) addvar));
4547 
4548  /* correct local data structure, add constraint entry to variable data */
4549  SCIP_CALL( addCliqueDataEntry(scip, addvar, arraypos, FALSE, usefulvars, nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs) );
4550 
4551  /* we need the new pointer to the variables, because due to adding variables it is possible that we
4552  * did reallocate the variables array inside the constraint, the index v should stay the same because the
4553  * added variable was inserted at the end and we are decreasing v in our for loop
4554  */
4555  vars = consdata->vars;
4556  nvars = consdata->nvars;
4557 
4558  /* we need to update our data structure */
4559 
4560  /* resize clique array if necessary, due to adding variables */
4561  if( (*maxnvars) < nvars )
4562  {
4563  while( (*maxnvars) < nvars )
4564  (*maxnvars) *= 2 ;
4565  SCIP_CALL( SCIPreallocBufferArray(scip, cliquevalues, (*maxnvars)) );
4566  }
4567  (*cliquevalues)[nvars - 1] = SCIPvarIsActive(addvar) ? TRUE : FALSE;
4568 
4569  (*chgcons) = TRUE;
4570  }
4571  }
4572  }
4573 
4574  if( !SCIPconsIsActive(cons) )
4575  return SCIP_OKAY;
4576 
4577  /* maybe we stopped because of cons(v reached -1) so try to add rest in usefulvars */
4578  for( ; v1 >= 0; --v1)
4579  {
4580  if( SCIPvarGetLbLocal(usefulvars[v1]) > 0.5 || SCIPvarGetUbLocal(usefulvars[v1]) < 0.5 )
4581  continue;
4582 
4583  /* get active variable and clique value */
4584  if( SCIPvarIsActive(usefulvars[v1]) )
4585  {
4586  var1 = usefulvars[v1];
4587  value = TRUE;
4588  }
4589  else
4590  {
4591  assert(SCIPvarGetStatus(usefulvars[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(usefulvars[v1])));
4592  var1 = SCIPvarGetNegationVar(usefulvars[v1]);
4593  value = FALSE;
4594  }
4595 
4596  assert(consdata == SCIPconsGetData(cons));
4597  assert(nvars <= consdata->nvars);
4598 
4599  /* check if every variable in the actual clique is in clique with the new variable */
4600  for( k = nvars - 1; k >= 0; --k )
4601  {
4602  if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4603  {
4604  /* there should no variables fixed to one occur in our constraint */
4605  assert(SCIPvarGetLbLocal(vars[k]) < 0.5);
4606 
4607  assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4608 
4609  if( (*cliquevalues)[k] )
4610  {
4611  assert(SCIPvarIsActive(vars[k]));
4612  var = vars[k];
4613  }
4614  else
4615  {
4617  var = SCIPvarGetNegationVar(vars[k]);
4618  }
4619 
4620  if( !SCIPvarsHaveCommonClique(var1, value, var, (*cliquevalues)[k], TRUE) )
4621  break;
4622  }
4623  }
4624 
4625  /* add new variable to clique constraint or fix some variables */
4626  if( k < 0 )
4627  {
4628  /* we found a variable which could be added to a partitioning constraint so we can fix it to zero */
4629  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
4630  {
4631  SCIPdebugMessage("trying to fix <%s> to 0 because this variable is in the same clique with a set partition\n", SCIPvarGetName(usefulvars[v1]));
4632 
4633  /* fix variable to zero */
4634  SCIP_CALL( SCIPfixVar(scip, usefulvars[v1], 0.0, cutoff, &fixed) );
4635  if( *cutoff )
4636  {
4637  SCIPdebugMessage("fixing led to cutoff\n");
4638 
4639  return SCIP_OKAY;
4640  }
4641  assert(fixed);
4642 
4643  ++(*nfixedvars);
4644  ++(*nadded);
4645  }
4646  /* add the found variable to the first constraint */
4647  else
4648  {
4649  SCIP_VAR* addvar;
4650 
4651  assert(SCIPconsIsActive(cons));
4652 
4653  addvar = usefulvars[v1];
4654 
4655  assert(SCIPvarGetLbLocal(addvar) < 0.5 && SCIPvarGetUbLocal(addvar) > 0.5);
4656 
4657  /* add representative instead */
4658  SCIPdebugMessage(" -> adding variable <%s> to constraint <%s> number %d\n", SCIPvarGetName(addvar), SCIPconsGetName(cons), arraypos);
4659  SCIP_CALL( addCoef(scip, cons, addvar) );
4660  assert(consdata == SCIPconsGetData(cons));
4661  /* we know that this constraint stays merged but later on we have to resort */
4662  consdata->merged = TRUE;
4663 
4664  /* second we add the constraint index to the list of indices where this variable occurs */
4665  assert(SCIPhashmapExists(vartoindex, (void*) addvar));
4666 
4667  /* correct local data structure, add constraint entry to variable data */
4668  SCIP_CALL( addCliqueDataEntry(scip, addvar, arraypos, FALSE, usefulvars, nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs) );
4669 
4670  /* we need the new pointer to the variables, because due to adding variables it is possible that we
4671  * did reallocate the variables array inside the constraint, the index v should stay the same because the
4672  * added variable was inserted at the end and we are decreasing v in our for loop
4673  */
4674  vars = consdata->vars;
4675  nvars = consdata->nvars;
4676 
4677  /* we need to update our data structure */
4678 
4679  /* resize clique array if necessary, due to adding variables */
4680  if( (*maxnvars) < nvars )
4681  {
4682  while( (*maxnvars) < nvars )
4683  (*maxnvars) *= 2 ;
4684  SCIP_CALL( SCIPreallocBufferArray(scip, cliquevalues, (*maxnvars)) );
4685  }
4686  (*cliquevalues)[nvars - 1] = SCIPvarIsActive(addvar) ? TRUE : FALSE;
4687 
4688  ++(*nadded);
4689  (*chgcons) = TRUE;
4690  }
4691  }
4692  }
4693 
4694  return SCIP_OKAY;
4695 }
4696 
4697 /** perform all collected aggregations */
4698 static
4700  SCIP*const scip, /**< SCIP data structure */
4701  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
4702  SCIP_VAR**const undoneaggrvars, /**< aggregation variables storage */
4703  SCIP_Bool*const undoneaggrtypes, /**< aggregation type storage, type FALSE means the aggregation is of the
4704  * form x + y = 1; type TRUE means the aggregation is of the form x = y;
4705  */
4706  int const naggregations, /**< number of aggregations to performed */
4707  int*const naggrvars, /**< pointer to count number of aggregated variables */
4708  SCIP_Bool*const cutoff /**< pointer to store if the problem is infeasible due to a fixing */
4709  )
4710 { /*lint --e{715}*/
4711  SCIP_VAR* var1;
4712  SCIP_VAR* var2;
4713  SCIP_Bool aggregated;
4714  SCIP_Bool redundant;
4715  int a;
4716 
4717  assert(scip != NULL);
4718  assert(conshdlrdata != NULL);
4719  assert(undoneaggrvars != NULL);
4720  assert(undoneaggrtypes != NULL);
4721  assert(naggregations > 0);
4722  assert(naggrvars != NULL);
4723  assert(cutoff != NULL);
4724 
4725  /* loop over all open aggreagtions and try to aggregate them */
4726  for( a = 0; a < naggregations; ++a )
4727  {
4728  var1 = undoneaggrvars[2 * a];
4729  var2 = undoneaggrvars[2 * a + 1];
4730  assert(var1 != NULL);
4731  assert(var2 != NULL);
4732 
4733  SCIPdebugMessage("trying to aggregate <%s> %s <%s>%s\n", SCIPvarGetName(var1), undoneaggrtypes[a] ? "=" : "+", SCIPvarGetName(var2), undoneaggrtypes[a] ? "" : " = 1");
4734 
4735 #ifdef VARUSES
4736  /* in order to not mess up the variable usage counting, we have to decrease usage counting, aggregate,
4737  * and increase usage counting again
4738  */
4739  SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, var1) );
4740  SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, var2) );
4741 #endif
4742 
4743  /* aggregate last remaining variables in the set partitioning constraint */
4744  if( undoneaggrtypes[a] )
4745  {
4746  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, -1.0, 0.0, cutoff, &redundant, &aggregated) );
4747  }
4748  else
4749  {
4750  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, 1.0, 1.0, cutoff, &redundant, &aggregated) );
4751  }
4752 
4753  if( *cutoff )
4754  {
4755  SCIPdebugMessage("aggregation was infeasible\n");
4756 
4757  return SCIP_OKAY;
4758  }
4759  /* binary variables should always be aggregated, or due to fixation the aggregation is redundant */
4760  assert(redundant);
4761 
4762  if( aggregated )
4763  ++(*naggrvars);
4764 
4765 #ifdef VARUSES
4766  /* increase variable usage counting again */
4767  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var1) );
4768  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var2) );
4769 #endif
4770  }
4771 
4772  return SCIP_OKAY;
4773 }
4774 
4775 /** check whether we can combine or grow cliques so some constraints become redundant or we can fix variables */
4776 /** @todo try another variant, by building up the clique graph and delete unnecessary (transitive closure) edges and do
4777  * a bfs search to search for common ancestors to get all possible lifting variables
4778  */
4779 static
4781  SCIP*const scip, /**< SCIP data structure */
4782  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
4783  SCIP_CONS**const conss, /**< constraint set */
4784  int const nconss, /**< number of constraints in constraint set */
4785  int const nrounds, /**< actual presolving round */
4786  int*const firstchange, /**< pointer to store first changed constraint */
4787  int*const firstclique, /**< pointer to store first constraint to start adding clique again */
4788  int*const lastclique, /**< pointer to store last constraint to add cliques again */
4789  int*const nfixedvars, /**< pointer to count number of deleted variables */
4790  int*const naggrvars, /**< pointer to count number of aggregated variables */
4791  int*const ndelconss, /**< pointer to count number of deleted constraints */
4792  int*const nchgcoefs, /**< pointer to count number of deleted coefficients */
4793  SCIP_Bool*const cutoff /**< pointer to store if the problem is infeasible due to a fixing */
4794  )
4795 {
4796  /* extend cliques/constraints by checking whether some variables are in the same clique, no pairwise clique lifting
4797  * which would be slower
4798  */
4799  SCIP_CONS** usefulconss; /* array with pointers of constraint of setpartitioning and setpacking type */
4800  SCIP_VAR** usefulvars; /* array with pointers of variables in setpartitioning and setpacking constraints */
4801  int** varconsidxs; /* array consisting of constraint indices in which the corresponding variable exists */
4802  int* varnconss; /* array consisting of number of constraints the variable occurs */
4803  int* maxnvarconsidx; /* maximal number of occurances of a variable */
4804  int* countofoverlapping = NULL; /* the amount of variables which are in another constraint */
4805  SCIP_Bool* cliquevalues = NULL; /* values of clique-variables, either one if the varibale is active or zero if the variable is negated */
4806 
4807  SCIP_HASHMAP* vartoindex; /* mapping of SCIP variables to indices */
4808  SCIP_CONSDATA* consdata;
4809 
4810  SCIP_Bool chgcons0;
4811  int nvars;
4812  int c;
4813  int v;
4814  int nusefulconss;
4815  int nusefulvars;
4816  int susefulvars;
4817  int maxnvars;
4818  int varindex;
4819 
4820  SCIP_VAR** undoneaggrvars; /* storage for not yet performed aggregations */
4821  SCIP_Bool* undoneaggrtypes; /* storage for not yet performed aggregation type (x = y or x + y = 1) */
4822  int saggregations;
4823  int naggregations;
4824 
4825  assert(scip != NULL);
4826  assert(conshdlrdata != NULL);
4827  assert(conss != NULL || nconss == 0);
4828  assert(firstchange != NULL);
4829  assert(firstclique != NULL);
4830  assert(lastclique != NULL);
4831  assert(nfixedvars != NULL);
4832  assert(naggrvars != NULL);
4833  assert(ndelconss != NULL);
4834  assert(nchgcoefs != NULL);
4835  assert(cutoff != NULL);
4836 
4837  *cutoff = FALSE;
4838 
4839  if( nconss == 0 )
4840  return SCIP_OKAY;
4841 
4842  nvars = SCIPgetNVars(scip);
4843 
4844  if( nvars == 0 )
4845  return SCIP_OKAY;
4846 
4847  susefulvars = 2 * nvars; /* two times because of negated vars, maybe due to deleted variables we need to increase this */
4848 
4849  /* a hashmap from varindex to postion in varconsidxs array, because above is still too small */
4850  SCIP_CALL( SCIPhashmapCreate(&vartoindex, SCIPblkmem(scip), SCIPcalcHashtableSize(5 * nvars)) );
4851 
4852  /* get temporary memory for the aggregation storage, to memorize aggregations which will be performed later, otherwise we would destroy our local data structures */
4853  saggregations = nvars;
4854  SCIP_CALL( SCIPallocBufferArray(scip, &undoneaggrvars, 2 * saggregations) );
4855  SCIP_CALL( SCIPallocBufferArray(scip, &undoneaggrtypes, saggregations) );
4856  BMSclearMemoryArray(undoneaggrtypes, saggregations);
4857  naggregations = 0;
4858 
4859  /* get temporary memory for all clique constraints, all appearing variables and the mapping from variables to constraints */
4860  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
4861  SCIP_CALL( SCIPallocBufferArray(scip, &usefulvars, susefulvars) );
4862  BMSclearMemoryArray(usefulvars, susefulvars);
4863  SCIP_CALL( SCIPallocBufferArray(scip, &varnconss, susefulvars + 1) );
4864  BMSclearMemoryArray(varnconss, susefulvars + 1);
4865  SCIP_CALL( SCIPallocBufferArray(scip, &maxnvarconsidx, susefulvars + 1) );
4866  SCIP_CALL( SCIPallocBufferArray(scip, &varconsidxs, susefulvars + 1) );
4867  BMSclearMemoryArray(varconsidxs, susefulvars + 1);
4868  nusefulvars = 0;
4869  nusefulconss = 0;
4870  maxnvars = 0;
4871 
4872  /* @todo: check for round limit for adding extra clique constraints */
4873  /* adding clique constraints which arises from global clique information */
4874  if( conshdlrdata->nclqpresolve == 0 && conshdlrdata->addvariablesascliques )
4875  {
4876  SCIP_VAR** binvars;
4877  int* cliquepartition;
4878  int ncliques;
4879  int nbinvars;
4880  int naddconss;
4881 
4882  nbinvars = SCIPgetNBinVars(scip);
4883  SCIP_CALL( SCIPduplicateBufferArray(scip, &binvars, SCIPgetVars(scip), nbinvars) );
4884  SCIP_CALL( SCIPallocBufferArray(scip, &cliquepartition, nbinvars) );
4885 
4886  /* @todo: check for better permutations/don't permutate the first round
4887  * @todo: take binary variables which are not of vartype SCIP_VARTYPE_BINARY into account
4888  */
4889  SCIPpermuteArray((void**)binvars, 0, nbinvars, &(conshdlrdata->randseed));
4890 
4891  /* try to create a clique-partition over all binary variables and create these cliques as new setppc constraints
4892  * and add them to the usefulconss array and adjust all necessary data this will hopefully lead to faster
4893  * detection of redundant constraints
4894  */
4895  SCIP_CALL( SCIPcalcCliquePartition(scip, binvars, nbinvars, cliquepartition, &ncliques) );
4896 
4897  /* resize usefulconss array if necessary */
4898  SCIP_CALL( SCIPreallocBufferArray(scip, &usefulconss, nconss + ncliques) );
4899 
4900  naddconss = 0;
4901 
4902  /* add extra clique constraints resulting from the cliquepartition calculation to SCIP and to the local data structure */
4903  SCIP_CALL( addExtraCliques(scip, binvars, nbinvars, cliquepartition, ncliques, usefulconss, &nusefulconss,
4904  nrounds, nfixedvars, &naddconss, ndelconss, nchgcoefs, cutoff) );
4905 
4906  /* bad hack, we don't want to count these artificial created constraints if they got deleted, so ndelconss
4907  * can become negative which will be change to zero at the end of this method if it's still negative
4908  */
4909  *ndelconss -= naddconss;
4910 
4911  SCIPfreeBufferArray(scip, &cliquepartition);
4912  SCIPfreeBufferArray(scip, &binvars);
4913 
4914  if( *cutoff )
4915  goto TERMINATE;
4916  }
4917 
4918  /* start to collect setpartitioning and setpacking constraints, and try to remove fixed variables and merged these
4919  * constraints
4920  */
4921  SCIP_CALL( collectCliqueConss(scip, conss, nconss, usefulconss, &nusefulconss, nfixedvars, ndelconss, nchgcoefs, cutoff) );
4922  /* @Note: Even after the call above some constraints can have fixed variables, because it might happen that caused by
4923  * mergeMultiplies some variables were fixed which occured already in previous constraints
4924  */
4925  if( *cutoff )
4926  goto TERMINATE;
4927 
4928  /* no usefulconss found */
4929  if( nusefulconss <= 1 )
4930  goto TERMINATE;
4931 
4932  /* @todo: maybe sort them after biggest indices too, or another variant would be to restore the order as they were
4933  * read in
4934  */
4935  /* sort constraints first after type (partitioning before packing) and second after number of variables such that the
4936  * partitioning constraints have increasing number of variables and the packing constraints have decreasing number of
4937  * variables, because we loop from back to front we sort them downwards, so they are the other way around
4938  */
4939  SCIPsortDownPtr((void**)usefulconss, setppcConssSort, nusefulconss);
4940 
4941  /* creating all necessary data in array structure, collect all clique constraint variables and occurances */
4942  SCIP_CALL( collectCliqueData(scip, usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs, &maxnvars) );
4943  assert(maxnvars > 0);
4944 
4945  /* allocate temporary memory for actual clique */
4946  SCIP_CALL( SCIPallocBufferArray(scip, &cliquevalues, maxnvars) );
4947  /* allocate temporary memory for counting an overlap of variables */
4948  SCIP_CALL( SCIPallocBufferArray(scip, &countofoverlapping, nusefulconss) );
4949 
4950  /* sort usefulvars after indices of variables, negated and active counterparts will stand side by side */
4951  SCIPsortDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, nusefulvars);
4952 
4953  /* extend cliques/constraints by checking whether some variables of a second constraint are in the same clique */
4954  for( c = nusefulconss - 1; c >= 0 && !SCIPisStopped(scip); --c )
4955  {
4956  SCIP_VAR** cons0vars; /* these are the clique variables */
4957  SCIP_CONS* cons0;
4958  int ncons0vars;
4959  SCIP_VAR* var0;
4960  int v1;
4961  int nadded; /* number of possible added variables to constraint */
4962  int cons0fixedzeros;
4963  int oldnchgcoefs;
4964 #ifndef NDEBUG
4965  const int oldnaggrvars = *naggrvars;
4966 #endif
4967  cons0 = usefulconss[c];
4968 
4969  if( !SCIPconsIsActive(cons0) )
4970  continue;
4971 
4972  /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
4973  * possible
4974  */
4975  SCIP_CALL( presolvePropagateCons(scip, cons0, FALSE, undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
4976 
4977  if( *cutoff )
4978  break;
4979 
4980  /* we can't handle aggregated variables later on so we should have saved them for later */
4981  assert(*naggrvars == oldnaggrvars);
4982 
4983  if( !SCIPconsIsActive(cons0) )
4984  continue;
4985 
4986  /* we need to determine the cliquedata in each iteration because we eventual will change it later */
4987  consdata = SCIPconsGetData(cons0);
4988  assert(consdata != NULL);
4989 
4990  cons0vars = consdata->vars;
4991  ncons0vars = consdata->nvars;
4992 
4993  /* sorting array after indices of variables, negated and active counterparts will stand side by side */
4994  SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
4995  /* standard setppc-sorting now lost */
4996  consdata->sorted = FALSE;
4997 
4998  /* clique array should be long enough */
4999  assert(maxnvars >= ncons0vars);
5000 
5001  /* clear old entries in overlapping constraint */
5002  BMSclearMemoryArray(countofoverlapping, nusefulconss);
5003 
5004  /* calculate overlapping */
5005  for( v = ncons0vars - 1; v >= 0 ; --v )
5006  {
5007  var0 = cons0vars[v];
5008 
5009  /* fixed variables later to the count */
5010  if( SCIPvarGetLbLocal(var0) > 0.5 || SCIPvarGetUbLocal(var0) < 0.5 )
5011  continue;
5012 
5013  assert(SCIPhashmapExists(vartoindex, (void*) var0));
5014 
5015  varindex = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) var0);
5016  for( v1 = varnconss[varindex] - 1; v1 >= 0 ; --v1 )
5017  ++(countofoverlapping[varconsidxs[varindex][v1]]);
5018  }
5019 
5020  oldnchgcoefs = *nchgcoefs;
5021  cons0fixedzeros = consdata->nfixedzeros;
5022 
5023  chgcons0 = FALSE;
5024 
5025  /* check for overlapping constraint before starting lifting */
5026  SCIP_CALL( checkForOverlapping(scip, cons0, c, c, usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex,
5027  varnconss, maxnvarconsidx, varconsidxs, countofoverlapping, conshdlrdata->cliqueshrinking, &chgcons0,
5028  undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations,
5029  nfixedvars, naggrvars, nchgcoefs, ndelconss, cutoff) );
5030 
5031  if( *cutoff )
5032  break;
5033 
5034  /* we can't handle aggregated variables later on so we should have saved them for later */
5035  assert(*naggrvars == oldnaggrvars);
5036 
5037  /* if cons0 changed, we need to reorder the variables */
5038  if( chgcons0 && *nchgcoefs > oldnchgcoefs )
5039  {
5040  consdata = SCIPconsGetData(cons0);
5041  assert(consdata != NULL);
5042 
5043  cons0vars = consdata->vars;
5044  ncons0vars = consdata->nvars;
5045 
5046  /* sorting array after indices of variables, negated and active counterparts will stand side by side */
5047  SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5048  /* standard setppc-sorting now lost */
5049  consdata->sorted = FALSE;
5050  }
5051 
5052  /* check cons0 again for redundancy/fixings, because due to fixings in all other constraints it might happen that cons0 is redundant now */
5053  if( consdata->nfixedones > 0 || consdata->nfixedzeros > cons0fixedzeros )
5054  {
5055  /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
5056  * possible
5057  */
5058  SCIP_CALL( presolvePropagateCons(scip, cons0, FALSE, undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
5059 
5060  if( *cutoff )
5061  break;
5062 
5063  /* we can't handle aggregated variables later on so we should have saved them for later */
5064  assert(*naggrvars == oldnaggrvars);
5065 
5066  if( !SCIPconsIsActive(cons0) )
5067  continue;
5068  }
5069 
5070  nadded = 0;
5071 
5072  /* iterate over the cliques variables and all possible new clique variables at the "same" time, determine starting
5073  * index
5074  *
5075  * @note: it might be better to start the first round with our computed v1, but maybe it's better to switch to
5076  * trying to add all variables the second time for set packing constraints
5077  */
5078 
5079  /* we try to add all variables to the partitioning constraints, to try to fix as much as possible */
5080  if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
5081  v1 = nusefulvars - 1;
5082  else
5083  {
5084  /* if we already ran a presolving round we want to try to add new variables */
5085  if( conshdlrdata->nclqpresolve > 0 )
5086  v1 = nusefulvars - 1;
5087  else
5088  {
5089  /* find start position of variable which we will try to add to our constraint, so we will get better clique constraints */
5090  (void) SCIPsortedvecFindDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, (void*)cons0vars[ncons0vars - 1], nusefulvars, &v1);
5091  assert(v1 >= 0 && v1 < nusefulvars);
5092  /* if constraint is not merged and we found a variable which is negated the same as it's neighbour we have to
5093  * increase v1 to make sure that we don't loose this important variable */
5094  if( v1 + 1 < nusefulvars && ((SCIPvarIsNegated(usefulvars[v1 + 1]) && SCIPvarGetNegatedVar(usefulvars[v1 + 1]) == usefulvars[v1]) || (SCIPvarIsNegated(usefulvars[v1]) && SCIPvarGetNegatedVar(usefulvars[v1]) == usefulvars[v1 + 1])) )
5095  ++v1;
5096  }
5097  }
5098 
5099  assert(maxnvars >= ncons0vars);
5100  /* initialize the cliquevalues array */
5101  for( v = ncons0vars - 1; v >= 0; --v )
5102  {
5103  if( SCIPvarGetLbLocal(cons0vars[v]) < 0.5 && SCIPvarGetUbLocal(cons0vars[v]) > 0.5 )
5104  {
5105  /* variable has to be either active or a negated variable of an active one */
5106  assert(SCIPvarIsActive(cons0vars[v]) || (SCIPvarGetStatus(cons0vars[v]) == SCIP_VARSTATUS_NEGATED &&
5107  SCIPvarIsActive(SCIPvarGetNegationVar(cons0vars[v]))));
5108  cliquevalues[v] = SCIPvarIsActive(cons0vars[v]) ? TRUE : FALSE;
5109  }
5110  }
5111 
5112  chgcons0 = FALSE;
5113 
5114  /* try to lift variables to cons0 */
5115  SCIP_CALL( liftCliqueVariables(scip, cons0, c, usefulvars, &nusefulvars, v1, &cliquevalues, vartoindex, varnconss,
5116  maxnvarconsidx, varconsidxs, &maxnvars, &nadded, &chgcons0, nfixedvars, ndelconss, cutoff) );
5117 
5118  if( *cutoff )
5119  break;
5120 
5121  if( !SCIPconsIsActive(cons0) )
5122  continue;
5123 
5124  /* check for redundant constraints due to changing cons0 */
5125  if( chgcons0 )
5126  {
5127  int i;
5128 
5129  *firstchange = MIN(*firstchange, c);
5130  *firstclique = MIN(*firstclique, c);
5131  *lastclique = MAX(*lastclique, c);
5132 
5133  /* variables array has changed due to lifting variables, so get new values */
5134  assert(consdata == SCIPconsGetData(cons0));
5135  cons0vars = consdata->vars;
5136  ncons0vars = consdata->nvars;
5137 
5138  /* resorting array, because we added new variables, in order of indices of variables, negated
5139  * and active counterparts would stand side by side
5140  */
5141  SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5142  /* standard setppc-sorting now lost */
5143  consdata->sorted = FALSE;
5144 
5145  /* clear old entries in overlapping constraint */
5146  BMSclearMemoryArray(countofoverlapping, nusefulconss);
5147 
5148  for( v = ncons0vars - 1; v >= 0 ; --v )
5149  {
5150  var0 = cons0vars[v];
5151 
5152  /* fixed variables later to the count */
5153  if( SCIPvarGetLbLocal(var0) > 0.5 || SCIPvarGetUbLocal(var0) < 0.5 )
5154  continue;
5155 
5156  assert(SCIPhashmapExists(vartoindex, (void*) var0));
5157 
5158  varindex = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) var0);
5159  for( i = varnconss[varindex] - 1; i >= 0 ; --i )
5160  ++(countofoverlapping[varconsidxs[varindex][i]]);
5161  }
5162 
5163  chgcons0 = FALSE;
5164 
5165  /* check for overlapping constraint after lifting, in the first round we will only check up front */
5166  SCIP_CALL( checkForOverlapping(scip, cons0, c, (conshdlrdata->nclqpresolve > 0) ? nusefulconss : c,
5167  usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs,
5168  countofoverlapping, conshdlrdata->cliqueshrinking, &chgcons0,
5169  undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations,
5170  nfixedvars, naggrvars, nchgcoefs, ndelconss, cutoff) );
5171 
5172  if( *cutoff )
5173  break;
5174 
5175  /* we can't handle aggregated variables later on so we should have saved them for later */
5176  assert(*naggrvars == oldnaggrvars);
5177  }
5178  }
5179 
5180  TERMINATE:
5181  SCIPfreeBufferArrayNull(scip, &countofoverlapping);
5182  SCIPfreeBufferArrayNull(scip, &cliquevalues);
5183 
5184  /* free temporary memory for constraints, variables and the mapping between them in reverse order as they were
5185  * allocated
5186  */
5187  for( c = nusefulvars; c > 0; --c )
5188  {
5189  if( varconsidxs[c] != NULL )
5190  {
5191  SCIPfreeBufferArrayNull(scip, &(varconsidxs[c]));
5192  }
5193  }
5194 
5195  SCIPfreeBufferArray(scip, &varconsidxs);
5196  SCIPfreeBufferArray(scip, &maxnvarconsidx);
5197  SCIPfreeBufferArray(scip, &varnconss);
5198  SCIPfreeBufferArray(scip, &usefulvars);
5199  SCIPfreeBufferArray(scip, &usefulconss);
5200 
5201 
5202  /* perform all collected aggregations */
5203  if( !*cutoff && naggregations > 0 && !SCIPdoNotAggr(scip) )
5204  {
5205  SCIP_CALL( performAggregations(scip, conshdlrdata, undoneaggrvars, undoneaggrtypes, naggregations, naggrvars, cutoff) );
5206  }
5207 
5208  /* free temporary memory for the aggregation storage */
5209  SCIPfreeBufferArray(scip, &undoneaggrtypes);
5210  SCIPfreeBufferArray(scip, &undoneaggrvars);
5211 
5212  /* free hashmap */
5213  SCIPhashmapFree(&vartoindex);
5214 
5215  if( *ndelconss < 0 )
5216  *ndelconss = 0;
5217 
5218  return SCIP_OKAY;
5219 }
5220 
5221 
5222 /** add cliques to SCIP */
5223 static
5225  SCIP* scip, /**< SCIP data structure */
5226  SCIP_CONS** conss, /**< constraint set */
5227  int nconss, /**< number of constraints in constraint set */
5228  int firstclique, /**< first constraint to start to add cliques */
5229  int lastclique, /**< last constraint to start to add cliques */
5230  int* naddconss, /**< pointer to count number of added constraints */
5231  int* ndelconss, /**< pointer to count number of deleted constraints */
5232  int* nchgbds, /**< pointer to count number of chnaged bounds */
5233  SCIP_Bool* cutoff /**< pointer to store if the problem is infeasible due to a fixing */
5234  )
5235 {
5236  SCIP_CONS* cons;
5237  SCIP_CONSDATA* consdata;
5238  SCIP_Bool infeasible;
5239  int nlocalbdchgs;
5240  int c;
5241 
5242  assert(scip != NULL);
5243  assert(conss != NULL || nconss == 0);
5244  assert(firstclique >= 0);
5245  assert(lastclique <= nconss);
5246 
5247  /* add clique and implication information */
5248  for( c = firstclique; c < lastclique; ++c )
5249  {
5250  cons = conss[c]; /*lint !e613*/
5251  assert(cons != NULL);
5252 
5253  /* ignore deleted constraints */
5254  if( !SCIPconsIsActive(cons) )
5255  continue;
5256 
5257  nlocalbdchgs = 0;
5258  SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, &nlocalbdchgs, cutoff) );
5259  *nchgbds += nlocalbdchgs;
5260 
5261  if( *cutoff )
5262  return SCIP_OKAY;
5263 
5264  consdata = SCIPconsGetData(cons);
5265  assert(consdata != NULL);
5266 
5267  if( SCIPconsIsDeleted(cons) )
5268  continue;
5269 
5270  if( !consdata->cliqueadded && consdata->nvars >= 2 )
5271  {
5272  /* add a set partitioning / packing constraint as clique */
5273  if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5274  {
5275  SCIP_CALL( SCIPaddClique(scip, consdata->vars, NULL, consdata->nvars,
5276  ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING), &infeasible, &nlocalbdchgs) );
5277  *nchgbds += nlocalbdchgs;
5278 
5279  if( infeasible )
5280  {
5281  *cutoff = TRUE;
5282  return SCIP_OKAY;
5283  }
5284  }
5285  else if( consdata->nvars == 2 && !SCIPconsIsModifiable(cons) )
5286  {
5287  /* a two-variable set covering constraint x + y >= 1 yields the implication x == 0 -> y == 1 */
5288  SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], FALSE, consdata->vars[1],
5289  SCIP_BOUNDTYPE_LOWER, 1.0, &infeasible, &nlocalbdchgs) );
5290  *nchgbds += nlocalbdchgs;
5291 
5292  if( infeasible )
5293  {
5294  *cutoff = TRUE;
5295  return SCIP_OKAY;
5296  }
5297  }
5298  consdata->cliqueadded = TRUE;
5299  }
5300  }
5301 
5302  return SCIP_OKAY;
5303 }
5304 
5305 /** perform multi-aggregation on variables resulting from a set-partitioning/-packing constraint */
5306 static
5308  SCIP* scip, /**< SCIP data structure */
5309  SCIP_Bool linearconshdlrexist,/**< does the linear constraint handler exist, necessaray for
5310  * multi-aggregations
5311  */
5312  SCIP_VAR** vars, /**< all variables including the variable to which will be
5313  * multi-aggregated
5314  */
5315  int nvars, /**< number of all variables */
5316  int pos, /**< position of variable for multi-aggregation */
5317  SCIP_Bool* infeasible, /**< pointer to store infeasibility status of aggregation */
5318  SCIP_Bool* aggregated /**< pointer to store aggregation status */
5319 )
5320 {
5321  SCIP_VAR** tmpvars;
5322  SCIP_Real* scalars;
5323  int v;
5324 
5325  assert(scip != NULL);
5326  assert(vars != NULL);
5327  assert(nvars > 1);
5328  assert(0 <= pos && pos < nvars);
5329  assert(infeasible != NULL);
5330  assert(aggregated != NULL);
5331 
5332  if( nvars == 2 )
5333  {
5334  SCIP_Bool redundant;
5335 
5336  SCIPdebugMessage("aggregating %s = 1 - %s\n", SCIPvarGetName(vars[pos]), SCIPvarGetName(vars[nvars - pos - 1]));
5337 
5338  /* perform aggregation on variables resulting from a set-packing constraint */
5339  SCIP_CALL( SCIPaggregateVars(scip, vars[pos], vars[nvars - pos - 1], 1.0, 1.0, 1.0, infeasible, &redundant, aggregated) );
5340  assert(*infeasible || *aggregated);
5341 
5342  return SCIP_OKAY;
5343  }
5344 
5345  if( !linearconshdlrexist )
5346  return SCIP_OKAY;
5347 
5348  /* if the last variable will be multi-aggregated, we do not need to copy the variables */
5349  if( pos == nvars - 1 )
5350  tmpvars = vars;
5351  else
5352  {
5353  /* copy variables for aggregation */
5354  SCIP_CALL( SCIPduplicateBufferArray(scip, &tmpvars, vars, nvars) );
5355  tmpvars[pos] = tmpvars[nvars - 1];
5356  }
5357 
5358  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, nvars - 1) );
5359  /* initialize scalars */
5360  for( v = nvars - 2; v >= 0; --v )
5361  scalars[v] = -1.0;
5362 
5363  SCIPdebugMessage("multi-aggregating binary variable <%s> (locks: [%d,%d]; to %d variables)\n", SCIPvarGetName(vars[pos]), SCIPvarGetNLocksDown(vars[pos]), SCIPvarGetNLocksUp(vars[pos]), nvars - 1);
5364 
5365  /* perform multi-aggregation */
5366  SCIP_CALL( SCIPmultiaggregateVar(scip, vars[pos], nvars - 1, tmpvars, scalars, 1.0, infeasible, aggregated) );
5367  assert(!(*infeasible));
5368 
5369  SCIPfreeBufferArray(scip, &scalars);
5370 
5371  if( pos < nvars - 1 )
5372  {
5373  assert(tmpvars != vars);
5374  SCIPfreeBufferArray(scip, &tmpvars);
5375  }
5376 
5377  return SCIP_OKAY;
5378 }
5379 
5380 /** determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and negated)
5381  * in any combination of set-partitioning and set-packing constraints
5382  *
5383  * we can multi-aggregate the variable and either change the set-partitioning constraint to a set-packing constraint or
5384  * even delete it
5385  *
5386  * 1. c1: x + y + z = 1, uplocks(x) = 1, downlocks(x) = 1 => x = 1 - y - z and change c1 to y + z <= 1
5387  *
5388  * 2. c2: x + y + z <= 1, uplocks(x) = 1, downlocks(x) = 0, obj(x) < 0 => x = 1 - y - z and change c2 to y + z <= 1
5389  *
5390  * 3. d1: x + y + z <= 1 and d2: ~x + u + v <= 1, uplocks(x) = 1, downlocks(x) = 1
5391  * a) obj(x) <= 0 => x = 1 - y - z and delete d1
5392  * b) obj(x) > 0 => ~x = 1 - u - v and delete d2
5393  *
5394  * 4. e1: x + y + z == 1 and e2: ~x + u + v (<= or ==) 1, uplocks(x) = (1 or 2), downlocks(x) = 2
5395  * => x = 1 - y - z and delete e1
5396  *
5397  * we can also aggregate a variable in a set-packing constraint with only two variables when the uplocks are equal to
5398  * one and then delete this constraint
5399  *
5400  * 5. f1: x + y <= 1, uplocks(x) = 1, obj(x) <= 0 => x = 1 - y and delete f1
5401  *
5402  * @todo might want to multi-aggregate variables even with more locks, when the fill in is still smaller or equal to
5403  * the old number of non-zeros, e.g.
5404  *
5405  * x + y + z = 1
5406  * ~x + u + v <=/= 1
5407  * ~x + w <= 1
5408  */
5409 static
5411  SCIP* scip, /**< SCIP data structure */
5412  SCIP_CONS** conss, /**< constraint set */
5413  int nconss, /**< number of constraints in constraint set */
5414  SCIP_Bool dualpresolvingenabled,/**< is dual presolving enabled */
5415  SCIP_Bool linearconshdlrexist,/**< does the linear constraint handler exist, necessaray for
5416  * multi-aggregations
5417  */
5418  int* nfixedvars, /**< pointer to count number of deleted variables */
5419  int* naggrvars, /**< pointer to count number of aggregated variables */
5420  int* ndelconss, /**< pointer to count number of deleted constraints */
5421  int* nchgcoefs, /**< pointer to count number of changed coefficients */
5422  int* nchgsides, /**< pointer to count number of changed left hand sides */
5423  SCIP_Bool* cutoff /**< pointer to store if a cut off was detedcted */
5424  )
5425 {
5426  SCIP_CONS** usefulconss;
5427  SCIP_VAR** binvars;
5428  SCIP_HASHMAP* vartoindex;
5429  SCIP_Bool* chgtype;
5430  int* considxs;
5431  int* posincons;
5432  SCIP_Bool infeasible;
5433  SCIP_Bool aggregated;
5434  SCIP_Bool donotaggr;
5435  SCIP_Bool donotmultaggr;
5436  SCIP_Bool mustcheck;
5437  SCIP_Bool addcut;
5438  int nposvars;
5439  int ndecs;
5440  int nbinvars;
5441  int nposbinvars;
5442  int nuplocks;
5443  int ndownlocks;
5444  int posreplacements;
5445  int nhashmapentries;
5446  int nlocaladdconss;
5447  int v;
5448  int c;
5449 
5450  assert(scip != NULL);
5451  assert(conss != NULL);
5452  assert(nconss > 0);
5453  assert(nfixedvars != NULL);
5454  assert(naggrvars != NULL);
5455  assert(ndelconss != NULL);
5456  assert(nchgcoefs != NULL);
5457  assert(nchgsides != NULL);
5458 
5459  nbinvars = SCIPgetNBinVars(scip);
5460  nposbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
5461  assert(nbinvars + SCIPgetNIntVars(scip) + SCIPgetNImplVars(scip) == nposbinvars);
5462 
5463  binvars = SCIPgetVars(scip);
5464 
5465  /* determine number for possible multi-aggregations */
5466  nposvars = 0;
5467  for( v = nposbinvars - 1; v >= 0; --v )
5468  {
5469  assert(SCIPvarGetType(binvars[v]) != SCIP_VARTYPE_CONTINUOUS);
5470 
5471  if( v < nbinvars || SCIPvarIsBinary(binvars[v]) )
5472  {
5473  nuplocks = SCIPvarGetNLocksUp(binvars[v]);
5474  ndownlocks = SCIPvarGetNLocksDown(binvars[v]);
5475 
5476  if( (nuplocks == 1 && ndownlocks <= 1) || (nuplocks <= 1 && ndownlocks == 1) || (nuplocks <= 2 && ndownlocks <= 2 && SCIPvarGetNegatedVar(binvars[v]) != NULL) )
5477  ++nposvars;
5478  }
5479  }
5480 
5481  SCIPdebugMessage("found %d binary variables for possible multi-aggregation\n", nposvars);
5482 
5483  if( nposvars == 0 )
5484  return SCIP_OKAY;
5485 
5486  /* a hashmap from var to index when found in a set-partitioning constraint */
5487  SCIP_CALL( SCIPhashmapCreate(&vartoindex, SCIPblkmem(scip), SCIPcalcHashtableSize(5 * nposvars)) );
5488 
5489  /* get temporary memory */
5490  SCIP_CALL( SCIPallocBufferArray(scip, &chgtype, nconss) );
5491  BMSclearMemoryArray(chgtype, nconss);
5492 
5493  SCIP_CALL( SCIPallocBufferArray(scip, &considxs, nposbinvars) );
5494  SCIP_CALL( SCIPallocBufferArray(scip, &posincons, nposbinvars) );
5495 
5496  SCIP_CALL( SCIPduplicateBufferArray(scip, &usefulconss, conss, nconss) );
5497  /* sort constraints */
5498  SCIPsortPtr((void**)usefulconss, setppcConssSort2, nconss);
5499 
5500  posreplacements = 0;
5501  nhashmapentries = 0;
5502  ndecs = 0;
5503  donotaggr = SCIPdoNotAggr(scip);
5504  donotmultaggr = SCIPdoNotMultaggr(scip);
5505  assert(!donotaggr || !donotmultaggr);
5506 
5507  /* determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and
5508  * negated) in any combination of set-partitioning and set-packing constraints
5509  *
5510  * we can multi-aggregate the variable and either change the set-partitioning constraint to a set-packing constraint
5511  * or even delete it
5512  */
5513  for( c = 0; c < nconss; ++c )
5514  {
5515  SCIP_CONS* cons;
5516  SCIP_CONSDATA* consdata;
5517  int oldnfixedvars;
5518  nlocaladdconss = 0;
5519 
5520  cons = usefulconss[c];
5521  assert(cons != NULL);
5522 
5523  if( SCIPconsIsDeleted(cons) )
5524  continue;
5525 
5526  consdata = SCIPconsGetData(cons);
5527  assert(consdata != NULL);
5528 
5529  /* if we cannot find any constraint to perform a useful multi-aggregation, stop */
5530  if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING )
5531  break;
5532 
5533  if( !SCIPconsIsChecked(cons) )
5534  continue;
5535 
5536  if( SCIPconsIsModifiable(cons) )
5537  continue;
5538 
5539  /* update the variables */
5540  SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
5541 
5542  if( *cutoff )
5543  break;
5544 
5545  /* due to resolving multi-aggregations a constraint can become deleted */
5546  if( SCIPconsIsDeleted(cons) )
5547  continue;
5548 
5549  SCIP_CALL( processFixings(scip, cons, cutoff, nfixedvars, &addcut, &mustcheck) );
5550  assert(!addcut);
5551 
5552  if( *cutoff )
5553  break;
5554 
5555  if( SCIPconsIsDeleted(cons) )
5556  continue;
5557 
5558  oldnfixedvars = *nfixedvars;
5559 
5560  /* merging unmerged constraints */
5561  SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
5562 
5563  if( *cutoff )
5564  break;
5565 
5566  if( SCIPconsIsDeleted(cons) )
5567  continue;
5568 
5569  if( oldnfixedvars < *nfixedvars )
5570  {
5571  /* update the variables */
5572  SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
5573  assert(!SCIPconsIsDeleted(cons));
5574  assert(nlocaladdconss == 0);
5575  assert(!*cutoff);
5576 
5577  if( SCIPconsIsDeleted(cons) )
5578  continue;
5579  }
5580 
5581  /* if the constraint was not merged and consists of a variable with its negation, the constraint is redundant */
5582  if( consdata->nvars < 2 )
5583  {
5584  /* deleting redundant set-packing constraint */
5585  if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5586  {
5587  SCIPdebugMessage("deleting redundant set-packing constraint <%s>\n", SCIPconsGetName(cons));
5588 
5589  SCIP_CALL( SCIPdelCons(scip, cons) );
5590  ++(*ndelconss);
5591 
5592  continue;
5593  }
5594  else
5595  {
5596  SCIP_Bool fixed;
5597 
5598  assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
5599 
5600  if( consdata->nvars == 0 )
5601  {
5602  SCIPdebugMessage("empty set partition constraint <%s> led to infeasibility\n", SCIPconsGetName(cons));
5603 
5604  *cutoff = TRUE;
5605  break;
5606  }
5607 
5608  SCIPdebugMessage("fixing <%s> to 1 because this variable is the last variable in a set partition constraint <%s>\n", SCIPvarGetName(consdata->vars[0]), SCIPconsGetName(cons));
5609 
5610  SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
5611  assert(!infeasible);
5612 
5613  if( fixed )
5614  ++(*nfixedvars);
5615 
5616  assert(SCIPvarGetLbGlobal(consdata->vars[0]) > 0.5);
5617 
5618  SCIPdebugMessage("deleting redundant set-partition constraint <%s>\n", SCIPconsGetName(cons));
5619 
5620  SCIP_CALL( SCIPdelCons(scip, cons) );
5621  ++(*ndelconss);
5622 
5623  continue;
5624  }
5625  }
5626 
5627  /* perform dualpresolve on set-packing constraints with exactly two variables */
5628  if( !donotaggr && consdata->nvars == 2 && dualpresolvingenabled && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5629  {
5630  SCIP_VAR* var;
5631  SCIP_Real objval;
5632  SCIP_Bool redundant;
5633 
5634  var = consdata->vars[0];
5635  assert(var != NULL);
5637 
5638  SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
5639 
5640  nuplocks = SCIPvarGetNLocksUp(var);
5641 
5642  if( nuplocks == 1 && objval <= 0 )
5643  {
5644  SCIPdebugMessage("dualpresolve, aggregating %s + %s = 1, in set-packing constraint %s\n", SCIPvarGetName(var), SCIPvarGetName(consdata->vars[1]), SCIPconsGetName(cons));
5645 
5646  /* perform aggregation on variables resulting from a set-packing constraint */
5647  SCIP_CALL( SCIPaggregateVars(scip, var, consdata->vars[1], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5648 
5649  if( infeasible )
5650  {
5651  *cutoff = TRUE;
5652  break;
5653  }
5654 
5655  assert(aggregated);
5656  ++(*naggrvars);
5657 
5658  SCIP_CALL( SCIPdelCons(scip, cons) );
5659  ++(*ndelconss);
5660 
5661  continue;
5662  }
5663  else
5664  {
5665  var = consdata->vars[1];
5666  assert(var != NULL);
5668 
5669  SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
5670 
5671  nuplocks = SCIPvarGetNLocksUp(var);
5672 
5673  if( nuplocks == 1 && objval <= 0 )
5674  {
5675  SCIPdebugMessage("dualpresolve, aggregating %s + %s = 1, in set-packing constraint %s\n", SCIPvarGetName(var), SCIPvarGetName(consdata->vars[0]), SCIPconsGetName(cons));
5676 
5677  /* perform aggregation on variables resulting from a set-packing constraint */
5678  SCIP_CALL( SCIPaggregateVars(scip, var, consdata->vars[0], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5679 
5680  if( infeasible )
5681  {
5682  *cutoff = TRUE;
5683  break;
5684  }
5685  assert(aggregated);
5686  ++(*naggrvars);
5687 
5688  SCIP_CALL( SCIPdelCons(scip, cons) );
5689  ++(*ndelconss);
5690 
5691  continue;
5692  }
5693  }
5694  }
5695  else if( !donotaggr && consdata->nvars == 2 && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
5696  {
5697  SCIP_Bool redundant;
5698 
5699  SCIPdebugMessage("aggregating %s + %s = 1, in set-partition constraint %s\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(consdata->vars[1]), SCIPconsGetName(cons));
5700 
5701  /* perform aggregation on variables resulting from a set-partitioning constraint */
5702  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5703 
5704  if( infeasible )
5705  {
5706  *cutoff = TRUE;
5707  break;
5708  }
5709 
5710  assert(aggregated);
5711  ++(*naggrvars);
5712 
5713  SCIP_CALL( SCIPdelCons(scip, cons) );
5714  ++(*ndelconss);
5715 
5716  continue;
5717  }
5718 
5719  /* we already found all possible variables for multi-aggregation */
5720  if( ndecs >= nposvars )
5721  continue;
5722 
5723  /* no multi aggregation is allowed, so we can continue */
5724  if( donotmultaggr )
5725  continue;
5726 
5727  /* if the following condition does not hold, we have an unmerged constraint, and we might need to merge it first */
5728  assert(nposbinvars >= consdata->nvars);
5729 
5730  /* search for possible variables for multi-aggregation */
5731  for( v = consdata->nvars - 1; v >= 0; --v )
5732  {
5733  SCIP_VAR* var;
5734  int deleteconsindex = -1;
5735 
5736  var = consdata->vars[v];
5737  assert(var != NULL);
5739 
5740  aggregated = FALSE;
5741  nuplocks = SCIPvarGetNLocksUp(var);
5742  ndownlocks = SCIPvarGetNLocksDown(var);
5743  assert(nuplocks >= 1 && ndownlocks >= 0); /* we are only treating set partitioning and set packing constraints, so every variable in there should have an uplock */
5744 
5745  if( dualpresolvingenabled && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING && nuplocks <= 1 && nuplocks + ndownlocks <= 2 )
5746  {
5747  assert(nuplocks == 1 && ndownlocks <= 1);
5748 
5749  /* we found a redundant variable in a set-partitioning constraint */
5750  if( ndownlocks == 0 )
5751  {
5752  SCIP_Real objval;
5753 
5754  SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
5755 
5756  /* if the objective value is >= 0 the fixing is normally done by the dualfix presolver */
5757  if( !SCIPisNegative(scip, objval) )
5758  {
5759  SCIP_Bool fixed;
5760 
5761  SCIPdebugMessage("dual-fixing of variable <%s> to 0.0\n", SCIPvarGetName(var));
5762 
5763  SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
5764  assert(!infeasible);
5765  assert(fixed);
5766 
5767  ++(*nfixedvars);
5768  }
5769  else
5770  {
5771  SCIPdebugMessage("multi-aggregating in set-packing constraint\n");
5772 
5773  /* perform aggregation on variables resulting from a set-packing constraint */
5774  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
5775 
5776  if( infeasible )
5777  {
5778  *cutoff = TRUE;
5779  break;
5780  }
5781  }
5782 
5783  ++ndecs;
5784  }
5785  else if( ndownlocks == 1 && SCIPvarGetNegatedVar(var) != NULL )
5786  {
5787  SCIP_CONSDATA* aggrconsdata;
5788  SCIP_VAR* negvar;
5789  SCIP_VAR* activevar;
5790  SCIP_Real objval;
5791  int multaggridx;
5792  int notmultaggridx;
5793  int image;
5794  int consindex;
5795  int varindex;
5796 
5797  assert(!SCIPhashmapExists(vartoindex, (void*) var));
5798 
5799  negvar = SCIPvarGetNegatedVar(var);
5800 
5801  /* if we found a new variable add it to the data */
5802  if( !SCIPhashmapExists(vartoindex, (void*) negvar) )
5803  {
5804  ++nhashmapentries;
5805  SCIP_CALL( SCIPhashmapInsert(vartoindex, (void*) var, (void*) (size_t) nhashmapentries) );
5806 
5807  considxs[nhashmapentries - 1] = c;
5808  posincons[nhashmapentries - 1] = v;
5809 
5810  ++posreplacements;
5811  continue;
5812  }
5813 
5814  assert(SCIPhashmapExists(vartoindex, (void*) negvar));
5815  image = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) negvar);
5816  assert(image > 0 && image <= nhashmapentries);
5817 
5818  consindex = considxs[image - 1];
5819  assert(0 <= consindex && consindex < nconss);
5820 
5821  /* if the following assert fails, the constraint was not merged, or something really strange happened */
5822  assert(consindex < c);
5823 
5824  ++ndecs;
5825  --posreplacements;
5826  assert(posreplacements >= 0);
5827 
5828  varindex = posincons[image - 1];
5829  considxs[image - 1] = -1;
5830  posincons[image - 1] = -1;
5831  SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) negvar) );
5832 
5833  /* if two variables in one constraint might be multi-aggregated, it might happen that this constraint was already removed */
5834  if( SCIPconsIsDeleted(usefulconss[consindex]) )
5835  continue;
5836 
5837  aggrconsdata = SCIPconsGetData(usefulconss[consindex]);
5838  assert(aggrconsdata != NULL);
5839  assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING);
5840  assert(0 <= varindex);
5841 
5842  /* it might be that due to other multi-aggregations the constraint has fewer variables than when we
5843  * remembered the position, therefore we need to find the variable again
5844  */
5845  if( varindex >= aggrconsdata->nvars || aggrconsdata->vars[varindex] != negvar )
5846  {
5847  int v2;
5848 
5849  /* if the following assert is raised, then the constraint is redundant and we do not need to aggregate
5850  * anymore and can delete this constraint
5851  */
5852  assert(aggrconsdata->nvars >= 2);
5853 
5854  for( v2 = aggrconsdata->nvars - 1; v2 >= 0; --v2 )
5855  {
5856  if( aggrconsdata->vars[v2] == negvar )
5857  break;
5858  }
5859  assert(v2 >= 0);
5860 
5861  varindex = v2;
5862  }
5863  assert(0 <= varindex && varindex < aggrconsdata->nvars);
5864  assert(aggrconsdata->vars[varindex] == negvar);
5866 
5867  /* determine active variable and constraint that corresponds to */
5869  {
5870  activevar = negvar;
5871  multaggridx = consindex;
5872  notmultaggridx = c;
5873  }
5874  else
5875  {
5876  activevar = var;
5877  multaggridx = c;
5878  notmultaggridx = consindex;
5879  }
5880  objval = SCIPvarGetObj(activevar);
5881 
5882  SCIPdebugMessage("multi-aggregating in two set-packing constraint\n");
5883 
5884  if( objval <= 0.0 )
5885  {
5886  /* perform aggregation on variables resulting from a set-packing constraint */
5887  if( multaggridx == c )
5888  {
5889  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
5890  }
5891  else
5892  {
5893  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
5894  }
5895  deleteconsindex = multaggridx;
5896  }
5897  else
5898  {
5899  /* perform aggregation on variables resulting from a set-packing constraint */
5900  if( multaggridx == c )
5901  {
5902  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
5903  }
5904  else
5905  {
5906  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
5907  }
5908  deleteconsindex = notmultaggridx;
5909  }
5910 
5911  if( infeasible )
5912  {
5913  *cutoff = TRUE;
5914  break;
5915  }
5916 
5917  assert(deleteconsindex >= 0 && deleteconsindex <= c);
5918  }
5919  }
5920  /* we found a redundant variable in a set-partitioning constraint */
5921  else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && nuplocks == 1 && ndownlocks == 1 )
5922  {
5923  SCIPdebugMessage("multi-aggregating in set-partitioning constraint\n");
5924 
5925  /* perform aggregation on variables resulting from a set-partitioning constraint */
5926  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
5927 
5928  if( infeasible )
5929  {
5930  *cutoff = TRUE;
5931  break;
5932  }
5933 
5934  ++ndecs;
5935  }
5936  /* we might have found a redundant variable */
5937  else if( ndownlocks <= 2 && nuplocks <= 2 && SCIPvarGetNegatedVar(var) != NULL )
5938  {
5939  SCIP_CONSDATA* aggrconsdata;
5940  int image;
5941  int consindex;
5942  int varindex;
5943 
5944  /* if we have two times the same variable in a set-partitioning constraint, we cannot aggregate this */
5945  if( SCIPhashmapExists(vartoindex, (void*) var) )
5946  {
5947  image = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) var);
5948  assert(image > 0 && image <= nhashmapentries);
5949 
5950  assert(0 <= considxs[image - 1] && considxs[image - 1] < nconss);
5951  assert(SCIPconsIsDeleted(usefulconss[considxs[image - 1]]) || chgtype[considxs[image - 1]] || (0 <= posincons[image - 1] && posincons[image - 1] < SCIPconsGetData(usefulconss[considxs[image - 1]])->nvars));
5952 
5953  considxs[image - 1] = -1;
5954  posincons[image - 1] = -1;
5955 
5956  SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) var) );
5957 
5958  --posreplacements;
5959  assert(posreplacements >= 0);
5960 
5961  continue;
5962  }
5963  else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
5964  {
5965  /* if we found a new variable add it to the data */
5966  if( !SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(var)) )
5967  {
5968  assert(!SCIPhashmapExists(vartoindex, (void*) var));
5969 
5970  ++nhashmapentries;
5971  SCIP_CALL( SCIPhashmapInsert(vartoindex, (void*) var, (void*) (size_t) nhashmapentries) );
5972 
5973  considxs[nhashmapentries - 1] = c;
5974  posincons[nhashmapentries - 1] = v;
5975 
5976  ++posreplacements;
5977  continue;
5978  }
5979  }
5980  else
5981  {
5982  assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING);
5983 
5984  /* the negated variable did not occur in a set partitioning constraint (those will be iterated over
5985  * first), so we cannot aggregate this variable
5986  */
5987  if( !SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(var)) )
5988  continue;
5989  }
5990 
5991  assert(!chgtype[c]);
5992  assert(SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(var)));
5993  image = (int) (size_t) SCIPhashmapGetImage(vartoindex, (void*) SCIPvarGetNegatedVar(var));
5994  assert(image > 0 && image <= nhashmapentries);
5995 
5996  consindex = considxs[image - 1];
5997  assert(0 <= consindex && consindex < nconss);
5998 
5999  /* if the following assert fails, the constraint was not merged, or something really strange happened */
6000  assert(consindex < c);
6001 
6002  ++ndecs;
6003  --posreplacements;
6004  assert(posreplacements >= 0);
6005 
6006  varindex = posincons[image - 1];
6007  considxs[image - 1] = -1;
6008  posincons[image - 1] = -1;
6009  SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) SCIPvarGetNegatedVar(var)) );
6010 
6011  /* if two variables in one constraint might be multi-aggregated, it might happen that this constraint was
6012  * already removed
6013  */
6014  if( SCIPconsIsDeleted(usefulconss[consindex]) )
6015  continue;
6016 
6017  aggrconsdata = SCIPconsGetData(usefulconss[consindex]);
6018  assert(aggrconsdata != NULL);
6019 
6020  /* must not multi-aggregate variables that are locked more then twice by all setppc constraints */
6021  if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING &&
6022  (SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING )
6023  {
6024  assert(!dualpresolvingenabled || nuplocks + ndownlocks > 2);
6025  continue;
6026  }
6027 
6028  assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ||
6029  (SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6030 
6031  /* we already removed a variable before, so our positioning information might be wrong, so we need to walk
6032  * over all variables again
6033  */
6034  if( chgtype[consindex] )
6035  {
6036 #ifndef NDEBUG
6037  int v2;
6038 
6039  assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING);
6040 
6041  /* negated variables needs to be still in the upgraded set-packing constraint */
6042  for( v2 = aggrconsdata->nvars - 1; v2 >= 0; --v2 )
6043  {
6044  if( aggrconsdata->vars[v2] == SCIPvarGetNegatedVar(var) )
6045  break;
6046  }
6047  assert(v2 >= 0);
6048 #endif
6049  assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6050 
6051  SCIPdebugMessage("multi-aggregating in one set-partitioning or one set-packing constraint\n");
6052 
6053  /* perform aggregation on variables resulting from a set-partitioning constraint */
6054  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6055 
6056  if( infeasible )
6057  {
6058  *cutoff = TRUE;
6059  break;
6060  }
6061  assert(deleteconsindex == -1);
6062  }
6063  else
6064  {
6065  /* @note it might have happened that we have a variable at hand which exists actually in a set-packing
6066  * constraint and due to some other aggregation we increased the number of locks and reached this
6067  * part of the code, where we would expect only set-partitioning constraints in general, so in
6068  * such a strange case we cannot aggregate anything
6069  */
6070  if( (SCIP_SETPPCTYPE)aggrconsdata->setppctype != SCIP_SETPPCTYPE_PARTITIONING )
6071  continue;
6072 
6073  assert(0 <= varindex && varindex < aggrconsdata->nvars);
6074  assert(aggrconsdata->vars[varindex] == SCIPvarGetNegatedVar(var));
6075  assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6076 
6077  SCIPdebugMessage("multi-aggregating in two set-partitioning or one set-partitioning and -packing constraint\n");
6078 
6079  /* perform aggregation on variables resulting from a set-partitioning constraint */
6080  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
6081 
6082  if( infeasible )
6083  {
6084  *cutoff = TRUE;
6085  break;
6086  }
6087 
6088  /* change pointer for deletion */
6089  cons = usefulconss[consindex];
6090  assert(deleteconsindex == -1);
6091  }
6092  }
6093 
6094  if( aggregated )
6095  {
6096  assert(nuplocks >= 1 && ndownlocks >= 0); /* repeated from above */
6097  ++(*naggrvars);
6098 
6099  if( nuplocks == 1 && ndownlocks == 0 && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
6100  {
6101  assert(deleteconsindex < 0);
6102 
6103  SCIP_CALL( delCoefPos(scip, cons, v) );
6104  ++(*nchgcoefs);
6105  }
6106  else if( nuplocks == 1 && ndownlocks == 1 && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
6107  {
6108  assert(deleteconsindex < 0);
6109 
6110  SCIP_CALL( delCoefPos(scip, cons, v) );
6111  ++(*nchgcoefs);
6112 
6113  SCIPdebugMessage("changing constraint <%s> from set-partitioning to set-packing, due to multi-aggregation\n", SCIPconsGetName(cons));
6114 
6115  chgtype[c] = TRUE;
6116 
6118  ++(*nchgsides);
6119  }
6120  else
6121  {
6122  if( deleteconsindex >= 0 )
6123  {
6124  SCIPdebugMessage("1: deleting redundant constraint <%s>, due to multi-aggregation\n", SCIPconsGetName(usefulconss[deleteconsindex]));
6125  SCIPdebugPrintCons(scip, usefulconss[deleteconsindex], NULL);
6126 
6127  assert(!SCIPconsIsDeleted(usefulconss[deleteconsindex]));
6128  SCIP_CALL( SCIPdelCons(scip, usefulconss[deleteconsindex]) );
6129  }
6130  else
6131  {
6132  SCIPdebugMessage("2: deleting redundant constraint <%s>, due to multi-aggregation\n", SCIPconsGetName(cons));
6133  SCIPdebugPrintCons(scip, cons, NULL);
6134 
6135  assert(!SCIPconsIsDeleted(cons));
6136  SCIP_CALL( SCIPdelCons(scip, cons) );
6137  }
6138  ++(*ndelconss);
6139  }
6140 
6141  break;
6142  }
6143  }
6144  }
6145 
6146  /* free temporary memory */
6147  SCIPfreeBufferArray(scip, &usefulconss);
6148  SCIPfreeBufferArray(scip, &posincons);
6149  SCIPfreeBufferArray(scip, &considxs);
6150  SCIPfreeBufferArray(scip, &chgtype);
6151 
6152  /* free hashmap */
6153  SCIPhashmapFree(&vartoindex);
6154 
6155  return SCIP_OKAY;
6156 }
6157 
6158 
6159 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
6160  * accordingly; in contrast to removeRedundantConstraints(), it uses a hash table
6161  */
6162 static
6164  SCIP* scip, /**< SCIP data structure */
6165  BMS_BLKMEM* blkmem, /**< block memory */
6166  SCIP_CONS** conss, /**< constraint set */
6167  int nconss, /**< number of constraints in constraint set */
6168  int* firstchange, /**< pointer to store first changed constraint */
6169  int* ndelconss, /**< pointer to count number of deleted constraints */
6170  int* nchgsides /**< pointer to count number of changed left/right hand sides */
6172 {
6173  SCIP_HASHTABLE* hashtable;
6174  int hashtablesize;
6175  int c;
6176 
6177  assert(scip != NULL);
6178  assert(blkmem != NULL);
6179  assert(conss != NULL || nconss == 0);
6180  assert(firstchange != NULL);
6181  assert(ndelconss != NULL);
6182  assert(nchgsides != NULL);
6183 
6184  if( nconss == 0 )
6185  return SCIP_OKAY;
6186 
6187  assert(conss != NULL);
6188 
6189  /* create a hash table for the constraint set */
6190  hashtablesize = SCIPcalcHashtableSize(10*nconss);
6191  hashtablesize = MAX(hashtablesize, HASHSIZE_SETPPCCONS);
6192  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
6193  hashGetKeySetppccons, hashKeyEqSetppccons, hashKeyValSetppccons, (void*) scip) );
6194 
6195  /* check all constraints in the given set for redundancy */
6196  for( c = 0; c < nconss; ++c )
6197  {
6198  SCIP_CONS* cons0;
6199  SCIP_CONS* cons1;
6200 
6201  cons0 = conss[c];
6202 
6203  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
6204  continue;
6205 
6206  /* get constraint from current hash table with same variables as cons0 and with coefficients either equal or negated
6207  * to the ones of cons0 */
6208  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
6209 
6210  if( cons1 != NULL )
6211  {
6212  SCIP_CONSDATA* consdata0;
6213  SCIP_CONSDATA* consdata1;
6214 
6215  assert(SCIPconsIsActive(cons1));
6216  assert(!SCIPconsIsModifiable(cons1));
6217 
6218  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
6219  * delete old constraints afterwards
6220  */
6221  consdata0 = SCIPconsGetData(cons0);
6222  consdata1 = SCIPconsGetData(cons1);
6223 
6224  assert(consdata0 != NULL && consdata1 != NULL);
6225  assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
6226 
6227  assert(consdata0->sorted && consdata1->sorted);
6228  assert(consdata0->vars[0] == consdata1->vars[0]);
6229 
6230  SCIPdebugMessage("setppc constraints <%s> and <%s> have identical variable sets\n",
6231  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6232  SCIPdebugPrintCons(scip, cons0, NULL);
6233  SCIPdebugPrintCons(scip, cons1, NULL);
6234 
6235  /* if necessary change type of setppc constraint */
6236  if( consdata1->setppctype != SCIP_SETPPCTYPE_PARTITIONING && consdata0->setppctype != consdata1->setppctype ) /*lint !e641*/
6237  {
6238  /* change the type of cons0 */
6240  (*nchgsides)++;
6241  }
6242 
6243  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
6244  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
6245 
6246  /* delete cons0 */
6247  SCIP_CALL( SCIPdelCons(scip, cons0) );
6248  (*ndelconss)++;
6249 
6250  /* update the first changed constraint to begin the next aggregation round with */
6251  if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
6252  *firstchange = SCIPconsGetPos(cons1);
6253 
6254  assert(SCIPconsIsActive(cons1));
6255  }
6256  else
6257  {
6258  /* no such constraint in current hash table: insert cons0 into hash table */
6259  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
6260  }
6261  }
6262 
6263  /* free hash table */
6264  SCIPhashtableFree(&hashtable);
6265 
6266  return SCIP_OKAY;
6267 }
6268 
6269 /** removes the redundant second constraint and updates the flags of the first one */
6270 static
6272  SCIP* scip, /**< SCIP data structure */
6273  SCIP_CONS* cons0, /**< constraint that should stay */
6274  SCIP_CONS* cons1, /**< constraint that should be deleted */
6275  int* ndelconss /**< pointer to count number of deleted constraints */
6276  )
6277 {
6278  assert(ndelconss != NULL);
6280  SCIPdebugMessage(" -> removing setppc constraint <%s> which is redundant to <%s>\n",
6281  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
6282  SCIPdebugPrintCons(scip, cons0, NULL);
6283  SCIPdebugPrintCons(scip, cons1, NULL);
6284 
6285  /* update flags of cons0 */
6286  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
6287 
6288  /* delete cons1 */
6289  SCIP_CALL( SCIPdelCons(scip, cons1) );
6290  (*ndelconss)++;
6291 
6292  return SCIP_OKAY;
6293 }
6294 
6295 /** for cons0 contained in cons1, fixes variables of cons1 that are not in cons0 to zero */
6296 static
6298  SCIP* scip, /**< SCIP data structure */
6299  SCIP_CONS* cons0, /**< constraint that is contained in the other */
6300  SCIP_CONS* cons1, /**< constraint that is a superset of the other */
6301  SCIP_Bool* cutoff, /**< pointer to store whether a cutoff was found */
6302  int* nfixedvars /**< pointer to count number of fixed variables */
6303  )
6304 {
6305  SCIP_CONSDATA* consdata0;
6306  SCIP_CONSDATA* consdata1;
6307  int v0;
6308  int v1;
6309 
6310  assert(cutoff != NULL);
6311  assert(nfixedvars != NULL);
6312 
6313  *cutoff = FALSE;
6314 
6315  /* get constraint data */
6316  consdata0 = SCIPconsGetData(cons0);
6317  consdata1 = SCIPconsGetData(cons1);
6318  assert(consdata0 != NULL);
6319  assert(consdata1 != NULL);
6320  assert(consdata0->nvars < consdata1->nvars);
6321  assert(consdata0->sorted);
6322  assert(consdata1->sorted);
6323 
6324  /* fix variables in the range of cons0 */
6325  for( v0 = 0, v1 = 0; v0 < consdata0->nvars && !(*cutoff); ++v0, ++v1 )
6326  {
6327  int index0;
6328 
6329  assert(v1 < consdata1->nvars);
6330  index0 = SCIPvarGetIndex(consdata0->vars[v0]);
6331  for( ; SCIPvarGetIndex(consdata1->vars[v1]) < index0 && !(*cutoff); ++v1 )
6332  {
6333  SCIP_Bool fixed;
6334 
6335  /* fix variable to zero */
6336  SCIP_CALL( SCIPfixVar(scip, consdata1->vars[v1], 0.0, cutoff, &fixed) );
6337  if( fixed )
6338  {
6339  SCIPdebugMessage(" -> fixed <%s> == 0\n", SCIPvarGetName(consdata1->vars[v1]));
6340  (*nfixedvars)++;
6341  }
6342  assert(v1 < consdata1->nvars-1);
6343  }
6344  assert(SCIPvarGetIndex(consdata1->vars[v1]) == index0 || *cutoff);
6345  }
6346 
6347  /* fix remaining variables of cons1 */
6348  for( ; v1 < consdata1->nvars && !(*cutoff); ++v1 )
6349  {
6350  SCIP_Bool fixed;
6351 
6352  assert(consdata0->nvars == 0
6353  || SCIPvarGetIndex(consdata1->vars[v1]) > SCIPvarGetIndex(consdata0->vars[consdata0->nvars-1]));
6354 
6355  /* fix variable to zero */
6356  SCIP_CALL( SCIPfixVar(scip, consdata1->vars[v1], 0.0, cutoff, &fixed) );
6357  if( fixed )
6358  {
6359  SCIPdebugMessage(" -> fixed <%s> == 0\n", SCIPvarGetName(consdata1->vars[v1]));
6360  (*nfixedvars)++;
6361  }
6362  }
6363 
6364  return SCIP_OKAY;
6365 }
6366 
6367 /** applies reductions for cons0 being contained in cons1 */
6368 static
6370  SCIP* scip, /**< SCIP data structure */
6371  SCIP_CONS* cons0, /**< constraint that is contained in the other */
6372  SCIP_CONS* cons1, /**< constraint that is a superset of the other */
6373  SCIP_Bool* cutoff, /**< pointer to store whether a cutoff was found */
6374  int* nfixedvars, /**< pointer to count number of fixed variables */
6375  int* ndelconss, /**< pointer to count number of deleted constraints */
6376  int* nchgsides /**< pointer to count number of changed left/right hand sides */
6377  )
6378 {
6379  SCIP_CONSDATA* consdata0;
6380  SCIP_CONSDATA* consdata1;
6381 
6382  assert(cutoff != NULL);
6383  assert(nfixedvars != NULL);
6384  assert(ndelconss != NULL);
6385  assert(nchgsides != NULL);
6386 
6387  *cutoff = FALSE;
6388 
6389  /* get constraint data */
6390  consdata0 = SCIPconsGetData(cons0);
6391  consdata1 = SCIPconsGetData(cons1);
6392  assert(consdata0 != NULL);
6393  assert(consdata1 != NULL);
6394  assert(consdata0->nvars < consdata1->nvars);
6395  assert(consdata0->sorted);
6396  assert(consdata1->sorted);
6397 
6398  switch( consdata0->setppctype )
6399  {
6401  switch( consdata1->setppctype )
6402  {
6405  /* cons0: partitioning, cons1: partitioning or packing
6406  * -> fix additional variables in cons1 to zero, remove cons1
6407  */
6408  SCIP_CALL( fixAdditionalVars(scip, cons0, cons1, cutoff, nfixedvars) );
6409  SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6410  break;
6411 
6413  /* cons0: partitioning, cons1: covering
6414  * -> remove cons1
6415  */
6416  SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6417  break;
6418 
6419  default:
6420  SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6421  return SCIP_INVALIDDATA;
6422  }
6423  break;
6424 
6426  switch( consdata1->setppctype )
6427  {
6430  /* cons0: packing, cons1: partitioning or packing
6431  * -> remove cons0
6432  */
6433  SCIP_CALL( removeRedundantCons(scip, cons1, cons0, ndelconss) );
6434  break;
6435 
6437  /* cons0: packing, cons1: covering
6438  * -> nothing can be deduced
6439  */
6440  break;
6441 
6442  default:
6443  SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6444  return SCIP_INVALIDDATA;
6445  }
6446  break;
6447 
6449  switch( consdata1->setppctype )
6450  {
6453  /* cons0: covering, cons1: partitioning or packing
6454  * -> fix additional variables in cons1 to zero, remove cons1, convert cons0 into partitioning
6455  */
6456  SCIP_CALL( fixAdditionalVars(scip, cons0, cons1, cutoff, nfixedvars) );
6458  SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6459  (*nchgsides)++;
6460  break;
6461 
6463  /* cons0: covering, cons1: covering
6464  * -> remove cons1
6465  */
6466  SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6467  break;
6468 
6469  default:
6470  SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6471  return SCIP_INVALIDDATA;
6472  }
6473  break;
6474 
6475  default:
6476  SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata0->setppctype, SCIPconsGetName(cons0));
6477  return SCIP_INVALIDDATA;
6478  }
6479 
6480  return SCIP_OKAY;
6481 }
6482 
6483 /** deletes redundant constraints */
6484 static
6486  SCIP* scip, /**< SCIP data structure */
6487  SCIP_CONS** conss, /**< constraint set */
6488  int firstchange, /**< first constraint that changed since last pair preprocessing round */
6489  int chkind, /**< index of constraint to check against all prior indices upto startind */
6490  SCIP_Bool* cutoff, /**< pointer to store whether a cutoff was found */
6491  int* nfixedvars, /**< pointer to count number of fixed variables */
6492  int* ndelconss, /**< pointer to count number of deleted constraints */
6493  int* nchgsides /**< pointer to count number of changed left/right hand sides */
6494  )
6495 {
6496  SCIP_CONS* cons0;
6497  SCIP_CONSDATA* consdata0;
6498  SCIP_Longint signature0;
6499  SCIP_Bool cons0changed;
6500  int c;
6501 
6502  assert(scip != NULL);
6503  assert(conss != NULL);
6504  assert(cutoff != NULL);
6505  assert(nfixedvars != NULL);
6506  assert(ndelconss != NULL);
6507  assert(nchgsides != NULL);
6508 
6509  *cutoff = FALSE;
6510 
6511  /* get the constraint to be checked against all prior constraints */
6512  cons0 = conss[chkind];
6513  assert(SCIPconsIsActive(cons0));
6514  assert(!SCIPconsIsModifiable(cons0));
6515 
6516  consdata0 = SCIPconsGetData(cons0);
6517  assert(consdata0 != NULL);
6518  assert(consdata0->nvars >= 1);
6519 
6520  /* sort the constraint cons0 */
6521  consdataSort(consdata0);
6522 
6523  /* get the bit signature of the constraint */
6524  signature0 = consdataGetSignature(consdata0);
6525 
6526  /* check constraint against all prior constraints */
6527  cons0changed = consdata0->changed;
6528  consdata0->changed = FALSE;
6529  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && SCIPconsIsActive(cons0); ++c )
6530  {
6531  SCIP_CONS* cons1;
6532  SCIP_CONSDATA* consdata1;
6533  SCIP_Longint signature1;
6534  SCIP_Longint jointsignature;
6535  SCIP_Bool cons0iscontained;
6536  SCIP_Bool cons1iscontained;
6537  int v0;
6538  int v1;
6539 
6540  cons1 = conss[c];
6541 
6542  /* ignore inactive and modifiable constraints */
6543  if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
6544  continue;
6545 
6546  consdata1 = SCIPconsGetData(cons1);
6547  assert(consdata1 != NULL);
6548 
6549  /* sort the constraint cons1 */
6550  consdataSort(consdata1);
6551 
6552  /* get the bit signature of cons1 */
6553  signature1 = consdataGetSignature(consdata1);
6554 
6555  /* check (based on signature) if the two constraints are not included in each other */
6556  jointsignature = (signature0 | signature1);
6557  if( jointsignature != signature0 && jointsignature != signature1 )
6558  continue;
6559 
6560  /* check whether one constraint is really a subset of the other */
6561  cons0iscontained = (consdata0->nvars <= consdata1->nvars);
6562  cons1iscontained = (consdata1->nvars <= consdata0->nvars);
6563  v0 = 0;
6564  v1 = 0;
6565  while( v0 < consdata0->nvars && v1 < consdata1->nvars )
6566  {
6567  int index0;
6568  int index1;
6569 
6570  index0 = SCIPvarGetIndex(consdata0->vars[v0]);
6571  index1 = SCIPvarGetIndex(consdata1->vars[v1]);
6572  if( index0 < index1 )
6573  {
6574  cons0iscontained = FALSE;
6575  if( !cons1iscontained )
6576  break;
6577  for( v0++; v0 < consdata0->nvars && SCIPvarGetIndex(consdata0->vars[v0]) < index1; v0++ )
6578  {}
6579  }
6580  else if( index1 < index0 )
6581  {
6582  cons1iscontained = FALSE;
6583  if( !cons0iscontained )
6584  break;
6585  for( v1++; v1 < consdata1->nvars && SCIPvarGetIndex(consdata1->vars[v1]) < index0; v1++ )
6586  {}
6587  }
6588  else
6589  {
6590  v0++;
6591  v1++;
6592  }
6593  }
6594  cons0iscontained = cons0iscontained && (v0 == consdata0->nvars);
6595  cons1iscontained = cons1iscontained && (v1 == consdata1->nvars);
6596 
6597  if( cons0iscontained && cons1iscontained )
6598  {
6599  SCIPdebugMessage("setppc constraints <%s> and <%s> have identical variable sets\n",
6600  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6601  SCIPdebugPrintCons(scip, cons0, NULL);
6602  SCIPdebugPrintCons(scip, cons1, NULL);
6603 
6604  /* both constraints consists of the same variables */
6605  if( consdata0->setppctype == consdata1->setppctype )
6606  {
6607  /* both constraints are equal: update flags in cons0 and delete cons1 */
6608  SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6609  }
6610  else if( consdata0->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
6611  {
6612  /* the set partitioning constraint is stronger: remove the other one */
6613  SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6614  }
6615  else if( consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
6616  {
6617  /* the set partitioning constraint is stronger: remove the other one */
6618  SCIP_CALL( removeRedundantCons(scip, cons1, cons0, ndelconss) );
6619  }
6620  else
6621  {
6622  /* one is a covering, the other one a packing constraint: replace them by a single partitioning constraint */
6623  assert((consdata0->setppctype == SCIP_SETPPCTYPE_COVERING && consdata1->setppctype == SCIP_SETPPCTYPE_PACKING)
6624  || (consdata1->setppctype == SCIP_SETPPCTYPE_COVERING && consdata0->setppctype == SCIP_SETPPCTYPE_PACKING)); /*lint !e641*/
6625 
6626  /* change the type of cons0 */
6628  (*nchgsides)++;
6629 
6630  /* delete cons1 */
6631  SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6632  }
6633  }
6634  else if( cons0iscontained )
6635  {
6636  /* cons0 is contained in cons1 */
6637  SCIPdebugMessage("setppc constraint <%s> is contained in <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6638  SCIPdebugPrintCons(scip, cons0, NULL);
6639  SCIPdebugPrintCons(scip, cons1, NULL);
6640  SCIP_CALL( processContainedCons(scip, cons0, cons1, cutoff, nfixedvars, ndelconss, nchgsides) );
6641  }
6642  else if( cons1iscontained )
6643  {
6644  /* cons1 is contained in cons1 */
6645  SCIPdebugMessage("setppc constraint <%s> is contained in <%s>\n", SCIPconsGetName(cons1), SCIPconsGetName(cons0));
6646  SCIPdebugPrintCons(scip, cons0, NULL);
6647  SCIPdebugPrintCons(scip, cons1, NULL);
6648  SCIP_CALL( processContainedCons(scip, cons1, cons0, cutoff, nfixedvars, ndelconss, nchgsides) );
6649  }
6650  }
6651 
6652  return SCIP_OKAY;
6653 }
6654 
6655 /* perform deletion of variables in all constraints of the constraint handler */
6656 static
6658  SCIP* scip, /**< SCIP data structure */
6659  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
6660  SCIP_CONS** conss, /**< array of constraints */
6661  int nconss /**< number of constraints */
6662  )
6663 {
6664  SCIP_CONSDATA* consdata;
6665  int i;
6666  int v;
6667 
6668 
6669  assert(scip != NULL);
6670  assert(conshdlr != NULL);
6671  assert(conss != NULL);
6672  assert(nconss >= 0);
6673  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
6674 
6675  /* iterate over all constraints */
6676  for( i = 0; i < nconss; i++ )
6677  {
6678  consdata = SCIPconsGetData(conss[i]);
6679 
6680  /* constraint is marked, that some of its variables were deleted */
6681  if( consdata->varsdeleted )
6682  {
6683  /* iterate over all variables of the constraint and delete marked variables */
6684  for( v = consdata->nvars - 1; v >= 0; v-- )
6685  {
6686  if( SCIPvarIsDeleted(consdata->vars[v]) )
6687  {
6688  SCIP_CALL( delCoefPos(scip, conss[i], v) );
6689  }
6690  }
6691  consdata->varsdeleted = FALSE;
6692  }
6693  }
6694 
6695  return SCIP_OKAY;
6696 }
6697 
6698 
6699 /*
6700  * upgrading of linear constraints
6701  */
6702 
6703 
6704 /** creates and captures a set partitioning / packing / covering constraint */
6705 static
6707  SCIP* scip, /**< SCIP data structure */
6708  SCIP_CONS** cons, /**< pointer to hold the created constraint */
6709  const char* name, /**< name of constraint */
6710  int nvars, /**< number of variables in the constraint */
6711  SCIP_VAR** vars, /**< array with variables of constraint entries */
6712  SCIP_SETPPCTYPE setppctype, /**< type of constraint: set partitioning, packing, or covering constraint */
6713  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
6714  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
6715  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
6716  * Usually set to TRUE. */
6717  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
6718  * TRUE for model constraints, FALSE for additional, redundant constraints. */
6719  SCIP_Bool check, /**< should the constraint be checked for feasibility?
6720  * TRUE for model constraints, FALSE for additional, redundant constraints. */
6721  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
6722  * Usually set to TRUE. */
6723  SCIP_Bool local, /**< is constraint only valid locally?
6724  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
6725  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
6726  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
6727  * adds coefficients to this constraint. */
6728  SCIP_Bool dynamic, /**< is constraint subject to aging?
6729  * Usually set to FALSE. Set to TRUE for own cuts which
6730  * are separated as constraints. */
6731  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
6732  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
6733  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
6734  * if it may be moved to a more global node?
6735  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
6736  )
6737 {
6738  SCIP_CONSHDLR* conshdlr;
6739  SCIP_CONSDATA* consdata;
6740  SCIP_CONSHDLRDATA* conshdlrdata;
6741 
6742  assert(scip != NULL);
6743 
6744  /* find the set partitioning constraint handler */
6745  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
6746  if( conshdlr == NULL )
6747  {
6748  SCIPerrorMessage("set partitioning / packing / covering constraint handler not found\n");
6749  return SCIP_INVALIDCALL;
6750  }
6751 
6752  /* create the constraint specific data */
6753  if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
6754  {
6755  /* create constraint in original problem */
6756  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, setppctype) );
6757  }
6758  else
6759  {
6760  /* create constraint in transformed problem */
6761  SCIP_CALL( consdataCreateTransformed(scip, &consdata, nvars, vars, setppctype) );
6762  }
6763 
6764  /* create constraint */
6765  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
6766  local, modifiable, dynamic, removable, stickingatnode) );
6767 
6768  conshdlrdata = SCIPconshdlrGetData(conshdlr);
6769  assert(conshdlrdata != NULL);
6770 
6771  if( SCIPisTransformed(scip) && setppctype == SCIP_SETPPCTYPE_PARTITIONING )
6772  {
6773  ++(conshdlrdata->nsetpart);
6774  assert(conshdlrdata->nsetpart >= 0);
6775  }
6776 
6777  if( SCIPgetStage(scip) != SCIP_STAGE_PROBLEM )
6778  {
6779  /* get event handler */
6780  assert(conshdlrdata->eventhdlr != NULL);
6781 
6782  /* catch bound change events of variables */
6783  SCIP_CALL( catchAllEvents(scip, *cons, conshdlrdata->eventhdlr) );
6784  }
6785 
6786  return SCIP_OKAY;
6787 }
6788 
6789 /** creates and captures a normalized (with all coefficients +1) setppc constraint */
6790 static
6792  SCIP* scip, /**< SCIP data structure */
6793  SCIP_CONS** cons, /**< pointer to hold the created constraint */
6794  const char* name, /**< name of constraint */
6795  int nvars, /**< number of variables in the constraint */
6796  SCIP_VAR** vars, /**< array with variables of constraint entries */
6797  SCIP_Real* vals, /**< array with coefficients (+1.0 or -1.0) */
6798  int mult, /**< multiplier on the coefficients(+1 or -1) */
6799  SCIP_SETPPCTYPE setppctype, /**< type of constraint: set partitioning, packing, or covering constraint */
6800  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
6801  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
6802  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
6803  * Usually set to TRUE. */
6804  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
6805  * TRUE for model constraints, FALSE for additional, redundant constraints. */
6806  SCIP_Bool check, /**< should the constraint be checked for feasibility?
6807  * TRUE for model constraints, FALSE for additional, redundant constraints. */
6808  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
6809  * Usually set to TRUE. */
6810  SCIP_Bool local, /**< is constraint only valid locally?
6811  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
6812  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
6813  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
6814  * adds coefficients to this constraint. */
6815  SCIP_Bool dynamic, /**< is constraint subject to aging?
6816  * Usually set to FALSE. Set to TRUE for own cuts which
6817  * are separated as constraints. */
6818  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
6819  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
6820  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
6821  * if it may be moved to a more global node?
6822  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
6823  )
6824 {
6825  SCIP_VAR** transvars;
6826  int v;
6827 
6828  assert(nvars == 0 || vars != NULL);
6829  assert(nvars == 0 || vals != NULL);
6830  assert(mult == +1 || mult == -1);
6831 
6832  /* get temporary memory */
6833  SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
6834 
6835  /* negate positive or negative variables */
6836  for( v = 0; v < nvars; ++v )
6837  {
6838  if( mult * vals[v] > 0.0 )
6839  transvars[v] = vars[v];
6840  else
6841  {
6842  SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
6843  }
6844  assert(transvars[v] != NULL);
6845  }
6846 
6847  /* create the constraint */
6848  SCIP_CALL( createConsSetppc(scip, cons, name, nvars, transvars, setppctype,
6849  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
6850 
6851  /* release temporary memory */
6852  SCIPfreeBufferArray(scip, &transvars);
6853 
6854  return SCIP_OKAY;
6855 }
6856 
6857 /** check, if linear constraint can be upgraded to set partitioning, packing, or covering constraint */
6858 static
6859 SCIP_DECL_LINCONSUPGD(linconsUpgdSetppc)
6860 { /*lint --e{715}*/
6861  assert(upgdcons != NULL);
6862  assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") == 0 );
6863 
6864  /* check, if linear constraint can be upgraded to set partitioning, packing, or covering constraint
6865  * - all set partitioning / packing / covering constraints consist only of binary variables with a
6866  * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
6867  * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
6868  * - negating all variables y = (1-Y) with negative coefficients gives:
6869  * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
6870  * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
6871  * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
6872  * - a set partitioning constraint has left hand side of +1.0, and right hand side of +1.0 : x(S) == 1.0
6873  * -> without negations: lhs == rhs == 1 - n or lhs == rhs == p - 1
6874  * - a set packing constraint has left hand side of -infinity, and right hand side of +1.0 : x(S) <= 1.0
6875  * -> without negations: (lhs == -inf and rhs == 1 - n) or (lhs == p - 1 and rhs = +inf)
6876  * - a set covering constraint has left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
6877  * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
6878  */
6879  if( nposbin + nnegbin + nposimplbin + nnegimplbin == nvars && ncoeffspone + ncoeffsnone == nvars )
6880  {
6881  int mult;
6882 
6883  if( SCIPisEQ(scip, lhs, rhs) && (SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) || SCIPisEQ(scip, lhs, ncoeffspone - 1.0)) )
6884  {
6885  SCIPdebugMessage("upgrading constraint <%s> to set partitioning constraint\n", SCIPconsGetName(cons));
6886 
6887  /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
6888  mult = SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) ? +1 : -1;
6889 
6890  /* create the set partitioning constraint (an automatically upgraded constraint is always unmodifiable) */
6891  assert(!SCIPconsIsModifiable(cons));
6892  SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
6898  }
6899  else if( (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, 1.0 - ncoeffsnone))
6900  || (SCIPisEQ(scip, lhs, ncoeffspone - 1.0) && SCIPisInfinity(scip, rhs)) )
6901  {
6902  SCIPdebugMessage("upgrading constraint <%s> to set packing constraint\n", SCIPconsGetName(cons));
6903 
6904  /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
6905  mult = SCIPisInfinity(scip, -lhs) ? +1 : -1;
6906 
6907  /* create the set packing constraint (an automatically upgraded constraint is always unmodifiable) */
6908  assert(!SCIPconsIsModifiable(cons));
6909  SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
6915  }
6916  else if( (SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, rhs))
6917  || (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, ncoeffspone - 1.0)) )
6918  {
6919  SCIPdebugMessage("upgrading constraint <%s> to set covering constraint\n", SCIPconsGetName(cons));
6920 
6921  /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
6922  mult = SCIPisInfinity(scip, rhs) ? +1 : -1;
6923 
6924  /* create the set covering constraint (an automatically upgraded constraint is always unmodifiable) */
6925  assert(!SCIPconsIsModifiable(cons));
6926  SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
6932  }
6933  }
6934 
6935  return SCIP_OKAY;
6936 }
6937 
6938 /** tries to upgrade a quadratic constraint to a setpacking constraint */
6939 static
6940 SCIP_DECL_QUADCONSUPGD(quadraticUpgdSetppc)
6941 {
6942  SCIP_QUADVARTERM* quadvarterms;
6943  SCIP_BILINTERM* term;
6944  SCIP_VAR* vars[2];
6945  SCIP_Real coefx;
6946  SCIP_Real coefy;
6947  SCIP_Real rhs;
6949  assert( scip != NULL );
6950  assert( cons != NULL );
6951  assert( nupgdconss != NULL );
6952  assert( upgdconss != NULL );
6953  assert( ! SCIPconsIsModifiable(cons) );
6954  assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "quadratic") == 0 );
6955 
6956  *nupgdconss = 0;
6957 
6958  SCIPdebugMessage("try to upgrade quadratic constraint <%s> to setpacking constraint ...\n", SCIPconsGetName(cons));
6959  SCIPdebugPrintCons(scip, cons, NULL);
6960 
6961  /* cannot currently handle linear part */
6962  if( SCIPgetNLinearVarsQuadratic(scip, cons) > 0 )
6963  return SCIP_OKAY;
6964 
6965  /* need only one bilinear term */
6966  if( SCIPgetNBilinTermsQuadratic(scip, cons) != 1 )
6967  return SCIP_OKAY;
6968 
6969  /* need exactly two quadratic variables */
6970  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) != 2 )
6971  return SCIP_OKAY;
6972 
6973  /* get bilinear term */
6974  term = SCIPgetBilinTermsQuadratic(scip, cons);
6975  if( SCIPisZero(scip, term->coef) )
6976  return SCIP_OKAY;
6977 
6978  /* check types */
6980  return SCIP_OKAY;
6981 
6982  /* left and right hand side need to be equal
6983  * @todo we could also handle inequalities
6984  */
6985  rhs = SCIPgetRhsQuadratic(scip, cons);
6986  if( SCIPisInfinity(scip, rhs) || !SCIPisEQ(scip, SCIPgetLhsQuadratic(scip, cons), rhs) )
6987  return SCIP_OKAY;
6988 
6989  quadvarterms = SCIPgetQuadVarTermsQuadratic(scip, cons);
6990 
6991  coefx = quadvarterms[0].lincoef + quadvarterms[0].sqrcoef; /* for binary variables, we can treat sqr coef as lin coef */
6992  coefy = quadvarterms[1].lincoef + quadvarterms[0].sqrcoef; /* for binary variables, we can treat sqr coef as lin coef */
6993 
6994  /* divide constraint by coefficient of x*y */
6995  coefx /= term->coef;
6996  coefy /= term->coef;
6997  rhs /= term->coef;
6998 
6999  /* constraint is now of the form coefx * x + coefy * y + x * y == rhs
7000  * we can rewrite as (x + coefy) * (y + coefx) == rhs + coefx * coefy
7001  */
7002 
7003  /* we can only upgrade if coefx and coefy are 0 or -1 and rhs == -coefx * coefy */
7004  if( !SCIPisZero(scip, coefx) && !SCIPisEQ(scip, coefx, -1.0) )
7005  return SCIP_OKAY;
7006  if( !SCIPisZero(scip, coefy) && !SCIPisEQ(scip, coefy, -1.0) )
7007  return SCIP_OKAY;
7008  if( !SCIPisEQ(scip, rhs, -coefx * coefy) )
7009  return SCIP_OKAY;
7010 
7011  if( SCIPisZero(scip, coefy) )
7012  {
7013  vars[0] = quadvarterms[0].var;
7014  }
7015  else
7016  {
7017  assert(SCIPisEQ(scip, coefy, -1.0));
7018  /* x - 1 = -(1-x) = -(~x) */
7019  SCIP_CALL( SCIPgetNegatedVar(scip, quadvarterms[0].var, &vars[0]) );
7020  }
7021  if( SCIPisZero(scip, coefx) )
7022  {
7023  vars[1] = quadvarterms[1].var;
7024  }
7025  else
7026  {
7027  assert(SCIPisEQ(scip, coefx, -1.0));
7028  /* y - 1 = -(1 - y) = -(~y) */
7029  SCIP_CALL( SCIPgetNegatedVar(scip, quadvarterms[1].var, &vars[1]) );
7030  }
7031 
7032  /* constraint is now of the form vars[0] * vars[1] == 0 */
7033 
7034  SCIPdebugMessage("constraint <%s> can be upgraded ...\n", SCIPconsGetName(cons));
7035 
7036  /* vars[0] + vars[1] <= 1 */
7037  SCIP_CALL( SCIPcreateConsSetpack(scip, &upgdconss[0], SCIPconsGetName(cons), 2, vars,
7041  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
7042 
7043  ++(*nupgdconss);
7044 
7045  return SCIP_OKAY;
7046 } /*lint !e715*/
7047 
7048 
7049 /*
7050  * Callback methods of constraint handler
7051  */
7052 
7053 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
7054 static
7055 SCIP_DECL_CONSHDLRCOPY(conshdlrCopySetppc)
7056 { /*lint --e{715}*/
7057  assert(scip != NULL);
7058  assert(conshdlr != NULL);
7059  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7060 
7061  /* call inclusion method of constraint handler */
7064  *valid = TRUE;
7065 
7066  return SCIP_OKAY;
7067 }
7068 
7069 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
7070 static
7071 SCIP_DECL_CONSFREE(consFreeSetppc)
7072 { /*lint --e{715}*/
7073  SCIP_CONSHDLRDATA* conshdlrdata;
7074 
7075  assert(conshdlr != NULL);
7076  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7077  assert(scip != NULL);
7078 
7079  /* free constraint handler data */
7080  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7081  assert(conshdlrdata != NULL);
7082 
7083  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
7084 
7085  SCIPconshdlrSetData(conshdlr, NULL);
7086 
7087  return SCIP_OKAY;
7088 }
7089 
7090 
7091 /** initialization method of constraint handler (called after problem was transformed) */
7092 static
7093 SCIP_DECL_CONSINIT(consInitSetppc)
7094 { /*lint --e{715}*/
7095  SCIP_CONSHDLRDATA* conshdlrdata;
7096 
7097  assert(conshdlr != NULL);
7098  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7099  assert(scip != NULL);
7100 
7101  /* free constraint handler data */
7102  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7103  assert(conshdlrdata != NULL);
7104 
7105  conshdlrdata->noldfixedvars = 0;
7106  conshdlrdata->noldimpls = 0;
7107  conshdlrdata->noldcliques = 0;
7108  conshdlrdata->noldupgrs = 0;
7109  conshdlrdata->nclqpresolve = 0;
7110  conshdlrdata->updatedsetppctype = FALSE;
7111  conshdlrdata->enablecliquelifting = TRUE;
7112  conshdlrdata->randseed = 1010010007; /*@todo try to take a better/another value */
7113 
7114  return SCIP_OKAY;
7115 }
7116 
7117 
7118 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
7119 static
7120 SCIP_DECL_CONSEXITPRE(consExitpreSetppc)
7121 { /*lint --e{715}*/
7122  int c;
7123 
7124  assert(scip != NULL);
7125  assert(conshdlr != NULL);
7126 
7127  for( c = 0; c < nconss; ++c )
7128  {
7129  if( !SCIPconsIsDeleted(conss[c]) )
7130  {
7131  /* we are not allowed to detect infeasibility in the exitpre stage */
7132  SCIP_CALL( applyFixings(scip, conss[c], NULL, NULL, NULL, NULL) );
7133  }
7134  }
7135 
7136  return SCIP_OKAY;
7137 }
7138 
7139 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
7140 static
7141 SCIP_DECL_CONSEXITSOL(consExitsolSetppc)
7142 { /*lint --e{715}*/
7143  SCIP_CONSDATA* consdata;
7144  int c;
7145 
7146  /* release the rows of all constraints */
7147  for( c = 0; c < nconss; ++c )
7148  {
7149  consdata = SCIPconsGetData(conss[c]);
7150  assert(consdata != NULL);
7151 
7152  if( consdata->row != NULL )
7153  {
7154  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
7155  }
7156  }
7157 
7158  return SCIP_OKAY;
7159 }
7160 
7161 
7162 /** frees specific constraint data */
7163 static
7164 SCIP_DECL_CONSDELETE(consDeleteSetppc)
7165 { /*lint --e{715}*/
7166  SCIP_CONSHDLRDATA* conshdlrdata;
7167 
7168  assert(conshdlr != NULL);
7169  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7170 
7171  /* get event handler */
7172  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7173  assert(conshdlrdata != NULL);
7174  assert(conshdlrdata->eventhdlr != NULL);
7175 
7176  if( SCIPisTransformed(scip) )
7177  {
7178  if( (SCIP_SETPPCTYPE)((*consdata)->setppctype) == SCIP_SETPPCTYPE_PARTITIONING )
7179  {
7180  --(conshdlrdata->nsetpart);
7181  assert(conshdlrdata->nsetpart >= 0);
7182  }
7183  }
7184 
7185  /* if constraint belongs to transformed problem space, drop bound change events on variables */
7186  if( (*consdata)->nvars > 0 && SCIPvarIsTransformed((*consdata)->vars[0]) )
7187  {
7188  SCIP_CALL( dropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7189  }
7190 
7191  /* free setppc constraint data */
7192  SCIP_CALL( consdataFree(scip, consdata) );
7193 
7194  return SCIP_OKAY;
7195 }
7196 
7197 
7198 /** transforms constraint data into data belonging to the transformed problem */
7199 static
7200 SCIP_DECL_CONSTRANS(consTransSetppc)
7201 { /*lint --e{715}*/
7202  SCIP_CONSHDLRDATA* conshdlrdata;
7203  SCIP_CONSDATA* sourcedata;
7204  SCIP_CONSDATA* targetdata;
7205 
7206  /*debugMessage("Trans method of setppc constraints\n");*/
7207 
7208  assert(conshdlr != NULL);
7209  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7210  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
7211  assert(sourcecons != NULL);
7212  assert(targetcons != NULL);
7213 
7214  /* get event handler */
7215  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7216  assert(conshdlrdata != NULL);
7217  assert(conshdlrdata->eventhdlr != NULL);
7218 
7219  sourcedata = SCIPconsGetData(sourcecons);
7220  assert(sourcedata != NULL);
7221  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
7222 
7223  /* create constraint data for target constraint */
7224  SCIP_CALL( consdataCreateTransformed(scip, &targetdata, sourcedata->nvars, sourcedata->vars,
7225  (SCIP_SETPPCTYPE)sourcedata->setppctype) );
7226 
7227  /* create target constraint */
7228  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
7229  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
7230  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
7231  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
7232  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
7233 
7234  if( (SCIP_SETPPCTYPE)sourcedata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
7235  {
7236  ++(conshdlrdata->nsetpart);
7237  assert(conshdlrdata->nsetpart >= 0);
7238  }
7239 
7240  /* catch bound change events of variables */
7241  SCIP_CALL( catchAllEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
7242 
7243  return SCIP_OKAY;
7244 }
7245 
7246 
7247 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
7248 static
7249 SCIP_DECL_CONSINITLP(consInitlpSetppc)
7250 { /*lint --e{715}*/
7251  SCIP_Bool cutoff = FALSE;
7252  int c;
7253 
7254  for( c = 0; c < nconss; ++c )
7255  {
7256  assert(SCIPconsIsInitial(conss[c]));
7257  SCIP_CALL( addCut(scip, conss[c], NULL, &cutoff) );
7258  /* ignore cutoff, cannot return value */
7259  }
7260 
7261  return SCIP_OKAY;
7262 }
7263 
7264 
7265 /** separation method of constraint handler for LP solutions */
7266 static
7267 SCIP_DECL_CONSSEPALP(consSepalpSetppc)
7268 { /*lint --e{715}*/
7269  SCIP_Bool cutoff;
7270  SCIP_Bool separated;
7271  SCIP_Bool reduceddom;
7272  int c;
7273 
7274  assert(conshdlr != NULL);
7275  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7276  assert(nconss == 0 || conss != NULL);
7277  assert(result != NULL);
7278 
7279  SCIPdebugMessage("separating %d/%d set partitioning / packing / covering constraints\n", nusefulconss, nconss);
7280 
7281  *result = SCIP_DIDNOTFIND;
7282 
7283  cutoff = FALSE;
7284  separated = FALSE;
7285  reduceddom = FALSE;
7286 
7287  /* check all useful set partitioning / packing / covering constraints for feasibility */
7288  for( c = 0; c < nusefulconss && !cutoff; ++c )
7289  {
7290  SCIP_CALL( separateCons(scip, conss[c], NULL, &cutoff, &separated, &reduceddom) );
7291  }
7292 
7293  /* combine set partitioning / packing / covering constraints to get more cuts */
7294  /**@todo further cuts of set partitioning / packing / covering constraints */
7295 
7296  /* return the correct result */
7297  if( cutoff )
7298  *result = SCIP_CUTOFF;
7299  else if( reduceddom )
7300  *result = SCIP_REDUCEDDOM;
7301  else if( separated )
7302  *result = SCIP_SEPARATED;
7303 
7304  return SCIP_OKAY;
7305 }
7306 
7307 
7308 /** separation method of constraint handler for arbitrary primal solutions */
7309 static
7310 SCIP_DECL_CONSSEPASOL(consSepasolSetppc)
7311 { /*lint --e{715}*/
7312  SCIP_Bool cutoff;
7313  SCIP_Bool separated;
7314  SCIP_Bool reduceddom;
7315  int c;
7316 
7317  assert(conshdlr != NULL);
7318  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7319  assert(nconss == 0 || conss != NULL);
7320  assert(result != NULL);
7321 
7322  SCIPdebugMessage("separating %d/%d set partitioning / packing / covering constraints\n", nusefulconss, nconss);
7323 
7324  *result = SCIP_DIDNOTFIND;
7325 
7326  cutoff = FALSE;
7327  separated = FALSE;
7328  reduceddom = FALSE;
7329 
7330  /* check all useful set partitioning / packing / covering constraints for feasibility */
7331  for( c = 0; c < nusefulconss && !cutoff; ++c )
7332  {
7333  SCIP_CALL( separateCons(scip, conss[c], sol, &cutoff, &separated, &reduceddom) );
7334  }
7335 
7336  /* combine set partitioning / packing / covering constraints to get more cuts */
7337  /**@todo further cuts of set partitioning / packing / covering constraints */
7338 
7339  /* return the correct result */
7340  if( cutoff )
7341  *result = SCIP_CUTOFF;
7342  else if( reduceddom )
7343  *result = SCIP_REDUCEDDOM;
7344  else if( separated )
7345  *result = SCIP_SEPARATED;
7346 
7347  return SCIP_OKAY;
7348 }
7349 
7350 
7351 #ifdef VARUSES
7352 #ifdef BRANCHLP
7353 /** if fractional variables exist, chooses a set S of them and branches on (i) x(S) == 0, and (ii) x(S) >= 1 */
7354 static
7355 SCIP_RETCODE branchLP(
7356  SCIP* scip, /**< SCIP data structure */
7357  SCIP_CONSHDLR* conshdlr, /**< set partitioning / packing / covering constraint handler */
7358  SCIP_RESULT* result /**< pointer to store the result SCIP_BRANCHED, if branching was applied */
7359  )
7360 {
7361  SCIP_CONSHDLRDATA* conshdlrdata;
7362  SCIP_INTARRAY* varuses;
7363  SCIP_VAR** lpcands;
7364  SCIP_VAR** sortcands;
7365  SCIP_VAR* var;
7366  SCIP_Real branchweight;
7367  SCIP_Real solval;
7368  int* uses;
7369  int nlpcands;
7370  int nsortcands;
7371  int nselcands;
7372  int numuses;
7373  int i;
7374  int j;
7375 
7376  /**@todo use a better set partitioning / packing / covering branching on LP solution (use SOS branching) */
7377 
7378  assert(conshdlr != NULL);
7379  assert(result != NULL);
7380 
7381  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7382  assert(conshdlrdata != NULL);
7383 
7384  varuses = conshdlrdata->varuses;
7385  assert(varuses != NULL);
7386 
7387  /* get fractional variables */
7388  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, NULL, &nlpcands, NULL, NULL) );
7389  if( nlpcands == 0 )
7390  return SCIP_OKAY;
7391 
7392  assert(MINBRANCHWEIGHT <= MAXBRANCHWEIGHT);
7393 
7394  /* get temporary memory */
7395  SCIP_CALL( SCIPallocBufferArray(scip, &sortcands, nlpcands) );
7396  SCIP_CALL( SCIPallocBufferArray(scip, &uses, nlpcands) );
7397 
7398  /* sort fractional variables by number of uses in enabled set partitioning / packing / covering constraints */
7399  nsortcands = 0;
7400  for( i = 0; i < nlpcands; ++i )
7401  {
7402  var = lpcands[i];
7403  numuses = SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var));
7404  if( numuses > 0 )
7405  {
7406  for( j = nsortcands; j > 0 && numuses > uses[j-1]; --j )
7407  {
7408  sortcands[j] = sortcands[j-1];
7409  uses[j] = uses[j-1];
7410  }
7411  assert(0 <= j && j <= nsortcands);
7412  sortcands[j] = var;
7413  uses[j] = numuses;
7414  nsortcands++;
7415  }
7416  }
7417  assert(nsortcands <= nlpcands);
7418 
7419  /* if none of the fractional variables is member of a set partitioning / packing / covering constraint,
7420  * we are not responsible for doing the branching
7421  */
7422  if( nsortcands > 0 )
7423  {
7424  SCIP_Real cumprio = 0.0;
7425  SCIP_Real minprio = SCIP_INVALID;
7426  SCIP_Real minestzero = SCIP_INVALID;
7427  SCIP_Real minestone = SCIP_INVALID;
7428  SCIP_Real tmp;
7429 
7430  /* select the first variables from the sorted candidate list, until MAXBRANCHWEIGHT is reached;
7431  * then choose one less
7432  */
7433  branchweight = 0.0;
7434  solval = 0.0;
7435  for( nselcands = 0; nselcands < nsortcands; ++nselcands )
7436  {
7437  solval = SCIPgetVarSol(scip, sortcands[nselcands]);
7438  assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
7439  branchweight += solval;
7440 
7441  /* did we exceed the maximal weight */
7442  if( branchweight > MAXBRANCHWEIGHT )
7443  break;
7444 
7445  /* @todo instead of taking the minimum into account try other variants like the maximum and the average */
7446  /* calculate priorities and estimates by adding up/taking the minimum of all single priorities/estimates */
7447  cumprio += SCIPcalcNodeselPriority(scip, sortcands[nselcands], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
7448  tmp = SCIPcalcNodeselPriority(scip, sortcands[nselcands], SCIP_BRANCHDIR_UPWARDS, 1.0);
7449  minprio = MIN(minprio, tmp);
7450  tmp = SCIPcalcChildEstimate(scip, sortcands[nselcands], 0.0);;
7451  minestzero = MIN(minestzero, tmp);
7452  tmp = SCIPcalcChildEstimate(scip, sortcands[nselcands], 1.0);;
7453  minestone = MIN(minestone, tmp);
7454  }
7455  assert(minestzero != SCIP_INVALID); /*lint !e777*/
7456  assert(minestone != SCIP_INVALID); /*lint !e777*/
7457  assert(minprio != SCIP_INVALID); /*lint !e777*/
7458  assert(nselcands > 0);
7459  branchweight -= solval;
7460 
7461  /* check, if we accumulated at least MIN and at most MAXBRANCHWEIGHT weight */
7462  if( MINBRANCHWEIGHT <= branchweight && branchweight <= MAXBRANCHWEIGHT )
7463  {
7464  SCIP_NODE* node;
7465 
7466  /* perform the binary set branching on the selected variables */
7467  assert(1 <= nselcands && nselcands <= nlpcands);
7468 
7469  /* create left child, fix x_i = 0 for all i \in S */
7470  SCIP_CALL( SCIPcreateChild(scip, &node, cumprio, minestzero) );
7471  for( i = 0; i < nselcands; ++i )
7472  {
7473  SCIP_CALL( SCIPchgVarUbNode(scip, node, sortcands[i], 0.0) );
7474  }
7475 
7476  /* create right child: add constraint x(S) >= 1 */
7477  SCIP_CALL( SCIPcreateChild(scip, &node, minprio, minestone) );
7478  if( nselcands == 1 )
7479  {
7480  /* only one candidate selected: fix it to 1.0 */
7481  SCIPdebugMessage("fixing variable <%s> to 1.0 in right child node\n", SCIPvarGetName(sortcands[0]));
7482  SCIP_CALL( SCIPchgVarLbNode(scip, node, sortcands[0], 1.0) );
7483  }
7484  else
7485  {
7486  SCIP_CONS* newcons;
7487  char name[SCIP_MAXSTRLEN];
7488 
7489  /* add set covering constraint x(S) >= 1 */
7490  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "BSB%"SCIP_LONGINT_FORMAT, SCIPgetNTotalNodes(scip));
7491 
7492  SCIP_CALL( SCIPcreateConsSetcover(scip, &newcons, name, nselcands, sortcands,
7493  FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
7494  SCIP_CALL( SCIPaddConsNode(scip, node, newcons, NULL) );
7495  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
7496  }
7497 
7498  *result = SCIP_BRANCHED;
7499 
7500 #ifdef SCIP_DEBUG
7501  SCIPdebugMessage("binary set branching: nselcands=%d/%d, weight(S)=%g, A={", nselcands, nlpcands, branchweight);
7502  for( i = 0; i < nselcands; ++i )
7503  SCIPdebugPrintf(" %s[%g]", SCIPvarGetName(sortcands[i]), SCIPgetSolVal(scip, NULL, sortcands[i]));
7504  SCIPdebugPrintf(" }\n");
7505 #endif
7506  }
7507  }
7508 
7509  /* free temporary memory */
7510  SCIPfreeBufferArray(scip, &uses);
7511  SCIPfreeBufferArray(scip, &sortcands);
7512 
7513  return SCIP_OKAY;
7514 }
7515 #endif
7516 
7517 /** if unfixed variables exist, chooses a set S of them and creates |S|+1 child nodes:
7518  * - for each variable i from S, create child node with x_0 = ... = x_i-1 = 0, x_i = 1
7519  * - create an additional child node x_0 = ... = x_n-1 = 0
7520  */
7521 static
7522 SCIP_RETCODE branchPseudo(
7523  SCIP* scip, /**< SCIP data structure */
7524  SCIP_CONSHDLR* conshdlr, /**< set partitioning / packing / covering constraint handler */
7525  SCIP_RESULT* result /**< pointer to store the result SCIP_BRANCHED, if branching was applied */
7526  )
7527 {
7528  SCIP_CONSHDLRDATA* conshdlrdata;
7529  SCIP_INTARRAY* varuses;
7530  SCIP_VAR** pseudocands;
7531  SCIP_VAR** branchcands;
7532  SCIP_VAR* var;
7533  SCIP_NODE* node;
7534  int* canduses;
7535  int npseudocands;
7536  int maxnbranchcands;
7537  int nbranchcands;
7538  int uses;
7539  int i;
7540  int j;
7541 
7542  /**@todo use a better set partitioning / packing / covering branching on pseudo solution (use SOS branching) */
7543 
7544  assert(conshdlr != NULL);
7545  assert(result != NULL);
7546 
7547  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7548  assert(conshdlrdata != NULL);
7549 
7550  /* check, if pseudo branching is disabled */
7551  if( conshdlrdata->npseudobranches <= 1 )
7552  return SCIP_OKAY;
7553 
7554  /* get fractional variables */
7555  SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, NULL, &npseudocands) );
7556  if( npseudocands == 0 )
7557  return SCIP_OKAY;
7558 
7559  varuses = conshdlrdata->varuses;
7560  assert(varuses != NULL);
7561 
7562  /* choose the maximal number of branching variables */
7563  maxnbranchcands = conshdlrdata->npseudobranches-1;
7564  assert(maxnbranchcands >= 1);
7565 
7566  /* get temporary memory */
7567  SCIP_CALL( SCIPallocBufferArray(scip, &branchcands, maxnbranchcands) );
7568  SCIP_CALL( SCIPallocBufferArray(scip, &canduses, maxnbranchcands) );
7569 
7570  /* sort unfixed variables by number of uses in enabled set partitioning / packing / covering constraints */
7571  nbranchcands = 0;
7572  for( i = 0; i < npseudocands; ++i )
7573  {
7574  var = pseudocands[i];
7575  uses = SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var));
7576  if( uses > 0 )
7577  {
7578  if( nbranchcands < maxnbranchcands || uses > canduses[nbranchcands-1] )
7579  {
7580  for( j = MIN(nbranchcands, maxnbranchcands-1); j > 0 && uses > canduses[j-1]; --j )
7581  {
7582  branchcands[j] = branchcands[j-1];
7583  canduses[j] = canduses[j-1];
7584  }
7585  assert(0 <= j && j <= nbranchcands && j < maxnbranchcands);
7586  branchcands[j] = var;
7587  canduses[j] = uses;
7588  if( nbranchcands < maxnbranchcands )
7589  nbranchcands++;
7590  }
7591  }
7592  }
7593  assert(nbranchcands <= maxnbranchcands);
7594 
7595  /* if none of the unfixed variables is member of a set partitioning / packing / covering constraint,
7596  * we are not responsible for doing the branching
7597  */
7598  if( nbranchcands > 0 )
7599  {
7600  SCIP_Real* estone;
7601  SCIP_Real minestzero = SCIP_INVALID;
7602  SCIP_Real tmp;
7603 
7604  SCIP_CALL( SCIPallocBufferArray(scip, &estone, nbranchcands) );
7605 
7606  /* @todo instead of taking the minimum into account try other variants like the maximum and the average */
7607  /* @todo calculate priorities instead of setting it to the number of branching candidates */
7608  /* calculate estimates by taking the minimum over all single estimates */
7609  for( i = 0; i < nbranchcands; ++i )
7610  {
7611  tmp = SCIPcalcChildEstimate(scip, branchcands[i], 0.0);;
7612  minestzero = MIN(minestzero, tmp);
7613  estone[i] = SCIPcalcChildEstimate(scip, branchcands[i], 1.0);
7614  }
7615  assert(minestzero != SCIP_INVALID); /*lint !e777*/
7616 
7617  /* branch on the first part of the sorted candidates:
7618  * - for each of these variables i, create a child node x_0 = ... = x_i-1 = 0, x_i = 1
7619  * - create an additional child node x_0 = ... = x_n-1 = 0
7620  */
7621  for( i = 0; i < nbranchcands; ++i )
7622  {
7623  /* create child with x_0 = ... = x_i-1 = 0, x_i = 1 */
7624  SCIP_CALL( SCIPcreateChild(scip, &node, (SCIP_Real)nbranchcands, MIN(minestzero, estone[i])) );
7625  for( j = 0; j < i; ++j )
7626  {
7627  SCIP_CALL( SCIPchgVarUbNode(scip, node, branchcands[j], 0.0) );
7628  }
7629  SCIP_CALL( SCIPchgVarLbNode(scip, node, branchcands[i], 1.0) );
7630  }
7631  /* create child with x_0 = ... = x_n = 0 */
7632  SCIP_CALL( SCIPcreateChild(scip, &node, (SCIP_Real)nbranchcands, minestzero) );
7633  for( i = 0; i < nbranchcands; ++i )
7634  {
7635  SCIP_CALL( SCIPchgVarUbNode(scip, node, branchcands[i], 0.0) );
7636  }
7637 
7638  *result = SCIP_BRANCHED;
7639 
7640  SCIPfreeBufferArray(scip, &estone);
7641 
7642 #ifdef SCIP_DEBUG
7643  {
7644  int nchildren;
7645  SCIP_CALL( SCIPgetChildren(scip, NULL, &nchildren) );
7646  SCIPdebugMessage("branched on pseudo solution: %d children\n", nchildren);
7647  }
7648 #endif
7649  }
7650 
7651  /* free temporary memory */
7652  SCIPfreeBufferArray(scip, &canduses);
7653  SCIPfreeBufferArray(scip, &branchcands);
7654 
7655  return SCIP_OKAY;
7656 }
7657 #endif
7658 
7659 
7660 /** constraint enforcing method of constraint handler for LP solutions */
7661 static
7662 SCIP_DECL_CONSENFOLP(consEnfolpSetppc)
7663 { /*lint --e{715}*/
7664  SCIP_Bool cutoff;
7665  SCIP_Bool separated;
7666  SCIP_Bool reduceddom;
7667  int c;
7668 
7669  assert(conshdlr != NULL);
7670  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7671  assert(nconss == 0 || conss != NULL);
7672  assert(result != NULL);
7673 
7674  SCIPdebugMessage("LP enforcing %d set partitioning / packing / covering constraints\n", nconss);
7675 
7676  *result = SCIP_FEASIBLE;
7677 
7678  cutoff = FALSE;
7679  separated = FALSE;
7680  reduceddom = FALSE;
7681 
7682  /* check all useful set partitioning / packing / covering constraints for feasibility */
7683  for( c = 0; c < nusefulconss && !cutoff && !reduceddom; ++c )
7684  {
7685  SCIP_CALL( separateCons(scip, conss[c], NULL, &cutoff, &separated, &reduceddom) );
7686  }
7687 
7688  /* check all obsolete set partitioning / packing / covering constraints for feasibility */
7689  for( c = nusefulconss; c < nconss && !cutoff && !separated && !reduceddom; ++c )
7690  {
7691  SCIP_CALL( separateCons(scip, conss[c], NULL, &cutoff, &separated, &reduceddom) );
7692  }
7693 
7694 #ifdef VARUSES
7695 #ifdef BRANCHLP
7696  if( !cutoff && !separated && !reduceddom )
7697  {
7698  /* if solution is not integral, choose a variable set to branch on */
7699  SCIP_CALL( branchLP(scip, conshdlr, result) );
7700  if( *result != SCIP_FEASIBLE )
7701  return SCIP_OKAY;
7702  }
7703 #endif
7704 #endif
7705 
7706  /* return the correct result */
7707  if( cutoff )
7708  *result = SCIP_CUTOFF;
7709  else if( separated )
7710  *result = SCIP_SEPARATED;
7711  else if( reduceddom )
7712  *result = SCIP_REDUCEDDOM;
7713 
7714  return SCIP_OKAY;
7715 }
7716 
7717 
7718 /** constraint enforcing method of constraint handler for pseudo solutions */
7719 static
7720 SCIP_DECL_CONSENFOPS(consEnfopsSetppc)
7721 { /*lint --e{715}*/
7722  SCIP_Bool cutoff;
7723  SCIP_Bool infeasible;
7724  SCIP_Bool reduceddom;
7725  SCIP_Bool solvelp;
7726  int c;
7727 
7728  assert(conshdlr != NULL);
7729  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7730  assert(nconss == 0 || conss != NULL);
7731  assert(result != NULL);
7732 
7733  /* if the solution is infeasible anyway due to objective value, skip the constraint processing and branch directly */
7734 #ifdef VARUSES
7735  if( objinfeasible )
7736  {
7737  *result = SCIP_DIDNOTRUN;
7738  SCIP_CALL( branchPseudo(scip, conshdlr, result) );
7739  return SCIP_OKAY;
7740  }
7741 #endif
7742 
7743  SCIPdebugMessage("pseudo enforcing %d set partitioning / packing / covering constraints\n", nconss);
7744 
7745  *result = SCIP_FEASIBLE;
7746 
7747  cutoff = FALSE;
7748  infeasible = FALSE;
7749  reduceddom = FALSE;
7750  solvelp = FALSE;
7751 
7752  /* check all set partitioning / packing / covering constraints for feasibility */
7753  for( c = 0; c < nconss && !cutoff && !reduceddom && !solvelp; ++c )
7754  {
7755  SCIP_CALL( enforcePseudo(scip, conss[c], &cutoff, &infeasible, &reduceddom, &solvelp) );
7756  }
7757 
7758  if( cutoff )
7759  *result = SCIP_CUTOFF;
7760  else if( reduceddom )
7761  *result = SCIP_REDUCEDDOM;
7762  else if( solvelp )
7763  *result = SCIP_SOLVELP;
7764  else if( infeasible )
7765  {
7766  *result = SCIP_INFEASIBLE;
7767 
7768 #ifdef VARUSES
7769  /* at least one constraint is violated by pseudo solution and we didn't find a better way to resolve this:
7770  * -> branch on pseudo solution
7771  */
7772  SCIP_CALL( branchPseudo(scip, conshdlr, result) );
7773 #endif
7774  }
7775 
7776  return SCIP_OKAY;
7777 }
7778 
7779 
7780 /** feasibility check method of constraint handler for integral solutions */
7781 static
7782 SCIP_DECL_CONSCHECK(consCheckSetppc)
7783 { /*lint --e{715}*/
7784  SCIP_CONS* cons;
7785  SCIP_CONSDATA* consdata;
7786  int c;
7787 
7788  assert(conshdlr != NULL);
7789  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7790  assert(nconss == 0 || conss != NULL);
7791  assert(result != NULL);
7792 
7793  *result = SCIP_FEASIBLE;
7794 
7795  /* check all set partitioning / packing / covering constraints for feasibility */
7796  for( c = 0; c < nconss; ++c )
7797  {
7798  cons = conss[c];
7799  consdata = SCIPconsGetData(cons);
7800  assert(consdata != NULL);
7801  if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
7802  {
7803  if( !checkCons(scip, consdata, sol) )
7804  {
7805  /* constraint is violated */
7806  *result = SCIP_INFEASIBLE;
7807 
7808  if( printreason )
7809  {
7810  SCIP_Real sum = 0.0;
7811  int v;
7812 
7813  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
7814 
7815  for( v = 0; v < consdata->nvars; ++v )
7816  {
7817  assert(SCIPvarIsBinary(consdata->vars[v]));
7818 
7819  sum += SCIPgetSolVal(scip, sol, consdata->vars[v]);
7820  }
7821  SCIPinfoMessage(scip, NULL, ";\n");
7822  SCIPinfoMessage(scip, NULL, "violation: the right hand side is violated by by %.15g\n", ABS(sum - 1));
7823  }
7824  return SCIP_OKAY;
7825  }
7826  }
7827  }
7828 
7829  return SCIP_OKAY;
7830 }
7831 
7832 /** domain propagation method of constraint handler */
7833 static
7834 SCIP_DECL_CONSPROP(consPropSetppc)
7835 { /*lint --e{715}*/
7836  SCIP_Bool cutoff;
7837  SCIP_Bool addcut;
7838  SCIP_Bool mustcheck;
7839  SCIP_Bool inpresolve;
7840  int nfixedvars = 0;
7841  int c;
7843  assert(conshdlr != NULL);
7844  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7845  assert(nconss == 0 || conss != NULL);
7846  assert(result != NULL);
7847 
7848  *result = SCIP_DIDNOTFIND;
7849 
7850  SCIPdebugMessage("propagating %d/%d set partitioning / packing / covering constraints\n", nmarkedconss, nconss);
7851 
7852  cutoff = FALSE;
7853  inpresolve = (SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE);
7854 
7855  /* propagate all useful set partitioning / packing / covering constraints */
7856  for( c = nmarkedconss - 1; c >= 0 && !cutoff; --c )
7857  {
7858  assert(SCIPconsGetData(conss[c]) != NULL);
7859 
7860  /* during presolving, we do not want to propagate constraints with multiaggregated variables. After presolving,
7861  * we want to resolve the multiaggregation to have a clean data structure; All initial constraints should not
7862  * have multiaggregated variables, but this is not true for constraints that were introduced during solving
7863  */
7864  if( SCIPconsGetData(conss[c])->existmultaggr )
7865  {
7866  int naddconss, ndelconss;
7867 
7868  if( inpresolve )
7869  continue;
7870 
7871  naddconss = ndelconss = 0;
7872  SCIP_CALL( applyFixings(scip, conss[c], &naddconss, &ndelconss, &nfixedvars, &cutoff) );
7873 
7874  if( cutoff )
7875  break;
7876  }
7877 
7878  /* all multiaggregations should be resolved at here */
7879  assert(inpresolve || ! SCIPconsGetData(conss[c])->existmultaggr);
7880 
7881  SCIP_CALL( processFixings(scip, conss[c], &cutoff, &nfixedvars, &addcut, &mustcheck) );
7882  }
7883 
7884  /* return the correct result */
7885  if( cutoff )
7886  *result = SCIP_CUTOFF;
7887  else if( nfixedvars > 0 )
7888  *result = SCIP_REDUCEDDOM;
7889 
7890  return SCIP_OKAY;
7891 }
7892 
7893 
7894 /** presolving method of constraint handler */
7895 static
7896 SCIP_DECL_CONSPRESOL(consPresolSetppc)
7897 { /*lint --e{715}*/
7898  SCIP_CONSHDLRDATA* conshdlrdata;
7899  int oldnfixedvars;
7900  int oldnaggrvars;
7901  int oldndelconss;
7902  int oldnchgcoefs;
7903  int firstchange;
7904  int firstclique;
7905  int lastclique;
7906  int startdelconss;
7907  int c;
7908  SCIP_Bool cutoff;
7909 
7910  assert(conshdlr != NULL);
7911  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7912  assert(scip != NULL);
7913  assert(result != NULL);
7914 
7915  *result = SCIP_DIDNOTFIND;
7916  oldnfixedvars = *nfixedvars;
7917  oldndelconss = *ndelconss;
7918  oldnaggrvars = *naggrvars;
7919  oldnchgcoefs = *nchgcoefs;
7920  cutoff = FALSE;
7921 
7922  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7923  assert(conshdlrdata != NULL);
7924 
7925  /* determine whether we want to run the clique lifting procedure */
7926  conshdlrdata->enablecliquelifting = conshdlrdata->enablecliquelifting || conshdlrdata->updatedsetppctype
7927  || conshdlrdata->noldfixedvars != SCIPgetNFixedVars(scip) || conshdlrdata->noldimpls != SCIPgetNImplications(scip)
7928  || conshdlrdata->noldcliques != SCIPgetNCliques(scip) || conshdlrdata->noldupgrs != nconss;
7929 
7930  /* remember old values */
7931  startdelconss = *ndelconss;
7932  conshdlrdata->noldimpls = SCIPgetNImplications(scip);
7933  conshdlrdata->noldcliques = SCIPgetNCliques(scip);
7934  conshdlrdata->updatedsetppctype = FALSE;
7935 
7936  /* process constraints */
7937  firstchange = INT_MAX;
7938  firstclique = INT_MAX;
7939  lastclique = -1;
7940  for( c = 0; c < nconss && !SCIPisStopped(scip); ++c )
7941  {
7942  SCIP_CONS* cons;
7943  SCIP_CONSDATA* consdata;
7944 
7945  assert(*result != SCIP_CUTOFF);
7946 
7947  cons = conss[c];
7948  assert(cons != NULL);
7949  consdata = SCIPconsGetData(cons);
7950  assert(consdata != NULL);
7951 
7952  /*SCIPdebugMessage("presolving set partitioning / packing / covering constraint <%s>\n", SCIPconsGetName(cons));*/
7953 
7954  /* remove all variables that are fixed to zero and replace all aggregated variables */
7955  if( consdata->nfixedzeros > 0 || nnewaggrvars > 0 || nnewaddconss > 0 || nnewupgdconss > 0
7956  || *naggrvars > oldnaggrvars || (nrounds == 0 && SCIPgetNRuns(scip) > 1) )
7957  {
7958  SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
7959 
7960  if( cutoff )
7961  {
7962  *result = SCIP_CUTOFF;
7963  return SCIP_OKAY;
7964  }
7965 
7966  if( SCIPconsIsDeleted(cons) )
7967  continue;
7968  }
7969 
7970  /* find pairs of negated variables in constraint:
7971  * partitioning/packing: all other variables must be zero, constraint is redundant
7972  * covering: constraint is redundant
7973  *
7974  * find sets of equal variables in constraint:
7975  * partitioning/packing: variable must be zero
7976  * covering: multiple entries of variable can be replaced by single entry
7977  */
7978  SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
7979 
7980  if( cutoff )
7981  {
7982  *result = SCIP_CUTOFF;
7983  return SCIP_OKAY;
7984  }
7985 
7986  /* if constraint was deleted while merging, go to the next constraint */
7987  if( !SCIPconsIsActive(cons) )
7988  continue;
7989 
7990  /* remove fixings found by merging */
7991  if( consdata->nfixedzeros > 0 )
7992  {
7993  SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
7994 
7995  if( cutoff )
7996  {
7997  *result = SCIP_CUTOFF;
7998  return SCIP_OKAY;
7999  }
8000 
8001  if( SCIPconsIsDeleted(cons) )
8002  continue;
8003  }
8004 
8005  /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
8006  * possible
8007  */
8008  SCIP_CALL( presolvePropagateCons(scip, cons, TRUE, NULL, NULL, NULL, NULL, nfixedvars, naggrvars, ndelconss, &cutoff) );
8009 
8010  if( cutoff )
8011  {
8012  *result = SCIP_CUTOFF;
8013  return SCIP_OKAY;
8014  }
8015 
8016  /* if constraint was deleted while propagation, go to the next constraint */
8017  if( !SCIPconsIsActive(cons) )
8018  continue;
8019 
8020  /* remove fixings found by presolvePropagateCons() */
8021  if( consdata->nfixedzeros > 0 )
8022  {
8023  SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
8024 
8025  if( cutoff )
8026  {
8027  *result = SCIP_CUTOFF;
8028  return SCIP_OKAY;
8029  }
8030 
8031  if( SCIPconsIsDeleted(cons) )
8032  continue;
8033  }
8034 
8035  /* perform dual reductions */
8036  if( conshdlrdata->dualpresolving && SCIPallowDualReds(scip) )
8037  {
8038  SCIP_CALL( dualPresolving(scip, cons, nfixedvars, ndelconss, result) );
8039 
8040  /* if dual reduction deleted the constraint we take the next */
8041  if( !SCIPconsIsActive(cons) )
8042  continue;
8043  }
8044 
8045  /* remember the first changed constraint to begin the next redundancy round with */
8046  if( firstchange == INT_MAX && consdata->changed )
8047  firstchange = c;
8048 
8049  /* remember the first and last constraints for which we have to add the clique information */
8050  if( !consdata->cliqueadded && consdata->nvars >= 2 )
8051  {
8052  if( firstclique == INT_MAX )
8053  firstclique = c;
8054  lastclique = c;
8055  }
8056  }
8057 
8058  /* update result pointer */
8059  if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss || oldnchgcoefs < *nchgcoefs )
8060  *result = SCIP_SUCCESS;
8061 
8062  if( firstchange < nconss && conshdlrdata->presolusehashing )
8063  {
8064  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
8065  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, ndelconss, nchgsides) );
8066  if( oldndelconss < *ndelconss )
8067  *result = SCIP_SUCCESS;
8068  }
8069 
8070  /* determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and
8071  * negated) in any combination of set-partitioning and set-packing constraints
8072  */
8073  if( nconss > 1 && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0
8074  && ((conshdlrdata->nsetpart > 0 && !SCIPdoNotMultaggr(scip) && conshdlrdata->conshdlrlinear != NULL)
8075  || (conshdlrdata->dualpresolving && SCIPallowDualReds(scip)
8076  && conshdlrdata->nsetpart < nconss && !SCIPdoNotAggr(scip))) )
8077  {
8078  SCIP_CALL( removeDoubleAndSingletonsAndPerformDualpresolve(scip, conss, nconss, conshdlrdata->dualpresolving
8079  && SCIPallowDualReds(scip), conshdlrdata->conshdlrlinear != NULL, nfixedvars,
8080  naggrvars, ndelconss, nchgcoefs, nchgsides, &cutoff) );
8081 
8082  if( cutoff )
8083  {
8084  *result = SCIP_CUTOFF;
8085  return SCIP_OKAY;
8086  }
8087  else if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss )
8088  *result = SCIP_SUCCESS;
8089  }
8090 
8091  /* clique lifting */
8092  if( conshdlrdata->cliquelifting && conshdlrdata->enablecliquelifting && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
8093  {
8094  /* add cliques first before lifting variables */
8095  SCIP_CALL( addCliques(scip, conss, nconss, firstclique, lastclique, naddconss, ndelconss, nchgbds, &cutoff) );
8096 
8097  if( cutoff )
8098  {
8099  *result = SCIP_CUTOFF;
8100  return SCIP_OKAY;
8101  }
8102 
8103  firstclique = nconss;
8104  lastclique = -1;
8105 
8106  /* lift variables and check for fixings due to clique infomation */
8107  SCIP_CALL( preprocessCliques(scip, conshdlrdata, conss, nconss, nrounds, &firstchange, &firstclique,
8108  &lastclique, nfixedvars, naggrvars, ndelconss, nchgcoefs, &cutoff) );
8109  ++(conshdlrdata->nclqpresolve);
8110 
8111  if( cutoff )
8112  {
8113  *result = SCIP_CUTOFF;
8114  return SCIP_OKAY;
8115  }
8116  else if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss || oldnchgcoefs < *nchgcoefs )
8117  *result = SCIP_SUCCESS;
8118 
8119  /* remember the number of fixings */
8120  conshdlrdata->noldfixedvars = *nfixedvars + *naggrvars;
8121  }
8122 
8123  if( oldndelconss == *ndelconss && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
8124  {
8125  /* check constraints for redundancy */
8126  if( conshdlrdata->presolpairwise )
8127  {
8128  SCIP_Longint npaircomparisons = 0;
8129 
8130  oldndelconss = *ndelconss;
8131  oldnfixedvars = *nfixedvars;
8132 
8133  for( c = firstchange; c < nconss && !SCIPisStopped(scip); ++c )
8134  {
8135  assert(*result != SCIP_CUTOFF);
8136 
8137  if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
8138  {
8139  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange);
8140 
8141  SCIP_CALL( removeRedundantConstraints(scip, conss, firstchange, c, &cutoff, nfixedvars, ndelconss, nchgsides) );
8142  if( cutoff )
8143  {
8144  *result = SCIP_CUTOFF;
8145  return SCIP_OKAY;
8146  }
8147 
8148  if( npaircomparisons > NMINCOMPARISONS )
8149  {
8150  if( (*ndelconss - oldndelconss + *nfixedvars - oldnfixedvars) / ((SCIP_Real)npaircomparisons) < MINGAINPERNMINCOMPARISONS )
8151  break;
8152  oldndelconss = *ndelconss;
8153  oldnfixedvars = *nfixedvars;
8154  npaircomparisons = 0;
8155  *result = SCIP_SUCCESS;
8156  }
8157  }
8158  }
8159  }
8160  }
8161 
8162  /* add cliques after lifting variables */
8163  SCIP_CALL( addCliques(scip, conss, nconss, MIN(firstclique, nconss), MIN(lastclique, nconss), naddconss, ndelconss,
8164  nchgbds, &cutoff) );
8165 
8166  if( cutoff )
8167  *result = SCIP_CUTOFF;
8168 
8169  conshdlrdata->enablecliquelifting = FALSE;
8170  conshdlrdata->noldupgrs = nconss - (*ndelconss - startdelconss);
8171 
8172  return SCIP_OKAY;
8173 }
8174 
8175 
8176 /** propagation conflict resolving method of constraint handler */
8177 static
8178 SCIP_DECL_CONSRESPROP(consRespropSetppc)
8179 { /*lint --e{715}*/
8180  SCIP_CONSDATA* consdata;
8181  int v;
8182 
8183  assert(conshdlr != NULL);
8184  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8185  assert(cons != NULL);
8186  assert(infervar != NULL);
8187  assert(result != NULL);
8188 
8189  consdata = SCIPconsGetData(cons);
8190  assert(consdata != NULL);
8191 
8192  SCIPdebugMessage("conflict resolving method of set partitioning / packing / covering constraint handler\n");
8193 
8194  if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING
8195  || ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
8196  && SCIPvarGetLbAtIndex(infervar, bdchgidx, TRUE) > 0.5) )
8197  {
8198 #ifndef NDEBUG
8199  SCIP_Bool confvarfound;
8200 #endif
8201 
8202  /* the inference constraint is a set partitioning or covering constraint with the inference variable infered to 1.0:
8203  * the reason for the deduction is the assignment of 0.0 to all other variables
8204  */
8205 #ifndef NDEBUG
8206  confvarfound = FALSE;
8207 #endif
8208  for( v = 0; v < consdata->nvars; ++v )
8209  {
8210  if( consdata->vars[v] != infervar )
8211  {
8212  /* the reason variable must be assigned to zero */
8213  assert(SCIPvarGetUbAtIndex(consdata->vars[v], bdchgidx, FALSE) < 0.5);
8214  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
8215  }
8216 #ifndef NDEBUG
8217  else
8218  {
8219  assert(!confvarfound);
8220  confvarfound = TRUE;
8221  }
8222 #endif
8223  }
8224  assert(confvarfound);
8225  }
8226  else
8227  {
8228  /* the inference constraint is a set partitioning or packing constraint with the inference variable infered to 0.0:
8229  * the reason for the deduction is the assignment of 1.0 to a single variable
8230  */
8231  assert(SCIPvarGetUbAtIndex(infervar, bdchgidx, TRUE) < 0.5);
8232 
8233  if( inferinfo >= 0 )
8234  {
8235  assert(SCIPvarGetLbAtIndex(consdata->vars[inferinfo], bdchgidx, FALSE) > 0.5);
8236  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[inferinfo]) );
8237  }
8238  else
8239  {
8240  for( v = 0; v < consdata->nvars; ++v )
8241  {
8242  if( SCIPvarGetLbAtIndex(consdata->vars[v], bdchgidx, FALSE) > 0.5 )
8243  {
8244  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
8245  break;
8246  }
8247  }
8248  assert(v < consdata->nvars);
8249  }
8250  }
8251 
8252  *result = SCIP_SUCCESS;
8253 
8254  return SCIP_OKAY;
8255 }
8256 
8257 
8258 /** variable rounding lock method of constraint handler */
8259 static
8260 SCIP_DECL_CONSLOCK(consLockSetppc)
8261 { /*lint --e{715}*/
8262  SCIP_CONSDATA* consdata;
8263  int nlocksdown;
8264  int nlocksup;
8265  int i;
8266 
8267  consdata = SCIPconsGetData(cons);
8268  assert(consdata != NULL);
8269 
8270  switch( consdata->setppctype )
8271  {
8273  nlocksdown = nlockspos + nlocksneg;
8274  nlocksup = nlockspos + nlocksneg;
8275  break;
8277  nlocksdown = nlocksneg;
8278  nlocksup = nlockspos;
8279  break;
8281  nlocksdown = nlockspos;
8282  nlocksup = nlocksneg;
8283  break;
8284  default:
8285  SCIPerrorMessage("unknown setppc type\n");
8286  return SCIP_INVALIDDATA;
8287  }
8288 
8289  for( i = 0; i < consdata->nvars; ++i )
8290  {
8291  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksdown, nlocksup) );
8292  }
8293 
8294  return SCIP_OKAY;
8295 }
8296 
8297 
8298 /** constraint activation notification method of constraint handler */
8299 static
8300 SCIP_DECL_CONSACTIVE(consActiveSetppc)
8301 { /*lint --e{715}*/
8302  assert(cons != NULL);
8303  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8304  assert(SCIPconsIsTransformed(cons));
8305 
8306  SCIPdebugMessage("activation information for set partitioning / packing / covering constraint <%s>\n",
8307  SCIPconsGetName(cons));
8309  /* we only might add the constraint to the propagation list, when we are not activating it in probing mode */
8311  {
8312  SCIP_CONSDATA* consdata = SCIPconsGetData(cons);
8313  assert(consdata != NULL);
8314 
8315  if( consdata->nfixedones >= 1 || consdata->nfixedzeros >= consdata->nvars - 1 )
8316  {
8317  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
8318  }
8319  }
8320 
8321 #ifdef VARUSES
8322  /* increase the number of uses for each variable in the constraint */
8323  SCIP_CALL( consdataIncVaruses(scip, SCIPconshdlrGetData(conshdlr), SCIPconsGetData(cons)) );
8324 #endif
8325 
8326  return SCIP_OKAY;
8327 }
8328 
8329 
8330 /** constraint deactivation notification method of constraint handler */
8331 #ifdef VARUSES
8332 static
8333 SCIP_DECL_CONSDEACTIVE(consDeactiveSetppc)
8334 { /*lint --e{715}*/
8335  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8336  assert(SCIPconsIsTransformed(cons));
8337 
8338  SCIPdebugMessage("deactivation information for set partitioning / packing / covering constraint <%s>\n",
8339  SCIPconsGetName(cons));
8340 
8341  /* decrease the number of uses for each variable in the constraint */
8342  SCIP_CALL( consdataDecVaruses(scip, SCIPconshdlrGetData(conshdlr), SCIPconsGetData(cons)) );
8343 
8344  return SCIP_OKAY;
8345 }
8346 #endif
8347 
8348 /** variable deletion method of constraint handler */
8349 static
8350 SCIP_DECL_CONSDELVARS(consDelvarsSetppc)
8351 {
8352  assert( scip != NULL );
8353  assert( conshdlr != NULL );
8354  assert( conss != NULL || nconss == 0 );
8355 
8356  if( nconss > 0 )
8357  {
8358  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
8359  }
8360 
8361  return SCIP_OKAY;
8362 }
8363 
8364 
8365 
8366 /** constraint display method of constraint handler */
8367 static
8368 SCIP_DECL_CONSPRINT(consPrintSetppc)
8369 { /*lint --e{715}*/
8370 
8371  assert( scip != NULL );
8372  assert( conshdlr != NULL );
8373  assert( cons != NULL );
8374 
8375  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
8377  return SCIP_OKAY;
8378 }
8379 
8380 /** constraint copying method of constraint handler */
8381 static
8382 SCIP_DECL_CONSCOPY(consCopySetppc)
8383 { /*lint --e{715}*/
8384  SCIP_VAR** sourcevars;
8385  const char* consname;
8386  SCIP_Real lhs;
8387  SCIP_Real rhs;
8388  int nvars;
8389  SCIP_SETPPCTYPE type;
8391  /* get variables and coefficients of the source constraint */
8392  sourcevars = SCIPgetVarsSetppc(sourcescip, sourcecons);
8393  nvars = SCIPgetNVarsSetppc(sourcescip, sourcecons);
8394 
8395  /* get setppc type */
8396  type = SCIPgetTypeSetppc(sourcescip, sourcecons);
8397  lhs = -SCIPinfinity(scip);
8398  rhs = SCIPinfinity(scip);
8399 
8400  switch( type )
8401  {
8403  lhs = 1.0;
8404  rhs = 1.0;
8405  break;
8407  rhs = 1.0;
8408  break;
8410  lhs = 1.0;
8411  break;
8412  default:
8413  SCIPerrorMessage("unknown setppc type\n");
8414  return SCIP_INVALIDDATA;
8415  }
8416 
8417  if( name != NULL )
8418  consname = name;
8419  else
8420  consname = SCIPconsGetName(sourcecons);
8421 
8422  /* copy the logic using the linear constraint copy method */
8423  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, NULL,
8424  lhs, rhs, varmap, consmap,
8425  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
8426  assert(cons != NULL);
8427 
8428  return SCIP_OKAY;
8429 }
8430 
8431 /** constraint parsing method of constraint handler */
8432 static
8433 SCIP_DECL_CONSPARSE(consParseSetppc)
8434 { /*lint --e{715}*/
8435  SCIP_VAR** vars;
8436  int nvars;
8437 
8438  assert(scip != NULL);
8439  assert(success != NULL);
8440  assert(str != NULL);
8441  assert(name != NULL);
8442  assert(cons != NULL);
8443 
8444  *success = TRUE;
8445 
8446  nvars = 0;
8447  vars = NULL;
8448 
8449  /* check if lhs is just 0 */
8450  if( str[0] == '0' )
8451  {
8452  assert(str[1] == ' ');
8453  str += 2;
8454  }
8455  else
8456  {
8457  SCIP_Real* coefs;
8458  char* endptr;
8459  int coefssize;
8460  int requsize;
8461 
8462  /* initialize buffers for storing the coefficients */
8463  coefssize = 100;
8464  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
8465  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
8466 
8467  /* parse linear sum to get variables and coefficients */
8468  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
8469 
8470  if( *success && requsize > coefssize )
8471  {
8472  /* realloc buffers and try again */
8473  coefssize = requsize;
8474  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
8475  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
8476 
8477  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
8478  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
8479  }
8480 
8481  if( !*success )
8482  {
8483  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", str);
8484  }
8485  else
8486  str = endptr;
8487 
8488  /* free coefficient array */
8489  SCIPfreeBufferArray(scip, &coefs);
8490  }
8491 
8492  /* remove white spaces */
8493  while( isspace((unsigned char)*str) )
8494  str++;
8495 
8496  if( *success )
8497  {
8498  switch( *str )
8499  {
8500  case '=' :
8501  SCIP_CALL( SCIPcreateConsSetpart(scip, cons, name, nvars, vars,
8502  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8503  break;
8504  case '<' :
8505  SCIP_CALL( SCIPcreateConsSetpack(scip, cons, name, nvars, vars,
8506  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8507  break;
8508  case '>' :
8509  SCIP_CALL( SCIPcreateConsSetcover(scip, cons, name, nvars, vars,
8510  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8511  break;
8512  default:
8513  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "error parsing setppc type\n");
8514  *success = FALSE;
8515  break;
8516  }
8517  }
8518 
8519  /* free variable array */
8520  SCIPfreeBufferArrayNull(scip, &vars);
8521 
8522  return SCIP_OKAY;
8523 }
8524 
8525 /** constraint method of constraint handler which returns the variables (if possible) */
8526 static
8527 SCIP_DECL_CONSGETVARS(consGetVarsSetppc)
8528 { /*lint --e{715}*/
8529  SCIP_CONSDATA* consdata;
8530 
8531  consdata = SCIPconsGetData(cons);
8532  assert(consdata != NULL);
8533 
8534  if( varssize < consdata->nvars )
8535  (*success) = FALSE;
8536  else
8537  {
8538  assert(vars != NULL);
8539 
8540  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
8541  (*success) = TRUE;
8542  }
8543 
8544  return SCIP_OKAY;
8545 }
8546 
8547 /** constraint method of constraint handler which returns the number of variables (if possible) */
8548 static
8549 SCIP_DECL_CONSGETNVARS(consGetNVarsSetppc)
8550 { /*lint --e{715}*/
8551  SCIP_CONSDATA* consdata;
8552 
8553  consdata = SCIPconsGetData(cons);
8554  assert(consdata != NULL);
8555 
8556  (*nvars) = consdata->nvars;
8557  (*success) = TRUE;
8558 
8559  return SCIP_OKAY;
8560 }
8561 
8562 /*
8563  * Callback methods of event handler
8564  */
8565 
8566 static
8567 SCIP_DECL_EVENTEXEC(eventExecSetppc)
8568 { /*lint --e{715}*/
8569  SCIP_CONS* cons;
8570  SCIP_CONSDATA* consdata;
8571  SCIP_EVENTTYPE eventtype;
8572 
8573  assert(eventhdlr != NULL);
8574  assert(eventdata != NULL);
8575  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
8576  assert(event != NULL);
8577 
8578  /*debugMessage("Exec method of bound change event handler for set partitioning / packing / covering constraints\n");*/
8579 
8580  cons = (SCIP_CONS*)eventdata;
8581  assert(cons != NULL);
8582 
8583  consdata = SCIPconsGetData(cons);
8584  assert(consdata != NULL);
8585 
8586  eventtype = SCIPeventGetType(event);
8587 
8588  switch( eventtype )
8589  {
8591  consdata->nfixedones++;
8592  consdata->propagated = FALSE;
8593  break;
8595  consdata->nfixedones--;
8596  break;
8598  consdata->nfixedzeros++;
8599  consdata->propagated = FALSE;
8600  break;
8602  consdata->nfixedzeros--;
8603  break;
8605  consdata->varsdeleted = TRUE;
8606  break;
8608  if( consdata->merged )
8609  {
8610  SCIP_VAR* var = SCIPeventGetVar(event);
8611 
8612  /* this event should only arise during the presolving stage */
8613  assert(SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING);
8614  assert(var != NULL);
8615 
8616  /* one variable was changed to a negated or aggregated variable, so maybe we can merge again */
8617  if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED && SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
8618  consdata->merged = FALSE;
8619  }
8620 
8621  if( !consdata->existmultaggr )
8622  {
8623  SCIP_VAR* var = SCIPeventGetVar(event);
8624  assert(var != NULL);
8625 
8627  consdata->existmultaggr = TRUE;
8628  }
8629  break;
8630  default:
8631  SCIPerrorMessage("invalid event type\n");
8632  return SCIP_INVALIDDATA;
8633  }
8634  assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nvars);
8635  assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nvars);
8636 
8637  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) && (consdata->nfixedones >= 1 || consdata->nfixedzeros >= consdata->nvars - 1) )
8638  {
8639  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
8640  }
8641 
8642  /*debugMessage(" -> constraint has %d zero-fixed and %d one-fixed of %d variables\n",
8643  consdata->nfixedzeros, consdata->nfixedones, consdata->nvars);*/
8644 
8645  return SCIP_OKAY;
8646 }
8647 
8648 
8649 
8650 
8651 /*
8652  * Callback methods of conflict handler
8653  */
8654 
8655 static
8656 SCIP_DECL_CONFLICTEXEC(conflictExecSetppc)
8657 { /*lint --e{715}*/
8658  SCIP_VAR** vars;
8659  int i;
8660 
8661  assert(conflicthdlr != NULL);
8662  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
8663  assert(bdchginfos != NULL || nbdchginfos == 0);
8664  assert(result != NULL);
8665 
8666  /* don't process already resolved conflicts */
8667  if( resolved )
8668  {
8669  *result = SCIP_DIDNOTRUN;
8670  return SCIP_OKAY;
8671  }
8672 
8673  *result = SCIP_DIDNOTFIND;
8674 
8675  /* for two (binary) variables we will create a set packing constraint and add the clique information of the conflict is global */
8676  if( nbdchginfos == 2 )
8677  {
8678  SCIP_CONS* cons;
8679  char consname[SCIP_MAXSTRLEN];
8680  SCIP_VAR* twovars[2];
8681 
8682  assert(bdchginfos != NULL);
8683 
8684  twovars[0] = SCIPbdchginfoGetVar(bdchginfos[0]);
8685 
8686  /* we can only treat binary variables */
8687  if( !SCIPvarIsBinary(twovars[0]) )
8688  return SCIP_OKAY;
8689 
8690  /* if the variable is fixed to zero in the conflict set, we have to use its negation */
8691  if( SCIPbdchginfoGetNewbound(bdchginfos[0]) < 0.5 )
8692  {
8693  SCIP_CALL( SCIPgetNegatedVar(scip, twovars[0], &twovars[0]) );
8694  }
8695 
8696  twovars[1] = SCIPbdchginfoGetVar(bdchginfos[1]);
8697 
8698  /* we can only treat binary variables */
8699  if( !SCIPvarIsBinary(twovars[1]) )
8700  return SCIP_OKAY;
8701 
8702  /* if the variable is fixed to zero in the conflict set, we have to use its negation */
8703  if( SCIPbdchginfoGetNewbound(bdchginfos[1]) < 0.5 )
8704  {
8705  SCIP_CALL( SCIPgetNegatedVar(scip, twovars[1], &twovars[1]) );
8706  }
8707 
8708  /* create a constraint out of the conflict set */
8709  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%d_%"SCIP_LONGINT_FORMAT, SCIPgetNRuns(scip), SCIPgetNConflictConssApplied(scip));
8710  SCIP_CALL( SCIPcreateConsSetpack(scip, &cons, consname, 2, twovars,
8711  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
8712  SCIP_CALL( SCIPaddConsNode(scip, node, cons, validnode) );
8713 
8714  /* if the constraint gets globally added, we also add the clique information */
8715  if( !SCIPconsIsLocal(cons) )
8716  {
8717  SCIP_Bool infeasible;
8718  int ncliquebdchgs;
8719 
8720  SCIP_CALL( SCIPaddClique(scip, twovars, NULL, 2, FALSE, &infeasible, &ncliquebdchgs) );
8721 
8722  SCIPdebugMessage("new clique of conflict constraint %s led to %d fixings\n", consname, ncliquebdchgs);
8723 
8724  if( infeasible )
8725  {
8726  SCIPdebugMessage("new clique of conflict constraint %s led to infeasibility\n", consname);
8727  }
8728  }
8729  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
8730 
8731  *result = SCIP_CONSADDED;
8732 
8733  return SCIP_OKAY;
8734  }
8735 
8736  /* create array of variables in conflict constraint */
8737  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
8738  for( i = 0; i < nbdchginfos; ++i )
8739  {
8740  assert(bdchginfos != NULL);
8741 
8742  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
8743 
8744  /* we can only treat binary variables */
8745  if( !SCIPvarIsBinary(vars[i]) )
8746  break;
8747 
8748  /* if the variable is fixed to one in the conflict set, we have to use its negation */
8749  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
8750  {
8751  SCIP_CALL( SCIPgetNegatedVar(scip, vars[i], &vars[i]) );
8752  }
8753  }
8754 
8755  if( i == nbdchginfos )
8756  {
8757  SCIP_CONS* cons;
8758  char consname[SCIP_MAXSTRLEN];
8759 
8760  /* create a constraint out of the conflict set */
8761  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%d_%"SCIP_LONGINT_FORMAT, SCIPgetNRuns(scip), SCIPgetNConflictConssApplied(scip));
8762  SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, consname, nbdchginfos, vars,
8763  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
8764  SCIP_CALL( SCIPaddConsNode(scip, node, cons, validnode) );
8765  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
8766 
8767  *result = SCIP_CONSADDED;
8768  }
8769 
8770  /* free temporary memory */
8771  SCIPfreeBufferArray(scip, &vars);
8772 
8773  return SCIP_OKAY;
8774 }
8775 
8776 
8777 
8778 
8779 /*
8780  * constraint specific interface methods
8781  */
8782 
8783 /** creates the handler for set partitioning / packing / covering constraints and includes it in SCIP */
8785  SCIP* scip /**< SCIP data structure */
8786  )
8787 {
8788  SCIP_CONSHDLRDATA* conshdlrdata;
8789  SCIP_CONSHDLR* conshdlr;
8790  SCIP_EVENTHDLR* eventhdlr;
8791 
8792  /* create event handler for bound change events */
8794  eventExecSetppc, NULL) );
8795 
8796  /* create conflict handler for setppc constraints */
8798  conflictExecSetppc, NULL) );
8799 
8800  /* create constraint handler data */
8801  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
8802 
8803  /* include constraint handler */
8806  consEnfolpSetppc, consEnfopsSetppc, consCheckSetppc, consLockSetppc,
8807  conshdlrdata) );
8808  assert(conshdlr != NULL);
8809 
8810  /* set non-fundamental callbacks via specific setter functions */
8811  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveSetppc) );
8812 #ifdef VARUSES
8813  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveSetppc) );
8814 #endif
8815  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySetppc, consCopySetppc) );
8816  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSetppc) );
8817  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsSetppc) );
8818  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreSetppc) );
8819  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolSetppc) );
8820  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSetppc) );
8821  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSetppc) );
8822  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSetppc) );
8823  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitSetppc) );
8824  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSetppc) );
8825  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSetppc) );
8826  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolSetppc, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
8827  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSetppc) );
8828  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropSetppc, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
8830  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSetppc) );
8831  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSetppc, consSepasolSetppc, CONSHDLR_SEPAFREQ,
8833  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSetppc) );
8834 
8835  conshdlrdata->conshdlrlinear = SCIPfindConshdlr(scip,"linear");
8836 
8837  if( conshdlrdata->conshdlrlinear != NULL )
8838  {
8839  /* include the linear constraint to setppc constraint upgrade in the linear constraint handler */
8841  }
8842  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
8843  {
8844  /* notify function that upgrades quadratic constraint to setpacking */
8846  }
8847 
8848 
8849  /* set partitioning constraint handler parameters */
8850  SCIP_CALL( SCIPaddIntParam(scip,
8851  "constraints/" CONSHDLR_NAME "/npseudobranches",
8852  "number of children created in pseudo branching (0: disable pseudo branching)",
8853  &conshdlrdata->npseudobranches, TRUE, DEFAULT_NPSEUDOBRANCHES, 0, INT_MAX, NULL, NULL) );
8855  "constraints/" CONSHDLR_NAME "/presolpairwise",
8856  "should pairwise constraint comparison be performed in presolving?",
8857  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
8859  "constraints/" CONSHDLR_NAME "/presolusehashing",
8860  "should hash table be used for detecting redundant constraints in advance",
8861  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
8863  "constraints/" CONSHDLR_NAME "/dualpresolving",
8864  "should dual presolving steps be performed?",
8865  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
8867  "constraints/" CONSHDLR_NAME "/cliquelifting",
8868  " should we try to lift variables into other clique constraints, fix variables, aggregate them, and also shrink the amount of variables in clique constraints",
8869  &conshdlrdata->cliquelifting, TRUE, DEFAULT_CLIQUELIFTING, NULL, NULL) );
8871  "constraints/" CONSHDLR_NAME "/addvariablesascliques",
8872  "should we try to generate extra cliques out of all binary variables to maybe fasten redundant constraint detection",
8873  &conshdlrdata->addvariablesascliques, TRUE, DEFAULT_ADDVARIABLESASCLIQUES, NULL, NULL) );
8875  "constraints/" CONSHDLR_NAME "/cliqueshrinking",
8876  "should we try to shrink the number of variables in a clique constraints, by replacing more than one variable by only one",
8877  &conshdlrdata->cliqueshrinking, TRUE, DEFAULT_CLIQUESHRINKING, NULL, NULL) );
8878 
8879  return SCIP_OKAY;
8880 }
8881 
8882 /** creates and captures a set partitioning constraint
8883  *
8884  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
8885  */
8887  SCIP* scip, /**< SCIP data structure */
8888  SCIP_CONS** cons, /**< pointer to hold the created constraint */
8889  const char* name, /**< name of constraint */
8890  int nvars, /**< number of variables in the constraint */
8891  SCIP_VAR** vars, /**< array with variables of constraint entries */
8892  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
8893  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
8894  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
8895  * Usually set to TRUE. */
8896  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
8897  * TRUE for model constraints, FALSE for additional, redundant constraints. */
8898  SCIP_Bool check, /**< should the constraint be checked for feasibility?
8899  * TRUE for model constraints, FALSE for additional, redundant constraints. */
8900  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
8901  * Usually set to TRUE. */
8902  SCIP_Bool local, /**< is constraint only valid locally?
8903  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
8904  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
8905  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
8906  * adds coefficients to this constraint. */
8907  SCIP_Bool dynamic, /**< is constraint subject to aging?
8908  * Usually set to FALSE. Set to TRUE for own cuts which
8909  * are separated as constraints. */
8910  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
8911  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
8912  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
8913  * if it may be moved to a more global node?
8914  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
8915  )
8916 {
8917  return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_PARTITIONING,
8918  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
8919 }
8920 
8921 /** creates and captures a set partitioning constraint with all constraint flags set
8922  * to their default values
8923  *
8924  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
8925  */
8927  SCIP* scip, /**< SCIP data structure */
8928  SCIP_CONS** cons, /**< pointer to hold the created constraint */
8929  const char* name, /**< name of constraint */
8930  int nvars, /**< number of variables in the constraint */
8931  SCIP_VAR** vars /**< array with variables of constraint entries */
8932  )
8933 {
8934  SCIP_CALL( SCIPcreateConsSetpart(scip, cons, name, nvars, vars,
8935  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8936 
8937  return SCIP_OKAY;
8938 }
8939 
8940 /** creates and captures a set packing constraint
8941  *
8942  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
8943  */
8945  SCIP* scip, /**< SCIP data structure */
8946  SCIP_CONS** cons, /**< pointer to hold the created constraint */
8947  const char* name, /**< name of constraint */
8948  int nvars, /**< number of variables in the constraint */
8949  SCIP_VAR** vars, /**< array with variables of constraint entries */
8950  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
8951  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
8952  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
8953  * Usually set to TRUE. */
8954  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
8955  * TRUE for model constraints, FALSE for additional, redundant constraints. */
8956  SCIP_Bool check, /**< should the constraint be checked for feasibility?
8957  * TRUE for model constraints, FALSE for additional, redundant constraints. */
8958  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
8959  * Usually set to TRUE. */
8960  SCIP_Bool local, /**< is constraint only valid locally?
8961  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
8962  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
8963  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
8964  * adds coefficients to this constraint. */
8965  SCIP_Bool dynamic, /**< is constraint subject to aging?
8966  * Usually set to FALSE. Set to TRUE for own cuts which
8967  * are separated as constraints. */
8968  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
8969  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
8970  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
8971  * if it may be moved to a more global node?
8972  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
8973  )
8974 {
8975  return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_PACKING,
8976  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
8977 }
8978 
8979 /** creates and captures a set packing constraint with all constraint flags set
8980  * to their default values
8981  *
8982  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
8983  */
8985  SCIP* scip, /**< SCIP data structure */
8986  SCIP_CONS** cons, /**< pointer to hold the created constraint */
8987  const char* name, /**< name of constraint */
8988  int nvars, /**< number of variables in the constraint */
8989  SCIP_VAR** vars /**< array with variables of constraint entries */
8990  )
8991 {
8992  SCIP_CALL( SCIPcreateConsSetpack(scip, cons, name, nvars, vars,
8993  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
8994 
8995  return SCIP_OKAY;
8996 
8997 }
8998 
8999 /** creates and captures a set covering constraint
9000  *
9001  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9002  */
9004  SCIP* scip, /**< SCIP data structure */
9005  SCIP_CONS** cons, /**< pointer to hold the created constraint */
9006  const char* name, /**< name of constraint */
9007  int nvars, /**< number of variables in the constraint */
9008  SCIP_VAR** vars, /**< array with variables of constraint entries */
9009  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
9010  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9011  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
9012  * Usually set to TRUE. */
9013  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
9014  * TRUE for model constraints, FALSE for additional, redundant constraints. */
9015  SCIP_Bool check, /**< should the constraint be checked for feasibility?
9016  * TRUE for model constraints, FALSE for additional, redundant constraints. */
9017  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
9018  * Usually set to TRUE. */
9019  SCIP_Bool local, /**< is constraint only valid locally?
9020  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9021  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
9022  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
9023  * adds coefficients to this constraint. */
9024  SCIP_Bool dynamic, /**< is constraint subject to aging?
9025  * Usually set to FALSE. Set to TRUE for own cuts which
9026  * are separated as constraints. */
9027  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
9028  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9029  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
9030  * if it may be moved to a more global node?
9031  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9032  )
9033 {
9034  return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_COVERING,
9035  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
9036 }
9037 
9038 /** creates and captures a set covering constraint with all constraint flags set
9039  * to their default values
9040  *
9041  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9042  */
9044  SCIP* scip, /**< SCIP data structure */
9045  SCIP_CONS** cons, /**< pointer to hold the created constraint */
9046  const char* name, /**< name of constraint */
9047  int nvars, /**< number of variables in the constraint */
9048  SCIP_VAR** vars /**< array with variables of constraint entries */
9049  )
9050 {
9051  SCIP_CALL( SCIPcreateConsSetcover(scip, cons, name, nvars, vars,
9052  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
9053 
9054  return SCIP_OKAY;
9055 
9056 }
9057 
9058 /** adds coefficient in set partitioning / packing / covering constraint */
9060  SCIP* scip, /**< SCIP data structure */
9061  SCIP_CONS* cons, /**< constraint data */
9062  SCIP_VAR* var /**< variable to add to the constraint */
9063  )
9064 {
9065  assert(var != NULL);
9066 
9067  /*debugMessage("adding variable <%s> to setppc constraint <%s>\n",
9068  SCIPvarGetName(var), SCIPconsGetName(cons));*/
9069 
9070  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9071  {
9072  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9073  return SCIP_INVALIDDATA;
9074  }
9075 
9076  SCIP_CALL( addCoef(scip, cons, var) );
9077 
9078  return SCIP_OKAY;
9079 }
9080 
9081 /** gets number of variables in set partitioning / packing / covering constraint */
9082 int SCIPgetNVarsSetppc(
9083  SCIP* scip, /**< SCIP data structure */
9084  SCIP_CONS* cons /**< constraint data */
9085  )
9086 {
9087  SCIP_CONSDATA* consdata;
9088 
9089  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9090  {
9091  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9092  SCIPABORT();
9093  return -1; /*lint !e527*/
9094  }
9095 
9096  consdata = SCIPconsGetData(cons);
9097  assert(consdata != NULL);
9098 
9099  return consdata->nvars;
9100 }
9101 
9102 /** gets array of variables in set partitioning / packing / covering constraint */
9104  SCIP* scip, /**< SCIP data structure */
9105  SCIP_CONS* cons /**< constraint data */
9106  )
9107 {
9108  SCIP_CONSDATA* consdata;
9109 
9110  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9111  {
9112  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9113  SCIPABORT();
9114  return NULL; /*lint !e527*/
9115  }
9116 
9117  consdata = SCIPconsGetData(cons);
9118  assert(consdata != NULL);
9119 
9120  return consdata->vars;
9121 }
9122 
9123 /** gets type of set partitioning / packing / covering constraint */
9125  SCIP* scip, /**< SCIP data structure */
9126  SCIP_CONS* cons /**< constraint data */
9127  )
9128 {
9129  SCIP_CONSDATA* consdata;
9130 
9131  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9132  {
9133  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9134  SCIPABORT();
9135  }
9136 
9137  consdata = SCIPconsGetData(cons);
9138  assert(consdata != NULL);
9139 
9140  return (SCIP_SETPPCTYPE)(consdata->setppctype);
9141 }
9142 
9143 /** gets the dual solution of the set partitioning / packing / covering constraint in the current LP */
9145  SCIP* scip, /**< SCIP data structure */
9146  SCIP_CONS* cons /**< constraint data */
9147  )
9148 {
9149  SCIP_CONSDATA* consdata;
9150 
9151  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9152  {
9153  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9154  SCIPABORT();
9155  return SCIP_INVALID; /*lint !e527*/
9156  }
9157 
9158  consdata = SCIPconsGetData(cons);
9159  assert(consdata != NULL);
9160 
9161  if( consdata->row != NULL )
9162  return SCIProwGetDualsol(consdata->row);
9163  else
9164  return 0.0;
9165 }
9166 
9167 /** gets the dual Farkas value of the set partitioning / packing / covering constraint in the current infeasible LP */
9169  SCIP* scip, /**< SCIP data structure */
9170  SCIP_CONS* cons /**< constraint data */
9171  )
9172 {
9173  SCIP_CONSDATA* consdata;
9174 
9175  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9176  {
9177  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9178  SCIPABORT();
9179  return SCIP_INVALID; /*lint !e527*/
9180  }
9181 
9182  consdata = SCIPconsGetData(cons);
9183  assert(consdata != NULL);
9184 
9185  if( consdata->row != NULL )
9186  return SCIProwGetDualfarkas(consdata->row);
9187  else
9188  return 0.0;
9189 }
9190 
9191 /** returns the linear relaxation of the given set partitioning / packing / covering constraint; may return NULL if no
9192  * LP row was yet created; the user must not modify the row!
9193  */
9195  SCIP* scip, /**< SCIP data structure */
9196  SCIP_CONS* cons /**< constraint data */
9197  )
9198 {
9199  SCIP_CONSDATA* consdata;
9200 
9201  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9202  {
9203  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9204  SCIPABORT();
9205  return NULL; /*lint !e527*/
9206  }
9207 
9208  consdata = SCIPconsGetData(cons);
9209  assert(consdata != NULL);
9210 
9211  return consdata->row;
9212 }
9213 
9214 /** returns current number of variables fixed to one in the constraint */
9216  SCIP* scip, /**< SCIP data structure */
9217  SCIP_CONS* cons /**< constraint data */
9218  )
9219 {
9220  SCIP_CONSDATA* consdata;
9221 
9222  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9223  {
9224  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9225  SCIPABORT();
9226  return -1; /*lint !e527*/
9227  }
9228 
9229  consdata = SCIPconsGetData(cons);
9230  assert(consdata != NULL);
9231 
9232  return consdata->nfixedones;
9233 }
9234 
9235 
9236 /** returns current number of variables fixed to zero in the constraint */
9238  SCIP* scip, /**< SCIP data structure */
9239  SCIP_CONS* cons /**< constraint data */
9240  )
9241 {
9242  SCIP_CONSDATA* consdata;
9243 
9244  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9245  {
9246  SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9247  SCIPABORT();
9248  return -1; /*lint !e527*/
9249  }
9250 
9251  consdata = SCIPconsGetData(cons);
9252  assert(consdata != NULL);
9253 
9254  return consdata->nfixedzeros;
9255 }
9256 
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
#define LINCONSUPGD_PRIORITY
Definition: cons_setppc.c:54
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:7879
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41180
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:32735
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
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41293
static SCIP_RETCODE dualPresolving(SCIP *scip, SCIP_CONS *cons, int *nfixedvars, int *ndelconss, SCIP_RESULT *result)
Definition: cons_setppc.c:1182
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10735
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5847
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:7943
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
SCIP_BILINTERM * SCIPgetBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE addCliques(SCIP *scip, SCIP_CONS **conss, int nconss, int firstclique, int lastclique, int *naddconss, int *ndelconss, int *nchgbds, SCIP_Bool *cutoff)
Definition: cons_setppc.c:5232
static SCIP_RETCODE addExtraCliques(SCIP *const scip, SCIP_VAR **const binvars, int const nbinvars, int *const cliquepartition, int const ncliques, SCIP_CONS **const usefulconss, int *const nusefulconss, int const nrounds, int *const nfixedvars, int *const naddconss, int *const ndelconss, int *const nchgcoefs, SCIP_Bool *const cutoff)
Definition: cons_setppc.c:2594
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
static SCIP_RETCODE analyzeConflictZero(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:1938
SCIP_VAR * var2
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:48
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:22873
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_setppc.c:984
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
SCIP_RETCODE SCIPsetIntarrayVal(SCIP *scip, SCIP_INTARRAY *intarray, int idx, int val)
Definition: scip.c:42317
static SCIP_DECL_CONSLOCK(consLockSetppc)
Definition: cons_setppc.c:8268
static SCIP_DECL_CONSPARSE(consParseSetppc)
Definition: cons_setppc.c:8441
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41256
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1562
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_setppc.c:1065
SCIP_RETCODE SCIPcreateConsSetpart(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:8894
SCIP_QUADVARTERM * SCIPgetQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11577
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16521
static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:1972
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1220
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, int *ndelconss, int *nchgsides)
Definition: cons_setppc.c:6171
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10690
#define SCIP_MAXSTRLEN
Definition: def.h:198
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:5603
SCIP_VAR * var1
static SCIP_RETCODE collectCliqueData(SCIP *const scip, SCIP_CONS **const usefulconss, int const nusefulconss, SCIP_VAR **const usefulvars, int *const nusefulvars, SCIP_HASHMAP *const vartoindex, int *const varnconss, int *const maxnvarconsidx, int **const varconsidxs, int *const maxnvars)
Definition: cons_setppc.c:2806
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
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_setppc.c:67
static SCIP_DECL_CONSCOPY(consCopySetppc)
Definition: cons_setppc.c:8390
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17011
#define CONSHDLR_EAGERFREQ
Definition: cons_setppc.c:43
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
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7685
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
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9090
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:16825
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:24307
static SCIP_RETCODE createNormalizedSetppc(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, int mult, SCIP_SETPPCTYPE setppctype, 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:6799
#define DEFAULT_ADDVARIABLESASCLIQUES
Definition: cons_setppc.c:87
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5787
#define CONSHDLR_PROP_TIMING
Definition: cons_setppc.c:52
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
static SCIP_DECL_CONSSEPASOL(consSepasolSetppc)
Definition: cons_setppc.c:7318
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
#define DEFAULT_NPSEUDOBRANCHES
Definition: cons_setppc.c:77
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
static SCIP_DECL_HASHKEYVAL(hashKeyValSetppccons)
Definition: cons_setppc.c:2561
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_ROW * SCIPgetRowSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9202
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7644
SCIP_RETCODE SCIPincludeConshdlrSetppc(SCIP *scip)
Definition: cons_setppc.c:8792
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
static SCIP_DECL_CONSGETVARS(consGetVarsSetppc)
Definition: cons_setppc.c:8535
static SCIP_RETCODE preprocessCliques(SCIP *const scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS **const conss, int const nconss, int const nrounds, int *const firstchange, int *const firstclique, int *const lastclique, int *const nfixedvars, int *const naggrvars, int *const ndelconss, int *const nchgcoefs, SCIP_Bool *const cutoff)
Definition: cons_setppc.c:4788
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41580
static SCIP_RETCODE enforcePseudo(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *reduceddom, SCIP_Bool *solvelp)
Definition: cons_setppc.c:2449
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:23070
SCIP_Real SCIPgetDualsolSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9152
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip.c:16416
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:25773
static SCIP_DECL_QUADCONSUPGD(quadraticUpgdSetppc)
Definition: cons_setppc.c:6948
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15695
#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
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16803
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2111
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:10915
SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_setppc.c:9067
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7843
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7783
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
SCIP_RETCODE SCIPcreateIntarray(SCIP *scip, SCIP_INTARRAY **intarray)
Definition: scip.c:42232
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:99
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:20418
static SCIP_RETCODE removeRedundantCons(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *ndelconss)
Definition: cons_setppc.c:6279
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11206
static SCIP_RETCODE processContainedCons(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss, int *nchgsides)
Definition: cons_setppc.c:6377
int SCIPgetIntarrayVal(SCIP *scip, SCIP_INTARRAY *intarray, int idx)
Definition: scip.c:42301
#define CONSHDLR_DELAYSEPA
Definition: cons_setppc.c:47
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 checkForOverlapping(SCIP *const scip, SCIP_CONS *const cons, int const considx, int const endidx, SCIP_CONS **const usefulconss, int const nusefulconss, SCIP_VAR **const usefulvars, int *const nusefulvars, SCIP_HASHMAP *const vartoindex, int *const varnconss, int *const maxnvarconsidx, int **const varconsidxs, int *const countofoverlapping, SCIP_Bool const shrinking, SCIP_Bool *const chgcons, SCIP_VAR **undoneaggrvars, SCIP_Bool *undoneaggrtypes, int *const naggregations, int *const saggregations, int *const nfixedvars, int *const naggrvars, int *const nchgcoefs, int *const ndelconss, SCIP_Bool *const cutoff)
Definition: cons_setppc.c:3367
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
#define DEFAULT_CLIQUELIFTING
Definition: cons_setppc.c:80
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:24707
SCIP_Bool SCIPdoNotMultaggr(SCIP *scip)
Definition: scip.c:23047
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_SETPPCTYPE setppctype)
Definition: cons_setppc.c:540
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip.c:5352
SCIP_Longint SCIPgetNTotalNodes(SCIP *scip)
Definition: scip.c:37009
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_RETCODE SCIPincIntarrayVal(SCIP *scip, SCIP_INTARRAY *intarray, int idx, int incval)
Definition: scip.c:42336
#define CONSHDLR_DESC
Definition: cons_setppc.c:37
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16460
static SCIP_DECL_CONSEXITSOL(consExitsolSetppc)
Definition: cons_setppc.c:7149
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2154
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3542
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:56
static SCIP_DECL_CONSPROP(consPropSetppc)
Definition: cons_setppc.c:7842
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
static SCIP_DECL_CONSPRINT(consPrintSetppc)
Definition: cons_setppc.c:8376
static SCIP_DECL_CONSRESPROP(consRespropSetppc)
Definition: cons_setppc.c:8186
int SCIPgetNFixedzerosSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9245
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17556
static SCIP_RETCODE removeDoubleAndSingletonsAndPerformDualpresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool dualpresolvingenabled, SCIP_Bool linearconshdlrexist, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgcoefs, int *nchgsides, SCIP_Bool *cutoff)
Definition: cons_setppc.c:5418
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36232
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff, SCIP_Bool *separated, SCIP_Bool *reduceddom)
Definition: cons_setppc.c:2364
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:17316
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:24329
static SCIP_RETCODE fixAdditionalVars(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_setppc.c:6305
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16483
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:25547
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:20383
#define CONFLICTHDLR_NAME
Definition: cons_setppc.c:60
#define SCIP_PRESOLTIMING_MEDIUM
Definition: type_timing.h:44
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
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20426
#define SCIPdebugPrintf
Definition: pub_message.h:80
static SCIP_DECL_CONSPRESOL(consPresolSetppc)
Definition: cons_setppc.c:7904
#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
SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
Definition: scip.c:33261
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:25287
static SCIP_RETCODE addCut(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff)
Definition: cons_setppc.c:2330
void SCIPsortDownPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define DEFAULT_DUALPRESOLVING
Definition: cons_setppc.c:78
static SCIP_RETCODE addCliqueDataEntry(SCIP *const scip, SCIP_VAR *const addvar, int const considx, SCIP_Bool const maybenew, SCIP_VAR **const usefulvars, int *const nusefulvars, SCIP_HASHMAP *const vartoindex, int *const varnconss, int *const maxnvarconsidx, int **const varconsidxs)
Definition: cons_setppc.c:2955
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41604
static SCIP_DECL_HASHGETKEY(hashGetKeySetppccons)
Definition: cons_setppc.c:2510
#define EVENTHDLR_DESC
Definition: cons_setppc.c:58
#define SCIP_DECL_CONSDEACTIVE(x)
Definition: type_cons.h:621
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
#define MINGAINPERNMINCOMPARISONS
Definition: cons_setppc.c:69
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:23037
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9111
static SCIP_DECL_CONSINIT(consInitSetppc)
Definition: cons_setppc.c:7101
#define CONFLICTHDLR_DESC
Definition: cons_setppc.c:61
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
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:28138
enum SCIP_SetppcType SCIP_SETPPCTYPE
Definition: cons_setppc.h:57
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:40927
static SCIP_DECL_CONSDELETE(consDeleteSetppc)
Definition: cons_setppc.c:7172
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7624
#define CONSHDLR_ENFOPRIORITY
Definition: cons_setppc.c:39
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
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16562
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
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2070
constraint handler for quadratic constraints
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:5472
static int setppcCompare(SCIP_CONS *const cons1, SCIP_CONS *const cons2)
Definition: cons_setppc.c:172
static SCIP_RETCODE consdataCreateTransformed(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_SETPPCTYPE setppctype)
Definition: cons_setppc.c:612
SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
Definition: scip.c:33074
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopySetppc)
Definition: cons_setppc.c:7063
static SCIP_DECL_EVENTEXEC(eventExecSetppc)
Definition: cons_setppc.c:8575
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:20391
static SCIP_RETCODE multiAggregateBinvar(SCIP *scip, SCIP_Bool linearconshdlrexist, SCIP_VAR **vars, int nvars, int pos, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: cons_setppc.c:5315
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 dropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_setppc.c:961
static void consdataSort(SCIP_CONSDATA *consdata)
Definition: cons_setppc.c:735
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_setppc.c:516
static SCIP_RETCODE catchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_setppc.c:838
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11573
static SCIP_RETCODE dropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_setppc.c:902
#define CONSHDLR_NAME
Definition: cons_setppc.c:36
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:58
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
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:55
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_setppc.c:6665
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:26341
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
static SCIP_DECL_HASHKEYEQ(hashKeyEqSetppccons)
Definition: cons_setppc.c:2518
#define CONSHDLR_NEEDSCONS
Definition: cons_setppc.c:49
static SCIP_DECL_CONFLICTEXEC(conflictExecSetppc)
Definition: cons_setppc.c:8664
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:31741
static SCIP_DECL_CONSTRANS(consTransSetppc)
Definition: cons_setppc.c:7208
static SCIP_DECL_SORTPTRCOMP(setppcConssSort)
Definition: cons_setppc.c:212
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:706
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:97
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7654
#define CONSHDLR_CHECKPRIORITY
Definition: cons_setppc.c:40
SCIP_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: scip.c:23007
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16968
static SCIP_RETCODE processFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, SCIP_Bool *addcut, SCIP_Bool *mustcheck)
Definition: cons_setppc.c:2011
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11966
#define DEFAULT_CLIQUESHRINKING
Definition: cons_setppc.c:92
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_setppc.c:64
SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:21688
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_setppc.c:285
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12117
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:17200
static SCIP_Bool checkCons(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_setppc.c:2243
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16771
#define CONFLICTHDLR_PRIORITY
Definition: cons_setppc.c:62
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip.c:5718
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:16934
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17021
static SCIP_RETCODE catchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_setppc.c:938
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:997
public data structures and miscellaneous methods
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
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
int SCIPgetNFixedonesSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9223
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16638
#define SCIP_Bool
Definition: def.h:50
SCIP_RETCODE SCIPfreeIntarray(SCIP *scip, SCIP_INTARRAY **intarray)
Definition: scip.c:42249
#define CONSHDLR_PRESOLTIMING
Definition: cons_setppc.c:51
#define NMINCOMPARISONS
Definition: cons_setppc.c:68
SCIP_RETCODE SCIPcalcCliquePartition(SCIP *const scip, SCIP_VAR **const vars, int const nvars, int *const cliquepartition, int *const ncliques)
Definition: scip.c:21846
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
#define EVENTHDLR_NAME
Definition: cons_setppc.c:57
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7863
static SCIP_DECL_CONSACTIVE(consActiveSetppc)
Definition: cons_setppc.c:8308
SCIP_Bool SCIPhaveVarsCommonClique(SCIP *scip, SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: scip.c:22152
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:20427
#define CONSHDLR_MAXPREROUNDS
Definition: cons_setppc.c:46
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_RETCODE setSetppcType(SCIP *scip, SCIP_CONS *cons, SCIP_SETPPCTYPE setppctype)
Definition: cons_setppc.c:767
static SCIP_DECL_CONSFREE(consFreeSetppc)
Definition: cons_setppc.c:7079
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
SCIP_RETCODE SCIPcreateConsBasicSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
Definition: cons_setppc.c:8934
SCIP_Real coef
int SCIPgetNCliques(SCIP *scip)
Definition: scip.c:22095
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSENFOPS(consEnfopsSetppc)
Definition: cons_setppc.c:7728
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:7634
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
static SCIP_Longint consdataGetSignature(SCIP_CONSDATA *consdata)
Definition: cons_setppc.c:714
static SCIP_RETCODE removeRedundantConstraints(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss, int *nchgsides)
Definition: cons_setppc.c:6493
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_setppc.c:665
#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 collectCliqueConss(SCIP *const scip, SCIP_CONS **const conss, int const nconss, SCIP_CONS **const usefulconss, int *const nusefulconss, int *const nfixedvars, int *const ndelconss, int *const nchgcoefs, SCIP_Bool *const cutoff)
Definition: cons_setppc.c:2714
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_setppc.c:355
SCIP_RETCODE SCIPgetChildren(SCIP *scip, SCIP_NODE ***children, int *nchildren)
Definition: scip.c:36461
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1270
SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19964
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1505
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_setppc.c:320
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip.c:16052
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 createConsSetppc(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_SETPPCTYPE setppctype, 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:6714
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16506
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20371
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16955
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2172
#define HASHSIZE_SETPPCCONS
Definition: cons_setppc.c:66
int SCIPgetNFixedVars(SCIP *scip)
Definition: scip.c:11052
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
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons, int *nfixedvars, int *ndelconss, int *nchgcoefs, SCIP_Bool *cutoff)
Definition: cons_setppc.c:1473
static SCIP_DECL_LINCONSUPGD(linconsUpgdSetppc)
Definition: cons_setppc.c:6867
static const SCIP_Real scalars[]
Definition: lp.c:5506
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1253
static SCIP_DECL_CONSEXITPRE(consExitpreSetppc)
Definition: cons_setppc.c:7128
int SCIPgetNBilinTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:10825
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)
static SCIP_RETCODE presolvePropagateCons(SCIP *const scip, SCIP_CONS *const cons, SCIP_Bool const aggregate, SCIP_VAR **undoneaggrvars, SCIP_Bool *undoneaggrtypes, int *const naggregations, int *const saggregations, int *const nfixedvars, int *const naggrvars, int *const ndelconss, SCIP_Bool *const cutoff)
Definition: cons_setppc.c:3024
static int setppcCompare2(SCIP_CONS *const cons1, SCIP_CONS *const cons2)
Definition: cons_setppc.c:228
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20422
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
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
SCIP_RETCODE SCIPchgVarUbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19997
#define SCIP_Real
Definition: def.h:124
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7803
SCIP_RETCODE SCIPcreateConsSetcover(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:9011
SCIP_Real SCIPgetDualfarkasSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9176
#define MIN(x, y)
Definition: memory.c:63
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
SCIP_RETCODE SCIPcreateConsBasicSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
Definition: cons_setppc.c:8992
static SCIP_RETCODE conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_setppc.c:380
static SCIP_DECL_CONSGETNVARS(consGetNVarsSetppc)
Definition: cons_setppc.c:8557
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41567
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:20397
#define SCIP_INVALID
Definition: def.h:144
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:40720
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
static SCIP_DECL_CONSSEPALP(consSepalpSetppc)
Definition: cons_setppc.c:7275
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
SCIP_Real SCIPgetVarSol(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:17711
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:19465
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
static SCIP_DECL_CONSENFOLP(consEnfolpSetppc)
Definition: cons_setppc.c:7670
#define CONSHDLR_PROPFREQ
Definition: cons_setppc.c:42
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
static void deleteCliqueDataEntry(SCIP_VAR *const var, int const considx, SCIP_HASHMAP *const vartoindex, int *const varnconss, int **const varconsidxs)
Definition: cons_setppc.c:2913
static SCIP_RETCODE performAggregations(SCIP *const scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_VAR **const undoneaggrvars, SCIP_Bool *const undoneaggrtypes, int const naggregations, int *const naggrvars, SCIP_Bool *const cutoff)
Definition: cons_setppc.c:4707
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9132
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16628
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip.c:33311
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:24560
static SCIP_RETCODE liftCliqueVariables(SCIP *const scip, SCIP_CONS *const cons, int const arraypos, SCIP_VAR **const usefulvars, int *const nusefulvars, int const endidx, SCIP_Bool **cliquevalues, SCIP_HASHMAP *const vartoindex, int *const varnconss, int *const maxnvarconsidx, int **const varconsidxs, int *const maxnvars, int *const nadded, SCIP_Bool *const chgcons, int *const nfixedvars, int *const ndelconss, SCIP_Bool *const cutoff)
Definition: cons_setppc.c:4233
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:40996
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2089
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_setppc.c:634
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:2288
#define CONSHDLR_DELAYPROP
Definition: cons_setppc.c:48
static SCIP_DECL_CONSDELVARS(consDelvarsSetppc)
Definition: cons_setppc.c:8358
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
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
SCIP_Real SCIPcalcChildEstimate(SCIP *scip, SCIP_VAR *var, SCIP_Real targetvalue)
Definition: scip.c:33288
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5810
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
#define CONSHDLR_SEPAPRIORITY
Definition: cons_setppc.c:38
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7793
#define QUADCONSUPGD_PRIORITY
Definition: cons_setppc.c:55
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7823
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
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNImplications(SCIP *scip)
Definition: scip.c:40227
static SCIP_Longint getVarSignature(SCIP_VAR *var)
Definition: cons_setppc.c:702
void SCIPsortedvecInsertDownPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *keyval, int *len, int *pos)
static SCIP_DECL_CONSINITLP(consInitlpSetppc)
Definition: cons_setppc.c:7257
SCIP_Bool SCIPsortedvecFindDownPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:47
SCIP_RETCODE SCIPcreateConsBasicSetcover(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
Definition: cons_setppc.c:9051
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, int *naddconss, int *ndelconss, int *nfixedvars, SCIP_Bool *cutoff)
Definition: cons_setppc.c:1617
#define CONSHDLR_SEPAFREQ
Definition: cons_setppc.c:41
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11168
static SCIP_DECL_CONSCHECK(consCheckSetppc)
Definition: cons_setppc.c:7790