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