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