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