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