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