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