Scippy

SCIP

Solving Constraint Integer Programs

cons_cardinality.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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_cardinality.c
17  * @brief constraint handler for cardinality constraints
18  * @author Tobias Fischer
19  *
20  * This constraint handler handles cardinality constraints of the form
21  * \f[
22  * |\mbox{supp}(x)| \leq b
23  * \f]
24  * with integer right-hand side \f$b\f$. Here, \f$|\mbox{supp}(x)|\f$ denotes the number of nonzero entries of the
25  * vector \f$x\f$.
26  *
27  * Note that cardinality constraints generalize special ordered set of type one (SOS1) constraints in which \f$b = 1\f$.
28  *
29  * The implementation of this constraint handler is based on@n
30  * "On the Structure of Linear Programs with Overlapping Cardinality Constraints"@n
31  * T. Fischer and M. E. Pfetsch, Tech. rep., 2016
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #include <assert.h>
37 
38 #include "scip/cons_cardinality.h"
39 #include "scip/cons_linear.h"
40 #include "scip/cons_knapsack.h"
41 #include <string.h>
42 #include <ctype.h>
43 
44 /* constraint handler properties */
45 #define CONSHDLR_NAME "cardinality"
46 #define CONSHDLR_DESC "cardinality constraint handler"
47 #define CONSHDLR_SEPAPRIORITY 10 /**< priority of the constraint handler for separation */
48 #define CONSHDLR_ENFOPRIORITY 100 /**< priority of the constraint handler for constraint enforcing */
49 #define CONSHDLR_CHECKPRIORITY -10 /**< priority of the constraint handler for checking feasibility */
50 #define CONSHDLR_SEPAFREQ 10 /**< frequency for separating cuts; zero means to separate only in the root node */
51 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
52 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
53  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
54 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in
55  * (-1: no limit) */
56 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
57 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
58 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
59 
60 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
61 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
62 
63 /* branching rules */
64 #define DEFAULT_BRANCHBALANCED FALSE /**< whether to use balanced instead of unbalanced branching */
65 #define DEFAULT_BALANCEDDEPTH 20 /**< maximum depth for using balanced branching (-1: no limit) */
66 #define DEFAULT_BALANCEDCUTOFF 2.0 /**< determines that balanced branching is only used if the branching cut off value
67  * w.r.t. the current LP solution is greater than a given value */
68 
69 /* event handler properties */
70 #define EVENTHDLR_NAME "cardinality"
71 #define EVENTHDLR_DESC "bound change event handler for cardinality constraints"
72 
73 
74 /** constraint data for cardinality constraints */
75 struct SCIP_ConsData
76 {
77  SCIP_CONS* cons; /**< cardinality constraint */
78  int cardval; /**< number of variables that the constraint allows to be nonzero */
79  int nvars; /**< number of variables in the constraint */
80  int maxvars; /**< maximal number of variables (= size of storage) */
81  int ntreatnonzeros; /**< number of variables in constraint that are either known to be nonzero
82  * (because zero is not in variable domain) or may be treated as nonzero */
83  SCIP_EVENTDATA** eventdatascurrent; /**< event datas for current bound change events */
84  SCIP_VAR** eventvarscurrent; /**< event variables for current bound change events */
85  int neventdatascurrent; /**< number of current bound change events */
86  SCIP_EVENTDATA** eventdatas; /**< event data array for bound change events */
87  SCIP_VAR** vars; /**< variables in constraint */
88  SCIP_VAR** indvars; /**< indicator variables that indicate which variables may be treated as
89  * nonzero in cardinality constraint */
90  SCIP_Real* weights; /**< weights determining the order (ascending), or NULL if not used */
91  SCIP_ROW* rowlb; /**< row corresponding to lower bounds, or NULL if not yet created */
92  SCIP_ROW* rowub; /**< row corresponding to upper bounds, or NULL if not yet created */
93 };
94 
95 /** cardinality constraint handler data */
96 struct SCIP_ConshdlrData
97 {
98  SCIP_HASHMAP* varhash; /**< hash map from implied variable to (binary) indicator variable */
99  SCIP_Bool branchbalanced; /**< whether to use balanced instead of unbalanced branching */
100  int balanceddepth; /**< maximum depth for using balanced branching (-1: no limit) */
101  SCIP_Real balancedcutoff; /**< determines that balanced branching is only used if the branching cut off
102  * value w.r.t. the current LP solution is greater than a given value */
103  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
104 };
105 
106 /** event data for bound changes events */
107 struct SCIP_EventData
108 {
109  SCIP_CONSDATA* consdata; /**< cardinality constraint data to process the bound change for */
110  SCIP_VAR* var; /**< implied variable */
111  SCIP_VAR* indvar; /**< indicator variable */
112  unsigned int pos:30; /**< position in constraint */
113  unsigned int varmarked:1; /**< whether implied variable is marked for propagation */
114  unsigned int indvarmarked:1; /**< whether indicator variable is marked for propagation */
115 };
116 
117 /** catches bound change events for a variable and its indicator variable */
118 static
120  SCIP* scip, /**< SCIP data structure */
121  SCIP_EVENTHDLR* eventhdlr, /**< event handler for bound change events */
122  SCIP_CONSDATA* consdata, /**< constraint data */
123  SCIP_VAR* var, /**< implied variable */
124  SCIP_VAR* indvar, /**< indicator variable */
125  int pos, /**< position in constraint */
126  SCIP_EVENTDATA** eventdata /**< pointer to store event data for bound change events */
127  )
128 {
129  assert(eventhdlr != NULL);
130  assert(consdata != NULL);
131  assert(var != NULL);
132  assert(indvar != NULL);
133  assert(pos >= 0);
134 
135  /* create event data of indicator variable */
136  SCIP_CALL( SCIPallocBlockMemory(scip, eventdata) );
137 
138  (*eventdata)->consdata = consdata;
139  (*eventdata)->var = var;
140  (*eventdata)->indvar = indvar;
141  (*eventdata)->varmarked = FALSE;
142  (*eventdata)->indvarmarked = FALSE;
143  (*eventdata)->pos = (unsigned int)pos;
144 
145  /* catch bound change events of each variable */
146  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, *eventdata, NULL) );
147  SCIP_CALL( SCIPcatchVarEvent(scip, indvar, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, *eventdata, NULL) );
148 
149  return SCIP_OKAY;
150 }
151 
152 /** drops bound change events for a variable and its indicator variable */
153 static
155  SCIP* scip, /**< SCIP data structure */
156  SCIP_EVENTHDLR* eventhdlr, /**< event handler for bound change events */
157  SCIP_CONSDATA* consdata, /**< constraint data */
158  SCIP_VAR* var, /**< implied variable */
159  SCIP_VAR* indvar, /**< indicator variable */
160  SCIP_EVENTDATA** eventdata /**< pointer of event data for bound change events */
161  )
162 {
163  assert(eventhdlr != NULL);
164  assert(consdata != NULL);
165  assert(var != NULL);
166  assert(indvar != NULL);
167  assert(eventdata != NULL);
168 
169  /* drop bound change events of each variable */
170  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, *eventdata, -1) );
171  SCIP_CALL( SCIPdropVarEvent(scip, indvar, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, *eventdata, -1) );
172 
173  /* free event data of indicator variable */
174  SCIPfreeBlockMemory(scip, eventdata);
175  *eventdata = NULL;
176 
177  return SCIP_OKAY;
178 }
179 
180 /** fix variable in given node to 0 or add constraint if variable is multi-aggregated
181  *
182  * @todo Try to handle multi-aggregated variables as in \ref fixVariableZero() below.
183  */
184 static
186  SCIP* scip, /**< SCIP pointer */
187  SCIP_VAR* var, /**< variable to be fixed to 0 */
188  SCIP_NODE* node, /**< node */
189  SCIP_Bool* infeasible /**< pointer to store if fixing is infeasible */
190  )
191 {
192  /* if variable cannot be nonzero */
193  *infeasible = FALSE;
195  {
196  *infeasible = TRUE;
197  return SCIP_OKAY;
198  }
199 
200  /* if variable is multi-aggregated */
202  {
203  SCIP_CONS* cons;
204  SCIP_Real val;
205 
206  val = 1.0;
207 
208  if( !SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || !SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
209  {
210  SCIPdebugMsg(scip, "creating constraint to force multi-aggregated variable <%s> to 0.\n", SCIPvarGetName(var));
211 
212  /* we have to insert a local constraint var = 0 */
213  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, "branch", 1, &var, &val, 0.0, 0.0, TRUE, TRUE, TRUE, TRUE, TRUE,
214  TRUE, FALSE, FALSE, FALSE, FALSE) );
215  SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
216  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
217  }
218  }
219  else
220  {
221  if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) )
222  {
223  SCIP_CALL( SCIPchgVarLbNode(scip, node, var, 0.0) );
224  }
225  if ( ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
226  {
227  SCIP_CALL( SCIPchgVarUbNode(scip, node, var, 0.0) );
228  }
229  }
230 
231  return SCIP_OKAY;
232 }
233 
234 /** try to fix variable to 0
235  *
236  * Try to treat fixing by special consideration of multiaggregated variables. For a multi-aggregation
237  * \f[
238  * x = \sum_{i=1}^n \alpha_i x_i + c,
239  * \f]
240  * we can express the fixing \f$x = 0\f$ by fixing all \f$x_i\f$ to 0 if \f$c = 0\f$ and the lower bounds of \f$x_i\f$
241  * are nonnegative if \f$\alpha_i > 0\f$ or the upper bounds are nonpositive if \f$\alpha_i < 0\f$.
242  */
243 static
245  SCIP* scip, /**< SCIP pointer */
246  SCIP_VAR* var, /**< variable to be fixed to 0*/
247  SCIP_Bool* infeasible, /**< if fixing is infeasible */
248  SCIP_Bool* tightened /**< if fixing was performed */
249  )
250 {
251  assert(scip != NULL);
252  assert(var != NULL);
253  assert(infeasible != NULL);
254  assert(tightened != NULL);
255 
256  *infeasible = FALSE;
257  *tightened = FALSE;
258 
260  {
261  SCIP_Real aggrconst;
262 
263  /* if constant is 0 */
264  aggrconst = SCIPvarGetMultaggrConstant(var);
265  if( SCIPisZero(scip, aggrconst) )
266  {
267  SCIP_VAR** aggrvars;
268  SCIP_Real* aggrvals;
269  SCIP_Bool allnonnegative = TRUE;
270  int naggrvars;
271  int i;
272 
274 
275  /* check whether all variables are "nonnegative" */
276  naggrvars = SCIPvarGetMultaggrNVars(var);
277  aggrvars = SCIPvarGetMultaggrVars(var);
278  aggrvals = SCIPvarGetMultaggrScalars(var);
279  for( i = 0; i < naggrvars; ++i )
280  {
281  if( (SCIPisPositive(scip, aggrvals[i]) && SCIPisNegative(scip, SCIPvarGetLbLocal(aggrvars[i]))) ||
282  (SCIPisNegative(scip, aggrvals[i]) && SCIPisPositive(scip, SCIPvarGetUbLocal(aggrvars[i]))) )
283  {
284  allnonnegative = FALSE;
285  break;
286  }
287  }
288 
289  if( allnonnegative )
290  {
291  /* all variables are nonnegative -> fix variables */
292  for( i = 0; i < naggrvars; ++i )
293  {
294  SCIP_Bool fixed;
295  SCIP_CALL( SCIPfixVar(scip, aggrvars[i], 0.0, infeasible, &fixed) );
296  if( *infeasible )
297  return SCIP_OKAY;
298  *tightened = *tightened || fixed;
299  }
300  }
301  }
302  }
303  else
304  {
305  SCIP_CALL( SCIPfixVar(scip, var, 0.0, infeasible, tightened) );
306  }
307 
308  return SCIP_OKAY;
309 }
310 
311 /** add lock on variable */
312 static
314  SCIP* scip, /**< SCIP data structure */
315  SCIP_CONS* cons, /**< constraint */
316  SCIP_VAR* var, /**< variable */
317  SCIP_VAR* indvar /**< indicator variable */
318  )
319 {
320  assert(scip != NULL);
321  assert(cons != NULL);
322  assert(var != NULL);
323 
324  /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
325  SCIP_CALL( SCIPlockVarCons(scip, var, cons, SCIPisFeasNegative(scip, SCIPvarGetLbLocal(var)),
326  SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var))) );
327  SCIP_CALL( SCIPlockVarCons(scip, indvar, cons, TRUE, TRUE) );
328 
329  return SCIP_OKAY;
330 }
331 
332 /* remove lock on variable */
333 static
335  SCIP* scip, /**< SCIP data structure */
336  SCIP_CONS* cons, /**< constraint */
337  SCIP_VAR* var, /**< variable */
338  SCIP_VAR* indvar /**< indicator variable */
339  )
340 {
341  assert(scip != NULL);
342  assert(cons != NULL);
343  assert(var != NULL);
344 
345  /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
346  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, SCIPisFeasNegative(scip, SCIPvarGetLbLocal(var)),
347  SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var))) );
348  SCIP_CALL( SCIPunlockVarCons(scip, indvar, cons, TRUE, TRUE) );
349 
350  return SCIP_OKAY;
351 }
352 
353 /** ensures that the vars and weights array can store at least num entries */
354 static
356  SCIP* scip, /**< SCIP data structure */
357  SCIP_CONSDATA* consdata, /**< constraint data */
358  int num, /**< minimum number of entries to store */
359  SCIP_Bool reserveweights /**< whether the weights array is handled */
360  )
361 {
362  assert(consdata != NULL);
363  assert(consdata->nvars <= consdata->maxvars);
364 
365  if( num > consdata->maxvars )
366  {
367  int newsize;
368 
369  newsize = SCIPcalcMemGrowSize(scip, num);
370  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->maxvars, newsize) );
371  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->indvars, consdata->maxvars, newsize) );
372  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdatas, consdata->maxvars, newsize) );
373  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdatascurrent, 4*consdata->maxvars, 4*newsize) );/*lint !e647*/
374  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventvarscurrent, 4*consdata->maxvars, 4*newsize) );/*lint !e647*/
375 
376  if ( reserveweights )
377  {
378  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->weights, consdata->maxvars, newsize) );
379  }
380  consdata->maxvars = newsize;
381  }
382  assert(num <= consdata->maxvars);
383 
384  return SCIP_OKAY;
385 }
386 
387 /** handle new variable that was added to the constraint
388  *
389  * We perform the following steps:
390  *
391  * - catch bound change events of variable.
392  * - update rounding locks of variable.
393  * - don't allow multiaggregation of variable, since this cannot be handled by branching in the current implementation
394  * - update lower and upper bound row, i.e., the linear representations of the cardinality constraints
395  */
396 static
398  SCIP* scip, /**< SCIP data structure */
399  SCIP_CONS* cons, /**< constraint */
400  SCIP_CONSDATA* consdata, /**< constraint data */
401  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
402  SCIP_VAR* var, /**< variable */
403  SCIP_VAR* indvar, /**< indicator variable to indicate whether variable may be treated as
404  * nonzero in cardinality constraint */
405  int pos, /**< position in constraint */
406  SCIP_Bool transformed, /**< whether original variable was transformed */
407  SCIP_EVENTDATA** eventdata /**< pointer to store event data for bound change events */
408  )
409 {
410  assert(scip != NULL);
411  assert(cons != NULL);
412  assert(consdata != NULL);
413  assert(conshdlrdata != NULL);
414  assert(var != NULL);
415 
416  /* if we are in transformed problem, catch the variable's events */
417  if( transformed )
418  {
419  /* catch bound change events of variable */
420  SCIP_CALL( catchVarEventCardinality(scip, conshdlrdata->eventhdlr, consdata, var, indvar, pos, eventdata) );
421  assert(eventdata != NULL );
422 
423  /* if the variable is fixed to nonzero */
424  assert(consdata->ntreatnonzeros >= 0 );
425  if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(indvar), 1.0) )
426  ++consdata->ntreatnonzeros;
427  }
428 
429  /* branching on multiaggregated variables does not seem to work well, so avoid it */
430  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, indvar) );
431 
432  /* install the rounding locks for the new variable */
433  SCIP_CALL( lockVariableCardinality(scip, cons, var, indvar) );
434 
435  /* add the new coefficient to the upper bound LP row, if necessary */
436  if( consdata->rowub != NULL && !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var))
437  && !SCIPisZero(scip, SCIPvarGetUbGlobal(var)) )
438  {
439  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rowub, var, 1.0/SCIPvarGetUbGlobal(var)) );
440  }
441 
442  /* add the new coefficient to the lower bound LP row, if necessary */
443  if( consdata->rowlb != NULL && !SCIPisInfinity(scip, SCIPvarGetLbGlobal(var))
444  && !SCIPisZero(scip, SCIPvarGetLbGlobal(var)) )
445  {
446  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rowlb, var, 1.0/SCIPvarGetLbGlobal(var)) );
447  }
448 
449  return SCIP_OKAY;
450 }
451 
452 /** adds a variable to a cardinality constraint, at position given by weight - ascending order */
453 static
455  SCIP* scip, /**< SCIP data structure */
456  SCIP_CONS* cons, /**< constraint */
457  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
458  SCIP_VAR* var, /**< variable to add to the constraint */
459  SCIP_VAR* indvar, /**< indicator variable to indicate whether variable may be treated as nonzero
460  * in cardinality constraint (or NULL) */
461  SCIP_Real weight /**< weight to determine position */
462  )
463 {
464  SCIP_EVENTDATA* eventdata = NULL;
465  SCIP_CONSDATA* consdata;
466  SCIP_Bool transformed;
467  int pos;
468 
469  assert(var != NULL);
470  assert(cons != NULL);
471  assert(conshdlrdata != NULL);
472 
473  consdata = SCIPconsGetData(cons);
474  assert(consdata != NULL );
475 
476  if( consdata->weights == NULL && consdata->maxvars > 0 )
477  {
478  SCIPerrorMessage("cannot add variable to cardinality constraint <%s> that does not contain weights.\n",
479  SCIPconsGetName(cons));
480  return SCIP_INVALIDCALL;
481  }
482 
483  /* check indicator variable */
484  if( indvar == NULL )
485  {
486  if( conshdlrdata->varhash == NULL )
487  {
488  /* set up hash map */
489  SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), SCIPgetNTotalVars(scip)) );
490  }
491 
492  /* check whether an indicator variable already exists for implied variable */
493  if( SCIPhashmapExists(conshdlrdata->varhash, var) )
494  {
495  assert((SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var) != NULL);
496  indvar = (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var);
497  assert(indvar != NULL);
498  }
499  else
500  {
501  /* if implied variable is binary, then it is also not necessary to create an indicator variable */
502  if( SCIPvarIsBinary(var) )
503  indvar = var;
504  else
505  {
506  char varname[SCIP_MAXSTRLEN];
507  SCIP_VAR* newvar;
508 
509  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ind_%s", SCIPvarGetName(var));
510  SCIP_CALL( SCIPcreateVar(scip, &newvar, varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, FALSE, FALSE,
511  NULL, NULL, NULL, NULL, NULL) );
512  SCIP_CALL( SCIPaddVar(scip, newvar) );
513  indvar = newvar;
514 
515  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
516  }
517  assert(indvar != NULL);
518 
519  /* insert implied variable to hash map */
520  SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varhash, var, (void*) indvar) );/*lint !e571*/
521  assert(indvar == (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var));
522  assert(SCIPhashmapExists(conshdlrdata->varhash, var));
523  }
524  }
525 
526  /* are we in the transformed problem? */
527  transformed = SCIPconsIsTransformed(cons);
528 
529  /* always use transformed variables in transformed constraints */
530  if( transformed )
531  {
532  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
533  SCIP_CALL( SCIPgetTransformedVar(scip, indvar, &indvar) );
534  }
535  assert(var != NULL);
536  assert(indvar != NULL);
537  assert(transformed == SCIPvarIsTransformed(var));
538  assert(transformed == SCIPvarIsTransformed(indvar));
539 
540  /* ensure that the new information can be storend in the constraint data */
541  SCIP_CALL( consdataEnsurevarsSizeCardinality(scip, consdata, consdata->nvars + 1, TRUE) );
542  assert(consdata->weights != NULL);
543  assert(consdata->maxvars >= consdata->nvars+1);
544 
545  /* move other variables, if necessary */
546  for( pos = consdata->nvars; pos >= 1; --pos )
547  {
548  if( consdata->weights[pos-1] > weight )
549  {
550  consdata->vars[pos] = consdata->vars[pos-1];
551  consdata->indvars[pos] = consdata->indvars[pos-1];
552  consdata->eventdatas[pos] = consdata->eventdatas[pos-1];
553  consdata->weights[pos] = consdata->weights[pos-1];
554 
555  if( consdata->eventdatas[pos] != NULL )
556  {
557  consdata->eventdatas[pos]->pos = (unsigned int)pos;
558  }
559  }
560  else
561  break;
562  }
563  assert(0 <= pos && pos <= consdata->nvars);
564 
565  /* handle the new variable */
566  SCIP_CALL( handleNewVariableCardinality(scip, cons, consdata, conshdlrdata, var, indvar, pos, transformed, &eventdata) );
567  assert(! transformed || eventdata != NULL);
568 
569  /* insert variable */
570  consdata->vars[pos] = var;
571  consdata->indvars[pos] = indvar;
572  consdata->eventdatas[pos] = eventdata;
573  consdata->weights[pos] = weight;
574  ++consdata->nvars;
575 
576  return SCIP_OKAY;
577 }
578 
579 /** appends a variable to a cardinality constraint */
580 static
582  SCIP* scip, /**< SCIP data structure */
583  SCIP_CONS* cons, /**< constraint */
584  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
585  SCIP_VAR* var, /**< variable to add to the constraint */
586  SCIP_VAR* indvar /**< indicator variable to indicate whether variable may be treated as nonzero
587  * in cardinality constraint */
588  )
589 {
590  SCIP_EVENTDATA* eventdata = NULL;
591  SCIP_CONSDATA* consdata;
592  SCIP_Bool transformed;
593 
594  assert(var != NULL);
595  assert(cons != NULL);
596  assert(conshdlrdata != NULL);
597 
598  consdata = SCIPconsGetData(cons);
599  assert(consdata != NULL);
600 
601  /* check indicator variable */
602  if( indvar == NULL )
603  {
604  if( conshdlrdata->varhash == NULL )
605  {
606  /* set up hash map */
607  SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), SCIPgetNTotalVars(scip)) );
608  }
609 
610  /* check whether an indicator variable already exists for implied variable */
611  if( SCIPhashmapExists(conshdlrdata->varhash, var) )
612  {
613  assert((SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var) != NULL);
614  indvar = (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var);
615  assert(indvar != NULL);
616  }
617  else
618  {
619  /* if implied variable is binary, then it is also not necessary to create an indicator variable */
620  if( SCIPvarIsBinary(var) )
621  indvar = var;
622  else
623  {
624  char varname[SCIP_MAXSTRLEN];
625  SCIP_VAR* newvar;
626 
627  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ind_%s", SCIPvarGetName(var));
628  SCIP_CALL( SCIPcreateVar(scip, &newvar, varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, FALSE, FALSE,
629  NULL, NULL, NULL, NULL, NULL) );
630  SCIP_CALL( SCIPaddVar(scip, newvar) );
631  indvar = newvar;
632 
633  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
634  }
635  assert(indvar != NULL);
636 
637  /* insert implied variable to hash map */
638  SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varhash, var, (void*) indvar) );/*lint !e571*/
639  assert(indvar == (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, var));
640  assert(SCIPhashmapExists(conshdlrdata->varhash, var));
641  }
642  }
643 
644  /* are we in the transformed problem? */
645  transformed = SCIPconsIsTransformed(cons);
646 
647  /* always use transformed variables in transformed constraints */
648  if( transformed )
649  {
650  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
651  SCIP_CALL( SCIPgetTransformedVar(scip, indvar, &indvar) );
652  }
653  assert(var != NULL);
654  assert(indvar != NULL);
655  assert(transformed == SCIPvarIsTransformed(var));
656  assert(transformed == SCIPvarIsTransformed(indvar));
657 
658  /* ensure that the new information can be stored in the constraint data */
659  SCIP_CALL( consdataEnsurevarsSizeCardinality(scip, consdata, consdata->nvars + 1, FALSE) );
660 
661  /* handle the new variable */
662  SCIP_CALL( handleNewVariableCardinality(scip, cons, consdata, conshdlrdata, var, indvar, consdata->nvars, transformed,
663  &eventdata) );
664  assert(!transformed || eventdata != NULL);
665 
666  /* insert variable */
667  consdata->vars[consdata->nvars] = var;
668  consdata->indvars[consdata->nvars] = indvar;
669  consdata->eventdatas[consdata->nvars] = eventdata;
670 
671  if( consdata->weights != NULL && consdata->nvars > 0 )
672  consdata->weights[consdata->nvars] = consdata->weights[consdata->nvars-1] + 1.0;
673  ++consdata->nvars;
674 
675  assert(consdata->weights != NULL || consdata->nvars > 0);
676 
677  return SCIP_OKAY;
678 }
679 
680 /** deletes a variable from a cardinality constraint */
681 static
683  SCIP* scip, /**< SCIP data structure */
684  SCIP_CONS* cons, /**< constraint */
685  SCIP_CONSDATA* consdata, /**< constraint data */
686  SCIP_EVENTHDLR* eventhdlr, /**< corresponding event handler */
687  int pos /**< position of variable in array */
688  )
689 { /*lint --e{679}*/
690  int j;
691 
692  assert(0 <= pos && pos < consdata->nvars);
693 
694  /* remove lock of variable */
695  SCIP_CALL( unlockVariableCardinality(scip, cons, consdata->vars[pos], consdata->indvars[pos]) );
696 
697  /* drop events on indicator variable and implied variable */
698  SCIP_CALL( dropVarEventCardinality(scip, eventhdlr, consdata, consdata->vars[pos], consdata->indvars[pos],
699  &consdata->eventdatas[pos]) );
700 
701  /* update number of variables that may be treated as nonzero */
702  if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->indvars[pos]), 1.0) )
703  --(consdata->ntreatnonzeros);
704 
705  /* delete variable - need to copy since order is important */
706  for( j = pos; j < consdata->nvars-1; ++j )
707  {
708  consdata->vars[j] = consdata->vars[j+1];
709  consdata->indvars[j] = consdata->indvars[j+1];
710  consdata->eventdatas[j] = consdata->eventdatas[j+1];
711  if( consdata->weights != NULL )
712  consdata->weights[j] = consdata->weights[j+1];
713 
714  consdata->eventdatas[j]->pos = (unsigned int)j;
715  }
716  --consdata->nvars;
717 
718  return SCIP_OKAY;
719 }
720 
721 /** for each indicator variable sets solution to 1.0 if the solution value of the implied variable is nonzero */
722 static
724  SCIP* scip, /**< SCIP pointer */
725  SCIP_CONS** conss, /**< constraints */
726  int nconss, /**< number of constraints */
727  SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
728  SCIP_SOL* primsol /**< primal solution */
729  )
730 {
731  SCIP_CONSDATA* consdata;
732  SCIP_VAR** indvars;
733  SCIP_VAR** vars;
734  int nvars;
735  int c;
736 
737  /* check each constraint */
738  for( c = 0; c < nconss; ++c )
739  {
740  SCIP_CONS* cons;
741  int j;
742 
743  cons = conss[c];
744  assert(cons != NULL);
745  consdata = SCIPconsGetData(cons);
746  assert(consdata != NULL);
747 
748  nvars = consdata->nvars;
749  vars = consdata->vars;
750  indvars = consdata->indvars;
751 
752  for( j = 0; j < nvars; ++j )
753  {
754  if( SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[j])) )
755  {
756  SCIP_CALL( SCIPsetSolVal(scip, primsol, indvars[j], 0.0) );
757  }
758  else
759  {
760  SCIP_CALL( SCIPsetSolVal(scip, primsol, indvars[j], 1.0) );
761  }
762  }
763  }
764 
765  return SCIP_OKAY;
766 }
767 
768 /** unmark variables that are marked for propagation */
769 static
771  SCIP_CONSDATA* consdata /**< constraint data */
772  )
773 {
774  SCIP_EVENTDATA** eventdatas;
775  int nvars;
776  int j;
777 
778  eventdatas = consdata->eventdatas;
779  nvars = consdata->nvars;
780  assert(eventdatas != NULL);
781 
782  for( j = 0; j < nvars; ++j )
783  {
784  SCIP_EVENTDATA* eventdata;
785 
786  eventdata = eventdatas[j];
787  eventdata->varmarked = FALSE;
788  eventdata->indvarmarked = FALSE;
789  }
790 
791  return SCIP_OKAY;
792 }
793 
794 /** perform one presolving round
795  *
796  * We perform the following presolving steps:
797  *
798  * - If the bounds of some variable force it to be nonzero, we can
799  * fix all other variables to zero and remove the cardinality constraints
800  * that contain it.
801  * - If a variable is fixed to zero, we can remove the variable.
802  * - If a variable appears twice, it can be fixed to 0.
803  * - We substitute appregated variables.
804  */
805 static
807  SCIP* scip, /**< SCIP pointer */
808  SCIP_CONS* cons, /**< constraint */
809  SCIP_CONSDATA* consdata, /**< constraint data */
810  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
811  SCIP_Bool* cutoff, /**< whether a cutoff happened */
812  SCIP_Bool* success, /**< whether we performed a successful reduction */
813  int* ndelconss, /**< number of deleted constraints */
814  int* nupgdconss, /**< number of upgraded constraints */
815  int* nfixedvars, /**< number of fixed variables */
816  int* nremovedvars /**< number of variables removed */
817  )
818 {
819  SCIP_VAR** indvars;
820  SCIP_VAR** vars;
821  SCIP_Bool allvarsbinary;
822  SCIP_Bool infeasible;
823  SCIP_Bool fixed;
824  int j;
825 
826  assert(scip != NULL);
827  assert(cons != NULL);
828  assert(consdata != NULL);
829  assert(eventhdlr != NULL);
830  assert(cutoff != NULL);
831  assert(success != NULL);
832  assert(ndelconss != NULL);
833  assert(nfixedvars != NULL);
834  assert(nremovedvars != NULL);
835 
836  *cutoff = FALSE;
837  *success = FALSE;
838 
839  SCIPdebugMsg(scip, "Presolving cardinality constraint <%s>.\n", SCIPconsGetName(cons) );
840 
841  /* reset number of events stored for propagation, since presolving already performs a
842  * complete propagation of all variables */
843  consdata->neventdatascurrent = 0;
845 
846  j = 0;
847  allvarsbinary = TRUE;
848  vars = consdata->vars;
849  indvars = consdata->indvars;
850 
851  /* check for variables fixed to 0 and bounds that fix a variable to be nonzero */
852  while ( j < consdata->nvars )
853  {
854  int l;
855  SCIP_VAR* var;
856  SCIP_VAR* oldvar;
857  SCIP_VAR* indvar;
858  SCIP_Real lb;
859  SCIP_Real ub;
860  SCIP_Real indlb;
861  SCIP_Real indub;
862  SCIP_Real scalar;
863  SCIP_Real constant;
864 
865  scalar = 1.0;
866  constant = 0.0;
867 
868  /* check for aggregation: if the constant is zero the variable is zero iff the aggregated
869  * variable is 0 */
870  var = vars[j];
871  indvar = indvars[j];
872  oldvar = var;
873  SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
874 
875  /* if constant is zero and we get a different variable, substitute variable */
876  if( SCIPisZero(scip, constant) && !SCIPisZero(scip, scalar) && var != vars[j] )
877  {
878  SCIPdebugMsg(scip, "substituted variable <%s> by <%s>.\n", SCIPvarGetName(vars[j]), SCIPvarGetName(var));
879 
880  /* we reuse the same indicator variable for the new variable */
881  SCIP_CALL( dropVarEventCardinality(scip, eventhdlr, consdata, consdata->vars[j], consdata->indvars[j],
882  &consdata->eventdatas[j]) );
883  SCIP_CALL( catchVarEventCardinality(scip, eventhdlr, consdata, var, consdata->indvars[j], j,
884  &consdata->eventdatas[j]) );
885  assert(consdata->eventdatas[j] != NULL);
886 
887  /* change the rounding locks */
888  SCIP_CALL( unlockVariableCardinality(scip, cons, consdata->vars[j], consdata->indvars[j]) );
889  SCIP_CALL( lockVariableCardinality(scip, cons, var, consdata->indvars[j]) );
890 
891  /* update event data */
892  consdata->eventdatas[j]->var = var;
893 
894  vars[j] = var;
895  }
896  assert(var == vars[j]);
897 
898  /* check whether the variable appears again later */
899  for( l = j+1; l < consdata->nvars; ++l )
900  {
901  if( var == vars[l] || oldvar == vars[l] )
902  {
903  SCIPdebugMsg(scip, "variable <%s> appears twice in constraint <%s>.\n", SCIPvarGetName(vars[j]),
904  SCIPconsGetName(cons));
905  return SCIP_INVALIDDATA;
906  }
907  }
908 
909  /* get bounds of variable */
910  lb = SCIPvarGetLbLocal(var);
911  ub = SCIPvarGetUbLocal(var);
912 
913  /* if the variable is fixed to nonzero */
914  if( SCIPisFeasPositive(scip, lb) || SCIPisFeasNegative(scip, ub) )
915  {
916  assert(SCIPvarIsBinary(indvar));
917 
918  /* fix (binary) indicator variable to 1.0 (the cardinality constraint will then be modified below) */
919  SCIP_CALL( SCIPfixVar(scip, indvar, 1.0, &infeasible, &fixed) );
920  if( infeasible )
921  {
922  *cutoff = TRUE;
923  return SCIP_OKAY;
924  }
925 
926  if( fixed )
927  {
928  SCIPdebugMsg(scip, "fixed binary variable <%s> to 1.0.\n", SCIPvarGetName(indvar));
929  ++(*nfixedvars);
930  }
931  }
932 
933  /* if the variable is fixed to 0 */
934  if( SCIPisFeasZero(scip, lb) && SCIPisFeasZero(scip, ub) )
935  {
936  assert(SCIPvarIsBinary(indvar));
937 
938  /* fix (binary) indicator variable to 0.0, if possible (the cardinality constraint will then be modified below)
939  * note that an infeasibility implies no cut off */
940  SCIP_CALL( SCIPfixVar(scip, indvar, 0.0, &infeasible, &fixed) );
941  if( fixed )
942  {
943  SCIPdebugMsg(scip, "fixed binary variable <%s> to 0.0.\n", SCIPvarGetName(indvar));
944  ++(*nfixedvars);
945  }
946  }
947 
948  /* get bounds of indicator variable */
949  indlb = SCIPvarGetLbLocal(indvar);
950  indub = SCIPvarGetUbLocal(indvar);
951 
952  /* if the variable may be treated as nonzero */
953  if( SCIPisFeasEQ(scip, indlb, 1.0) )
954  {
955  assert(indub == 1.0);
956 
957  /* modify row and delete variable */
958  SCIP_CALL( deleteVarCardinality(scip, cons, consdata, eventhdlr, j) );
959  SCIPdebugMsg(scip, "deleting variable <%s> from constraint <%s>, since it may be treated as nonzero.\n",
960  SCIPvarGetName(var), SCIPconsGetName(cons));
961  --(consdata->cardval);
962  ++(*nremovedvars);
963  }
964  /* if the indicator variable is fixed to 0 */
965  else if( SCIPisFeasEQ(scip, indub, 0.0) )
966  {
967  assert(indlb == 0.0);
968 
969  /* fix variable to 0.0 */
970  SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
971  if( infeasible )
972  {
973  *cutoff = TRUE;
974  return SCIP_OKAY;
975  }
976  if( fixed )
977  {
978  SCIPdebugMsg(scip, "fixed variable <%s> to 0.0.\n", SCIPvarGetName(var));
979  ++(*nfixedvars);
980  }
981 
982  /* delete variable */
983  SCIP_CALL( deleteVarCardinality(scip, cons, consdata, eventhdlr, j) );
984  SCIPdebugMsg(scip, "deleting variable <%s> from constraint <%s>, since it is fixed to 0.\n", SCIPvarGetName(var),
985  SCIPconsGetName(cons));
986  ++(*nremovedvars);
987  }
988  else
989  {
990  /* check whether all variables are binary */
991  if( !SCIPvarIsBinary(var) )
992  allvarsbinary = FALSE;
993 
994  ++j;
995  }
996  }
997 
998  /* if the cardinality value is smaller than 0, then the problem is infeasible */
999  if( consdata->cardval < 0 )
1000  {
1001  SCIPdebugMsg(scip, "The problem is infeasible: more variables have bounds that keep them from being 0 than allowed.\n");
1002 
1003  *cutoff = TRUE;
1004  return SCIP_OKAY;
1005  }
1006  /* else if the cardinality value is 0 */
1007  else if( consdata->cardval == 0 )
1008  {
1009  /* fix all variables of the constraint to 0 */
1010  for( j = 0; j < consdata->nvars; ++j )
1011  {
1012  SCIP_CALL( SCIPfixVar(scip, consdata->vars[j], 0.0, &infeasible, &fixed) );
1013  if( infeasible )
1014  {
1015  *cutoff = TRUE;
1016  return SCIP_OKAY;
1017  }
1018  if( fixed )
1019  {
1020  SCIPdebugMsg(scip, "fixed variable <%s> to 0.0.\n", SCIPvarGetName(consdata->vars[j]));
1021  ++(*nfixedvars);
1022  }
1023  }
1024  }
1025 
1026  /* if the cardinality constraint is redundant */
1027  if( consdata->nvars <= consdata->cardval )
1028  {
1029  SCIPdebugMsg(scip, "Deleting cardinality constraint <%s> with <%d> variables and cardinality value <%d>.\n",
1030  SCIPconsGetName(cons), consdata->nvars, consdata->cardval);
1031 
1032  /* delete constraint */
1033  assert(!SCIPconsIsModifiable(cons));
1034  SCIP_CALL( SCIPdelCons(scip, cons) );
1035  ++(*ndelconss);
1036  *success = TRUE;
1037  return SCIP_OKAY;
1038  }
1039  else
1040  {
1041  /* if all variables are binary create a knapsack constraint */
1042  if( allvarsbinary )
1043  {
1044  SCIP_CONS* knapsackcons;
1045  SCIP_Longint* vals;
1046 
1047  SCIP_CALL( SCIPallocBufferArray(scip, &vals, consdata->nvars) );
1048  for( j = 0; j < consdata->nvars; ++j )
1049  vals[j] = 1;
1050 
1051  /* create, add, and release the knapsack constraint */
1052  SCIP_CALL( SCIPcreateConsKnapsack(scip, &knapsackcons, SCIPconsGetName(cons), consdata->nvars, consdata->vars,
1053  vals, (SCIP_Longint) consdata->cardval, SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons),
1056  SCIPconsIsStickingAtNode(cons)) );/*lint !e524*/
1057  SCIP_CALL( SCIPaddCons(scip, knapsackcons) );
1058  SCIP_CALL( SCIPreleaseCons(scip, &knapsackcons) );
1059 
1060  SCIPfreeBufferArray(scip, &vals);
1061 
1062  SCIPdebugMsg(scip, "Upgrading cardinality constraint <%s> to knapsack constraint.\n", SCIPconsGetName(cons));
1063 
1064  /* remove the cardinality constraint globally */
1065  assert(!SCIPconsIsModifiable(cons));
1066  SCIP_CALL( SCIPdelCons(scip, cons) );
1067  ++(*nupgdconss);
1068  *success = TRUE;
1069  }
1070  }
1071 
1072  return SCIP_OKAY;
1073 }
1074 
1075 /** propagates a cardinality constraint and its variables
1076  *
1077  * The number 'ntreatnonzeros' that is assigned to the constraint data returns the number of variables that are either
1078  * known to be nonzero or can be treated as nonzero. We say that a variable is known to be nonzero, if zero is outside
1079  * the domain of this variable. A variable can be treated as nonzero, if its corresponding indicator variable 'indvar' is
1080  * fixed to 1.0, e.g., by branching.
1081  *
1082  * We perform the following propagation steps:
1083  *
1084  * - if the number 'ntreatnonzeros' is greater than the cardinality value of the constraint, then the current subproblem
1085  * is marked as infeasible.
1086  * - if the cardinality constraint is saturated, i.e., the number 'ntreatnonzeros' is equal to the cardinality value of
1087  * the constraint, then fix all the other variables of the constraint to zero.
1088  * - remove the cardinality constraint locally if all variables are either fixed to zero or can be treated as nonzero.
1089  * - if a (binary) indicator variable is fixed to zero, then fix the corresponding implied variable to zero.
1090  * - if zero is outside of the domain of an implied variable, then fix the corresponding indicator variable to one.
1091  */
1092 static
1094  SCIP* scip, /**< SCIP pointer */
1095  SCIP_CONS* cons, /**< constraint */
1096  SCIP_CONSDATA* consdata, /**< constraint data */
1097  SCIP_Bool* cutoff, /**< whether a cutoff happened */
1098  int* nchgdomain /**< number of domain changes */
1099  )
1100 {
1101  assert(scip != NULL);
1102  assert(cons != NULL);
1103  assert(consdata != NULL);
1104  assert(cutoff != NULL);
1105  assert(nchgdomain != NULL);
1106 
1107  *cutoff = FALSE;
1108 
1109  /* if more variables may be treated as nonzero than allowed */
1110  if( consdata->ntreatnonzeros > consdata->cardval )
1111  {
1112  SCIPdebugMsg(scip, "the node is infeasible, more than %d variables are fixed to be nonzero.\n", consdata->cardval);
1113  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1114  *cutoff = TRUE;
1115 
1116  return SCIP_OKAY;
1117  }
1118 
1119  /* if number of nonzeros is saturated */
1120  if( consdata->ntreatnonzeros == consdata->cardval )
1121  {
1122  SCIP_VAR** vars;
1123  SCIP_VAR** indvars;
1124  SCIP_Bool infeasible;
1125  SCIP_Bool tightened;
1126  SCIP_Bool allvarfixed;
1127  int nvars;
1128  int cnt = 0;
1129  int j;
1130 
1131  nvars = consdata->nvars;
1132  vars = consdata->vars;
1133  indvars = consdata->indvars;
1134  assert(vars != NULL);
1135  assert(indvars != NULL);
1136 
1137  /* fix free variables to zero */
1138  allvarfixed = TRUE;
1139  for( j = 0; j < nvars; ++j )
1140  {
1141  /* if variable is implied to be treated as nonzero */
1142  if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(indvars[j]), 1.0) )
1143  ++cnt;
1144  /* else fix variable to zero if not done already */
1145  else
1146  {
1147  SCIP_VAR* var;
1148 
1149  var = vars[j];
1150 
1151  /* fix variable */
1153  {
1154  SCIP_CALL( fixVariableZero(scip, var, &infeasible, &tightened) );
1155  if( infeasible )
1156  {
1157  SCIPdebugMsg(scip, "the node is infeasible, more than %d variables are fixed to be nonzero.\n",
1158  consdata->cardval);
1159  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1160  *cutoff = TRUE;
1161 
1162  return SCIP_OKAY;
1163  }
1164 
1165  if( tightened )
1166  {
1167  SCIPdebugMsg(scip, "fixed variable <%s> to 0, since constraint <%s> with cardinality value %d is \
1168  saturated.\n", SCIPvarGetName(var), SCIPconsGetName(cons), consdata->cardval);
1169  ++(*nchgdomain);
1170  }
1171  else
1172  allvarfixed = FALSE;
1173  }
1174  }
1175  }
1176  assert(cnt == consdata->ntreatnonzeros);
1177 
1178  /* reset constraint age counter */
1179  if( *nchgdomain > 0 )
1180  {
1181  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1182  }
1183 
1184  /* delete constraint locally */
1185  if( allvarfixed )
1186  {
1187  assert(!SCIPconsIsModifiable(cons));
1188  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1189 
1190  return SCIP_OKAY;
1191  }
1192  }
1193 
1194  /* if relevant bound change events happened */
1195  if( consdata->neventdatascurrent > 0 )
1196  {
1197  SCIP_EVENTDATA** eventdatas;
1198  SCIP_VAR** eventvars;
1199  int neventdatas;
1200  int j;
1201 
1202  neventdatas = consdata->neventdatascurrent;
1203  eventvars = consdata->eventvarscurrent;
1204  eventdatas = consdata->eventdatascurrent;
1205  assert(eventdatas != NULL && eventvars != NULL);
1206 
1207  for( j = 0; j < neventdatas; ++j )
1208  {
1209  SCIP_EVENTDATA* eventdata;
1210  SCIP_Bool infeasible;
1211  SCIP_Bool tightened;
1212  SCIP_VAR* var;
1213 
1214  eventdata = eventdatas[j];
1215  var = eventvars[j];
1216  assert(var != NULL && eventdata != NULL);
1217  assert(eventdata->var != NULL);
1218  assert(eventdata->indvar != NULL);
1219  assert(var == eventdata->var || var == eventdata->indvar);
1220  assert(SCIPvarIsBinary(eventdata->indvar));
1221 
1222  /* if variable is an indicator variable */
1223  if( eventdata->indvar == var )
1224  {
1225  assert(eventdata->indvarmarked);
1226 
1227  /* if variable is fixed to zero */
1228  if( SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
1229  {
1230  SCIP_VAR* implvar;
1231 
1232  implvar = eventdata->var;
1233 
1234  /* fix implied variable to zero if not done already */
1235  if( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(implvar)) ||
1236  SCIPisFeasPositive(scip, SCIPvarGetUbLocal(implvar)) )
1237  {
1238  SCIP_CALL( fixVariableZero(scip, implvar, &infeasible, &tightened) );
1239 
1240  if( infeasible )
1241  {
1242  SCIPdebugMsg(scip, "the node is infeasible, indicator variable %s is fixed to zero although implied "
1243  "variable %s is nonzero.\n", SCIPvarGetName(var), SCIPvarGetName(implvar));
1244  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1245  *cutoff = TRUE;
1246 
1247  return SCIP_OKAY;
1248  }
1249 
1250  if( tightened )
1251  {
1252  SCIPdebugMsg(scip, "fixed variable <%s> to 0, since indicator variable %s is 0.\n",
1253  SCIPvarGetName(implvar), SCIPvarGetName(var));
1254  ++(*nchgdomain);
1255  }
1256  }
1257  }
1258  eventdata->indvarmarked = FALSE;
1259  }
1260  /* else if variable is an implied variable */
1261  else
1262  {
1263  assert(eventdata->var == var);
1264  assert(eventdata->varmarked);
1265 
1266  /* if variable is is nonzero */
1268  {
1269  SCIP_VAR* indvar;
1270 
1271  indvar = eventdata->indvar;
1272  assert(SCIPvarIsBinary(indvar));
1273 
1274  /* fix indicator variable to 1.0 if not done already */
1275  if( !SCIPisFeasEQ(scip, SCIPvarGetLbLocal(indvar), 1.0) )
1276  {
1277  /* if fixing is infeasible */
1278  if( SCIPvarGetUbLocal(indvar) != 1.0 )
1279  {
1280  SCIPdebugMsg(scip, "the node is infeasible, implied variable %s is fixed to nonzero "
1281  "although indicator variable %s is 0.\n", SCIPvarGetName(var), SCIPvarGetName(indvar));
1282  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1283  *cutoff = TRUE;
1284 
1285  return SCIP_OKAY;
1286  }
1287  SCIP_CALL( SCIPchgVarLb(scip, indvar, 1.0) );
1288  SCIPdebugMsg(scip, "fixed variable <%s> to 1.0, since implied variable %s is nonzero.\n",
1289  SCIPvarGetName(indvar), SCIPvarGetName(var));
1290  ++(*nchgdomain);
1291  }
1292  }
1293  eventdata->varmarked = FALSE;
1294  }
1295  }
1296  }
1297  consdata->neventdatascurrent = 0;
1298 
1299  return SCIP_OKAY;
1300 }
1301 
1302 /** apply unbalanced branching (see the function \ref enforceCardinality() for further information) */
1303 static
1305  SCIP* scip, /**< SCIP pointer */
1306  SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
1307  SCIP_CONS* branchcons, /**< cardinality constraint */
1308  SCIP_VAR** vars, /**< variables of constraint */
1309  SCIP_VAR** indvars, /**< indicator variables */
1310  int nvars, /**< number of variables of constraint */
1311  int cardval, /**< cardinality value of constraint */
1312  int branchnnonzero, /**< number of variables that are fixed to be nonzero */
1313  int branchpos /**< position in array 'vars' */
1314  )
1315 {
1316  SCIP_Bool infeasible;
1317  SCIP_NODE* node1;
1318  SCIP_NODE* node2;
1319 
1320  /* check whether the variable selected for branching has a nonzero LP solution */
1321  assert(!SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[branchpos])));
1322  assert(SCIPisFeasZero(scip, SCIPvarGetLbLocal(indvars[branchpos])));
1323  assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(indvars[branchpos]), 1.0));
1324 
1325  /* create branches */
1326  SCIPdebugMsg(scip, "apply unbalanced branching on variable <%s> of constraint <%s>.\n",
1327  SCIPvarGetName(indvars[branchpos]), SCIPconsGetName(branchcons));
1328 
1329  /* create node 1 */
1330 
1331  /* calculate node selection and objective estimate for node 1 */
1332  SCIP_CALL( SCIPcreateChild(scip, &node1, SCIPcalcNodeselPriority(scip, vars[branchpos], SCIP_BRANCHDIR_DOWNWARDS, 0.0),
1333  SCIPcalcChildEstimate(scip, vars[branchpos], 0.0) ) );
1334 
1335  /* fix branching variable to zero */
1336  SCIP_CALL( fixVariableZeroNode(scip, vars[branchpos], node1, &infeasible) );
1337  assert(! infeasible);
1338 
1339  /* create node 2 */
1340 
1341  /* if the new number of nonzero variables is equal to the number of allowed nonzero variables;
1342  * i.e. cardinality constraint is saturated */
1343  assert(branchnnonzero + 1 <= cardval);
1344  if( branchnnonzero + 1 == cardval )
1345  {
1346  SCIP_Real nodeselest;
1347  SCIP_Real objest;
1348  int cnt;
1349  int j;
1350 
1351  /* calculate node selection and objective estimate for node 2 */
1352  nodeselest = 0.0;
1353  objest = 0.0;
1354  cnt = 0;
1355  for( j = 0; j < nvars; ++j )
1356  {
1357  /* we only consider variables in constraint that are not the branching variable and are not fixed to nonzero */
1358  if( j != branchpos && SCIPvarGetLbLocal(indvars[j]) != 1.0 && !SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j]))
1359  && !SCIPisFeasNegative(scip, SCIPvarGetUbLocal(vars[j]))
1360  )
1361  {
1362  nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
1363  objest += SCIPcalcChildEstimate(scip, vars[j], 0.0);
1364  ++cnt;
1365  }
1366  }
1367  assert(cnt == nvars - (1 + branchnnonzero));
1368  assert(cnt > 0);
1369 
1370  /* take the average of the individual estimates */
1371  objest = objest / (SCIP_Real) cnt;
1372 
1373  /* create node 2 */
1374  SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
1375 
1376  /* indicate that branching variable may be treated as nonzero */
1377  SCIP_CALL( SCIPchgVarLbNode(scip, node2, indvars[branchpos], 1.0) );
1378 
1379  /* fix variables to zero since cardinality constraint is now saturated */
1380  for( j = 0; j < nvars; ++j )
1381  {
1382  /* we only consider variables in constraint that are not the branching variable and are not fixed to nonzero */
1383  if( j != branchpos && SCIPvarGetLbLocal(indvars[j]) != 1.0
1384  && !SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j]))
1385  && !SCIPisFeasNegative(scip, SCIPvarGetUbLocal(vars[j]))
1386  )
1387  {
1388  SCIP_CALL( fixVariableZeroNode(scip, vars[j], node2, &infeasible) );
1389  assert(!infeasible);
1390  }
1391  }
1392  }
1393  else
1394  {
1395  /* calculate node selection estimate for node 2 */
1396  SCIP_CALL( SCIPcreateChild(scip, &node2, 0.0, SCIPgetLocalTransEstimate(scip)) );
1397 
1398  /* indicate that branching variable may be treated as nonzero */
1399  SCIP_CALL( SCIPchgVarLbNode(scip, node2, indvars[branchpos], 1.0) );
1400  }
1401 
1402  return SCIP_OKAY;
1403 }
1404 
1405 /** apply balanced branching (see the function enforceCardinality() for further information) */
1406 static
1408  SCIP* scip, /**< SCIP pointer */
1409  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1410  SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
1411  SCIP_CONS* branchcons, /**< cardinality constraint */
1412  SCIP_VAR** vars, /**< variables of constraint */
1413  SCIP_VAR** indvars, /**< indicator variables */
1414  int nvars, /**< number of variables of constraint */
1415  int cardval, /**< cardinality value of constraint */
1416  int branchnnonzero, /**< number of variables that are fixed to be nonzero */
1417  int branchpos, /**< position in array 'vars' */
1418  SCIP_Real balancedcutoff /**< cut off value for deciding whether to apply balanced branching */
1419  )
1420 {
1421  SCIP_VAR** branchvars;
1422  SCIP_VAR** branchindvars;
1423  int nbranchvars;
1424  SCIP_Real splitval1;
1425  SCIP_Real splitval2;
1426  SCIP_Real weight1;
1427  SCIP_Real weight2;
1428  SCIP_Real sum1;
1429  SCIP_Real sum2;
1430  SCIP_Real w;
1431  int newcardval;
1432  int nnonzero;
1433  int nzero;
1434  int nbuffer;
1435  int ind;
1436  int cnt;
1437  int j;
1438 
1439  /* check parameters */
1440  if( SCIPconshdlrGetSepaFreq(conshdlr) != 1 )
1441  {
1442  SCIPerrorMessage("balanced branching is only possible if separation frequency of constraint handler is 1.\n");
1443  return SCIP_PARAMETERWRONGVAL;
1444  }
1445 
1446  cnt = 0;
1447  nzero = 0;
1448  nnonzero = 0;
1449  nbranchvars = 0;
1450 
1451  weight1 = 0.0;
1452  weight2 = 0.0;
1453  sum1 = 0.0;
1454  sum2 = 0.0;
1455 
1456  /* allocate buffer arrays */
1457  nbuffer = nvars-branchnnonzero;
1458  SCIP_CALL( SCIPallocBufferArray(scip, &branchvars, nbuffer) );
1459  SCIP_CALL( SCIPallocBufferArray(scip, &branchindvars, nbuffer) );
1460 
1461  /* compute weight */
1462  for( j = 0; j < nvars; ++j )
1463  {
1464  SCIP_VAR* var;
1465 
1466  var = vars[j];
1467 
1468  /* if(binary) indicator variable is not fixed to 1.0 */
1469  if( SCIPvarGetLbLocal(indvars[j]) != 1.0 && !SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var))
1470  && !SCIPisFeasNegative(scip, SCIPvarGetUbLocal(var)) )
1471  {
1472  /* if implied variable is not already fixed to zero */
1473  if( !SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || !SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
1474  {
1475  SCIP_Real val = REALABS(SCIPgetSolVal(scip, sol, var));
1476 
1477  weight1 += val * (SCIP_Real) (j - (nnonzero + nzero));
1478  weight2 += val;
1479  branchindvars[nbranchvars] = indvars[j];
1480  branchvars[nbranchvars++] = var;
1481 
1482  if( !SCIPisFeasZero(scip, val) )
1483  ++cnt;
1484  }
1485  else
1486  ++nzero;
1487  }
1488  else
1489  ++nnonzero;
1490  }
1491  assert(nnonzero == branchnnonzero);
1492  assert(nbranchvars <= nvars - branchnnonzero);
1493 
1494  assert(cnt >= cardval-nnonzero);
1495  assert(!SCIPisFeasZero(scip, weight2));
1496  w = weight1/weight2; /*lint !e414*/
1497 
1498  ind = (int)SCIPfloor(scip, w);
1499  assert(0 <= ind && ind < nbranchvars-1);
1500 
1501  /* compute LP sums */
1502  for( j = 0; j <= ind; ++j )
1503  {
1504  SCIP_Real val;
1505 
1506  val = SCIPgetSolVal(scip, sol, branchvars[j]);
1507 
1508  if( SCIPisFeasPositive(scip, val) )
1509  {
1510  assert(SCIPisFeasPositive(scip, SCIPvarGetUbLocal(branchvars[j])));
1511  sum1 += val / SCIPvarGetUbLocal(branchvars[j]);
1512  }
1513  else if( SCIPisFeasNegative(scip, val) )
1514  {
1515  assert(SCIPisFeasNegative(scip, SCIPvarGetLbLocal(branchvars[j])));
1516  sum1 += val / SCIPvarGetLbLocal(branchvars[j]);
1517  }
1518  }
1519  for( j = ind+1; j < nbranchvars; ++j )
1520  {
1521  SCIP_Real val;
1522 
1523  val = SCIPgetSolVal(scip, sol, branchvars[j]);
1524 
1525  if( SCIPisFeasPositive(scip, val) )
1526  {
1527  assert(SCIPisFeasPositive(scip, SCIPvarGetUbLocal(branchvars[j])));
1528  sum2 += val/SCIPvarGetUbLocal(branchvars[j]);
1529  }
1530  else if( SCIPisFeasNegative(scip, val) )
1531  {
1532  assert(SCIPisFeasNegative(scip, SCIPvarGetLbLocal(branchvars[j])));
1533  sum2 += val/SCIPvarGetLbLocal(branchvars[j]);
1534  }
1535  }
1536 
1537  /* compute cardinality values of branching constraints */
1538  newcardval = cardval - nnonzero;
1539  splitval1 = sum1 + (SCIP_Real)newcardval - sum2 - 1.0;/*lint !e834*/
1540  splitval1 = SCIPfloor(scip, splitval1/2);
1541  splitval1 = MAX(splitval1, 0);
1542  assert((int)splitval1 >= 0);
1543  assert((int)splitval1 <= MIN(newcardval-1, ind));
1544  splitval2 = (SCIP_Real)(newcardval-1);
1545  splitval2 -= splitval1;
1546 
1547  /* the lower or upper LP row of each branching constraint should cut off the current LP solution
1548  * if this is not the case, then use unbalanced branching */
1549  if ( !SCIPisFeasLT(scip, (SCIP_Real) splitval1 + balancedcutoff, sum1) ||
1550  !SCIPisFeasLT(scip, (SCIP_Real) splitval2 + balancedcutoff, sum2) )
1551  {
1552  SCIP_CALL( branchUnbalancedCardinality(scip, sol, branchcons, vars, indvars, nvars, cardval,
1553  branchnnonzero, branchpos) );
1554  }
1555  else
1556  {
1557  char name[SCIP_MAXSTRLEN];
1558  SCIP_NODE* node1;
1559  SCIP_NODE* node2;
1560  SCIP_CONS* cons1;
1561  SCIP_CONS* cons2;
1562 
1563  SCIPdebugMsg(scip, "apply balanced branching on constraint <%s>.\n", SCIPconsGetName(branchcons));
1564 
1565  if( SCIPisFeasZero(scip, splitval1) )
1566  {
1567  SCIP_Bool infeasible;
1568  SCIP_Real nodeselest;
1569  SCIP_Real objest;
1570 
1571  nodeselest = 0.0;
1572  objest = 0.0;
1573 
1574  /* calculate node selection and objective estimate for node */
1575  for( j = 0; j <= ind; ++j )
1576  {
1577  nodeselest += SCIPcalcNodeselPriority(scip, branchvars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
1578  objest += SCIPcalcChildEstimate(scip, branchvars[j], 0.0);
1579  }
1580 
1581  /* take the average of the individual estimates */
1582  objest = objest/(SCIP_Real)(ind + 1.0);
1583 
1584  /* create node 1 */
1585  SCIP_CALL( SCIPcreateChild(scip, &node1, nodeselest, objest) );
1586 
1587  for( j = 0; j <= ind; ++j )
1588  {
1589  SCIP_CALL( fixVariableZeroNode(scip, branchvars[j], node1, &infeasible) );
1590  assert(!infeasible);
1591  }
1592  }
1593  else
1594  {
1595  /* calculate node selection and objective estimate for node */
1596  SCIP_CALL( SCIPcreateChild(scip, &node1, 0.0, SCIPgetLocalTransEstimate(scip)) );
1597 
1598  /* create branching constraint for node 1 */
1599  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "brleft_#%d", SCIPgetNNodes(scip));
1600  SCIP_CALL( SCIPcreateConsCardinality(scip, &cons1, name, ind+1, branchvars, (int)splitval1, branchindvars, NULL,
1601  FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE) );
1602 
1603  /* add constraint to node */
1604  SCIP_CALL( SCIPaddConsNode(scip, node1, cons1, NULL) );
1605 
1606  /* release constraint */
1607  SCIP_CALL( SCIPreleaseCons(scip, &cons1) );
1608  }
1609 
1610  if( SCIPisFeasZero(scip, splitval2) )
1611  {
1612  SCIP_Bool infeasible;
1613  SCIP_Real nodeselest;
1614  SCIP_Real objest;
1615 
1616  nodeselest = 0.0;
1617  objest = 0.0;
1618 
1619  /* calculate node selection and objective estimate for node */
1620  for( j = ind+1; j < nbranchvars; ++j )
1621  {
1622  nodeselest += SCIPcalcNodeselPriority(scip, branchvars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
1623  objest += SCIPcalcChildEstimate(scip, branchvars[j], 0.0);
1624  }
1625  assert(nbranchvars - (ind + 1) > 0);
1626 
1627  /* take the average of the individual estimates */
1628  objest = objest/((SCIP_Real)(nbranchvars - (ind + 1)));/*lint !e414*/
1629 
1630  /* create node 1 */
1631  SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
1632 
1633  for( j = ind+1; j < nbranchvars; ++j )
1634  {
1635  SCIP_CALL( fixVariableZeroNode(scip, branchvars[j], node2, &infeasible) );
1636  assert(!infeasible);
1637  }
1638  }
1639  else
1640  {
1641  /* calculate node selection and objective estimate for node */
1642  SCIP_CALL( SCIPcreateChild(scip, &node2, 0.0, SCIPgetLocalTransEstimate(scip)) );
1643 
1644  /* shift the second half of variables */
1645  cnt = 0;
1646  for( j = ind+1; j < nbranchvars; ++j )
1647  {
1648  branchvars[cnt] = branchvars[j];
1649  branchindvars[cnt++] = branchindvars[j];
1650  }
1651  assert(cnt == nbranchvars - (ind + 1));
1652 
1653  /* create branching constraint for node 2 */
1654  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "brright_#%d", SCIPgetNNodes(scip));
1655  SCIP_CALL( SCIPcreateConsCardinality(scip, &cons2, name, cnt, branchvars, (int)splitval2, branchindvars, NULL,
1656  FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE) );
1657 
1658  /* add constraint to node */
1659  SCIP_CALL( SCIPaddConsNode(scip, node2, cons2, NULL) );
1660 
1661  /* release constraint */
1662  SCIP_CALL( SCIPreleaseCons(scip, &cons2) );
1663  }
1664  }
1665 
1666  /* free buffer arrays */
1667  SCIPfreeBufferArray(scip, &branchindvars);
1668  SCIPfreeBufferArray(scip, &branchvars);
1669 
1670  return SCIP_OKAY;
1671 }
1672 
1673 /** enforcement method
1674  *
1675  * We check whether the current solution is feasible. If not, the cardinality constraints can be enforced by different
1676  * branching rules:
1677  *
1678  * - Unbalanced branching: Branch on the neighborhood of a single variable \f$i\f$, i.e., in one branch \f$x_i\f$ is
1679  * fixed to zero and in the other we modify cardinality constraints \f$|\mbox{supp}(x)| \leq k\f$ with \f$i\in D\f$ to
1680  * \f$|\mbox{supp}(x_{D\setminus i}) \leq k-1\f$
1681  *
1682  * - Balanced branching: First, choose a cardinality constraint \f$|\mbox{supp}(x_D) \leq k\f$ that is violated by the
1683  * current LP solution. Then, we compute \f$W = \sum_{j=1}^n |x_i|\f$ and \f$w = \sum_{j=1}^n j\, |x_i|\f$. Next,
1684  * search for the index \f$r\f$ that satisfies
1685  * \f[
1686  * r \leq \frac{w}{W} < r+1.
1687  * \f]
1688  * Choose a number \f$s\f$ with \f$0\leq s < \min\{k, r\}\f$. The branches are then
1689  * \f[
1690  * |\mbox{supp}(x_{d_1}, \ldots, x_{d_r})| \leq s \qquad \mbox{and}\qquad
1691  * |\mbox{supp}(x_{d_{r+1}}, \ldots, x_{d_{n}})| \leq k-s-1,
1692  * \f]
1693  * where \f$d_1, \ldots, d_n\f$ are the elements of the set \f$D\f$.
1694  *
1695  * The branching constraint is chosen by the largest sum of variable values.
1696  */
1697 static
1699  SCIP* scip, /**< SCIP pointer */
1700  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1701  SCIP_SOL* sol, /**< solution to be enforced (or NULL) */
1702  int nconss, /**< number of constraints */
1703  SCIP_CONS** conss, /**< indicator constraints */
1704  SCIP_RESULT* result /**< result */
1705  )
1706 {
1707  SCIP_CONSHDLRDATA* conshdlrdata;
1708  SCIP_CONSDATA* consdata;
1709  SCIP_CONS* branchcons;
1710  SCIP_Real maxweight;
1711  SCIP_VAR** indvars;
1712  SCIP_VAR** vars;
1713  int nvars;
1714  int cardval;
1715 
1716  SCIP_Bool branchbalanced = FALSE;
1717  SCIP_Bool branchallpos = TRUE;
1718  SCIP_Bool branchallneg = TRUE;
1719  int branchnnonzero;
1720  int branchpos;
1721  int c;
1722 
1723  assert(scip != NULL);
1724  assert(conshdlr != NULL);
1725  assert(conss != NULL);
1726  assert(result != NULL);
1727 
1728  maxweight = -SCIP_REAL_MAX;
1729  branchcons = NULL;
1730  branchnnonzero = -1;
1731  branchpos = -1;
1732 
1733  SCIPdebugMsg(scip, "Enforcing cardinality constraints <%s>.\n", SCIPconshdlrGetName(conshdlr) );
1734  *result = SCIP_FEASIBLE;
1735 
1736  /* get constraint handler data */
1737  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1738  assert(conshdlrdata != NULL);
1739 
1740  /* search for a constraint with largest violation; from this constraint, we select the variable with largest LP value */
1741  for( c = 0; c < nconss; ++c )
1742  {
1743  SCIP_CONS* cons;
1744  SCIP_Bool cutoff;
1745  SCIP_Real weight;
1746  SCIP_Real maxval;
1747  SCIP_Bool allpos = TRUE;
1748  SCIP_Bool allneg = TRUE;
1749  int nnonzero; /* number of variables that are currently deactivated in constraint */
1750  int pos; /* position of variable with largest LP solution value */
1751  int nchgdomain;
1752  int cnt;
1753  int j;
1754 
1755  cons = conss[c];
1756  assert(cons != NULL);
1757  consdata = SCIPconsGetData(cons);
1758  assert(consdata != NULL);
1759 
1760  nchgdomain = 0;
1761  cnt = 0;
1762  nnonzero = 0;
1763  pos = -1;
1764  nvars = consdata->nvars;
1765  vars = consdata->vars;
1766  indvars = consdata->indvars;
1767  cardval = consdata->cardval;
1768 
1769  /* do nothing if there are not enough variables - this is usually eliminated by preprocessing */
1770  if( nvars < 2 )
1771  continue;
1772 
1773  /* first perform propagation (it might happen that standard propagation is turned off) */
1774  SCIP_CALL( propCardinality(scip, cons, consdata, &cutoff, &nchgdomain) );
1775 
1776  SCIPdebugMsg(scip, "propagating <%s> in enforcing (cutoff: %u, domain reductions: %d).\n",
1777  SCIPconsGetName(cons), cutoff, nchgdomain);
1778  if( cutoff )
1779  {
1780  *result = SCIP_CUTOFF;
1781  return SCIP_OKAY;
1782  }
1783  if( nchgdomain > 0 )
1784  {
1785  *result = SCIP_REDUCEDDOM;
1786  return SCIP_OKAY;
1787  }
1788  assert(nchgdomain == 0);
1789 
1790  /* check constraint */
1791  weight = 0.0;
1792  maxval = -SCIPinfinity(scip);
1793 
1794  for( j = 0; j < nvars; ++j )
1795  {
1796  SCIP_VAR* var;
1797 
1798  /* check whether indicator variable is zero, but variable in cardinality constraint is not fixed to zero;
1799  * if the variable is not multiaggregated this case should already be handled in propagation */
1800  if( SCIPvarGetUbLocal(indvars[j]) == 0.0 &&
1801  (
1802  !SCIPisFeasZero(scip, SCIPvarGetLbLocal(vars[j])) || !SCIPisFeasZero(scip, SCIPvarGetUbLocal(vars[j]))
1803  )
1804  )
1805  {
1806  *result = SCIP_CUTOFF;
1807  return SCIP_OKAY;
1808  }
1809 
1810  assert(SCIPvarGetStatus(indvars[j]) != SCIP_VARSTATUS_MULTAGGR);
1811 
1812  var = vars[j];
1813 
1814  /* variable is not fixed to nonzero */
1815  if( SCIPvarGetLbLocal(indvars[j]) != 1.0
1816  && !SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var))
1817  && !SCIPisFeasNegative(scip, SCIPvarGetUbLocal(var))
1818  )
1819  {
1820  SCIP_Real val;
1821 
1822  val = SCIPgetSolVal(scip, sol, var);
1823  if( SCIPisFeasPositive(scip, val))
1824  allneg = FALSE;
1825  else if( SCIPisFeasNegative(scip, val))
1826  allpos = FALSE;
1827  val = REALABS(val);
1828 
1829  if( !SCIPisFeasZero(scip, val) )
1830  {
1831  /* determine maximum nonzero-variable solution value */
1832  if( SCIPisFeasGT(scip, val, maxval) )
1833  {
1834  pos = j;
1835  maxval = val;
1836  }
1837 
1838  weight += val;
1839  ++cnt;
1840  }
1841  }
1842  else
1843  ++nnonzero;
1844  }
1845  weight -= cardval;
1846  weight += nnonzero;
1847 
1848  /* if we detected a cut off */
1849  if( nnonzero > cardval )
1850  {
1851  SCIPdebugMsg(scip, "Detected cut off: constraint <%s> has %d many variables that can be treated as nonzero, \
1852  although only %d many are feasible.\n", SCIPconsGetName(cons), nnonzero, cardval);
1853  *result = SCIP_CUTOFF;
1854  return SCIP_OKAY;
1855  }
1856  /* else if domain can be reduced (since node 2 created in branchUnbalancedCardinality() would be infeasible) */
1857  else if( cnt > 0 && nnonzero + 1 > cardval )
1858  {
1859  SCIP_Bool infeasible;
1860  int v;
1861 
1862  for( v = 0; v < nvars; ++v )
1863  {
1864  SCIP_VAR* var;
1865 
1866  var = vars[v];
1867 
1868  /* variable is not fixed to nonzero */
1869  if( !SCIPisFeasEQ(scip, SCIPvarGetLbLocal(indvars[v]), 1.0)
1870  && !SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var))
1871  && !SCIPisFeasNegative(scip, SCIPvarGetUbLocal(var))
1872  )
1873  {
1874  SCIP_CALL( fixVariableZeroNode(scip, var, SCIPgetCurrentNode(scip), &infeasible) );
1875  assert(!infeasible);
1876  SCIPdebugMsg(scip, "detected domain reduction in enforcing: fixed variable <%s> to zero.\n", SCIPvarGetName(var));
1877  }
1878  }
1879 
1880  *result = SCIP_REDUCEDDOM;
1881  return SCIP_OKAY;
1882  }
1883 
1884  /* if constraint is violated */
1885  if( cnt > cardval - nnonzero && weight > maxweight )
1886  {
1887  maxweight = weight;
1888  branchcons = cons;
1889  branchnnonzero = nnonzero;
1890  branchpos = pos;
1891  branchallneg = allneg;
1892  branchallpos = allpos;
1893  }
1894  }
1895 
1896  /* if all constraints are feasible */
1897  if( branchcons == NULL )
1898  {
1899  SCIP_SOL* primsol;
1900  SCIP_Bool success;
1901 
1902  /* polish primal solution */
1903  SCIP_CALL( SCIPcreateSolCopy(scip, &primsol, sol) );
1904  SCIP_CALL( polishPrimalSolution(scip, conss, nconss, sol, primsol) );
1905  SCIP_CALL( SCIPtrySol(scip, primsol, FALSE, TRUE, FALSE, TRUE, FALSE, &success) );
1906  SCIP_CALL( SCIPfreeSol(scip, &primsol) );
1907 
1908  SCIPdebugMsg(scip, "All cardinality constraints are feasible.\n");
1909  return SCIP_OKAY;
1910  }
1911  assert(branchnnonzero >= 0);
1912  assert(branchpos >= 0);
1913 
1914  /* get data for branching or domain reduction */
1915  consdata = SCIPconsGetData(branchcons);
1916  assert(consdata != NULL);
1917  nvars = consdata->nvars;
1918  vars = consdata->vars;
1919  indvars = consdata->indvars;
1920  cardval = consdata->cardval;
1921 
1922  /* we only use balanced branching if either the lower or the upper bound row of the branching constraint is known
1923  * to be tight or violated */
1924  if( conshdlrdata->branchbalanced && !SCIPisFeasNegative(scip, maxweight) && ( branchallneg || branchallpos )
1925  && (conshdlrdata->balanceddepth == -1 || SCIPgetDepth(scip) <= conshdlrdata->balanceddepth)
1926  )
1927  {
1928  branchbalanced = TRUE;
1929  }
1930 
1931  /* apply branching rule */
1932  if( branchbalanced )
1933  {
1934  SCIP_CALL( branchBalancedCardinality(scip, conshdlr, sol, branchcons, vars, indvars, nvars, cardval, branchnnonzero, branchpos,
1935  conshdlrdata->balancedcutoff) );
1936  }
1937  else
1938  {
1939  SCIP_CALL( branchUnbalancedCardinality(scip, sol, branchcons, vars, indvars, nvars, cardval, branchnnonzero,
1940  branchpos) );
1941  }
1942 
1943  SCIP_CALL( SCIPresetConsAge(scip, branchcons) );
1944  *result = SCIP_BRANCHED;
1945 
1946  return SCIP_OKAY;
1947 }
1948 
1949 /** Generate row
1950  *
1951  * We generate the row corresponding to the following simple valid inequalities:
1952  * \f[
1953  * \frac{x_1}{u_1} + \ldots + \frac{x_n}{u_n} \leq k\qquad\mbox{and}\qquad
1954  * \frac{x_1}{\ell_1} + \ldots + \frac{x_n}{\ell_1} \leq k,
1955  * \f]
1956  * where \f$\ell_1, \ldots, \ell_n\f$ and \f$u_1, \ldots, u_n\f$ are the nonzero and finite lower and upper bounds of
1957  * the variables \f$x_1, \ldots, x_n\f$ and k is the right hand side of the cardinality constraint. If at least k upper
1958  * bounds < 0 or a lower bounds > 0, the constraint itself is redundant, so the cut is not applied (lower bounds > 0
1959  * and upper bounds < 0 are usually detected in presolving or propagation). Infinite bounds and zero are skipped. Thus
1960  * \f$\ell_1, \ldots, \ell_n\f$ are all negative, which results in the \f$\leq\f$ inequality.
1961  *
1962  * Note that in fact, any mixture of nonzero finite lower and upper bounds would lead to a valid inequality as
1963  * above. However, usually either the lower or upper bound is nonzero. Thus, the above inequalities are the most
1964  * interesting.
1965  */
1966 static
1968  SCIP* scip, /**< SCIP pointer */
1969  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1970  SCIP_CONS* cons, /**< constraint */
1971  SCIP_Bool local, /**< produce local cut? */
1972  SCIP_ROW** rowlb, /**< output: row for lower bounds (or NULL if not needed) */
1973  SCIP_ROW** rowub /**< output: row for upper bounds (or NULL if not needed) */
1974  )
1975 {
1976  char name[SCIP_MAXSTRLEN];
1977  SCIP_CONSDATA* consdata;
1978  SCIP_VAR** vars;
1979  SCIP_Real* vals;
1980  SCIP_Real val;
1981  int nvars;
1982  int cnt;
1983  int j;
1984 
1985  assert(scip != NULL);
1986  assert(conshdlr != NULL);
1987  assert(cons != NULL);
1988 
1989  consdata = SCIPconsGetData(cons);
1990  assert(consdata != NULL);
1991  assert(consdata->vars != NULL);
1992  assert(consdata->indvars != NULL);
1993 
1994  nvars = consdata->nvars;
1995  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
1996  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
1997 
1998  /* take care of upper bounds */
1999  if( rowub != NULL )
2000  {
2001  int cardval;
2002 
2003  cnt = 0;
2004  cardval = consdata->cardval;
2005  for( j = 0; j < nvars; ++j )
2006  {
2007  if( local )
2008  val = SCIPvarGetLbLocal(consdata->vars[j]);
2009  else
2010  val = SCIPvarGetUbGlobal(consdata->vars[j]);
2011 
2012  /* if a variable may be treated as nonzero, then update cardinality value */
2013  if( SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->indvars[j]), 1.0) )
2014  {
2015  --cardval;
2016  continue;
2017  }
2018 
2019  if( !SCIPisInfinity(scip, val) && !SCIPisZero(scip, val) && !SCIPisNegative(scip, val) )
2020  {
2021  assert(consdata->vars[j] != NULL);
2022  vars[cnt] = consdata->vars[j];
2023  vals[cnt++] = 1.0/val;
2024  }
2025  }
2026  assert(cardval >= 0);
2027 
2028  /* if cut is meaningful */
2029  if( cnt > cardval )
2030  {
2031  /* create upper bound inequality if at least two of the bounds are finite and nonzero */
2032  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cardub#%s", SCIPconsGetName(cons));
2033  SCIP_CALL( SCIPcreateEmptyRowCons(scip, rowub, conshdlr, name, -SCIPinfinity(scip), (SCIP_Real)cardval,
2034  local, TRUE, FALSE) );
2035  SCIP_CALL( SCIPaddVarsToRow(scip, *rowub, cnt, vars, vals) );
2036  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowub, NULL) ) );
2037  }
2038  }
2039 
2040  /* take care of lower bounds */
2041  if( rowlb != NULL )
2042  {
2043  int cardval;
2044 
2045  cnt = 0;
2046  cardval = consdata->cardval;
2047  for( j = 0; j < nvars; ++j )
2048  {
2049  if( local )
2050  val = SCIPvarGetLbLocal(consdata->vars[j]);
2051  else
2052  val = SCIPvarGetLbGlobal(consdata->vars[j]);
2053 
2054  /* if a variable may be treated as nonzero, then update cardinality value */
2055  if( SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->indvars[j]), 1.0) )
2056  {
2057  --cardval;
2058  continue;
2059  }
2060 
2061  if( !SCIPisInfinity(scip, -val) && !SCIPisZero(scip, val) && !SCIPisPositive(scip, val) )
2062  {
2063  assert(consdata->vars[j] != NULL);
2064  vars[cnt] = consdata->vars[j];
2065  vals[cnt++] = 1.0/val;
2066  }
2067  }
2068  assert(cardval >= 0);
2069 
2070  /* if cut is meaningful */
2071  if( cnt > cardval )
2072  {
2073  /* create lower bound inequality if at least two of the bounds are finite and nonzero */
2074  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "cardlb#%s", SCIPconsGetName(cons));
2075  SCIP_CALL( SCIPcreateEmptyRowCons(scip, rowlb, conshdlr, name, -SCIPinfinity(scip), (SCIP_Real)cardval,
2076  local, TRUE, FALSE) );
2077  SCIP_CALL( SCIPaddVarsToRow(scip, *rowlb, nvars, vars, vals) );
2078  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowlb, NULL) ) );
2079  }
2080  }
2081 
2082  SCIPfreeBufferArray(scip, &vals);
2083  SCIPfreeBufferArray(scip, &vars);
2084 
2085  return SCIP_OKAY;
2086 }
2087 
2088 /** initialize or separate bound inequalities from cardinality constraints
2089  * (see the function \ref generateRowCardinality() for an explanation of bound inequalities)
2090  */
2091 static
2093  SCIP* scip, /**< SCIP pointer */
2094  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2095  SCIP_CONS** conss, /**< cardinality constraints */
2096  int nconss, /**< number of cardinality constraints */
2097  SCIP_SOL* sol, /**< LP solution to be separated (or NULL) */
2098  SCIP_Bool solvedinitlp, /**< TRUE if initial LP relaxation at a node is solved */
2099  int* ngen, /**< pointer to store number of cuts generated (or NULL) */
2100  SCIP_Bool* cutoff /**< pointer to store whether a cutoff occurred */
2101  )
2102 {
2103  int cnt = 0;
2104  int c;
2105 
2106  assert(scip != NULL);
2107  assert(conss != NULL);
2108 
2109  *cutoff = FALSE;
2110 
2111  for( c = nconss-1; c >= 0; --c )
2112  {
2113  SCIP_CONSDATA* consdata;
2114  SCIP_ROW* rowub = NULL;
2115  SCIP_ROW* rowlb = NULL;
2116  SCIP_Bool release = FALSE;
2117 
2118  assert(conss != NULL);
2119  assert(conss[c] != NULL);
2120  consdata = SCIPconsGetData(conss[c]);
2121  assert(consdata != NULL);
2122 
2123  if( solvedinitlp )
2124  SCIPdebugMsg(scip, "Separating inequalities for cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]) );
2125  else
2126  SCIPdebugMsg(scip, "Checking for initial rows for cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]) );
2127 
2128  /* generate rows associated to cardinality constraint; the rows are stored in the constraint data
2129  * if they are globally valid */
2130  if( SCIPconsIsLocal(conss[c]) )
2131  {
2132  SCIP_CALL( generateRowCardinality(scip, conshdlr, conss[c], TRUE, &rowlb, &rowub) );
2133  release = TRUE;
2134  }
2135  else
2136  {
2137  if( consdata->rowub == NULL || consdata->rowlb == NULL )
2138  {
2139  SCIP_CALL( generateRowCardinality(scip, conshdlr, conss[c], FALSE,
2140  (consdata->rowlb == NULL) ? &consdata->rowlb : NULL,
2141  (consdata->rowub == NULL) ? &consdata->rowub : NULL) );/*lint !e826*/
2142  }
2143  rowub = consdata->rowub;
2144  rowlb = consdata->rowlb;
2145  }
2146 
2147  /* put corresponding rows into LP */
2148  if( rowub != NULL && !SCIProwIsInLP(rowub) && ( solvedinitlp || SCIPisCutEfficacious(scip, sol, rowub) ) )
2149  {
2150  assert(SCIPisInfinity(scip, -SCIProwGetLhs(rowub)));
2151  assert(SCIPisLE(scip, SCIProwGetRhs(rowub), (SCIP_Real)consdata->cardval));
2152 
2153  SCIP_CALL( SCIPaddCut(scip, NULL, rowub, FALSE, cutoff) );
2154  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowub, NULL) ) );
2155 
2156  if( solvedinitlp )
2157  {
2158  SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
2159  }
2160  ++cnt;
2161  }
2162 
2163  if( ! (*cutoff) && rowlb != NULL && !SCIProwIsInLP(rowlb)
2164  && ( solvedinitlp || SCIPisCutEfficacious(scip, sol, rowlb) )
2165  )
2166  {
2167  assert(SCIPisInfinity(scip, -SCIProwGetLhs(rowlb)));
2168  assert(SCIPisLE(scip, SCIProwGetRhs(rowlb), (SCIP_Real)consdata->cardval));
2169 
2170  SCIP_CALL( SCIPaddCut(scip, NULL, rowlb, FALSE, cutoff) );
2171  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowlb, NULL) ) );
2172 
2173  if( solvedinitlp )
2174  {
2175  SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
2176  }
2177  ++cnt;
2178  }
2179 
2180  if( release )
2181  {
2182  if( rowlb != NULL )
2183  {
2184  SCIP_CALL( SCIPreleaseRow(scip, &rowlb) );
2185  }
2186  if( rowub != NULL )
2187  {
2188  SCIP_CALL( SCIPreleaseRow(scip, &rowub) );
2189  }
2190  }
2191 
2192  if( *cutoff )
2193  break;
2194  }
2195 
2196  /* store number of generated cuts */
2197  if( ngen != NULL )
2198  *ngen = cnt;
2199 
2200  return SCIP_OKAY;
2201 }
2202 
2203 /** separates cardinality constraints for arbitrary solutions */
2204 static
2206  SCIP* scip, /**< SCIP pointer */
2207  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2208  SCIP_SOL* sol, /**< solution to be separated (or NULL) */
2209  int nconss, /**< number of constraints */
2210  SCIP_CONS** conss, /**< cardinality constraints */
2211  SCIP_RESULT* result /**< result */
2212  )
2213 {
2214  SCIP_Bool cutoff;
2215  int ngen = 0;
2216 
2217  assert(scip != NULL);
2218  assert(conshdlr != NULL);
2219  assert(conss != NULL);
2220  assert(result != NULL);
2221 
2222  *result = SCIP_DIDNOTRUN;
2223 
2224  if( nconss == 0 )
2225  return SCIP_OKAY;
2226 
2227  /* only separate cuts if we are not close to terminating */
2228  if( SCIPisStopped(scip) )
2229  return SCIP_OKAY;
2230 
2231  *result = SCIP_DIDNOTFIND;
2232 
2233  /* separate bound inequalities from cardinality constraints */
2234  SCIP_CALL( initsepaBoundInequalityFromCardinality(scip, conshdlr, conss, nconss, sol, TRUE, &ngen, &cutoff) );
2235  if( cutoff )
2236  {
2237  *result = SCIP_CUTOFF;
2238  return SCIP_OKAY;
2239  }
2240 
2241  /* evaluate results */
2242  if( ngen > 0 )
2243  *result = SCIP_SEPARATED;
2244  SCIPdebugMsg(scip, "Separated %d bound inequalities.\n", ngen);
2245 
2246  return SCIP_OKAY;
2247 }
2248 
2249 /* ---------------------------- constraint handler callback methods ----------------------*/
2250 
2251 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
2252 static
2253 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyCardinality)
2254 { /*lint --e{715}*/
2255  assert(scip != NULL);
2256  assert(conshdlr != NULL);
2257  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2258 
2259  /* call inclusion method of constraint handler */
2261 
2262  *valid = TRUE;
2263 
2264  return SCIP_OKAY;
2265 }
2266 
2267 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
2268 static
2269 SCIP_DECL_CONSFREE(consFreeCardinality)
2270 {
2271  SCIP_CONSHDLRDATA* conshdlrdata;
2273  assert(scip != NULL);
2274  assert(conshdlr != NULL);
2275  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2276 
2277  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2278  assert(conshdlrdata != NULL);
2279 
2280  /* free hash map */
2281  if( conshdlrdata->varhash != NULL )
2282  {
2283  SCIPhashmapFree(&conshdlrdata->varhash);
2284  }
2285 
2286  SCIPfreeBlockMemory(scip, &conshdlrdata);
2287 
2288  return SCIP_OKAY;
2289 }
2290 
2291 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
2292 static
2293 SCIP_DECL_CONSEXITSOL(consExitsolCardinality)
2294 { /*lint --e{715}*/
2295  SCIP_CONSHDLRDATA* conshdlrdata;
2296  int c;
2297 
2298  assert(scip != NULL);
2299  assert(conshdlr != NULL);
2300  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2301 
2302  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2303  assert(conshdlrdata != NULL);
2304 
2305  /* check each constraint */
2306  for( c = 0; c < nconss; ++c )
2307  {
2308  SCIP_CONSDATA* consdata;
2309 
2310  assert(conss != NULL);
2311  assert(conss[c] != NULL);
2312  consdata = SCIPconsGetData(conss[c]);
2313  assert(consdata != NULL);
2314 
2315  SCIPdebugMsg(scip, "Exiting cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]) );
2316 
2317  /* free rows */
2318  if( consdata->rowub != NULL )
2319  {
2320  SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowub) );
2321  }
2322  if( consdata->rowlb != NULL )
2323  {
2324  SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowlb) );
2325  }
2326  }
2327 
2328  /* free hash map */
2329  if( conshdlrdata->varhash != NULL )
2330  {
2331  SCIPhashmapFree(&conshdlrdata->varhash);
2332  }
2333 
2334  return SCIP_OKAY;
2335 }
2336 
2337 /** frees specific constraint data */
2338 static
2339 SCIP_DECL_CONSDELETE(consDeleteCardinality)
2340 { /*lint --e{737, 647}*/
2341  assert(scip != NULL);
2342  assert(conshdlr != NULL);
2343  assert(cons != NULL);
2344  assert(consdata != NULL);
2345  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2346 
2347  SCIPdebugMsg(scip, "Deleting cardinality constraint <%s>.\n", SCIPconsGetName(cons) );
2348 
2349  /* drop events on transformed variables */
2350  if( SCIPconsIsTransformed(cons) )
2351  {
2352  SCIP_CONSHDLRDATA* conshdlrdata;
2353  int j;
2354 
2355  /* get constraint handler data */
2356  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2357  assert(conshdlrdata != NULL);
2358  assert(conshdlrdata->eventhdlr != NULL);
2359 
2360  for( j = 0; j < (*consdata)->nvars; ++j )
2361  {
2362  SCIP_CALL( dropVarEventCardinality(scip, conshdlrdata->eventhdlr, *consdata, (*consdata)->vars[j],
2363  (*consdata)->indvars[j], &(*consdata)->eventdatas[j]) );
2364  assert((*consdata)->eventdatas[j] == NULL);
2365  }
2366  }
2367 
2368  if( (*consdata)->weights != NULL )
2369  {
2370  SCIPfreeBlockMemoryArray(scip, &(*consdata)->weights, (*consdata)->maxvars);
2371  }
2372  SCIPfreeBlockMemoryArray(scip, &(*consdata)->eventdatas, (*consdata)->maxvars);
2373  SCIPfreeBlockMemoryArray(scip, &(*consdata)->eventvarscurrent, 4 * (*consdata)->maxvars);/*lint !e647*/
2374  SCIPfreeBlockMemoryArray(scip, &(*consdata)->eventdatascurrent, 4 * (*consdata)->maxvars);/*lint !e647*/
2375  SCIPfreeBlockMemoryArray(scip, &(*consdata)->indvars, (*consdata)->maxvars);
2376  SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->maxvars);
2377 
2378  /* free rows */
2379  if( (*consdata)->rowub != NULL )
2380  {
2381  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowub) );
2382  }
2383  if( (*consdata)->rowlb != NULL )
2384  {
2385  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowlb) );
2386  }
2387  assert((*consdata)->rowub == NULL);
2388  assert((*consdata)->rowlb == NULL);
2389 
2390  SCIPfreeBlockMemory(scip, consdata);
2391 
2392  return SCIP_OKAY;
2393 }
2394 
2395 /** transforms constraint data into data belonging to the transformed problem */
2396 static
2397 SCIP_DECL_CONSTRANS(consTransCardinality)
2398 {
2399  SCIP_CONSDATA* consdata;
2400  SCIP_CONSHDLRDATA* conshdlrdata;
2401  SCIP_CONSDATA* sourcedata;
2402  char s[SCIP_MAXSTRLEN];
2403  int j;
2404 
2405  assert(scip != NULL);
2406  assert(conshdlr != NULL);
2407  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2408  assert(sourcecons != NULL);
2409  assert(targetcons != NULL);
2410 
2411  /* get constraint handler data */
2412  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2413  assert(conshdlrdata != NULL);
2414  assert(conshdlrdata->eventhdlr != NULL);
2415 
2416  SCIPdebugMsg(scip, "Transforming cardinality constraint: <%s>.\n", SCIPconsGetName(sourcecons) );
2417 
2418  /* get data of original constraint */
2419  sourcedata = SCIPconsGetData(sourcecons);
2420  assert(sourcedata != NULL);
2421  assert(sourcedata->nvars > 0);
2422  assert(sourcedata->nvars <= sourcedata->maxvars);
2423 
2424  /* create constraint data */
2425  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
2426 
2427  consdata->cons = NULL;
2428  consdata->nvars = sourcedata->nvars;
2429  consdata->maxvars = sourcedata->nvars;
2430  consdata->cardval = sourcedata->cardval;
2431  consdata->rowub = NULL;
2432  consdata->rowlb = NULL;
2433  consdata->eventdatascurrent = NULL;
2434  consdata->neventdatascurrent = 0;
2435  consdata->ntreatnonzeros = 0;
2436  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, consdata->nvars) );
2437  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->indvars, consdata->nvars) );
2438  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatas, consdata->nvars) );
2439  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatascurrent, 4*consdata->nvars) );/*lint !e647*/
2440  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventvarscurrent, 4*consdata->nvars) );/*lint !e647*/
2441 
2442  /* if weights were used */
2443  if( sourcedata->weights != NULL )
2444  {
2445  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, sourcedata->weights, consdata->nvars) );
2446  }
2447  else
2448  consdata->weights = NULL;
2449 
2450  for( j = 0; j < sourcedata->nvars; ++j )
2451  {
2452  assert(sourcedata->vars[j] != 0);
2453  assert(sourcedata->indvars[j] != 0);
2454  SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[j], &(consdata->vars[j])) );
2455  SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->indvars[j], &(consdata->indvars[j])) );
2456 
2457  /* if variable is fixed to be nonzero */
2458  if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->indvars[j]), 1.0) )
2459  ++(consdata->ntreatnonzeros);
2460  }
2461 
2462  /* create transformed constraint with the same flags */
2463  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
2464  SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
2465  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
2466  SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
2467  SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
2468  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
2469  SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
2470 
2471  consdata->cons = *targetcons;
2472  assert(consdata->cons != NULL);
2473 
2474  /* catch bound change events on variable */
2475  for( j = 0; j < consdata->nvars; ++j )
2476  {
2477  SCIP_CALL( catchVarEventCardinality(scip, conshdlrdata->eventhdlr, consdata,
2478  consdata->vars[j], consdata->indvars[j], j, &consdata->eventdatas[j]) );
2479  assert(consdata->eventdatas[j] != NULL);
2480  }
2481 
2482 #ifdef SCIP_DEBUG
2483  if( SCIPisGT(scip, (SCIP_Real)consdata->ntreatnonzeros, consdata->cardval) )
2484  {
2485  SCIPdebugMsg(scip, "constraint <%s> has %d variables fixed to be nonzero, allthough the constraint allows \
2486  only %d nonzero variables\n", SCIPconsGetName(*targetcons), consdata->ntreatnonzeros, consdata->cardval);
2487  }
2488 #endif
2489 
2490  return SCIP_OKAY;
2491 }
2492 
2493 /** presolving method of constraint handler */
2494 static
2495 SCIP_DECL_CONSPRESOL(consPresolCardinality)
2496 { /*lint --e{715}*/
2497  /* cppcheck-suppress unassignedVariable */
2498  int oldnfixedvars;
2499  /* cppcheck-suppress unassignedVariable */
2500  int oldndelconss;
2501  /* cppcheck-suppress unassignedVariable */
2502  int oldnupgdconss;
2503  int nremovedvars;
2504  SCIP_EVENTHDLR* eventhdlr;
2505  int c;
2506 
2507  assert(scip != NULL);
2508  assert(conshdlr != NULL);
2509  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2510  assert(result != NULL);
2511 
2512  SCIPdebugMsg(scip, "Presolving cardinality constraints.\n");
2513 
2514  *result = SCIP_DIDNOTRUN;
2515  SCIPdebug( oldnfixedvars = *nfixedvars; )
2516  SCIPdebug( oldndelconss = *ndelconss; )
2517  SCIPdebug( oldnupgdconss = *nupgdconss; )
2518  nremovedvars = 0;
2519 
2520  /* only run if success if possible */
2521  if( nrounds == 0 || nnewfixedvars > 0 || nnewaggrvars > 0 )
2522  {
2523  /* get constraint handler data */
2524  assert(SCIPconshdlrGetData(conshdlr) != NULL);
2525  eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
2526  assert(eventhdlr != NULL);
2527 
2528  *result = SCIP_DIDNOTFIND;
2529 
2530  /* check each constraint */
2531  for( c = 0; c < nconss; ++c )
2532  {
2533  SCIP_CONSDATA* consdata;
2534  SCIP_CONS* cons;
2535  SCIP_Bool cutoff;
2536  SCIP_Bool success;
2537 
2538  assert(conss != NULL);
2539  assert(conss[c] != NULL);
2540  cons = conss[c];
2541  consdata = SCIPconsGetData(cons);
2542 
2543  assert(consdata != NULL);
2544  assert(consdata->nvars >= 0);
2545  assert(consdata->nvars <= consdata->maxvars);
2546  assert(!SCIPconsIsModifiable(cons));
2547 
2548  /* perform one presolving round */
2549  SCIP_CALL( presolRoundCardinality(scip, cons, consdata, eventhdlr, &cutoff, &success,
2550  ndelconss, nupgdconss, nfixedvars, &nremovedvars) );
2551 
2552  if( cutoff )
2553  {
2554  SCIPdebugMsg(scip, "presolving detected cutoff.\n");
2555  *result = SCIP_CUTOFF;
2556  return SCIP_OKAY;
2557  }
2558 
2559  if( success )
2560  *result = SCIP_SUCCESS;
2561  }
2562  }
2563  (*nchgcoefs) += nremovedvars;
2564 
2565  SCIPdebugMsg(scip, "presolving fixed %d variables, removed %d variables, deleted %d constraints, \
2566  and upgraded %d constraints.\n", *nfixedvars - oldnfixedvars, nremovedvars, *ndelconss - oldndelconss,
2567  *nupgdconss - oldnupgdconss);
2568 
2569  return SCIP_OKAY;
2570 }
2571 
2572 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
2573 static
2574 SCIP_DECL_CONSINITLP(consInitlpCardinality)
2575 { /*lint --e{715}*/
2576  SCIP_Bool cutoff;
2578  assert(scip != NULL);
2579  assert(conshdlr != NULL);
2580 
2581  /* checking for initial rows for cardinality constraints */
2582  SCIP_CALL( initsepaBoundInequalityFromCardinality(scip, conshdlr, conss, nconss, NULL, FALSE, NULL, &cutoff) );
2583  assert(!cutoff);
2584 
2585  return SCIP_OKAY;
2586 }
2587 
2588 /** separation method of constraint handler for LP solutions */
2589 static
2590 SCIP_DECL_CONSSEPALP(consSepalpCardinality)
2591 { /*lint --e{715}*/
2592  assert(scip != NULL);
2593  assert(conshdlr != NULL);
2594  assert(conss != NULL);
2595  assert(result != NULL);
2596 
2597  SCIP_CALL( separateCardinality(scip, conshdlr, NULL, nconss, conss, result) );
2598 
2599  return SCIP_OKAY;
2600 }
2601 
2602 /** separation method of constraint handler for arbitrary primal solutions */
2603 static
2604 SCIP_DECL_CONSSEPASOL(consSepasolCardinality)
2605 { /*lint --e{715}*/
2606  assert(scip != NULL);
2607  assert(conshdlr != NULL);
2608  assert(conss != NULL);
2609  assert(result != NULL);
2610 
2611  SCIP_CALL( separateCardinality(scip, conshdlr, sol, nconss, conss, result) );
2612 
2613  return SCIP_OKAY;
2614 }
2615 
2616 /** constraint enforcing method of constraint handler for LP solutions */
2617 static
2618 SCIP_DECL_CONSENFOLP(consEnfolpCardinality)
2619 { /*lint --e{715}*/
2620  assert(scip != NULL);
2621  assert(conshdlr != NULL);
2622  assert(conss != NULL);
2623  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2624  assert(result != NULL);
2625 
2626  SCIP_CALL( enforceCardinality(scip, conshdlr, NULL, nconss, conss, result) );
2627 
2628  return SCIP_OKAY;
2629 }
2630 
2631 /** constraint enforcing method of constraint handler for relaxation solutions */
2632 static
2633 SCIP_DECL_CONSENFORELAX(consEnforelaxCardinality)
2634 { /*lint --e{715}*/
2635  assert( scip != NULL );
2636  assert( conshdlr != NULL );
2637  assert( conss != NULL );
2638  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2639  assert( result != NULL );
2640 
2641  SCIP_CALL( enforceCardinality(scip, conshdlr, sol, nconss, conss, result) );
2642 
2643  return SCIP_OKAY;
2644 }
2645 
2646 /** constraint enforcing method of constraint handler for pseudo solutions */
2647 static
2648 SCIP_DECL_CONSENFOPS(consEnfopsCardinality)
2649 { /*lint --e{715}*/
2650  assert(scip != NULL);
2651  assert(conshdlr != NULL);
2652  assert(conss != NULL);
2653  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2654  assert(result != NULL);
2655 
2656  SCIP_CALL( enforceCardinality(scip, conshdlr, NULL, nconss, conss, result) );
2657 
2658  return SCIP_OKAY;
2659 }
2660 
2661 /** feasibility check method of constraint handler for integral solutions
2662  *
2663  * We simply check whether more variables than allowed are nonzero in the given solution.
2664  */
2665 static
2666 SCIP_DECL_CONSCHECK(consCheckCardinality)
2667 { /*lint --e{715}*/
2668  int c;
2670  assert(scip != NULL);
2671  assert(conshdlr != NULL);
2672  assert(conss != NULL);
2673  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2674  assert(result != NULL);
2675 
2676  /* check each constraint */
2677  for( c = 0; c < nconss; ++c )
2678  {
2679  SCIP_CONSDATA* consdata;
2680  int cardval;
2681  int j;
2682  int cnt;
2683 
2684  cnt = 0;
2685  assert(conss[c] != NULL);
2686  consdata = SCIPconsGetData(conss[c]);
2687  assert(consdata != NULL);
2688  cardval = consdata->cardval;
2689  SCIPdebugMsg(scip, "Checking cardinality constraint <%s>.\n", SCIPconsGetName(conss[c]));
2690 
2691  /* check all variables */
2692  for( j = 0; j < consdata->nvars; ++j )
2693  {
2694  /* if variable is nonzero */
2695  if( !SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[j])) )
2696  {
2697  ++cnt;
2698 
2699  /* if more variables than allowed are nonzero */
2700  if( cnt > cardval )
2701  {
2702  SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
2703  *result = SCIP_INFEASIBLE;
2704 
2705  if( printreason )
2706  {
2707  int l;
2708 
2709  SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) );
2710  SCIPinfoMessage(scip, NULL, ";\nviolation: ");
2711 
2712  for( l = 0; l < consdata->nvars; ++l )
2713  {
2714  /* if variable is nonzero */
2715  if( !SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[l])) )
2716  {
2717  SCIPinfoMessage(scip, NULL, "<%s> = %.15g ",
2718  SCIPvarGetName(consdata->vars[l]), SCIPgetSolVal(scip, sol, consdata->vars[l]));
2719  }
2720  }
2721  SCIPinfoMessage(scip, NULL, "\n");
2722  }
2723  return SCIP_OKAY;
2724  }
2725  }
2726  }
2727  }
2728  *result = SCIP_FEASIBLE;
2729 
2730  return SCIP_OKAY;
2731 }
2732 
2733 /** domain propagation method of constraint handler */
2734 static
2735 SCIP_DECL_CONSPROP(consPropCardinality)
2736 { /*lint --e{715}*/
2737  int nchgdomain = 0;
2738  int c;
2739 
2740  assert(scip != NULL);
2741  assert(conshdlr != NULL);
2742  assert(conss != NULL);
2743  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2744  assert(result != NULL);
2745  *result = SCIP_DIDNOTRUN;
2746 
2747  assert(SCIPisTransformed(scip));
2748 
2749  /* check each constraint */
2750  for( c = 0; c < nconss; ++c )
2751  {
2752  SCIP_CONS* cons;
2753  SCIP_CONSDATA* consdata;
2754  SCIP_Bool cutoff;
2755 
2756  *result = SCIP_DIDNOTFIND;
2757  assert(conss[c] != NULL);
2758  cons = conss[c];
2759  consdata = SCIPconsGetData(cons);
2760  assert(consdata != NULL);
2761  SCIPdebugMsg(scip, "Propagating cardinality constraint <%s>.\n", SCIPconsGetName(cons) );
2762 
2763  *result = SCIP_DIDNOTFIND;
2764  SCIP_CALL( propCardinality(scip, cons, consdata, &cutoff, &nchgdomain) );
2765  if( cutoff )
2766  {
2767  *result = SCIP_CUTOFF;
2768  return SCIP_OKAY;
2769  }
2770  }
2771  SCIPdebugMsg(scip, "Propagated %d domains.\n", nchgdomain);
2772  if( nchgdomain > 0 )
2773  *result = SCIP_REDUCEDDOM;
2774 
2775  return SCIP_OKAY;
2776 }
2777 
2778 /** variable rounding lock method of constraint handler
2779  *
2780  * Let lb and ub be the lower and upper bounds of a
2781  * variable. Preprocessing usually makes sure that lb <= 0 <= ub.
2782  *
2783  * - If lb < 0 then rounding down may violate the constraint.
2784  * - If ub > 0 then rounding up may violated the constraint.
2785  * - If lb > 0 or ub < 0 then the rhs of the constraint can be updated and the variable
2786  * can be removed from the constraint. Thus, we do not have to deal with it here.
2787  * - If lb == 0 then rounding down does not violate the constraint.
2788  * - If ub == 0 then rounding up does not violate the constraint.
2789  */
2790 static
2791 SCIP_DECL_CONSLOCK(consLockCardinality)
2792 {
2793  SCIP_CONSDATA* consdata;
2794  SCIP_VAR** vars;
2795  int nvars;
2796  SCIP_VAR** indvars;
2797  int j;
2798 
2799  assert(scip != NULL);
2800  assert(conshdlr != NULL);
2801  assert(cons != NULL);
2802  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2803  consdata = SCIPconsGetData(cons);
2804  assert(consdata != NULL);
2805 
2806  SCIPdebugMsg(scip, "Locking constraint <%s>.\n", SCIPconsGetName(cons));
2807 
2808  vars = consdata->vars;
2809  indvars = consdata->indvars;
2810  nvars = consdata->nvars;
2811  assert(vars != NULL);
2812 
2813  for( j = 0; j < nvars; ++j )
2814  {
2815  SCIP_VAR* var;
2816  SCIP_VAR* indvar;
2817  var = vars[j];
2818  indvar = indvars[j];
2819 
2820  /* if lower bound is negative, rounding down may violate constraint */
2821  if( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(var)) )
2822  {
2823  SCIP_CALL( SCIPaddVarLocks(scip, var, nlockspos, nlocksneg) );
2824  }
2825 
2826  /* additionally: if upper bound is positive, rounding up may violate constraint */
2827  if( SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var)) )
2828  {
2829  SCIP_CALL( SCIPaddVarLocks(scip, var, nlocksneg, nlockspos) );
2830  }
2831 
2832  /* add lock on indicator variable; @todo write constraint handler to handle down locks */
2833  SCIP_CALL( SCIPaddVarLocks(scip, indvar, nlockspos, nlockspos) );
2834  }
2835 
2836  return SCIP_OKAY;
2837 }
2838 
2839 /** constraint display method of constraint handler */
2840 static
2841 SCIP_DECL_CONSPRINT(consPrintCardinality)
2842 { /*lint --e{715}*/
2843  SCIP_CONSDATA* consdata;
2844  int j;
2845 
2846  assert(scip != NULL);
2847  assert(conshdlr != NULL);
2848  assert(cons != NULL);
2849  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2850 
2851  consdata = SCIPconsGetData(cons);
2852  assert(consdata != NULL);
2853 
2854  for( j = 0; j < consdata->nvars; ++j )
2855  {
2856  if( j > 0 )
2857  SCIPinfoMessage(scip, file, ", ");
2858  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[j], FALSE) );
2859  if( consdata->weights == NULL )
2860  SCIPinfoMessage(scip, file, " (%d)", j+1);
2861  else
2862  SCIPinfoMessage(scip, file, " (%3.2f)", consdata->weights[j]);
2863  }
2864  SCIPinfoMessage(scip, file, " <= %d", consdata->cardval);
2865 
2866  return SCIP_OKAY;
2867 }
2868 
2869 /** constraint copying method of constraint handler */
2870 static
2871 SCIP_DECL_CONSCOPY(consCopyCardinality)
2872 { /*lint --e{715}*/
2873  SCIP_CONSDATA* sourceconsdata;
2874  SCIP_VAR** sourcevars;
2875  SCIP_VAR** targetvars;
2876  SCIP_VAR** sourceindvars;
2877  SCIP_VAR** targetindvars;
2878  SCIP_Real* sourceweights;
2879  SCIP_Real* targetweights;
2880  const char* consname;
2881  int nvars;
2882  int v;
2883 
2884  assert(scip != NULL);
2885  assert(sourcescip != NULL);
2886  assert(sourcecons != NULL);
2887  assert(SCIPisTransformed(sourcescip));
2888  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(sourcecons)), CONSHDLR_NAME) == 0);
2889 
2890  *valid = TRUE;
2891 
2892  if( name != NULL )
2893  consname = name;
2894  else
2895  consname = SCIPconsGetName(sourcecons);
2896 
2897  SCIPdebugMsg(scip, "Copying cardinality constraint <%s> ...\n", consname);
2898 
2899  sourceconsdata = SCIPconsGetData(sourcecons);
2900  assert(sourceconsdata != NULL);
2901 
2902  /* get variables and weights of the source constraint */
2903  nvars = sourceconsdata->nvars;
2904 
2905  if( nvars == 0 )
2906  return SCIP_OKAY;
2907 
2908  sourcevars = sourceconsdata->vars;
2909  assert(sourcevars != NULL);
2910  sourceindvars = sourceconsdata->indvars;
2911  assert(sourceindvars != NULL);
2912  sourceweights = sourceconsdata->weights;
2913  assert(sourceweights != NULL);
2914 
2915  /* duplicate variable array */
2916  SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetvars, nvars) );
2917  SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetindvars, nvars) );
2918  SCIP_CALL( SCIPduplicateBufferArray(sourcescip, &targetweights, sourceweights, nvars) );
2919 
2920  /* get copied variables in target SCIP */
2921  for( v = 0; v < nvars && *valid; ++v )
2922  {
2923  assert(sourcevars[v] != NULL);
2924  assert(sourceindvars[v] != NULL);
2925 
2926  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &(targetvars[v]), varmap, consmap, global, valid) );
2927  if( *valid )
2928  {
2929  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceindvars[v], &(targetindvars[v]), varmap, consmap, global, valid) );
2930  }
2931  }
2932 
2933  /* only create the target constraint, if all variables could be copied */
2934  if( *valid )
2935  {
2936  SCIP_CALL( SCIPcreateConsCardinality(scip, cons, consname, nvars, targetvars, sourceconsdata->cardval, targetindvars,
2937  targetweights, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
2938  }
2939 
2940  /* free buffer array */
2941  SCIPfreeBufferArray(sourcescip, &targetweights);
2942  SCIPfreeBufferArray(sourcescip, &targetindvars);
2943  SCIPfreeBufferArray(sourcescip, &targetvars);
2944 
2945  return SCIP_OKAY;
2946 }
2947 
2948 /** constraint parsing method of constraint handler */
2949 static
2950 SCIP_DECL_CONSPARSE(consParseCardinality)
2951 { /*lint --e{715}*/
2952  SCIP_VAR* var;
2953  SCIP_Real weight;
2954  int cardval;
2955  const char* s;
2956  char* t;
2957 
2958  assert(scip != NULL);
2959  assert(conshdlr != NULL);
2960  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2961  assert(cons != NULL);
2962  assert(success != NULL);
2963 
2964  *success = TRUE;
2965  s = str;
2966 
2967  /* create empty cardinality constraint */
2968  SCIP_CALL( SCIPcreateConsCardinality(scip, cons, name, 0, NULL, 0, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
2969 
2970  /* loop through string */
2971  do
2972  {
2973  /* parse variable name */
2974  SCIP_CALL( SCIPparseVarName(scip, s, &var, &t) );
2975  s = t;
2976 
2977  /* skip until beginning of weight */
2978  while ( *s != '\0' && *s != '(' )
2979  ++s;
2980 
2981  if ( *s == '\0' )
2982  {
2983  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: expected weight at input: %s\n", s);
2984  *success = FALSE;
2985  return SCIP_OKAY;
2986  }
2987  /* skip '(' */
2988  ++s;
2989 
2990  /* find weight */
2991  weight = strtod(s, &t);
2992  if ( t == NULL )
2993  {
2994  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error during parsing of the weight: %s\n", s);
2995  *success = FALSE;
2996  return SCIP_OKAY;
2997  }
2998  s = t;
2999 
3000  /* skip white space, ',', and ')' */
3001  while ( *s != '\0' && ( isspace((unsigned char)*s) || *s == ',' || *s == ')' ) )
3002  ++s;
3003 
3004  /* add variable */
3005  SCIP_CALL( SCIPaddVarCardinality(scip, *cons, var, NULL, weight) );
3006 
3007  /* check if there is a '<=' */
3008  if ( *s == '<' && *s+1 == '=' )
3009  {
3010  s = s + 2;
3011 
3012  /* skip white space */
3013  while ( isspace((unsigned char)*s) )
3014  ++s;
3015 
3016  cardval = (int)strtod(s, &t);
3017  if ( t == NULL )
3018  {
3019  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error during parsing of the cardinality restriction value: %s\n", s);
3020  *success = FALSE;
3021  return SCIP_OKAY;
3022  }
3023  s = t;
3024 
3025  SCIP_CALL( SCIPchgCardvalCardinality(scip, *cons, cardval));
3026  }
3027  }
3028  while ( *s != '\0' );
3029 
3030  return SCIP_OKAY;
3031 }
3032 
3033 /** constraint method of constraint handler which returns the variables (if possible) */
3034 static
3035 SCIP_DECL_CONSGETVARS(consGetVarsCardinality)
3036 { /*lint --e{715}*/
3037  SCIP_CONSDATA* consdata;
3039  consdata = SCIPconsGetData(cons);
3040  assert(consdata != NULL);
3041 
3042  if( varssize < consdata->nvars )
3043  (*success) = FALSE;
3044  else
3045  {
3046  assert(vars != NULL);
3047 
3048  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
3049  (*success) = TRUE;
3050  }
3051 
3052  return SCIP_OKAY;
3053 }
3054 
3055 /** constraint method of constraint handler which returns the number of variables (if possible) */
3056 static
3057 SCIP_DECL_CONSGETNVARS(consGetNVarsCardinality)
3058 { /*lint --e{715}*/
3059  SCIP_CONSDATA* consdata;
3061  consdata = SCIPconsGetData(cons);
3062  assert(consdata != NULL);
3063 
3064  (*nvars) = consdata->nvars;
3065  (*success) = TRUE;
3066 
3067  return SCIP_OKAY;
3068 }
3069 
3070 /* ---------------- Callback methods of event handler ---------------- */
3071 
3072 /* exec the event handler
3073  *
3074  * update the number of variables fixed to be nonzero
3075  * update the bound constraints
3076  */
3077 static
3078 SCIP_DECL_EVENTEXEC(eventExecCardinality)
3079 {
3080  SCIP_EVENTTYPE eventtype;
3081  SCIP_CONSDATA* consdata;
3082  SCIP_Real oldbound;
3083  SCIP_Real newbound;
3084  SCIP_VAR* var;
3085 
3086  assert(eventhdlr != NULL);
3087  assert(eventdata != NULL);
3088  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
3089  assert(event != NULL);
3090 
3091  consdata = eventdata->consdata;
3092  assert(consdata != NULL);
3093  assert(0 <= consdata->ntreatnonzeros && consdata->ntreatnonzeros <= consdata->nvars);
3094  assert(consdata->eventdatascurrent != NULL);
3095  assert(consdata->eventvarscurrent != NULL);
3096 
3097  var = SCIPeventGetVar(event);
3098  assert(var != NULL);
3099  oldbound = SCIPeventGetOldbound(event);
3100  newbound = SCIPeventGetNewbound(event);
3101  eventtype = SCIPeventGetType(event);
3102 
3103 #ifdef SCIP_DEBUG
3104  if( ( eventdata->varmarked && var == eventdata->var) || ( eventdata->indvarmarked && var == eventdata->indvar) )
3105  {
3106  int i;
3107 
3108  for( i = 0; i < consdata->neventdatascurrent; ++i )
3109  {
3110  if( var == consdata->eventvarscurrent[i] )
3111  {
3112  break;
3113  }
3114  }
3115  assert(i < consdata->neventdatascurrent);
3116  }
3117 #endif
3118 
3119  /* if variable is an indicator variable */
3120  if( var == eventdata->indvar )
3121  {
3122  assert(SCIPvarIsBinary(var));
3123  assert(consdata->cons != NULL);
3124 
3125  if( eventtype == SCIP_EVENTTYPE_LBTIGHTENED || eventtype == SCIP_EVENTTYPE_LBRELAXED )
3126  {
3127  if( eventtype == SCIP_EVENTTYPE_LBTIGHTENED )
3128  ++(consdata->ntreatnonzeros);
3129  else if( eventtype == SCIP_EVENTTYPE_LBRELAXED )
3130  --(consdata->ntreatnonzeros);
3131 
3132  assert(0 <= consdata->ntreatnonzeros && consdata->ntreatnonzeros <= consdata->nvars);
3133  }
3134  else if( eventtype == SCIP_EVENTTYPE_UBTIGHTENED && ! eventdata->indvarmarked )
3135  {
3136  assert(oldbound == 1.0 && newbound == 0.0 );
3137 
3138  /* save event data for propagation */
3139  consdata->eventdatascurrent[consdata->neventdatascurrent] = eventdata;
3140  consdata->eventvarscurrent[consdata->neventdatascurrent] = var;
3141  ++consdata->neventdatascurrent;
3142  eventdata->indvarmarked = TRUE;
3143  assert(consdata->neventdatascurrent <= 4 * consdata->maxvars);
3144  assert(var == eventdata->indvar );
3145  }
3146  }
3147 
3148  /* if variable is an implied variable,
3149  * notice that the case consdata->var = consdata->indvar is possible */
3150  if( var == eventdata->var && ! eventdata->varmarked )
3151  {
3152  if( eventtype == SCIP_EVENTTYPE_LBTIGHTENED )
3153  {
3154  /* if variable is now fixed to be nonzero */
3155  if( !SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
3156  {
3157  /* save event data for propagation */
3158  consdata->eventdatascurrent[consdata->neventdatascurrent] = eventdata;
3159  consdata->eventvarscurrent[consdata->neventdatascurrent] = var;
3160  ++consdata->neventdatascurrent;
3161  eventdata->varmarked = TRUE;
3162  assert(consdata->neventdatascurrent <= 4 * consdata->maxvars );
3163  assert(var == eventdata->var );
3164  }
3165  }
3166  else if( eventtype == SCIP_EVENTTYPE_UBTIGHTENED )
3167  {
3168  /* if variable is now fixed to be nonzero */
3169  if( !SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
3170  {
3171  /* save event data for propagation */
3172  consdata->eventdatascurrent[consdata->neventdatascurrent] = eventdata;
3173  consdata->eventvarscurrent[consdata->neventdatascurrent] = var;
3174  ++consdata->neventdatascurrent;
3175  eventdata->varmarked = TRUE;
3176  assert(consdata->neventdatascurrent <= 4 * consdata->maxvars );
3177  assert(var == eventdata->var);
3178  }
3179  }
3180  }
3181  assert(0 <= consdata->ntreatnonzeros && consdata->ntreatnonzeros <= consdata->nvars);
3182 
3183  SCIPdebugMsg(scip, "event exec cons <%s>: changed bound of variable <%s> from %f to %f (ntreatnonzeros: %d).\n",
3184  SCIPconsGetName(consdata->cons), SCIPvarGetName(SCIPeventGetVar(event)),
3185  oldbound, newbound, consdata->ntreatnonzeros);
3186 
3187  return SCIP_OKAY;
3188 }
3189 
3190 /* ---------------- Constraint specific interface methods ---------------- */
3191 
3192 /** creates the handler for cardinality constraints and includes it in SCIP */
3194  SCIP* scip /**< SCIP data structure */
3195  )
3197  SCIP_CONSHDLRDATA* conshdlrdata;
3198  SCIP_CONSHDLR* conshdlr;
3199 
3200  /* create constraint handler data */
3201  SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
3202  conshdlrdata->eventhdlr = NULL;
3203  conshdlrdata->varhash = NULL;
3204 
3205  /* create event handler for bound change events */
3206  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &conshdlrdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC,
3207  eventExecCardinality, NULL) );
3208  if( conshdlrdata->eventhdlr == NULL )
3209  {
3210  SCIPerrorMessage("event handler for cardinality constraints not found.\n");
3211  return SCIP_PLUGINNOTFOUND;
3212  }
3213 
3214  /* include constraint handler */
3217  consEnfolpCardinality, consEnfopsCardinality, consCheckCardinality, consLockCardinality, conshdlrdata) );
3218  assert(conshdlr != NULL);
3219 
3220  /* set non-fundamental callbacks via specific setter functions */
3221  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyCardinality, consCopyCardinality) );
3222  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteCardinality) );
3223  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolCardinality) );
3224  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeCardinality) );
3225  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsCardinality) );
3226  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsCardinality) );
3227  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpCardinality) );
3228  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseCardinality) );
3229  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolCardinality, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
3230  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintCardinality) );
3231  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropCardinality, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
3233  /*SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropCardinality) ); @todo: implement repropagation */
3234  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpCardinality, consSepasolCardinality, CONSHDLR_SEPAFREQ,
3236  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransCardinality) );
3237  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxCardinality) );
3238 
3239  /* add cardinality constraint handler parameters */
3240  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/branchbalanced",
3241  "whether to use balanced instead of unbalanced branching",
3242  &conshdlrdata->branchbalanced, TRUE, DEFAULT_BRANCHBALANCED, NULL, NULL) );
3243 
3244  SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/balanceddepth",
3245  "maximum depth for using balanced branching (-1: no limit)",
3246  &conshdlrdata->balanceddepth, TRUE, DEFAULT_BALANCEDDEPTH, -1, INT_MAX, NULL, NULL) );
3247 
3248  SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/balancedcutoff",
3249  "determines that balanced branching is only used if the branching cut off value \
3250  w.r.t. the current LP solution is greater than a given value",
3251  &conshdlrdata->balancedcutoff, TRUE, DEFAULT_BALANCEDCUTOFF, 0.01, SCIP_REAL_MAX, NULL, NULL) );
3252 
3253  return SCIP_OKAY;
3254 }
3255 
3256 /** creates and captures a cardinality constraint
3257  *
3258  * We set the constraint to not be modifable. If the weights are non
3259  * NULL, the variables are ordered according to these weights (in
3260  * ascending order).
3261  *
3262  * @note the constraint gets captured, hence at one point you have to release it using the method \ref SCIPreleaseCons()
3263  */
3265  SCIP* scip, /**< SCIP data structure */
3266  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3267  const char* name, /**< name of constraint */
3268  int nvars, /**< number of variables in the constraint */
3269  SCIP_VAR** vars, /**< array with variables of constraint entries */
3270  int cardval, /**< number of variables allowed to be nonzero */
3271  SCIP_VAR** indvars, /**< indicator variables indicating which variables may be treated as nonzero
3272  * in cardinality constraint, or NULL if new indicator variables should be
3273  * introduced automatically */
3274  SCIP_Real* weights, /**< weights determining the variable order, or NULL if variables should be
3275  ordered in the same way they were added to the constraint */
3276  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3277  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3278  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3279  * Usually set to TRUE. */
3280  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3281  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3282  SCIP_Bool check, /**< should the constraint be checked for feasibility?
3283  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3284  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3285  * Usually set to TRUE. */
3286  SCIP_Bool local, /**< is constraint only valid locally?
3287  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3288  SCIP_Bool dynamic, /**< is constraint subject to aging?
3289  * Usually set to FALSE. Set to TRUE for own cuts which
3290  * are separated as constraints. */
3291  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3292  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3293  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3294  * if it may be moved to a more global node?
3295  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3296  )
3297 {
3298  SCIP_CONSHDLRDATA* conshdlrdata;
3299  SCIP_CONSHDLR* conshdlr;
3300  SCIP_CONSDATA* consdata;
3301  SCIP_Bool modifiable;
3302  SCIP_Bool transformed;
3303  int v;
3304 
3305  modifiable = FALSE;
3306 
3307  /* find the cardinality constraint handler */
3308  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3309  if( conshdlr == NULL )
3310  {
3311  SCIPerrorMessage("<%s> constraint handler not found\n", CONSHDLR_NAME);
3312  return SCIP_PLUGINNOTFOUND;
3313  }
3314 
3315  /* get constraint handler data */
3316  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3317  assert(conshdlrdata != NULL);
3318 
3319  /* are we in the transformed problem? */
3320  transformed = SCIPgetStage(scip) >= SCIP_STAGE_TRANSFORMED;
3321 
3322  /* create constraint data */
3323  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
3324  consdata->cons = NULL;
3325  consdata->vars = NULL;
3326  consdata->indvars = NULL;
3327  consdata->eventdatas = NULL;
3328  consdata->nvars = nvars;
3329  consdata->cardval = cardval;
3330  consdata->maxvars = nvars;
3331  consdata->rowub = NULL;
3332  consdata->rowlb = NULL;
3333  consdata->eventdatascurrent = NULL;
3334  consdata->eventvarscurrent = NULL;
3335  consdata->neventdatascurrent = 0;
3336  consdata->ntreatnonzeros = transformed ? 0 : -1;
3337  consdata->weights = NULL;
3338 
3339  if( nvars > 0 )
3340  {
3341  /* duplicate memory for implied variables */
3342  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->vars, vars, nvars) );
3343 
3344  /* create indicator variables if not present */
3345  if( indvars != NULL )
3346  {
3347  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->indvars, indvars, nvars) );
3348  }
3349  else
3350  {
3351  if( conshdlrdata->varhash == NULL )
3352  {
3353  /* set up hash map */
3354  SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), SCIPgetNTotalVars(scip)) );
3355  }
3356 
3357  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->indvars, nvars) );
3358  for( v = 0; v < nvars; ++v )
3359  {
3360  SCIP_VAR* implvar;
3361 
3362  implvar = vars[v];
3363  assert(implvar != NULL);
3364 
3365  /* check whether an indicator variable already exists for implied variable */
3366  if( SCIPhashmapExists(conshdlrdata->varhash, implvar) )
3367  {
3368  assert((SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, implvar) != NULL);
3369  consdata->indvars[v] = (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, implvar);
3370  }
3371  else
3372  {
3373  /* if implied variable is binary, then it is not necessary to create an indicator variable */
3374  if( SCIPvarIsBinary(implvar) )
3375  consdata->indvars[v] = implvar;
3376  else
3377  {
3378  char varname[SCIP_MAXSTRLEN];
3379  SCIP_VAR* var;
3380 
3381  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "ind_%s", SCIPvarGetName(vars[v]));
3382  SCIP_CALL( SCIPcreateVar(scip, &var, varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY, FALSE, FALSE,
3383  NULL, NULL, NULL, NULL, NULL) );
3384  SCIP_CALL( SCIPaddVar(scip, var) );
3385  consdata->indvars[v] = var;
3386  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3387  }
3388 
3389  /* insert implied variable to hash map */
3390  SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varhash, implvar, (void*) consdata->indvars[v]) );/*lint !e571*/
3391  assert(consdata->indvars[v] == (SCIP_VAR*) SCIPhashmapGetImage(conshdlrdata->varhash, implvar));
3392  assert(SCIPhashmapExists(conshdlrdata->varhash, implvar));
3393  }
3394  }
3395  }
3396 
3397  /* allocate block memory */
3398  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatascurrent, 4*nvars) );/*lint !e647*/
3399  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventvarscurrent, 4*nvars) );/*lint !e647*/
3400  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatas, nvars) );
3401 
3402  /* check weights */
3403  if( weights != NULL )
3404  {
3405  int* dummy;
3406 
3407  /* store weights */
3408  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, weights, nvars) );
3409 
3410  /* create dummy array to make code compatible with SCIP 3.2.0
3411  * (the function SCIPsortRealPtrPtr() is not available) */
3412  SCIP_CALL( SCIPallocBufferArray(scip, &dummy, nvars) );
3413  for( v = 0; v < nvars; ++v )
3414  dummy[v] = 0;
3415 
3416  /* sort variables - ascending order */
3417  SCIPsortRealPtrPtrInt(consdata->weights, (void**)consdata->vars, (void**)consdata->indvars, dummy, nvars);
3418 
3419  SCIPfreeBufferArray(scip, &dummy);
3420  }
3421  }
3422  else
3423  {
3424  assert(weights == NULL);
3425  }
3426 
3427  /* create cardinality constraint */
3428  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3429  local, modifiable, dynamic, removable, stickingatnode) );
3430 
3431  consdata->cons = *cons;
3432  assert(consdata->cons != NULL);
3433 
3434  /* replace original variables by transformed variables in transformed constraint, add locks, and catch events */
3435  for( v = nvars - 1; v >= 0; --v )
3436  {
3437  /* always use transformed variables in transformed constraints */
3438  if( transformed )
3439  {
3440  SCIP_CALL( SCIPgetTransformedVar(scip, consdata->vars[v], &(consdata->vars[v])) );
3441  SCIP_CALL( SCIPgetTransformedVar(scip, consdata->indvars[v], &(consdata->indvars[v])) );
3442  }
3443  assert(consdata->vars[v] != NULL);
3444  assert(consdata->indvars[v] != NULL);
3445  assert(transformed == SCIPvarIsTransformed(consdata->vars[v]));
3446  assert(transformed == SCIPvarIsTransformed(consdata->indvars[v]));
3447 
3448  /* handle the new variable */
3449  SCIP_CALL( handleNewVariableCardinality(scip, *cons, consdata, conshdlrdata, consdata->vars[v],
3450  consdata->indvars[v], v, transformed, &consdata->eventdatas[v]) );
3451  assert(! transformed || consdata->eventdatas[v] != NULL);
3452  }
3453 
3454  return SCIP_OKAY;
3455 }
3456 
3457 /** creates and captures a cardinality constraint with all constraint flags set to their default values.
3458  *
3459  * @warning Do NOT set the constraint to be modifiable manually, because this might lead
3460  * to wrong results as the variable array will not be resorted
3461  *
3462  * @note the constraint gets captured, hence at one point you have to release it using the method \ref SCIPreleaseCons()
3463  */
3465  SCIP* scip, /**< SCIP data structure */
3466  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3467  const char* name, /**< name of constraint */
3468  int nvars, /**< number of variables in the constraint */
3469  SCIP_VAR** vars, /**< array with variables of constraint entries */
3470  int cardval, /**< number of variables allowed to be nonzero */
3471  SCIP_VAR** indvars, /**< indicator variables indicating which variables may be treated as nonzero
3472  * in cardinality constraint, or NULL if new indicator variables should be
3473  * introduced automatically */
3474  SCIP_Real* weights /**< weights determining the variable order, or NULL if variables should be
3475  * ordered in the same way they were added to the constraint */
3476  )
3477 {
3478  SCIP_CALL( SCIPcreateConsCardinality(scip, cons, name, nvars, vars, cardval, indvars, weights, TRUE, TRUE, TRUE, TRUE,
3479  TRUE, FALSE, FALSE, FALSE, FALSE) );
3480 
3481  return SCIP_OKAY;
3482 }
3483 
3484 /** changes cardinality value of cardinality constraint (i.e., right hand side of cardinality constraint) */
3486  SCIP* scip, /**< SCIP data structure */
3487  SCIP_CONS* cons, /**< pointer to hold the created constraint */
3488  int cardval /**< number of variables allowed to be nonzero */
3489  )
3490 {
3491  SCIP_CONSDATA* consdata;
3492 
3493  assert(scip != NULL);
3494  assert(cons != NULL);
3495 
3496  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3497  {
3498  SCIPerrorMessage("constraint is not a cardinality constraint.\n");
3499  return SCIP_INVALIDDATA;
3500  }
3501 
3502  consdata = SCIPconsGetData(cons);
3503  assert(consdata != NULL);
3504 
3505  SCIPdebugMsg(scip, "modify right hand side of cardinality constraint from <%i> to <%i>\n", consdata->cardval, cardval);
3506 
3507  /* create constraint data */
3508  consdata->cardval = cardval;
3509 
3510  return SCIP_OKAY;
3511 }
3512 
3513 /** adds variable to cardinality constraint, the position is determined by the given weight */
3515  SCIP* scip, /**< SCIP data structure */
3516  SCIP_CONS* cons, /**< constraint */
3517  SCIP_VAR* var, /**< variable to add to the constraint */
3518  SCIP_VAR* indvar, /**< indicator variable indicating whether variable may be treated as nonzero
3519  * in cardinality constraint (or NULL if this variable should be created
3520  * automatically) */
3521  SCIP_Real weight /**< weight determining position of variable */
3522  )
3523 {
3524  SCIP_CONSHDLRDATA* conshdlrdata;
3525  SCIP_CONSHDLR* conshdlr;
3526 
3527  assert(scip != NULL);
3528  assert(var != NULL);
3529  assert(cons != NULL);
3530 
3531  SCIPdebugMsg(scip, "adding variable <%s> to constraint <%s> with weight %g\n", SCIPvarGetName(var),
3532  SCIPconsGetName(cons), weight);
3533 
3534  conshdlr = SCIPconsGetHdlr(cons);
3535  assert(conshdlr != NULL);
3536  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
3537  {
3538  SCIPerrorMessage("constraint is not a cardinality constraint.\n");
3539  return SCIP_INVALIDDATA;
3540  }
3541 
3542  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3543  assert(conshdlrdata != NULL);
3544 
3545  SCIP_CALL( addVarCardinality(scip, cons, conshdlrdata, var, indvar, weight) );
3546 
3547  return SCIP_OKAY;
3548 }
3549 
3550 /** appends variable to cardinality constraint */
3552  SCIP* scip, /**< SCIP data structure */
3553  SCIP_CONS* cons, /**< constraint */
3554  SCIP_VAR* var, /**< variable to add to the constraint */
3555  SCIP_VAR* indvar /**< indicator variable indicating whether variable may be treated as nonzero
3556  * in cardinality constraint (or NULL if this variable should be created
3557  * automatically) */
3558  )
3559 {
3560  SCIP_CONSHDLRDATA* conshdlrdata;
3561  SCIP_CONSHDLR* conshdlr;
3562 
3563  assert(scip != NULL);
3564  assert(var != NULL);
3565  assert(cons != NULL);
3566 
3567  SCIPdebugMsg(scip, "appending variable <%s> to constraint <%s>\n", SCIPvarGetName(var), SCIPconsGetName(cons));
3568 
3569  conshdlr = SCIPconsGetHdlr(cons);
3570  assert(conshdlr != NULL);
3571  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
3572  {
3573  SCIPerrorMessage("constraint is not a cardinality constraint.\n");
3574  return SCIP_INVALIDDATA;
3575  }
3576 
3577  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3578  assert(conshdlrdata != NULL);
3579 
3580  SCIP_CALL( appendVarCardinality(scip, cons, conshdlrdata, var, indvar) );
3581 
3582  return SCIP_OKAY;
3583 }
3584 
3585 /** gets number of variables in cardinality constraint */
3587  SCIP* scip, /**< SCIP data structure */
3588  SCIP_CONS* cons /**< constraint */
3589  )
3590 {
3591  SCIP_CONSDATA* consdata;
3592 
3593  assert(scip != NULL);
3594  assert(cons != NULL);
3595 
3596  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3597  {
3598  SCIPerrorMessage("constraint is not a cardinality constraint.\n");
3599  SCIPABORT();
3600  return -1; /*lint !e527*/
3601  }
3602 
3603  consdata = SCIPconsGetData(cons);
3604  assert(consdata != NULL);
3605 
3606  return consdata->nvars;
3607 }
3608 
3609 /** gets array of variables in cardinality constraint */
3611  SCIP* scip, /**< SCIP data structure */
3612  SCIP_CONS* cons /**< constraint data */
3613  )
3614 {
3615  SCIP_CONSDATA* consdata;
3616 
3617  assert(scip != NULL);
3618  assert(cons != NULL);
3619 
3620  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3621  {
3622  SCIPerrorMessage("constraint is not a cardinality constraint.\n");
3623  SCIPABORT();
3624  return NULL; /*lint !e527*/
3625  }
3626 
3627  consdata = SCIPconsGetData(cons);
3628  assert(consdata != NULL);
3629 
3630  return consdata->vars;
3631 }
3632 
3633 /** gets cardinality value of cardinality constraint (i.e., right hand side of cardinality constraint) */
3635  SCIP* scip, /**< SCIP data structure */
3636  SCIP_CONS* cons /**< constraint data */
3637  )
3638 {
3639  SCIP_CONSDATA* consdata;
3640 
3641  assert(scip != NULL);
3642  assert(cons != NULL);
3643 
3644  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3645  {
3646  SCIPerrorMessage("constraint is not a cardinality constraint.\n");
3647  return -1; /*lint !e527*/
3648  }
3649 
3650  consdata = SCIPconsGetData(cons);
3651  assert(consdata != NULL);
3652 
3653  return consdata->cardval;
3654 }
3655 
3656 /** gets array of weights in cardinality constraint (or NULL if not existent) */
3658  SCIP* scip, /**< SCIP data structure */
3659  SCIP_CONS* cons /**< constraint data */
3660  )
3661 {
3662  SCIP_CONSDATA* consdata;
3663 
3664  assert(scip != NULL);
3665  assert(cons != NULL);
3666 
3667  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3668  {
3669  SCIPerrorMessage("constraint is not a cardinality constraint.\n");
3670  SCIPABORT();
3671  return NULL; /*lint !e527*/
3672  }
3673 
3674  consdata = SCIPconsGetData(cons);
3675  assert(consdata != NULL);
3676 
3677  return consdata->weights;
3678 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21975
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:46385
static SCIP_RETCODE handleNewVariableCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_VAR *var, SCIP_VAR *indvar, int pos, SCIP_Bool transformed, SCIP_EVENTDATA **eventdata)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:21964
#define CONSHDLR_SEPAPRIORITY
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18906
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6263
#define EVENTHDLR_NAME
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21958
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46320
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:40680
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:814
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8140
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16961
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6286
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46333
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:40502
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6576
void SCIPsortRealPtrPtrInt(SCIP_Real *realarray, void **ptrarray1, void **ptrarray2, int *intarray, int len)
static SCIP_DECL_CONSSEPASOL(consSepasolCardinality)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17169
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6516
SCIP_Real SCIPgetLocalTransEstimate(SCIP *scip)
Definition: scip.c:13232
#define SCIP_MAXSTRLEN
Definition: def.h:225
SCIP_RETCODE SCIPaddVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar, SCIP_Real weight)
static SCIP_DECL_CONSGETVARS(consGetVarsCardinality)
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6008
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28056
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12530
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:45835
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16949
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30418
static SCIP_DECL_CONSPRESOL(consPresolCardinality)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:46110
static SCIP_RETCODE fixVariableZeroNode(SCIP *scip, SCIP_VAR *var, SCIP_NODE *node, SCIP_Bool *infeasible)
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17225
static SCIP_DECL_CONSPARSE(consParseCardinality)
SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:21875
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8561
static SCIP_DECL_CONSEXITSOL(consExitsolCardinality)
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18652
static SCIP_RETCODE enforceCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, int nconss, SCIP_CONS **conss, SCIP_RESULT *result)
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:17733
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18461
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16735
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:46409
static SCIP_RETCODE deleteVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:16391
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2764
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
static SCIP_RETCODE generateRowCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_Bool local, SCIP_ROW **rowlb, SCIP_ROW **rowub)
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.c:5866
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:46050
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:46122
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
#define EVENTHDLR_DESC
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define DEFAULT_BRANCHBALANCED
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21349
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8160
#define CONSHDLR_DESC
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8190
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21973
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.c:5920
SCIP_RETCODE SCIPchgVarUbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:21919
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:21999
int SCIPconshdlrGetSepaFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4999
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:21705
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2902
static SCIP_DECL_CONSTRANS(consTransCardinality)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22003
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21956
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1010
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8150
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6309
#define SCIPdebugMsg
Definition: scip.h:451
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.c:4237
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6493
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1336
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.c:27240
static SCIP_RETCODE addVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_VAR *var, SCIP_VAR *indvar, SCIP_Real weight)
#define CONSHDLR_DELAYPROP
static SCIP_DECL_CONSPROP(consPropCardinality)
static SCIP_RETCODE appendVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_VAR *var, SCIP_VAR *indvar)
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16602
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2996
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:64
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17179
static SCIP_RETCODE fixVariableZero(SCIP *scip, SCIP_VAR *var, SCIP_Bool *infeasible, SCIP_Bool *tightened)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:21970
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:33891
Constraint handler for knapsack constraints of the form , x binary and .
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1162
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:37468
static SCIP_RETCODE catchVarEventCardinality(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_VAR *indvar, int pos, SCIP_EVENTDATA **eventdata)
SCIP_RETCODE SCIPincludeConshdlrCardinality(SCIP *scip)
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:6032
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12459
static SCIP_RETCODE lockVariableCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar)
static SCIP_DECL_CONSINITLP(consInitlpCardinality)
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13160
#define CONSHDLR_MAXPREROUNDS
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:19006
static SCIP_RETCODE branchUnbalancedCardinality(SCIP *scip, SCIP_SOL *sol, SCIP_CONS *branchcons, SCIP_VAR **vars, SCIP_VAR **indvars, int nvars, int cardval, int branchnnonzero, int branchpos)
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45753
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21477
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyCardinality)
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:25588
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8100
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6057
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2797
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
static SCIP_DECL_CONSENFORELAX(consEnforelaxCardinality)
#define NULL
Definition: lpi_spx1.cpp:137
#define REALABS(x)
Definition: def.h:169
SCIP_RETCODE SCIPcreateConsKnapsack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Longint *weights, SCIP_Longint capacity, 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 SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip.c:36877
static SCIP_DECL_CONSLOCK(consLockCardinality)
#define CONSHDLR_DELAYSEPA
#define SCIP_CALL(x)
Definition: def.h:316
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
int SCIPgetNTotalVars(SCIP *scip)
Definition: scip.c:12257
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46359
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16973
static SCIP_DECL_CONSFREE(consFreeCardinality)
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:16401
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1353
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8120
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:33999
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
static SCIP_RETCODE polishPrimalSolution(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_SOL *primsol)
static SCIP_RETCODE presolRoundCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *success, int *ndelconss, int *nupgdconss, int *nfixedvars, int *nremovedvars)
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:13009
int SCIPgetCardvalCardinality(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSENFOLP(consEnfolpCardinality)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21991
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:38042
static SCIP_DECL_CONSSEPALP(consSepalpCardinality)
static SCIP_RETCODE dropVarEventCardinality(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_VAR *indvar, SCIP_EVENTDATA **eventdata)
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:982
#define CONSHDLR_NAME
#define SCIP_Bool
Definition: def.h:61
static SCIP_DECL_CONSPRINT(consPrintCardinality)
static SCIP_DECL_CONSGETNVARS(consGetNVarsCardinality)
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
static SCIP_RETCODE separateCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, int nconss, SCIP_CONS **conss, SCIP_RESULT *result)
#define DEFAULT_BALANCEDDEPTH
SCIP_Real * SCIPgetWeightsCardinality(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30152
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:42321
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:28746
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_DECL_CONSENFOPS(consEnfopsCardinality)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7901
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:37806
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8080
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8050
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:40548
SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
Definition: scip.c:36827
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17314
static SCIP_RETCODE unlockVariableCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar)
#define CONSHDLR_SEPAFREQ
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:25235
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:93
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21403
#define CONSHDLR_PROP_TIMING
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6470
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16937
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:46061
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:39976
SCIP_Real SCIPcalcChildEstimate(SCIP *scip, SCIP_VAR *var, SCIP_Real targetvalue)
Definition: scip.c:36854
static SCIP_RETCODE consdataEnsurevarsSizeCardinality(SCIP *scip, SCIP_CONSDATA *consdata, int num, SCIP_Bool reserveweights)
#define SCIP_REAL_MAX
Definition: def.h:146
static SCIP_RETCODE consdataUnmarkEventdataVars(SCIP_CONSDATA *consdata)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
#define CONSHDLR_EAGERFREQ
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30290
#define CONSHDLR_PRESOLTIMING
SCIP_RETCODE SCIPcreateConsCardinality(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, int cardval, SCIP_VAR **indvars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46024
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1912
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11360
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7911
#define CONSHDLR_PROPFREQ
constraint handler for cardinality constraints
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27417
#define CONSHDLR_NEEDSCONS
SCIP_RETCODE SCIPcreateConsBasicCardinality(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, int cardval, SCIP_VAR **indvars, SCIP_Real *weights)
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6225
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1138
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:46397
static SCIP_RETCODE propCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *cutoff, int *nchgdomain)
#define DEFAULT_BALANCEDCUTOFF
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16674
#define SCIP_Real
Definition: def.h:145
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8130
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:30444
int SCIPgetNVarsCardinality(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1138
#define MIN(x, y)
Definition: memory.c:75
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6539
SCIP_RETCODE SCIPchgCardvalCardinality(SCIP *scip, SCIP_CONS *cons, int cardval)
static SCIP_RETCODE initsepaBoundInequalityFromCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_Bool solvedinitlp, int *ngen, SCIP_Bool *cutoff)
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8070
SCIP_RETCODE SCIPappendVarCardinality(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_VAR *indvar)
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8060
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:30892
#define SCIP_Longint
Definition: def.h:130
static SCIP_DECL_CONSCOPY(consCopyCardinality)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:46098
SCIP_VAR ** SCIPgetVarsCardinality(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46011
#define CONSHDLR_CHECKPRIORITY
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17235
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16697
static SCIP_DECL_EVENTEXEC(eventExecCardinality)
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2845
static SCIP_DECL_CONSCHECK(consCheckCardinality)
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6153
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:41409
#define SCIPABORT()
Definition: def.h:288
static SCIP_RETCODE branchBalancedCardinality(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_SOL *sol, SCIP_CONS *branchcons, SCIP_VAR **vars, SCIP_VAR **indvars, int nvars, int cardval, int branchnnonzero, int branchpos, SCIP_Real balancedcutoff)
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:17430
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38182
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4293
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:46171
#define CONSHDLR_ENFOPRIORITY
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.c:4211
static SCIP_DECL_CONSDELETE(consDeleteCardinality)
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5966