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