Scippy

SCIP

Solving Constraint Integer Programs

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