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