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