Scippy

SCIP

Solving Constraint Integer Programs

cons_linking.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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_linking.c
17  * @brief constraint handler for linking constraints
18  * @author Stefan Heinz
19  * @author Jens Schulz
20  *
21  * The constraints handler stores linking constraints between an integer variable and an array of binary variables. Such
22  * a linking constraint has the form:
23  *
24  * intvar = sum_{i=1}^n {vals[i] * binvars[i]}
25  *
26  * with the additional side condition that exactly one binary variable has to be one (set partitioning condition).
27  *
28  * This constraint can be created only with the integer variable. In this case the binary variables are only created on
29  * demand. That is, whenever someone asks for the binary variables. Therefore, such constraints can be used to get a
30  * "binary representation" of the domain of the integer variable which will be dynamically created.
31  *
32  *
33  * @todo add pairwise comparison of constraints in presolving (fast hash table version and complete pairwise comparison)
34  * @todo in case the integer variable is set to lower or upper bound it follows that only the corresponding binary
35  * variable has a positive value which is one, this can be used to fasten the checking routine
36  */
37 
38 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
39 
40 #include <assert.h>
41 #include <string.h>
42 #include <ctype.h>
43 
44 #include "scip/cons_linear.h"
45 #include "scip/cons_linking.h"
46 #include "scip/cons_setppc.h"
47 
48 /* constraint handler properties */
49 #define CONSHDLR_NAME "linking"
50 #define CONSHDLR_DESC "linking constraint x = sum_{i=1}^{n} c_i*y_i, y1+...+yn = 1, x integer, y's binary"
51 
52 #define EVENTHDLR_NAME "linking"
53 #define EVENTHDLR_DESC "event handler for linking constraints"
54 
55 #define CONSHDLR_SEPAPRIORITY 750000 /**< priority of the constraint handler for separation */
56 #define CONSHDLR_ENFOPRIORITY -2050000 /**< priority of the constraint handler for constraint enforcing */
57 #define CONSHDLR_CHECKPRIORITY -750000 /**< priority of the constraint handler for checking feasibility */
58 #define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
59 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
60 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation, propagation and enforcement, -1 for no eager evaluations, 0 for first only */
61 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
62 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
63 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
64 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
65 
66 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
67 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
68 
69 
70 #define HASHSIZE_BINVARSCONS 500 /**< minimal size of hash table in linking constraint handler */
71 #define DEFAULT_LINEARIZE FALSE /**< should the linking constraint be linearize after the binary variable are created */
72 
73 /*
74  * Data structures
75  */
76 
77 /** constraint data for linking constraints */
78 struct SCIP_ConsData
79 {
80  SCIP_VAR* intvar; /**< integer variable which is linked */
81  SCIP_VAR** binvars; /**< binary variables */
82  int* vals; /**< coefficients */
83  SCIP_ROW* row1; /**< LP row for the linking itself */
84  SCIP_ROW* row2; /**< LP row ensuring the set partitioning condition of the binary variables */
85  int nbinvars; /**< number of binary variables */
86  int sizebinvars; /**< size of the binary variable array */
87  int nfixedzeros; /**< current number of variables fixed to zero in the constraint */
88  int nfixedones; /**< current number of variables fixed to one in the constraint */
89  int firstnonfixed; /**< index of first locally non-fixed binary variable in binvars array */
90  int lastnonfixed; /**< index of last locally non-fixed binary variable in binvars array */
91  unsigned int cliqueadded:1; /**< was the set partitioning condition already added as clique? */
92  unsigned int sorted:1; /**< are the coefficients of the binary variables are sorted in non-decreasing order */
93 };
94 
95 /** constraint handler data */
96 struct SCIP_ConshdlrData
97 {
98  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events on binary variables */
99  SCIP_HASHMAP* varmap; /**< hash map mapping an integer variable to its linking constraint */
100  SCIP_Bool linearize; /**< should the linking constraint be linearize after the binary variable are created */
101 };
102 
103 /*
104  * Local methods
105  */
106 
107 /** returns for a given integer variable the corresponding hash map key */
108 static
110  SCIP_VAR* var /**< variable to get the hash map key for */
111  )
112 {
113  /* return the unique variable index + 1 */
114  return (void*)(size_t)(SCIPvarGetIndex(var) + 1); /*lint !e571 !e776*/
115 }
116 
117 /* sort binary variable in non-decreasing order w.r.t. coefficients */
118 static
120  SCIP_CONSDATA* consdata /**< linking constraint data */
121  )
122 {
123  if( consdata->sorted )
124  return;
125 
126  /* sort binary variable in non-decreasing order w.r.t. coefficients */
127  SCIPsortIntPtr(consdata->vals, (void**)consdata->binvars, consdata->nbinvars);
128 
129  consdata->sorted = TRUE;
130 }
131 
132 
133 /** installs rounding locks for the binary variables in the given linking constraint */
134 static
136  SCIP* scip, /**< SCIP data structure */
137  SCIP_CONS* cons, /**< linking constraint */
138  SCIP_VAR** binvars, /**< binary variables */
139  int nbinvars /**< number of binary variables */
140  )
141 {
142  int b;
143 
144  for( b = 0; b < nbinvars; ++b )
145  {
146  SCIP_CALL( SCIPlockVarCons(scip, binvars[b], cons, TRUE, TRUE) );
147  }
148 
149  return SCIP_OKAY;
150 }
151 
152 /** creates constraint handler data for the linking constraint handler */
153 static
155  SCIP* scip, /**< SCIP data structure */
156  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
157  SCIP_EVENTHDLR* eventhdlr /**< event handler */
158  )
159 {
160  assert(scip != NULL);
161  assert(conshdlrdata != NULL);
162  assert(eventhdlr != NULL);
163 
164  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
165 
166  /* create hash map */
167  (*conshdlrdata)->varmap = NULL;
168 
169  /* set event handler for bound change events on binary variables */
170  (*conshdlrdata)->eventhdlr = eventhdlr;
171 
172  return SCIP_OKAY;
173 }
174 
175 /** frees constraint handler data for linking constraint handler */
176 static
178  SCIP* scip, /**< SCIP data structure */
179  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
180  )
181 {
182  assert(conshdlrdata != NULL);
183  assert(*conshdlrdata != NULL);
184 
185  /* free hash map */
186  if( (*conshdlrdata)->varmap != NULL )
187  SCIPhashmapFree(&(*conshdlrdata)->varmap);
188 
189  /* free memory of constraint handler data */
190  SCIPfreeBlockMemory(scip, conshdlrdata);
191 
192  return SCIP_OKAY;
193 }
194 
195 /** prints linking constraint to file stream */
196 static
198  SCIP* scip, /**< SCIP data structure */
199  SCIP_CONSDATA* consdata, /**< linking constraint data */
200  FILE* file /**< output file (or NULL for standard output) */
201  )
202 {
203  SCIP_VAR** binvars;
204  SCIP_VAR* intvar;
205  int nbinvars;
206  int b;
207 
208  assert(scip != NULL);
209  assert(consdata != NULL);
210 
211  intvar = consdata->intvar;
212  binvars = consdata->binvars;
213  nbinvars = consdata->nbinvars;
214 
215  assert(intvar != NULL);
216  assert(binvars != NULL || nbinvars == 0);
217 
218  /* print integer variable */
219  SCIP_CALL( SCIPwriteVarName(scip, file, intvar, FALSE) );
220 
221  SCIPinfoMessage(scip, file, " = ");
222 
223  if( nbinvars == 0 )
224  {
225  SCIPinfoMessage(scip, file, " no binary variables yet");
226  }
227  else
228  {
229  SCIP_Real* vals;
230 
231  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbinvars) );
232 
233  assert(binvars != NULL);
234 
235  /* convert integer coefficients into SCIP_Real */
236  for( b = 0; b < nbinvars; ++b )
237  {
238  vals[b] = (SCIP_Real)consdata->vals[b];
239  }
240 
241  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, binvars, vals, nbinvars, FALSE) );
242 
243  SCIPfreeBufferArray(scip, &vals);
244  }
245 
246  return SCIP_OKAY;
247 }
248 
249 /** catches events for variable at given position */
250 static
252  SCIP* scip, /**< SCIP data structure */
253  SCIP_CONSDATA* consdata, /**< linking constraint data */
254  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
255  int pos /**< array position of variable to catch bound change events for */
256  )
257 {
258  SCIP_VAR* var;
259 
260  assert(consdata != NULL);
261  assert(eventhdlr != NULL);
262  assert(0 <= pos && pos < consdata->nbinvars);
263  assert(consdata->binvars != NULL);
264 
265  var = consdata->binvars[pos];
266  assert(var != NULL);
267 
268  /* catch bound change events on variable */
269  /**@todo do we have to add the event SCIP_EVENTTYPE_VARFIXED? */
270  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
271 
272  /* update the fixed variables counters for this variable */
273  if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
274  consdata->nfixedzeros++;
275  else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
276  consdata->nfixedones++;
277 
278  return SCIP_OKAY;
279 }
280 
281 /** drops events for variable at given position */
282 static
284  SCIP* scip, /**< SCIP data structure */
285  SCIP_CONSDATA* consdata, /**< linking constraint data */
286  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
287  int pos /**< array position of variable to catch bound change events for */
288  )
289 {
290  SCIP_VAR* var;
291 
292  assert(consdata != NULL);
293  assert(eventhdlr != NULL);
294  assert(0 <= pos && pos < consdata->nbinvars);
295  assert(consdata->binvars != NULL);
296 
297  var = consdata->binvars[pos];
298  assert(var != NULL);
299 
300  /* drop events on variable */
301  SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
302 
303  /* update the fixed variables counters for this variable */
304  if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
305  consdata->nfixedzeros--;
306  else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
307  consdata->nfixedones--;
308 
309  return SCIP_OKAY;
310 }
311 
312 /** catches bound change events for all variables in transformed linking constraint */
313 static
315  SCIP* scip, /**< SCIP data structure */
316  SCIP_CONSDATA* consdata, /**< linking constraint data */
317  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
318  )
319 {
320  int i;
321 
322  assert(consdata != NULL);
323 
324  if( consdata->nbinvars <= 1 )
325  return SCIP_OKAY;
326 
327  /* catch event for every single variable */
328  for( i = 0; i < consdata->nbinvars; ++i )
329  {
330  SCIP_CALL( catchEvent(scip, consdata, eventhdlr, i) );
331  }
332 
333  return SCIP_OKAY;
334 }
335 
336 /** drops bound change events for all variables in transformed linking constraint */
337 static
339  SCIP* scip, /**< SCIP data structure */
340  SCIP_CONSDATA* consdata, /**< linking constraint data */
341  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
342  )
343 {
344  int i;
345 
346  assert(consdata != NULL);
347 
348  if( consdata->nbinvars <= 1 )
349  return SCIP_OKAY;
350 
351  /* drop event of every single variable */
352  for( i = 0; i < consdata->nbinvars; ++i )
353  {
354  SCIP_CALL( dropEvent(scip, consdata, eventhdlr, i) );
355  }
356 
357  return SCIP_OKAY;
358 }
359 
360 /** linearize the given linking constraint into a set partitioning constraint for the binary variables and a linear
361  * constraint for the linking between the integer variable and the binary variables */
362 static
364  SCIP* scip, /**< SCIP data structure */
365  SCIP_CONS* cons, /**< linking constraint */
366  SCIP_CONSDATA* consdata /**< linking constraint data */
367  )
368 {
369  SCIP_CONS* lincons;
370  int b;
371 
372  SCIPdebugMsg(scip, "linearized linking constraint <%s>\n", SCIPconsGetName(cons));
373 
374  /* create set partitioning constraint for the binary variables */
375  SCIP_CALL( SCIPcreateConsSetpart(scip, &lincons, SCIPconsGetName(cons), consdata->nbinvars, consdata->binvars,
379  SCIP_CALL( SCIPaddCons(scip, lincons) );
380  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
381 
382  /* create linear constraint for the linking between the binary variables and the integer variable */
383  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons), 0, NULL, NULL, 0.0, 0.0,
387 
388  for( b = 0; b < consdata->nbinvars; ++b )
389  {
390  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->binvars[b], (SCIP_Real)consdata->vals[b]) );
391  }
392  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->intvar, -1.0) );
393 
394  SCIP_CALL( SCIPaddCons(scip, lincons) );
395  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
396 
397  return SCIP_OKAY;
398 }
399 
400 /** creates the binary variables */
401 static
403  SCIP* scip, /**< SCIP data structure */
404  SCIP_CONS* cons, /**< linking constraint */
405  SCIP_CONSDATA* consdata, /**< linking constraint data */
406  SCIP_EVENTHDLR* eventhdlr, /**< event handler for bound change events on binary variables */
407  SCIP_Bool linearize /**< should the linking constraint be linearized */
408  )
409 {
410  SCIP_VAR* intvar;
411  SCIP_VAR* binvar;
412  char name[SCIP_MAXSTRLEN];
413  int nbinvars;
414  int lb;
415  int ub;
416  int b;
417 
418  assert(scip != NULL);
419  assert(consdata != NULL);
420  assert(consdata->nbinvars == 0);
421  assert(consdata->binvars == NULL);
422 
423  SCIPdebugMsg(scip, "create binary variables for integer variable <%s>\n", SCIPvarGetName(consdata->intvar));
424 
425  intvar = consdata->intvar;
426  lb = SCIPconvertRealToInt(scip, SCIPvarGetLbGlobal(intvar));
427  ub = SCIPconvertRealToInt(scip, SCIPvarGetUbGlobal(intvar));
428  nbinvars = ub-lb+1;
429  assert(nbinvars > 0);
430 
431  /* allocate block memory for the binary variables */
432  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->binvars, nbinvars) );
433  consdata->sizebinvars = nbinvars;
434 
435  /* check if the integer variable is fixed */
436  if( nbinvars == 1 )
437  {
438  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s[%d]", SCIPvarGetName(intvar), lb);
439 
440  /* creates and captures a fixed binary variables */
441  SCIP_CALL( SCIPcreateVar(scip, &binvar, name, 1.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
442  FALSE, TRUE, NULL, NULL, NULL, NULL, NULL) );
443  SCIP_CALL( SCIPaddVar(scip, binvar) );
444 
445  consdata->binvars[0] = binvar;
446  consdata->vals[0] = lb;
447  }
448  else
449  {
450  for( b = 0; b < nbinvars; ++b)
451  {
452  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s[%d]", SCIPvarGetName(intvar), lb + b);
453 
454  /* creates and captures variables */
455  SCIP_CALL( SCIPcreateVar(scip, &binvar, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
456  TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
457 
458  /* add variable to the problem */
459  SCIP_CALL( SCIPaddVar(scip, binvar) );
460  consdata->binvars[b] = binvar;
461  consdata->vals[b] = lb + b;
462  }
463  }
464 
465  consdata->nbinvars = nbinvars;
466 
467  assert(consdata->nfixedzeros == 0);
468  assert(consdata->nfixedones == 0);
469 
470  if( SCIPisTransformed(scip) )
471  {
472  /* (rounding) lock binary variable */
473  SCIP_CALL( lockRounding(scip, cons, consdata->binvars, consdata->nbinvars) );
474 
475  /* catch bound change events of variables */
476  SCIP_CALL( catchAllEvents(scip, consdata, eventhdlr) );
477 
478  if( nbinvars > 1 )
479  {
480  if( linearize )
481  {
482  SCIP_CALL( consdataLinearize(scip, cons, consdata) );
483  }
484  else
485  {
486  /* enable constraint */
487  SCIP_CALL( SCIPenableCons(scip, cons) );
488  }
489  }
490  }
491 
492  return SCIP_OKAY;
493 }
494 
495 /** creates consdata */
496 static
498  SCIP* scip, /**< SCIP data structure */
499  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
500  SCIP_CONSDATA** consdata, /**< pointer to constraint data */
501  SCIP_VAR* intvar, /**< integer variable which is linked */
502  SCIP_VAR** binvars, /**< binary variables */
503  int* vals, /**< coefficients of the binary variables */
504  int nbinvars /**< number of binary starting variables */
505  )
506 {
507  int v;
508 
509  assert(scip!= NULL);
510  assert(consdata != NULL);
511  assert(intvar != NULL);
512  assert(binvars != NULL || nbinvars == 0);
513  assert(SCIPvarGetType(intvar) != SCIP_VARTYPE_CONTINUOUS);
514 
515  /* allocate memory for consdata */
516  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
517 
518  (*consdata)->intvar = intvar;
519  (*consdata)->nbinvars = nbinvars;
520  (*consdata)->sizebinvars = nbinvars;
521  (*consdata)->row1 = NULL;
522  (*consdata)->row2 = NULL;
523  (*consdata)->cliqueadded = FALSE;
524 
525  /* initialize constraint state */
526  (*consdata)->sorted = FALSE;
527  (*consdata)->firstnonfixed = 0;
528  (*consdata)->lastnonfixed = nbinvars - 1;
529  (*consdata)->nfixedzeros = 0;
530  (*consdata)->nfixedones = 0;
531 
532  if( nbinvars == 0 )
533  {
534  (*consdata)->binvars = NULL;
535  (*consdata)->vals = NULL;
536  }
537  else
538  {
539  /* copy binary variable array */
540  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->binvars, binvars, nbinvars) );
541 
542  /* copy coefficients */
543  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, vals, nbinvars) );
544  }
545 
546  /* get transformed variable, if we are in the transformed problem */
547  if( SCIPisTransformed(scip) )
548  {
549  if( nbinvars > 0 )
550  {
551  SCIP_CALL( SCIPgetTransformedVars(scip, nbinvars, (*consdata)->binvars, (*consdata)->binvars) );
552 
553  /* catch bound change events of variables */
554  SCIP_CALL( catchAllEvents(scip, *consdata, eventhdlr) );
555  }
556 
557  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->intvar, &(*consdata)->intvar) );
558  }
559 
560  /* mark integer variable to be not multi-aggregated */
561  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->intvar) );
562 
563  /* capture variables */
564  for( v = 0; v < nbinvars; ++v )
565  {
566  assert((*consdata)->binvars[v] != NULL);
567  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->binvars[v]) );
568  }
569  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->intvar) );
570 
571  return SCIP_OKAY;
572 }
573 
574 
575 /** free consdata */
576 static
578  SCIP* scip, /**< SCIP data structure */
579  SCIP_CONSDATA** consdata /**< pointer to consdata */
580  )
581 {
582  int v;
583 
584  assert(consdata != NULL);
585  assert(*consdata != NULL);
586  assert((*consdata)->nbinvars == 0 || (*consdata)->binvars != NULL);
587 
588  /* release the rows */
589  if( (*consdata)->row1 != NULL )
590  {
591  assert((*consdata)->row2 != NULL);
592 
593  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row1) );
594  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row2) );
595  }
596 
597  /* capture variables */
598  for( v = 0; v < (*consdata)->nbinvars; ++v )
599  {
600  assert((*consdata)->binvars[v] != NULL);
601  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->binvars[v]) );
602  }
603  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->intvar) );
604 
605  /* free binary variable array */
606  if( (*consdata)->sizebinvars > 0 )
607  {
608  /* if constraint belongs to transformed problem space, drop bound change events on variables */
609  SCIPfreeBlockMemoryArray(scip, &(*consdata)->vals, (*consdata)->sizebinvars);
610  SCIPfreeBlockMemoryArray(scip, &(*consdata)->binvars, (*consdata)->sizebinvars);
611  }
612 
613  /* check if the fixed counters are reset */
614  assert((*consdata)->nfixedzeros == 0);
615  assert((*consdata)->nfixedones == 0);
616 
617  /* free constraint data */
618  SCIPfreeBlockMemory(scip, consdata);
619 
620  return SCIP_OKAY;
621 }
622 
623 
624 /** analyzes conflicting assignment on given constraint where reason comes from the integer variable lower or upper
625  * bound
626  */
627 static
629  SCIP* scip, /**< SCIP data structure */
630  SCIP_CONS* cons, /**< linking constraint to be processed */
631  SCIP_VAR* intvar, /**< integer variable */
632  SCIP_VAR* binvar, /**< binary variable is the reason */
633  SCIP_Bool lbintvar, /**< lower bound of integer variable is the reason */
634  SCIP_Bool ubintvar /**< upper bound of integer variable is the reason */
635  )
636 {
637  assert(scip != NULL);
638 
639  /* conflict analysis can only be applied in solving stage and if it is turned on */
641  return SCIP_OKAY;
642 
643  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
645 
646  if( lbintvar )
647  {
648  assert(intvar != NULL);
649  SCIP_CALL( SCIPaddConflictLb(scip, intvar, NULL) );
650  }
651 
652  if( ubintvar )
653  {
654  assert(intvar != NULL);
655  SCIP_CALL( SCIPaddConflictUb(scip, intvar, NULL) );
656  }
657 
658  if( binvar != NULL )
659  {
660  SCIP_CALL( SCIPaddConflictBinvar(scip, binvar) );
661  }
662 
663  /* analyze the conflict */
664  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
665 
666  return SCIP_OKAY;
667 }
668 
669 /** fix integer variable to the value of the binary variable at pos */
670 static
672  SCIP* scip, /**< SCIP data structure */
673  SCIP_CONS* cons, /**< linking constraint to be processed */
674  int pos, /**< position of binary variable */
675  SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
676  )
677 {
678  SCIP_CONSDATA* consdata;
679  SCIP_VAR* intvar;
680  SCIP_Bool infeasible;
681  SCIP_Bool tightened;
682  SCIP_Real coef;
683 
684  consdata = SCIPconsGetData(cons);
685  assert(consdata != NULL);
686 
687  intvar = consdata->intvar;
688  coef = (SCIP_Real)consdata->vals[pos];
689 
690  /* change lower bound of the integer variable */
691  SCIP_CALL( SCIPinferVarLbCons(scip, intvar, coef, cons, pos, TRUE, &infeasible, &tightened) );
692 
693  if( infeasible )
694  {
695  assert(coef > SCIPvarGetUbLocal(intvar));
696  assert(coef >= SCIPvarGetLbLocal(intvar));
697 
698  SCIP_CALL( analyzeConflict(scip, cons, intvar, consdata->binvars[pos], FALSE, TRUE) );
699 
700  *cutoff = TRUE;
701  return SCIP_OKAY;
702  }
703  assert(coef <= SCIPvarGetUbLocal(intvar));
704 
705  /* change upper bound of the integer variable */
706  SCIP_CALL( SCIPinferVarUbCons(scip, intvar, coef, cons, pos, TRUE, &infeasible, &tightened) );
707 
708  if( infeasible )
709  {
710  assert(coef < SCIPvarGetLbLocal(intvar));
711  assert(coef <= SCIPvarGetUbLocal(intvar));
712 
713  SCIP_CALL( analyzeConflict(scip, cons, intvar, consdata->binvars[pos], TRUE, FALSE) );
714 
715  *cutoff = TRUE;
716  return SCIP_OKAY;
717  }
718 
719  assert((int)(SCIPvarGetUbLocal(intvar)+0.5) == (int)(SCIPvarGetLbLocal(intvar)+0.5) );
720 
721  return SCIP_OKAY;
722 }
723 
724 /** checks constraint for violation from the local bound of the integer variable, applies fixings to the binary
725  * variables if possible
726  */
727 static
729  SCIP* scip, /**< SCIP data structure */
730  SCIP_CONS* cons, /**< linking constraint to be processed */
731  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
732  int* nchgbds, /**< pointer to store the number of changes (foxed) variable bounds */
733  SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
734  )
735 {
736  SCIP_CONSDATA* consdata;
737  SCIP_VAR** binvars;
738  SCIP_VAR* intvar;
739  int* vals;
740  int nbinvars;
741  int lblocal;
742  int ublocal;
743  int b;
744  SCIP_Bool infeasible;
745  SCIP_Bool tightened;
746 
747  assert(cons != NULL);
748  assert(SCIPconsGetHdlr(cons) != NULL);
749  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
750  assert(cutoff != NULL);
751  assert(nchgbds != NULL);
752  assert(mustcheck != NULL);
753 
754  consdata = SCIPconsGetData(cons);
755  assert(consdata != NULL);
756 
757  /* ensure that the binary variables are sorted in non-decreasing order w.r.t. their coefficients */
758  consdataSort(consdata);
759 
760  nbinvars = consdata->nbinvars;
761 
762  /* in case there is only at most one binary variables, the constraints should already be disabled */
763  assert(nbinvars > 1);
764 
765  /* if more than one binary variable is fixed to one or at least nbinvars minus one variable are fixed to zero */
766  if( consdata->nfixedones > 0 || consdata->nfixedzeros >= nbinvars-1 )
767  return SCIP_OKAY;
768 
769  intvar = consdata->intvar;
770  assert(intvar != NULL);
771 
772  binvars = consdata->binvars;
773  vals = consdata->vals;
774 
775  lblocal = SCIPconvertRealToInt(scip, SCIPvarGetLbLocal(intvar));
776  ublocal = SCIPconvertRealToInt(scip, SCIPvarGetUbLocal(intvar));
777  assert(lblocal <= ublocal);
778 
779 #ifndef NDEBUG
780  /* check that the first variable are locally fixed to zero */
781  for( b = 0; b < consdata->firstnonfixed; ++b )
782  assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
783 
784  /* check that the last variable are locally fixed to zero */
785  for( b = consdata->lastnonfixed + 1; b < nbinvars; ++b )
786  assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
787 #endif
788 
789  for( b = consdata->firstnonfixed; b < nbinvars; ++b )
790  {
791  if( vals[b] < lblocal )
792  {
793  SCIP_VAR* var;
794 
795  var = binvars[b];
796  assert(var != NULL);
797 
798  SCIPdebugMsg(scip, "fix variable <%s> to zero due to the lower bound of the integer variable <%s> [%g,%g]\n",
799  SCIPvarGetName(var), SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar));
800 
801  SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, -2, &infeasible, &tightened) );
802 
803  if( infeasible )
804  {
805  SCIP_CALL( analyzeConflict(scip, cons, intvar, var, TRUE, FALSE) );
806  *cutoff = TRUE;
807  return SCIP_OKAY;
808  }
809 
810  if( tightened )
811  (*nchgbds)++;
812 
813  /* adjust constraint state */
814  consdata->firstnonfixed++;
815  }
816  else
817  break;
818  }
819  assert(consdata->firstnonfixed <= consdata->lastnonfixed);
820 
821  /* fix binary variables to zero if not yet fixed, from local upper bound + 1*/
822  for( b = consdata->lastnonfixed; b >= 0; --b )
823  {
824  if( vals[b] > ublocal )
825  {
826  SCIP_VAR* var;
827 
828  var = binvars[b];
829  assert(var != NULL);
830 
831  SCIPdebugMsg(scip, "fix variable <%s> to zero due to the upper bound of the integer variable <%s> [%g,%g]\n",
832  SCIPvarGetName(var), SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar));
833 
834  SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, -3, &infeasible, &tightened) );
835 
836  if( infeasible )
837  {
838  SCIP_CALL( analyzeConflict(scip, cons, intvar, var, FALSE, TRUE) );
839  *cutoff = TRUE;
840  return SCIP_OKAY;
841  }
842 
843  if( tightened )
844  (*nchgbds)++;
845 
846  /* adjust constraint state */
847  consdata->lastnonfixed--;
848  }
849  else
850  break;
851  }
852 
853  if( consdata->firstnonfixed > consdata->lastnonfixed )
854  {
855  *cutoff = TRUE;
856  return SCIP_OKAY;
857  }
858 
859  *mustcheck = (*nchgbds) == 0;
860 
861  /* if integer variables is fixed, create for the binary variables which have a coefficient equal to the fixed vale a
862  * set partitioning constraint
863  */
864  if( lblocal == ublocal )
865  {
866  if( consdata->firstnonfixed == consdata->lastnonfixed )
867  {
868  SCIP_VAR* var;
869 
870  var = binvars[consdata->firstnonfixed];
871 
872  SCIPdebugMsg(scip, "fix variable <%s> to one due to the fixed integer variable <%s> [%g,%g]\n",
873  SCIPvarGetName(var), SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar));
874 
875  SCIP_CALL( SCIPinferBinvarCons(scip, var, TRUE, cons, -6, &infeasible, &tightened) );
876 
877  if( infeasible )
878  {
879  SCIP_CALL( analyzeConflict(scip, cons, intvar, var, TRUE, TRUE) );
880  *cutoff = TRUE;
881  return SCIP_OKAY;
882  }
883 
884  if( tightened )
885  (*nchgbds)++;
886 
887  SCIPdebugMsg(scip, " -> disabling linking constraint <%s>\n", SCIPconsGetName(cons));
888  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
889 
890  *mustcheck = FALSE;
891  }
892  else if( SCIPgetDepth(scip) <= 0 )
893  {
894  SCIP_CONS* setppc;
895  SCIP_VAR** vars;
896  int nvars;
897 
898  /* get sub array of variables which have the same coefficient */
899  vars = &consdata->binvars[consdata->firstnonfixed];
900  nvars = consdata->lastnonfixed - consdata->firstnonfixed + 1;
901 
902  SCIP_CALL( SCIPcreateConsSetpart(scip, &setppc, SCIPconsGetName(cons), nvars, vars,
906 
907  SCIP_CALL( SCIPaddCons(scip, setppc) );
908  SCIP_CALL( SCIPreleaseCons(scip, &setppc) );
909 
910  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
911  }
912  }
913 
914  return SCIP_OKAY;
915 }
916 
917 /** deletes coefficient at given position from the binary variable array */
918 static
920  SCIP* scip, /**< SCIP data structure */
921  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
922  SCIP_CONS* cons, /**< linking constraint */
923  int pos /**< position of coefficient to delete */
924  )
925 {
926  SCIP_CONSDATA* consdata;
927  SCIP_VAR* var;
928 
929  assert(scip != NULL);
930  assert(eventhdlr != NULL);
931 
932  consdata = SCIPconsGetData(cons);
933  assert(consdata != NULL);
934  assert(0 <= pos && pos < consdata->nbinvars);
935 
936  var = consdata->binvars[pos];
937  assert(var != NULL);
938  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
939 
940  /* remove the rounding locks for the deleted variable */
941  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
942 
943  /* if we are in transformed problem, delete the event data of the variable */
944  if( SCIPconsIsTransformed(cons) )
945  {
946  SCIP_CONSHDLR* conshdlr;
947  SCIP_CONSHDLRDATA* conshdlrdata;
948 
949  /* get event handler */
950  conshdlr = SCIPconsGetHdlr(cons);
951  conshdlrdata = SCIPconshdlrGetData(conshdlr);
952  assert(conshdlrdata != NULL);
953  assert(conshdlrdata->eventhdlr != NULL);
954 
955  /* drop bound change events of variable */
956  SCIP_CALL( dropEvent(scip, consdata, conshdlrdata->eventhdlr, pos) );
957  }
958 
959  /* move the last variable to the free slot */
960  if( pos != consdata->nbinvars - 1 )
961  {
962  consdata->binvars[pos] = consdata->binvars[consdata->nbinvars-1];
963  consdata->vals[pos] = consdata->vals[consdata->nbinvars-1];
964  consdata->sorted = FALSE;
965  }
966 
967  consdata->nbinvars--;
968 
969  /* release variable */
970  SCIP_CALL( SCIPreleaseVar(scip, &var) );
971 
972  return SCIP_OKAY;
973 }
974 
975 /** remove the trailing and leeading binary variable which are fixed to zero */
976 static
978  SCIP* scip, /**< SCIP data structure */
979  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
980  SCIP_CONS* cons /**< linking constraint */
981  )
982 {
983  SCIP_CONSDATA* consdata;
984  int nbinvars;
985  int b;
986 
987  consdata = SCIPconsGetData(cons);
988  assert(consdata != NULL);
989  assert(consdata->sorted);
990 
991  assert(SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING || SCIPgetDepth(scip) <= 0);
992  assert(!SCIPinProbing(scip));
993  assert(!SCIPinRepropagation(scip));
994 
995  nbinvars = consdata->nbinvars;
996 
997  for( b = nbinvars - 1; b > consdata->lastnonfixed; --b )
998  {
999  SCIP_CALL( delCoefPos(scip, eventhdlr, cons, b) );
1000  }
1001 
1002  for( b = consdata->firstnonfixed - 1; b >= 0; --b )
1003  {
1004  SCIP_CALL( delCoefPos(scip, eventhdlr, cons, b) );
1005  }
1006 
1007  for( b = consdata->nbinvars - 1; b >= 0; --b )
1008  {
1009  if( SCIPvarGetUbLocal(consdata->binvars[b]) < 0.5 )
1010  {
1011  SCIP_CALL( delCoefPos(scip, eventhdlr, cons, b) );
1012  }
1013  }
1014 
1015  /* set the constraint state */
1016  consdata->firstnonfixed = 0;
1017  consdata->lastnonfixed = consdata->nbinvars - 1;
1018 
1019  return SCIP_OKAY;
1020 }
1021 
1022 /** tightened the integer variable due to binary variables which are fixed to zero */
1023 static
1025  SCIP* scip, /**< SCIP data structure */
1026  SCIP_CONS* cons, /**< linking constraint to be processed */
1027  SCIP_CONSDATA* consdata, /**< linking constraint to be processed */
1028  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1029  int* nchgbds /**< pointer to store the number of changed variable bounds */
1030  )
1031 {
1032  SCIP_VAR** binvars;
1033  SCIP_VAR* intvar;
1034  int* vals;
1035 
1036  SCIP_Bool infeasible;
1037  SCIP_Bool tightened;
1038  int nbinvars;
1039  int b;
1040 
1041  /* if more than one binary variable is fixed to one or at least nbinvars minus one variable are fixed to zero return */
1042  if( consdata->nfixedones > 1 || consdata->nfixedzeros >= consdata->nbinvars-1 )
1043  return SCIP_OKAY;
1044 
1045  if( *cutoff )
1046  return SCIP_OKAY;
1047 
1048  assert(consdata->sorted);
1049 
1050  intvar = consdata->intvar;
1051  binvars = consdata->binvars;
1052  vals = consdata->vals;
1053  nbinvars = consdata->nbinvars;
1054 
1055 #ifndef NDEBUG
1056  /* check that the first variable are locally fixed to zero */
1057  for( b = 0; b < consdata->firstnonfixed; ++b )
1058  assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
1059 #endif
1060 
1061  assert(consdata->firstnonfixed < nbinvars);
1062  assert(consdata->lastnonfixed < nbinvars);
1063 
1064  /* find first non fixed binary variable */
1065  for( b = consdata->firstnonfixed; b < nbinvars; ++b )
1066  {
1067  if( SCIPvarGetUbLocal(binvars[b]) > 0.5 )
1068  break;
1069 
1070  consdata->firstnonfixed++;
1071  }
1072 
1073  SCIP_CALL( SCIPinferVarLbCons(scip, intvar, (SCIP_Real)vals[b], cons, -4, TRUE, &infeasible, &tightened) );
1074 
1075  /* start conflict analysis if infeasible */
1076  if( infeasible )
1077  {
1078  /* analyze the cutoff if if SOLVING stage and conflict analysis is turned on */
1080  {
1081  SCIPdebugMsg(scip, "conflict at <%s> due to bounds and fixed binvars: [lb,ub] = [%g,%g]; b= %d; coef = %d \n",
1082  SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar), b, vals[b]);
1083 
1085 
1086  /* ??????????? use resolve method and only add binvars which are needed to exceed the upper bound */
1087 
1088  /* add conflicting variables */
1089  SCIP_CALL( SCIPaddConflictUb(scip, intvar, NULL) );
1090 
1091  for( b = 0; b < consdata->firstnonfixed; ++b )
1092  {
1093  SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
1094  }
1095 
1096  /* analyze the conflict */
1097  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1098  }
1099 
1100  *cutoff = TRUE;
1101  return SCIP_OKAY;
1102  }
1103 
1104  if( tightened )
1105  (*nchgbds)++;
1106 
1107 #ifndef NDEBUG
1108  /* check that the last variable are locally fixed to zero */
1109  for( b = consdata->lastnonfixed + 1; b < nbinvars; ++b )
1110  assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
1111 #endif
1112 
1113  /* find last non fixed variable */
1114  for( b = consdata->lastnonfixed; b >= 0; --b )
1115  {
1116  if( SCIPvarGetUbLocal(binvars[b]) > 0.5 )
1117  break;
1118 
1119  consdata->lastnonfixed--;
1120  }
1121 
1122  SCIP_CALL( SCIPinferVarUbCons(scip, intvar, (SCIP_Real)vals[b], cons, -5, TRUE, &infeasible, &tightened) );
1123 
1124  if( infeasible )
1125  {
1126  /* conflict analysis can only be applied in solving stage and if conflict analysis is turned on */
1128  {
1129  SCIPdebugMsg(scip, "conflict at <%s> due to bounds and fixed binvars: [lb,ub] = [%g,%g]; b = %d; coef = %d,\n",
1130  SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar), b, vals[b]);
1131 
1133 
1134  /* ??????????? use resolve method and only add binvars which are needed to fall below the lower bound */
1135 
1136  /* add conflicting variables */
1137  SCIP_CALL( SCIPaddConflictLb(scip, intvar, NULL) );
1138 
1139  for( b = consdata->lastnonfixed + 1; b < nbinvars; ++b )
1140  {
1141  SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
1142  }
1143 
1144  /* analyze the conflict */
1145  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1146  }
1147 
1148  *cutoff = TRUE;
1149  return SCIP_OKAY;
1150  }
1151 
1152  if( tightened )
1153  (*nchgbds)++;
1154 
1155  return SCIP_OKAY;
1156 }
1157 
1158 /** checks constraint for violation only looking at the fixed binary variables, applies further fixings if possible */
1159 static
1161  SCIP* scip, /**< SCIP data structure */
1162  SCIP_CONS* cons, /**< linking constraint to be processed */
1163  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1164  int* nchgbds, /**< pointer to store the number of changed variable bounds */
1165  SCIP_Bool* addcut, /**< pointer to store whether this constraint must be added as a cut */
1166  SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1167  )
1168 {
1169  SCIP_CONSDATA* consdata;
1170  SCIP_Bool infeasible;
1171  SCIP_Bool tightened;
1172 
1173  assert(cons != NULL);
1174  assert(SCIPconsGetHdlr(cons) != NULL);
1175  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1176  assert(cutoff != NULL);
1177  assert(nchgbds != NULL);
1178  assert(addcut != NULL);
1179  assert(mustcheck != NULL);
1180 
1181  consdata = SCIPconsGetData(cons);
1182  assert(consdata != NULL);
1183  assert(consdata->nbinvars == 0 || consdata->binvars != NULL);
1184  assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nbinvars);
1185  assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nbinvars);
1186 
1187  /* ensure that the binary variables are sorted in non-decreasing order w.r.t. their coefficients */
1188  consdataSort(consdata);
1189 
1190  /* in case there is only at most one binary variables, the constraints should already be disabled */
1191  assert(consdata->nbinvars > 1);
1192 
1193  if( *cutoff )
1194  return SCIP_OKAY;
1195 
1196  if( consdata->nfixedones == 1 )
1197  {
1198  /* exactly one variable is fixed to 1:
1199  * - all other binary variables in a set partitioning must be zero
1200  * - integer variable are fixed to that binary variable
1201  */
1202  if( consdata->nfixedzeros < consdata->nbinvars - 1 ||
1203  SCIPisLT(scip, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar)) )
1204  {
1205  SCIP_VAR** vars;
1206  SCIP_VAR* var;
1207 #ifndef NDEBUG
1208  SCIP_Bool fixedonefound;
1209 #endif
1210  int nvars;
1211  int v;
1212 
1213  SCIPdebugMsg(scip, " -> fixing all other variables to zero due to the set partitioning condition <%s>\n",
1214  SCIPconsGetName(cons));
1215 
1216  /* unfixed variables exist: fix them to zero;
1217  * this could result in additional variables fixed to one due to aggregations; in this case, the
1218  * constraint is infeasible in local bounds
1219  */
1220  vars = consdata->binvars;
1221  nvars = consdata->nbinvars;
1222 #ifndef NDEBUG
1223  fixedonefound = FALSE;
1224 #endif
1225 
1226  for( v = 0; v < nvars && consdata->nfixedones == 1 && !(*cutoff); ++v )
1227  {
1228  var = vars[v];
1229  assert(SCIPvarIsBinary(var));
1230  if( SCIPvarGetLbLocal(var) < 0.5 )
1231  {
1232  SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, -1, &infeasible, &tightened) );
1233  assert(!infeasible);
1234  SCIPdebugMsg(scip, " -> fixed <%s> to zero (tightened=%u)\n", SCIPvarGetName(var), tightened);
1235  }
1236  else
1237  {
1238 #ifndef NDEBUG
1239  fixedonefound = TRUE;
1240 #endif
1241  /* fix integer variable */
1242  SCIP_CALL( consFixInteger(scip, cons, v, cutoff) );
1243  }
1244  }
1245  if( !(*cutoff) )
1246  {
1247  /* the fixed to one variable must have been found, and at least one variable must have been fixed */
1248  assert(consdata->nfixedones >= 1 || fixedonefound);
1249 
1250  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1251  (*nchgbds)++;
1252  }
1253  }
1254 
1255  /* now all other variables are fixed to zero:
1256  * the constraint is feasible, and if it's not modifiable, it is redundant
1257  */
1258  if( !SCIPconsIsModifiable(cons) && consdata->nfixedones == 1 )
1259  {
1260  SCIPdebugMsg(scip, " -> disabling set linking constraint <%s>\n", SCIPconsGetName(cons));
1261  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1262  }
1263  }
1264  else if( consdata->nfixedones >= 2 )
1265  {
1266  /* at least two variables are fixed to 1:
1267  * - the set partitioning condition is violated
1268  */
1269  SCIPdebugMsg(scip, " -> conflict on " CONSHDLR_NAME " constraint <%s> due to the set partitioning condition\n", SCIPconsGetName(cons));
1270 
1271  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1272 
1273  /* conflict analysis can only be applied in solving stage and if it is applicable */
1275  {
1276  SCIP_VAR** vars;
1277  int nvars;
1278  int n;
1279  int v;
1280 
1281  vars = consdata->binvars;
1282  nvars = consdata->nbinvars;
1283 
1284  /* initialize conflict analysis, and add the two variables assigned to one to conflict candidate queue */
1286 
1287  n = 0;
1288 
1289  for( v = 0; v < nvars && n < 2; ++v )
1290  {
1291  if( SCIPvarGetLbLocal(vars[v]) > 0.5 )
1292  {
1293  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[v]) );
1294  n++;
1295  }
1296  }
1297  assert(n == 2);
1298 
1299  /* analyze the conflict */
1300  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1301  }
1302 
1303  *cutoff = TRUE;
1304  }
1305  else if( consdata->nfixedzeros == consdata->nbinvars )
1306  {
1307  /* all variables are fixed to zero:
1308  * - the set partitioning condition is violated, and if it's unmodifiable, the node
1309  * can be cut off -- otherwise, the constraint must be added as a cut and further pricing must
1310  * be performed
1311  */
1312  assert(consdata->nfixedones == 0);
1313 
1314  SCIPdebugMsg(scip, " -> " CONSHDLR_NAME " constraint <%s> is infeasible due to the set partitioning condition\n",
1315  SCIPconsGetName(cons));
1316 
1317  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1318  if( SCIPconsIsModifiable(cons) )
1319  *addcut = TRUE;
1320  else
1321  {
1322  /* conflict analysis can only be applied in solving stage and if it is applicable */
1324  {
1325  SCIP_VAR** vars;
1326  int nvars;
1327  int v;
1328 
1329  vars = consdata->binvars;
1330  nvars = consdata->nbinvars;
1331 
1332  /* initialize conflict analysis, add all variables of infeasible constraint to conflict candidate queue */
1334 
1335  for( v = 0; v < nvars; ++v )
1336  {
1337  assert(SCIPvarGetUbLocal(vars[v]) < 0.5);
1338  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[v]) );
1339  }
1340 
1341  /* analyze the conflict */
1342  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1343  }
1344  *cutoff = TRUE;
1345  }
1346  }
1347  else if( consdata->nfixedzeros == consdata->nbinvars - 1 )
1348  {
1349  /* all variables except one are fixed to zero:
1350  * - an unmodifiable set partitioning constraint is feasible and can be disabled after the
1351  * remaining variable is fixed to one
1352  * - a modifiable set partitioning constraint must be checked manually
1353  */
1354  assert(consdata->nfixedones == 0);
1355 
1356  if( !SCIPconsIsModifiable(cons) )
1357  {
1358  SCIP_VAR** vars;
1359  SCIP_VAR* var;
1360  int nvars;
1361  int v;
1362 
1363  /* search the single variable that can be fixed */
1364  vars = consdata->binvars;
1365  nvars = consdata->nbinvars;
1366  for( v = 0; v < nvars && !(*cutoff); ++v )
1367  {
1368  var = vars[v];
1369  assert(SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)));
1370  assert(SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), 1.0));
1371  if( SCIPvarGetUbLocal(var) > 0.5 )
1372  {
1373  assert(SCIPvarGetLbLocal(var) < 0.5);
1374  SCIPdebugMsg(scip, " -> fixing remaining binary variable <%s> to one in " CONSHDLR_NAME " constraint <%s>\n",
1375  SCIPvarGetName(var), SCIPconsGetName(cons));
1376 
1377  SCIP_CALL( SCIPinferBinvarCons(scip, var, TRUE, cons, -1, &infeasible, &tightened) );
1378  assert(!infeasible);
1379  assert(tightened);
1380 
1381  /* fix integer variable */
1382  SCIP_CALL( consFixInteger(scip, cons, v, cutoff) );
1383  break;
1384  }
1385  }
1386  assert(v < nvars);
1387  assert(consdata->nfixedzeros == consdata->nbinvars - 1);
1388  assert(consdata->nfixedones == 1);
1389 
1390  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1391  (*nchgbds)++;
1392  }
1393  }
1394  else
1395  {
1396  SCIP_CALL( tightenedIntvar(scip, cons, consdata, cutoff, nchgbds) );
1397  }
1398 
1399  *mustcheck = (*nchgbds) == 0;
1400 
1401  assert(consdata->nfixedzeros + consdata->nfixedones <= consdata->nbinvars);
1402 
1403  return SCIP_OKAY;
1404 }
1405 
1406 /** returns whether the given solution is feasible for the given linking constraint */
1407 static
1409  SCIP* scip, /**< SCIP data structure */
1410  SCIP_CONS* cons, /**< linking constraint to be checked */
1411  SCIP_SOL* sol /**< primal solution, or NULL for current LP/pseudo solution */
1412  )
1413 {
1414  SCIP_CONSDATA* consdata;
1415  SCIP_VAR** binvars;
1416  int* vals;
1417  SCIP_Real solval;
1418  SCIP_Real linksum;
1419  SCIP_VAR* intvarval;
1420  SCIP_Real setpartsum;
1421  SCIP_Real setpartsumbound;
1422  SCIP_Real absviol;
1423  SCIP_Real relviol;
1424  int nbinvars;
1425  int b;
1426 
1427  assert(scip != NULL);
1428  assert(cons != NULL);
1429 
1430  SCIPdebugMsg(scip, "checking linking constraint <%s> for feasibility of solution %p\n", SCIPconsGetName(cons), (void*)sol);
1431 
1432  consdata = SCIPconsGetData(cons);
1433  assert(consdata != NULL);
1434  assert(consdata->binvars != NULL || consdata->nbinvars == 0);
1435 
1436  /* in case there is only at most one binary variables, the constraints should already be disabled */
1437  assert(consdata->nbinvars > 1);
1438 
1439  /* calculate the constraint's activity for the linking part and the set partitioning part */
1440  binvars = consdata->binvars;
1441  vals = consdata->vals;
1442  nbinvars = consdata->nbinvars;
1443 
1444  linksum = 0.0;
1445  setpartsum = 0.0;
1446  setpartsumbound = 1.0 + 2*SCIPfeastol(scip);
1447 
1448  for( b = 0; b < nbinvars && setpartsum < setpartsumbound; ++b ) /* if sum >= sumbound, the feasibility is clearly decided */
1449  {
1450  assert(SCIPvarIsBinary(binvars[b]));
1451 
1452  solval = SCIPgetSolVal(scip, sol, binvars[b]);
1453  assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
1454 
1455  linksum += vals[b] * solval;
1456  setpartsum += solval;
1457  }
1458 
1459  /* calculate and update absolute and relative violation of the equality constraint */
1460  intvarval = consdata->intvar;
1461  absviol = REALABS(linksum - SCIPgetSolVal(scip, sol, intvarval));
1462  relviol = REALABS(SCIPrelDiff(linksum, SCIPgetSolVal(scip, sol, intvarval)));
1463  if( sol != NULL )
1464  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
1465 
1466  /* calculate and update absolute and relative violation of the set partitioning constraint */
1467  absviol = REALABS(setpartsum - 1.0);
1468  relviol = REALABS(SCIPrelDiff(setpartsum, 1.0));
1469  if( sol != NULL )
1470  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
1471 
1472  /* check if the fixed binary variable match with the integer variable */
1473  return SCIPisFeasEQ(scip, linksum, SCIPgetSolVal(scip, sol, consdata->intvar)) && SCIPisFeasEQ(scip, setpartsum, 1.0);
1474 }
1475 
1476 #if 0
1477 /** transfer aggregated integer variables to the corresponding binary variables */
1478 static
1480  SCIP* scip, /**< SCIP data structure */
1481  SCIP_HASHMAP* varmap, /**< hash map mapping a integer variables to its linking constraint */
1482  SCIP_CONS** conss, /**< array of linking constraint */
1483  int nconss, /**< number of linking constraints */
1484  int* naggrvars, /**< pointer to store the number of aggregate variables */
1485  SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
1486  )
1487 {
1488  SCIP_CONS* aggrcons;
1489  SCIP_CONSDATA* aggrconsdata;
1490  SCIP_CONSDATA* consdata;
1491  SCIP_VAR** binvars;
1492  SCIP_VAR** aggrbinvars;
1493  SCIP_VAR* intvar;
1494  SCIP_VAR* aggrvar;
1495  SCIP_Real aggrconst;
1496  SCIP_Real aggrscalar;
1497  SCIP_Bool infeasible;
1498  SCIP_Bool redundant;
1499  SCIP_Bool aggregated;
1500  int offset;
1501  int aggroffset;
1502  int nbinvars;
1503  int shift;
1504  int b;
1505  int c;
1506 
1507  assert(varmap != NULL);
1508 
1509  for( c = 0; c < nconss; ++c )
1510  {
1511  consdata = SCIPconsGetData(conss[c]);
1512  assert(consdata != NULL);
1513 
1514  intvar = consdata->intvar;
1515  assert(intvar != NULL);
1516 
1518  {
1519  aggrvar = SCIPvarGetAggrVar(intvar);
1520  aggrcons = (SCIP_CONS*) SCIPhashmapGetImage(varmap, getHashmapKey(aggrvar));
1521 
1522  /* check if the aggregate variable belongs to a linking constraint */
1523  if( aggrcons != NULL )
1524  {
1525  aggrconsdata = SCIPconsGetData(aggrcons);
1526  assert(aggrconsdata != NULL);
1527 
1528  aggrconst = SCIPvarGetAggrConstant(intvar);
1529  aggrscalar = SCIPvarGetAggrScalar(intvar);
1530 
1531  /**@todo extend the aggregation for those cases were the aggrscalar is not equal to 1.0 */
1532  if( SCIPisEQ(scip, aggrscalar, 1.0 ) )
1533  {
1534  /* since both variables are integer variable and the aggrscalar is 1.0 the aggrconst should
1535  * integral
1536  */
1537  assert(SCIPisIntegral(scip, aggrconst));
1538  shift = SCIPconvertRealToInt(scip, aggrconst);
1539 
1540  offset = consdata->offset;
1541  binvars = consdata->binvars;
1542  aggroffset = aggrconsdata->offset;
1543  aggrbinvars = aggrconsdata->binvars;
1544 
1545  nbinvars = MIN(consdata->nbinvars + offset, aggrconsdata->nbinvars + shift + aggroffset);
1546 
1547  for( b = MAX(offset, aggroffset-shift); b < nbinvars; ++b )
1548  {
1549  assert(b - offset >= 0);
1550  assert(b + shift - aggroffset >= 0);
1551  assert(b < consdata->nbinvars);
1552  assert(b < aggrconsdata->nbinvars - shift);
1553 
1554  /* add aggregation x - y = 0.0 */
1555  SCIP_CALL( SCIPaggregateVars(scip, binvars[b-offset], aggrbinvars[b+shift-aggroffset], 1.0, -1.0, 0.0,
1556  &infeasible, &redundant, &aggregated) );
1557 
1558  if( infeasible )
1559  {
1560  (*cutoff) = TRUE;
1561  return SCIP_OKAY;
1562  }
1563 
1564  if( aggregated )
1565  (*naggrvars)++;
1566  }
1567  }
1568  }
1569  }
1570  }
1571  return SCIP_OKAY;
1572 }
1573 #endif
1574 
1575 /** create two rows for the linking constraint
1576  *
1577  * - row1: {sum_{b=1}^n-1 vals[b] * binvars[b]} - intvar = 0
1578  * - row2: {sum_{b=0}^n-1 binvars[b]} = 1.0
1579  */
1580 static
1582  SCIP* scip, /**< SCIP data structure */
1583  SCIP_CONS* cons /**< linking constraint */
1584  )
1585 {
1586  SCIP_CONSDATA* consdata;
1587  char rowname[SCIP_MAXSTRLEN];
1588  int b;
1589 
1590  assert( cons != NULL);
1591 
1592  /* get constraint data */
1593  consdata = SCIPconsGetData(cons);
1594  assert(consdata != NULL);
1595  assert(consdata->row1 == NULL);
1596  assert(consdata->row2 == NULL);
1597  assert(consdata->nbinvars > 1);
1598 
1599  /* create the LP row which captures the linking between the integer and binary variables */
1600  (void)SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s[link]", SCIPconsGetName(cons));
1601 
1602  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row1, SCIPconsGetHdlr(cons), rowname, 0.0, 0.0,
1604 
1605  /* add integer variable to the row */
1606  assert(consdata->intvar != NULL);
1607  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row1, consdata->intvar, -1.0) );
1608 
1609  /* adding all except the first binary variable to the row */
1610  assert(consdata->binvars != NULL);
1611  for( b = 0; b < consdata->nbinvars; ++b )
1612  {
1613  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row1, consdata->binvars[b], (SCIP_Real)consdata->vals[b]) );
1614  }
1615 
1616  /* create the LP row which captures the set partitioning condition of the binary variables */
1617  (void)SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s[setppc]", SCIPconsGetName(cons));
1618  assert( consdata->nbinvars > 0 );
1619 
1620  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row2, SCIPconsGetHdlr(cons), rowname, 1.0, 1.0,
1622 
1623  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row2, consdata->nbinvars, consdata->binvars, 1.0) );
1624 
1625  return SCIP_OKAY;
1626 }
1627 
1628 
1629 /** adds linking constraint as cut to the LP */
1630 static
1632  SCIP* scip, /**< SCIP data structure */
1633  SCIP_CONS* cons, /**< linking constraint */
1634  SCIP_Bool* cutoff /**< whether a cutoff has been detected */
1635  )
1636 {
1637  SCIP_CONSDATA* consdata;
1638 
1639  assert( cutoff != NULL );
1640  *cutoff = FALSE;
1641 
1642  consdata = SCIPconsGetData(cons);
1643  assert(consdata != NULL);
1644 
1645  /* in case there is only at most one binary variables, the constraints should already be disabled */
1646  assert(consdata->nbinvars > 1);
1647 
1648  if( consdata->row1 == NULL )
1649  {
1650  assert(consdata->row2 == NULL);
1651 
1652  /* convert linking data into LP rows */
1653  SCIP_CALL( createRows(scip, cons) );
1654  }
1655  assert(consdata->row1 != NULL);
1656  assert(consdata->row2 != NULL);
1657 
1658  /* insert LP linking row as cut */
1659  if( !SCIProwIsInLP(consdata->row1) )
1660  {
1661  SCIPdebugMsg(scip, "adding linking row of constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1662  SCIP_CALL( SCIPaddRow(scip, consdata->row1, TRUE/*FALSE*/, cutoff) );
1663  }
1664 
1665  /* insert LP set partitioning row as cut */
1666  if( !SCIProwIsInLP(consdata->row2) )
1667  {
1668  SCIPdebugMsg(scip, "adding set partitioning row of constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1669  SCIP_CALL( SCIPaddRow(scip, consdata->row2, TRUE/*FALSE*/, cutoff) );
1670  }
1671 
1672  return SCIP_OKAY;
1673 }
1674 
1675 
1676 /** checks constraint for violation, and adds it as a cuts if possible */
1677 static
1679  SCIP* scip, /**< SCIP data structure */
1680  SCIP_CONS* cons, /**< linking constraint to be separated */
1681  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1682  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1683  SCIP_Bool* separated, /**< pointer to store TRUE, if a cut was found */
1684  int* nchgbds /**< pointer to store the number of changed variables bounds */
1685  )
1686 {
1687  SCIP_CONSDATA* consdata;
1688  SCIP_Bool addcut;
1689  SCIP_Bool mustcheck;
1690 
1691  assert(cons != NULL);
1692  assert(SCIPconsGetHdlr(cons) != NULL);
1693  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1694  assert(cutoff != NULL);
1695  assert(separated != NULL);
1696  assert(nchgbds != NULL);
1697 
1698  consdata = SCIPconsGetData(cons);
1699  assert(consdata != NULL);
1700 
1701  /* in case there is only at most one binary variables, the constraints should already be disabled */
1702  assert(consdata->nbinvars > 1);
1703 
1704  SCIPdebugMsg(scip, "separating constraint <%s>\n", SCIPconsGetName(cons));
1705 
1706  *cutoff = FALSE;
1707  addcut = FALSE;
1708  mustcheck = TRUE;
1709 
1710  /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
1711  if( sol == NULL )
1712  {
1713  SCIP_CALL( processIntegerBoundChg(scip, cons, cutoff, nchgbds, &mustcheck) );
1714  }
1715 
1716  if( mustcheck && !(*cutoff) )
1717  {
1718  /* variable's fixings didn't give us any information -> we have to check the constraint */
1719  if( sol == NULL && consdata->row1 != NULL )
1720  {
1721  SCIP_Real feasibility;
1722  SCIP_Real tmp;
1723 
1724  assert(consdata->row2 != NULL);
1725 
1726  /* skip constraints already in the LP */
1727  if( SCIProwIsInLP(consdata->row1) && SCIProwIsInLP(consdata->row2))
1728  return SCIP_OKAY;
1729 
1730  feasibility = 1.0;
1731 
1732  /* check first row (linking) for feasibility */
1733  if( !SCIProwIsInLP(consdata->row1) )
1734  {
1735  tmp = SCIPgetRowLPFeasibility(scip, consdata->row1);
1736  feasibility = MIN(feasibility, tmp);
1737  }
1738 
1739  /* check second row (setppc) for feasibility */
1740  if( !SCIProwIsInLP(consdata->row2) )
1741  {
1742  tmp = SCIPgetRowLPFeasibility(scip, consdata->row2);
1743  feasibility = MIN(feasibility, tmp);
1744  }
1745  addcut = SCIPisFeasNegative(scip, feasibility);
1746  }
1747  else
1748  addcut = !checkCons(scip, cons, sol);
1749 
1750 
1751  if( !addcut )
1752  {
1753  /* constraint was feasible -> increase age */
1754  SCIP_CALL( SCIPincConsAge(scip, cons) );
1755  }
1756  }
1757 
1758  if( addcut )
1759  {
1760  /* insert LP row as cut */
1761  assert(!(*cutoff));
1762  SCIP_CALL( addCuts(scip, cons, cutoff) );
1763  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1764  *separated = TRUE;
1765  }
1766 
1767  return SCIP_OKAY;
1768 }
1769 
1770 /** enforces the pseudo solution on the given constraint */
1771 static
1773  SCIP* scip, /**< SCIP data structure */
1774  SCIP_CONS* cons, /**< linking constraint to be separated */
1775  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1776  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
1777  int* nchgbds, /**< pointer to store the number of changed variable bounds */
1778  SCIP_Bool* solvelp /**< pointer to store TRUE, if the LP has to be solved */
1779  )
1780 {
1781  SCIP_Bool addcut;
1782  SCIP_Bool mustcheck;
1783 
1784  assert(!SCIPhasCurrentNodeLP(scip));
1785  assert(cons != NULL);
1786  assert(SCIPconsGetHdlr(cons) != NULL);
1787  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1788  assert(cutoff != NULL);
1789  assert(infeasible != NULL);
1790  assert(nchgbds != NULL);
1791  assert(solvelp != NULL);
1792 
1793  addcut = FALSE;
1794  mustcheck = TRUE;
1795 
1796  /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
1797  SCIP_CALL( processIntegerBoundChg(scip, cons, cutoff, nchgbds, &mustcheck) );
1798  SCIP_CALL( processBinvarFixings(scip, cons, cutoff, nchgbds, &addcut, &mustcheck) );
1799 
1800  if( mustcheck )
1801  {
1802  assert(!addcut);
1803 
1804  if( checkCons(scip, cons, NULL) )
1805  {
1806  /* constraint was feasible -> increase age */
1807  SCIP_CALL( SCIPincConsAge(scip, cons) );
1808  }
1809  else
1810  {
1811  /* constraint was infeasible -> reset age */
1812  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1813  *infeasible = TRUE;
1814  }
1815  }
1816 
1817  if( addcut )
1818  {
1819  assert(!(*cutoff));
1820  /* a cut must be added to the LP -> we have to solve the LP immediately */
1821  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1822  *solvelp = TRUE;
1823  }
1824 
1825  return SCIP_OKAY;
1826 }
1827 
1828 /** helper function to enforce constraints */
1829 static
1831  SCIP* scip, /**< SCIP data structure */
1832  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1833  SCIP_CONS** conss, /**< constraints to process */
1834  int nconss, /**< number of constraints */
1835  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
1836  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
1837  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
1838  )
1839 {
1840  SCIP_Bool cutoff;
1841  SCIP_Bool separated;
1842  int nchgbds;
1843  int c;
1844 
1845  assert(conshdlr != NULL);
1846  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1847  assert(nconss == 0 || conss != NULL);
1848  assert(result != NULL);
1849 
1850  SCIPdebugMsg(scip, "Enforcing %d linking constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
1851 
1852  cutoff = FALSE;
1853  separated = FALSE;
1854  nchgbds = 0;
1855 
1856  /* check all useful linking constraints for feasibility */
1857  for( c = 0; c < nusefulconss && !cutoff && nchgbds == 0; ++c )
1858  {
1859  SCIP_CALL( separateCons(scip, conss[c], sol, &cutoff, &separated, &nchgbds) );
1860  }
1861 
1862  /* check all obsolete linking constraints for feasibility */
1863  for( c = nusefulconss; c < nconss && !cutoff && !separated && nchgbds == 0; ++c )
1864  {
1865  SCIP_CALL( separateCons(scip, conss[c], sol, &cutoff, &separated, &nchgbds) );
1866  }
1867 
1868  /* return the correct result */
1869  if( cutoff )
1870  *result = SCIP_CUTOFF;
1871  else if( nchgbds > 0 )
1872  *result = SCIP_REDUCEDDOM;
1873  else if( separated )
1874  *result = SCIP_SEPARATED;
1875  else
1876  *result = SCIP_FEASIBLE;
1877 
1878  return SCIP_OKAY;
1879 }
1880 
1881 
1882 /*
1883  * Callback methods of constraint handler
1884  */
1885 
1886 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1887 static
1888 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinking)
1889 { /*lint --e{715}*/
1890  assert(scip != NULL);
1891  assert(conshdlr != NULL);
1892  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1893 
1894  /* call inclusion method of constraint handler */
1896 
1897  *valid = TRUE;
1898 
1899  return SCIP_OKAY;
1900 }
1901 
1902 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
1903 static
1904 SCIP_DECL_CONSFREE(consFreeLinking)
1905 {
1906  SCIP_CONSHDLRDATA* conshdlrdata;
1907 
1908  assert(conshdlr != NULL);
1909  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1910  assert(scip != NULL);
1911 
1912  /* free constraint handler data */
1913  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1914  assert(conshdlrdata != NULL);
1915 
1916  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
1917 
1918  return SCIP_OKAY;
1919 }
1920 
1921 
1922 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
1923 static
1924 SCIP_DECL_CONSINITPRE(consInitpreLinking)
1925 { /*lint --e{715}*/
1926  SCIP_CONSHDLRDATA* conshdlrdata;
1927  SCIP_CONSDATA* consdata;
1928  int c;
1929 
1930  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1931  assert(conshdlrdata != NULL);
1932 
1933  /* disable all linking constraints which contain at most one binary variable */
1934  for( c = 0; c < nconss; ++c )
1935  {
1936  consdata = SCIPconsGetData(conss[c]);
1937  assert(consdata != NULL);
1938 
1939  /* skip constraints which are not added */
1940  if( !SCIPconsIsAdded(conss[c]) )
1941  continue;
1942 
1943  if( consdata->nbinvars <= 1 )
1944  {
1945  SCIP_CALL( SCIPdisableCons(scip, conss[c]) );
1946  assert(consdata->nbinvars == 0 || SCIPvarGetLbGlobal(consdata->binvars[0]) > 0.5);
1947  }
1948  else if( conshdlrdata->linearize )
1949  {
1950  SCIP_CALL( consdataLinearize(scip, conss[c], consdata) );
1951  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
1952  }
1953  }
1954 
1955  return SCIP_OKAY;
1956 }
1957 
1958 
1959 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
1960 static
1961 SCIP_DECL_CONSEXITSOL(consExitsolLinking)
1962 { /*lint --e{715}*/
1963  SCIP_CONSDATA* consdata;
1964  int c;
1965 
1966  for( c = 0; c < nconss; ++c )
1967  {
1968  consdata = SCIPconsGetData(conss[c]);
1969  assert(consdata != NULL);
1970 
1971  /* release the rows of all constraints */
1972  if( consdata->row1 != NULL )
1973  {
1974  assert(consdata->row2 != NULL);
1975 
1976  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row1) );
1977  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row2) );
1978  }
1979  }
1980 
1981  return SCIP_OKAY;
1982 }
1983 
1984 
1985 /** frees specific constraint data */
1986 static
1987 SCIP_DECL_CONSDELETE(consDeleteLinking)
1988 { /*lint --e{715}*/
1989  SCIP_CONSHDLRDATA* conshdlrdata;
1990 
1991  assert(conshdlr != NULL);
1992  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1993  assert(consdata != NULL);
1994  assert(*consdata != NULL);
1995 
1996  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1997  assert(conshdlrdata != NULL);
1998  assert(conshdlrdata->eventhdlr != NULL);
1999 
2000  /* remove linking constraint form variable hash map */
2001  assert(conshdlrdata->varmap != NULL);
2002  assert(SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey((*consdata)->intvar)));
2003  SCIP_CALL( SCIPhashmapRemove(conshdlrdata->varmap, getHashmapKey((*consdata)->intvar)) );
2004 
2005  if( (*consdata)->nbinvars > 0 && SCIPisTransformed(scip) )
2006  {
2007  SCIP_CALL( dropAllEvents(scip, *consdata, conshdlrdata->eventhdlr) );
2008  }
2009 
2010  /* free consdata */
2011  SCIP_CALL( consdataFree(scip, consdata) );
2012 
2013  return SCIP_OKAY;
2014 }
2015 
2016 
2017 /** transforms constraint data into data belonging to the transformed problem */
2018 static
2019 SCIP_DECL_CONSTRANS(consTransLinking)
2020 { /*lint --e{715}*/
2021  SCIP_CONSDATA* sourcedata;
2022  SCIP_CONSDATA* targetdata;
2023  SCIP_CONSHDLRDATA* conshdlrdata;
2024 
2025  assert(conshdlr != NULL);
2026  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2027  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
2028  assert(sourcecons != NULL);
2029  assert(targetcons != NULL);
2030 
2031  /* free constraint handler data */
2032  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2033  assert(conshdlrdata != NULL);
2034  assert(conshdlrdata->eventhdlr != NULL);
2035 
2036  sourcedata = SCIPconsGetData(sourcecons);
2037  assert(sourcedata != NULL);
2038  assert(sourcedata->row1 == NULL); /* in original problem, there cannot be LP rows */
2039  assert(sourcedata->row2 == NULL); /* in original problem, there cannot be LP rows */
2040 
2041  SCIPdebugMsg(scip, "transform linking constraint for variable <%s>\n", SCIPvarGetName(sourcedata->intvar));
2042 
2043  /* create constraint data for target constraint */
2044  SCIP_CALL( consdataCreate(scip, conshdlrdata->eventhdlr, &targetdata,
2045  sourcedata->intvar, sourcedata->binvars, sourcedata->vals, sourcedata->nbinvars) );
2046 
2047  /* create target constraint */
2048  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
2049  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
2050  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
2051  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
2052  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
2053 
2054  /* insert (transformed) linking constraint into the hash map */
2055  assert(conshdlrdata->varmap != NULL);
2056  SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varmap, getHashmapKey(targetdata->intvar), *targetcons) );
2057 
2058  return SCIP_OKAY;
2059 }
2060 
2061 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
2062 static
2063 SCIP_DECL_CONSINITLP(consInitlpLinking)
2064 { /*lint --e{715}*/
2065  SCIP_CONSDATA* consdata;
2066  int c;
2067 
2068  *infeasible = FALSE;
2069 
2070  for( c = 0; c < nconss && !(*infeasible); ++c )
2071  {
2072  assert(SCIPconsIsInitial(conss[c]));
2073 
2074  consdata = SCIPconsGetData(conss[c]);
2075  assert(consdata != NULL);
2076 
2077  if( consdata->nbinvars <= 1 )
2078  continue;
2079 
2080  SCIP_CALL( addCuts(scip, conss[c], infeasible) );
2081  }
2082 
2083  return SCIP_OKAY;
2084 }
2085 
2086 
2087 /** separation method of constraint handler for LP solutions */
2088 static
2089 SCIP_DECL_CONSSEPALP(consSepalpLinking)
2090 { /*lint --e{715}*/
2091  SCIP_Bool cutoff;
2092  SCIP_Bool separated;
2093  int nchgbds;
2094  int c;
2095 
2096  assert(conshdlr != NULL);
2097  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2098  assert(nconss == 0 || conss != NULL);
2099  assert(result != NULL);
2100 
2101  SCIPdebugMsg(scip, "separating %d/%d linking constraints\n", nusefulconss, nconss);
2102 
2103  cutoff = FALSE;
2104  separated = FALSE;
2105  nchgbds = 0;
2106 
2107  /* check all useful linking constraints for feasibility */
2108  for( c = 0; c < nusefulconss && !cutoff; ++c )
2109  {
2110  SCIP_CALL( separateCons(scip, conss[c], NULL, &cutoff, &separated, &nchgbds) );
2111  }
2112 
2113  /* return the correct result */
2114  if( cutoff )
2115  *result = SCIP_CUTOFF;
2116  else if( nchgbds > 0 )
2117  *result = SCIP_REDUCEDDOM;
2118  else if( separated )
2119  *result = SCIP_SEPARATED;
2120  else
2121  *result = SCIP_DIDNOTFIND;
2122 
2123  return SCIP_OKAY;
2124 }
2125 
2126 
2127 /** separation method of constraint handler for arbitrary primal solutions */
2128 static
2129 SCIP_DECL_CONSSEPASOL(consSepasolLinking)
2130 { /*lint --e{715}*/
2131  SCIP_Bool cutoff;
2132  SCIP_Bool separated;
2133  int nchgbds;
2134  int c;
2135 
2136  assert(conshdlr != NULL);
2137  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2138  assert(nconss == 0 || conss != NULL);
2139  assert(result != NULL);
2140 
2141  SCIPdebugMsg(scip, "separating %d/%d " CONSHDLR_NAME " constraints\n", nusefulconss, nconss);
2142 
2143  cutoff = FALSE;
2144  separated = FALSE;
2145  nchgbds = 0;
2146 
2147  /* check all useful set partitioning / packing / covering constraints for feasibility */
2148  for( c = 0; c < nusefulconss && !cutoff; ++c )
2149  {
2150  SCIP_CALL( separateCons(scip, conss[c], sol, &cutoff, &separated, &nchgbds) );
2151  }
2152 
2153  /* return the correct result */
2154  if( cutoff )
2155  *result = SCIP_CUTOFF;
2156  else if( nchgbds > 0 )
2157  *result = SCIP_REDUCEDDOM;
2158  else if( separated )
2159  *result = SCIP_SEPARATED;
2160  else
2161  *result = SCIP_DIDNOTFIND;
2162 
2163  return SCIP_OKAY;
2164 }
2165 
2166 
2167 /** constraint enforcing method of constraint handler for LP solutions */
2168 static
2169 SCIP_DECL_CONSENFOLP(consEnfolpLinking)
2170 { /*lint --e{715}*/
2171  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
2172 
2173  return SCIP_OKAY;
2174 }
2175 
2176 
2177 /** constraint enforcing method of constraint handler for relaxation solutions */
2178 static
2179 SCIP_DECL_CONSENFORELAX(consEnforelaxLinking)
2180 { /*lint --e{715}*/
2181  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
2182 
2183  return SCIP_OKAY;
2184 }
2185 
2186 
2187 /** constraint enforcing method of constraint handler for pseudo solutions */
2188 static
2189 SCIP_DECL_CONSENFOPS(consEnfopsLinking)
2190 { /*lint --e{715}*/
2191  SCIP_Bool cutoff;
2192  SCIP_Bool infeasible;
2193  int nchgbds;
2194  SCIP_Bool solvelp;
2195  int c;
2196 
2197  assert(conshdlr != NULL);
2198  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2199  assert(nconss == 0 || conss != NULL);
2200  assert(result != NULL);
2201 
2202  SCIPdebugMsg(scip, "pseudo enforcing %d " CONSHDLR_NAME " constraints\n", nconss);
2203 
2204  if( objinfeasible )
2205  {
2206  *result = SCIP_DIDNOTRUN;
2207  return SCIP_OKAY;
2208  }
2209 
2210  cutoff = FALSE;
2211  infeasible = FALSE;
2212  nchgbds = 0;
2213  solvelp = FALSE;
2214 
2215  /* check all linking constraint for domain reductions and feasibility */
2216  for( c = 0; c < nconss && !cutoff && !solvelp; ++c )
2217  {
2218  SCIP_CALL( enforcePseudo(scip, conss[c], &cutoff, &infeasible, &nchgbds, &solvelp) );
2219  }
2220 
2221  if( cutoff )
2222  *result = SCIP_CUTOFF;
2223  else if( nchgbds > 0 )
2224  *result = SCIP_REDUCEDDOM;
2225  else if( solvelp )
2226  *result = SCIP_SOLVELP;
2227  else if( infeasible )
2228  *result = SCIP_INFEASIBLE;
2229  else
2230  *result = SCIP_FEASIBLE;
2231 
2232  return SCIP_OKAY;
2233 }
2234 
2235 
2236 /** feasibility check method of constraint handler for integral solutions */
2237 static
2238 SCIP_DECL_CONSCHECK(consCheckLinking)
2239 { /*lint --e{715}*/
2240  SCIP_CONS* cons;
2241  SCIP_CONSDATA* consdata;
2242  int c;
2243 
2244  assert(conshdlr != NULL);
2245  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2246  assert(nconss == 0 || conss != NULL);
2247  assert(result != NULL);
2248 
2249  *result = SCIP_FEASIBLE;
2250 
2251  /* check all linking constraints for feasibility */
2252  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
2253  {
2254  cons = conss[c];
2255  consdata = SCIPconsGetData(cons);
2256  assert(consdata != NULL);
2257 
2258  if( consdata->nbinvars > 1 && (checklprows || consdata->row1 == NULL || !SCIProwIsInLP(consdata->row1)) )
2259  {
2260  if( !checkCons(scip, cons, sol) )
2261  {
2262  /* constraint is violated */
2263  *result = SCIP_INFEASIBLE;
2264 
2265  if( printreason )
2266  {
2267  int pos;
2268  int b;
2269 
2270  pos = -1;
2271 
2272 #ifndef NDEBUG
2273  for( b = 0; b < consdata->nbinvars; ++b )
2274  {
2275  assert(consdata->binvars[b] != NULL);
2276  assert(SCIPvarIsBinary(consdata->binvars[b]));
2277  }
2278 #endif
2279 
2280  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
2281  SCIPinfoMessage(scip, NULL, ";\n");
2282 
2283  /* check that at most one binary variable is fixed */
2284  for( b = 0; b < consdata->nbinvars; ++b )
2285  {
2286  assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, consdata->binvars[b])) );
2287 
2288  /* check if binary variable is fixed */
2289  if( SCIPgetSolVal(scip, sol, consdata->binvars[b]) > 0.5 )
2290  {
2291  if( pos != -1 )
2292  {
2293  SCIPinfoMessage(scip, NULL, "violation: more than one binary variable is set to one");
2294  break;
2295  }
2296  pos = b ;
2297  }
2298  }
2299 
2300  /* check that at least one binary variable is fixed */
2301  if( pos == -1 )
2302  {
2303  SCIPinfoMessage(scip, NULL, "violation: none of the binary variables is set to one");
2304  }
2305  else if( !SCIPisFeasEQ(scip, (SCIP_Real) (consdata->vals[pos]), SCIPgetSolVal(scip, sol, consdata->intvar)) )
2306  {
2307  /* check if the fixed binary variable match with the integer variable */
2308  SCIPinfoMessage(scip, NULL, "violation: <%s> = <%g> and <%s> is one\n",
2309  SCIPvarGetName(consdata->intvar), SCIPgetSolVal(scip, sol, consdata->intvar),
2310  SCIPvarGetName(consdata->binvars[pos]) );
2311  }
2312  }
2313  }
2314  }
2315  }
2316 
2317  return SCIP_OKAY;
2318 }
2319 
2320 /** domain propagation method of constraint handler */
2321 static
2322 SCIP_DECL_CONSPROP(consPropLinking)
2323 { /*lint --e{715}*/
2324  SCIP_Bool cutoff;
2325  SCIP_Bool addcut;
2326  SCIP_Bool mustcheck;
2327  int nchgbds;
2328  int c;
2329 
2330  assert(conshdlr != NULL);
2331  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2332  assert(nconss == 0 || conss != NULL);
2333  assert(result != NULL);
2334 
2335  SCIPdebugMsg(scip, "propagating %d/%d " CONSHDLR_NAME " constraints\n", nusefulconss, nconss);
2336 
2337  cutoff = FALSE;
2338  nchgbds = 0;
2339  addcut = FALSE;
2340  mustcheck = TRUE;
2341 
2342  /* propagate all useful set partitioning / packing / covering constraints */
2343  for( c = 0; c < nusefulconss && !cutoff; ++c )
2344  {
2345  SCIP_CALL( processIntegerBoundChg(scip, conss[c], &cutoff, &nchgbds, &mustcheck) );
2346  SCIP_CALL( processBinvarFixings(scip, conss[c], &cutoff, &nchgbds, &addcut, &mustcheck) );
2347  }
2348 
2349  /* return the correct result */
2350  if( cutoff )
2351  *result = SCIP_CUTOFF;
2352  else if( nchgbds > 0 )
2353  *result = SCIP_REDUCEDDOM;
2354  else
2355  *result = SCIP_DIDNOTFIND;
2356 
2357  return SCIP_OKAY;
2358 }
2359 
2360 
2361 /** presolving method of constraint handler */
2362 static
2363 SCIP_DECL_CONSPRESOL(consPresolLinking)
2364 { /*lint --e{715}*/
2365  SCIP_CONSHDLRDATA* conshdlrdata;
2366  int oldnfixedvars;
2367  int oldnchgbds;
2368  int oldnaggrvars;
2369  int oldndelconss;
2370  int firstchange;
2371  int firstclique;
2372  int lastclique;
2373  int c;
2374  SCIP_Bool fixed;
2375  SCIP_Bool cutoff;
2376  SCIP_Bool infeasible;
2377  SCIP_Bool mustcheck;
2378 
2379  assert(conshdlr != NULL);
2380  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2381  assert(scip != NULL);
2382  assert(result != NULL);
2383 
2384  SCIPdebugMsg(scip, "presolve %d linking constraints\n", nconss);
2385 
2386  (*result) = SCIP_DIDNOTFIND;
2387 
2388  oldnchgbds = *nchgbds;
2389  oldnaggrvars = *naggrvars;
2390  oldnfixedvars = *nfixedvars;
2391  oldndelconss = *ndelconss;
2392  cutoff = FALSE;
2393 
2394  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2395  assert(conshdlrdata != NULL);
2396 
2397  /* process constraints */
2398  firstchange = INT_MAX;
2399  firstclique = INT_MAX;
2400  lastclique = -1;
2401 
2402  /* check for each linking constraint the set partitioning condition */
2403  for( c = 0; c < nconss && !SCIPisStopped(scip); ++c )
2404  {
2405  SCIP_CONS* cons;
2406  SCIP_CONSDATA* consdata;
2407 
2408  assert(*result != SCIP_CUTOFF);
2409 
2410  cons = conss[c];
2411  assert(cons != NULL);
2412  assert(!SCIPconsIsModifiable(cons));
2413 
2414  SCIPdebugMsg(scip, "presolve linking constraints <%s>\n", SCIPconsGetName(cons));
2415 
2416  consdata = SCIPconsGetData(cons);
2417  assert(consdata != NULL);
2418 
2419  if( !SCIPconsIsEnabled(cons) /* || consdata->nbinvars <= 1 */ )
2420  continue;
2421 
2422  /* in case there is only at most one binary variables, the constraints should already be disabled */
2423  assert(consdata->nbinvars > 1);
2424 
2425  /*SCIPdebugMsg(scip, "presolving set partitioning / packing / covering constraint <%s>\n", SCIPconsGetName(cons));*/
2426  if( consdata->nfixedones >= 2 )
2427  {
2428  /* at least two variables are fixed to 1:
2429  * - a linking constraint is infeasible due to the set partitioning condition
2430  */
2431  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> is infeasible\n", SCIPconsGetName(cons));
2432  *result = SCIP_CUTOFF;
2433  return SCIP_OKAY;
2434  }
2435 
2436  if( consdata->nfixedones == 1 )
2437  {
2438  /* exactly one variable is fixed to 1:
2439  * - all other binary variables must be zero due to the set partitioning condition
2440  * - integer variable has to be fixed to corresponding binary variable which is fixed to one
2441  * - if constraint is not modifiable it can be removed
2442  */
2443  SCIP_VAR* var;
2444  int v;
2445 
2446  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> has a binary variable fixed to 1.0\n", SCIPconsGetName(cons));
2447 
2448  for( v = 0; v < consdata->nbinvars; ++v )
2449  {
2450  var = consdata->binvars[v];
2451  assert(var != NULL);
2452 
2453  if( SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
2454  {
2455  SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
2456 
2457  if( infeasible )
2458  {
2459  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == 0\n",
2460  SCIPconsGetName(cons), SCIPvarGetName(var));
2461 
2462  *result = SCIP_CUTOFF;
2463  return SCIP_OKAY;
2464  }
2465  assert(fixed);
2466  (*nfixedvars)++;
2467  }
2468  else if( SCIPvarGetLbGlobal(var) > 0.5 )
2469  {
2470  /* fix integer variable */
2471  SCIP_CALL( SCIPfixVar(scip, consdata->intvar, (SCIP_Real)(consdata->vals[v]), &infeasible, &fixed) );
2472 
2473  if( infeasible )
2474  {
2475  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == %d\n",
2476  SCIPconsGetName(cons), SCIPvarGetName(consdata->intvar), consdata->vals[v]);
2477 
2478  *result = SCIP_CUTOFF;
2479  return SCIP_OKAY;
2480  }
2481 
2482  if( fixed )
2483  (*nfixedvars)++;
2484  }
2485  }
2486 
2487  /* now all other variables are fixed to zero:
2488  * the constraint is feasible, and if it's not modifiable, it is redundant
2489  */
2490  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> is redundant\n", SCIPconsGetName(cons));
2491  SCIP_CALL( SCIPdelCons(scip, cons) );
2492  (*ndelconss)++;
2493  continue;
2494  }
2495 
2496  if( consdata->nfixedzeros == consdata->nbinvars )
2497  {
2498  /* all variables are fixed to zero:
2499  * - a linking constraint is infeasible due the set partitioning condition
2500  */
2501  assert(consdata->nfixedones == 0);
2502 
2503  SCIPdebugMsg(scip, "linking constraint <%s> is infeasible due to set partitioning condition\n", SCIPconsGetName(cons));
2504  *result = SCIP_CUTOFF;
2505  return SCIP_OKAY;
2506  }
2507 
2508  if( consdata->nfixedzeros == consdata->nbinvars - 1 )
2509  {
2510  /* all variables except one are fixed to zero:
2511  * - a linking constraint is feasible due the set partitioning condition
2512  * - the remaining binary variable can be fixed to one
2513  * - integer variable has to be fixed to corresponding binary variable which is fixed to one
2514  * - constraint can be deleted since it is not modifiable
2515  */
2516  SCIP_VAR* var;
2517  SCIP_Bool found;
2518  int v;
2519 
2520  assert(consdata->nfixedones == 0);
2521 
2522  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> has only one binary variable not fixed to zero\n",
2523  SCIPconsGetName(cons));
2524 
2525  /* search unfixed variable */
2526  found = FALSE;
2527  var = NULL;
2528  for( v = 0; v < consdata->nbinvars && !found; ++v )
2529  {
2530  var = consdata->binvars[v];
2531  found = SCIPvarGetUbGlobal(var) > 0.5;
2532  }
2533  assert(found);
2534 
2535  /* fix remaining binary variable */
2536  SCIP_CALL( SCIPfixVar(scip, var, 1.0, &infeasible, &fixed) );
2537  if( infeasible )
2538  {
2539  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == 1\n",
2540  SCIPconsGetName(cons), SCIPvarGetName(var));
2541  *result = SCIP_CUTOFF;
2542  return SCIP_OKAY;
2543  }
2544  assert(fixed);
2545  (*nfixedvars)++;
2546 
2547  /* fix integer variable */
2548  SCIP_CALL( SCIPfixVar(scip, consdata->intvar, (SCIP_Real)(consdata->vals[v]), &infeasible, &fixed) );
2549  if( infeasible )
2550  {
2551  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == %d\n",
2552  SCIPconsGetName(cons), SCIPvarGetName(consdata->intvar), consdata->vals[v]);
2553 
2554  *result = SCIP_CUTOFF;
2555  return SCIP_OKAY;
2556  }
2557  assert(fixed);
2558  (*nfixedvars)++;
2559 
2560  /* delete constraint from problem */
2561  SCIP_CALL( SCIPdelCons(scip, cons) );
2562  (*ndelconss)++;
2563  continue;
2564  }
2565 
2566  if( consdata->nfixedzeros == consdata->nbinvars - 2 ) /*lint !e641*/
2567  {
2568  SCIP_VAR* var;
2569  SCIP_VAR* var1;
2570  SCIP_VAR* var2;
2571  SCIP_Bool redundant;
2572  SCIP_Bool aggregated;
2573  int v;
2574 
2575  /* aggregate variable, if set partitioning condition consists only of two
2576  * non-fixed variables
2577  */
2578 
2579  /* search unfixed variable */
2580  var1 = NULL;
2581  var2 = NULL;
2582  for( v = 0; v < consdata->nbinvars && var2 == NULL; ++v )
2583  {
2584  var = consdata->binvars[v];
2585  if( SCIPvarGetUbGlobal(var) > 0.5 )
2586  {
2587  if( var1 == NULL )
2588  var1 = var;
2589  else
2590  var2 = var;
2591  }
2592  }
2593  assert(var1 != NULL && var2 != NULL);
2594 
2595  /* aggregate binary equality var1 + var2 == 1 */
2596  SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: aggregate <%s> + <%s> == 1\n",
2597  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
2598  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
2599 
2600  /* evaluate aggregation result */
2601  if( infeasible )
2602  {
2603  SCIPdebugMsg(scip, "linking constraint <%s>: infeasible aggregation <%s> + <%s> == 1\n",
2604  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
2605  *result = SCIP_CUTOFF;
2606  return SCIP_OKAY;
2607  }
2608  if( aggregated )
2609  (*naggrvars)++;
2610  }
2611 
2612  /* apply integer bound to binary variables */
2613  SCIP_CALL( processIntegerBoundChg(scip, cons, &cutoff, nchgbds, &mustcheck) );
2614 
2615  /* tightened integer variable */
2616  SCIP_CALL( tightenedIntvar(scip, cons, consdata, &cutoff, nchgbds) );
2617 
2618  /* remove the trailing and leeading binary variable which are fixed to zero */
2619  SCIP_CALL( removeFixedBinvars(scip, conshdlrdata->eventhdlr, cons) );
2620 
2621  if( cutoff )
2622  {
2623  *result = SCIP_CUTOFF;
2624  return SCIP_OKAY;
2625  }
2626 
2627  /* remember the first changed constraint to begin the next redundancy round with */
2628  if( firstchange == INT_MAX )
2629  firstchange = c;
2630 
2631  /* remember the first and last constraints for which we have to add the clique information */
2632  if( !consdata->cliqueadded && consdata->nbinvars >= 2 )
2633  {
2634  if( firstclique == INT_MAX )
2635  firstclique = c;
2636  lastclique = c;
2637  }
2638  }
2639 
2640  /* add clique and implication information */
2641  for( c = firstclique; c < lastclique && !SCIPisStopped(scip); ++c )
2642  {
2643  SCIP_CONS* cons;
2644  SCIP_CONSDATA* consdata;
2645 
2646  assert(*result != SCIP_CUTOFF);
2647 
2648  cons = conss[c];
2649  assert(cons != NULL);
2650 
2651  /* ignore deleted constraints */
2652  if( !SCIPconsIsActive(cons) )
2653  continue;
2654 
2655  consdata = SCIPconsGetData(cons);
2656  assert(consdata != NULL);
2657 
2658  if( !consdata->cliqueadded && consdata->nbinvars >= 3 )
2659  {
2660  /* add set partitioning condition as clique */
2661  int ncliquebdchgs;
2662 
2663  SCIP_CALL( SCIPaddClique(scip, consdata->binvars, NULL, consdata->nbinvars, TRUE, &infeasible, &ncliquebdchgs) );
2664  *nchgbds += ncliquebdchgs;
2665 
2666  if( infeasible )
2667  {
2668  *result = SCIP_CUTOFF;
2669  return SCIP_OKAY;
2670  }
2671 
2672  consdata->cliqueadded = TRUE;
2673  }
2674  }
2675 
2676 #if 0
2677  /* transfer aggregated integer variables to the corresponding binary variables */
2678  assert(conshdlrdata->varmap != NULL);
2679  SCIP_CALL( aggregateVariables(scip, conshdlrdata->varmap, conss, nconss, naggrvars, &cutoff) );
2680 #endif
2681 
2682  if( cutoff )
2683  *result = SCIP_CUTOFF;
2684  else if( oldndelconss < *ndelconss || oldnfixedvars < *nfixedvars || oldnchgbds < *nchgbds || oldnaggrvars < *naggrvars)
2685  *result = SCIP_SUCCESS;
2686 
2687  return SCIP_OKAY;
2688 }
2689 
2690 
2691 /** propagation conflict resolving method of constraint handler */
2692 static
2693 SCIP_DECL_CONSRESPROP(consRespropLinking)
2694 { /*lint --e{715}*/
2695 
2696  SCIP_CONSDATA* consdata;
2697  SCIP_VAR* intvar;
2698  int v;
2699 
2700  SCIPdebugMsg(scip, "conflict resolving method of " CONSHDLR_NAME " constraint handler\n");
2701 
2702  consdata = SCIPconsGetData(cons);
2703  assert(consdata != NULL);
2704 
2705  intvar = consdata->intvar;
2706  assert( intvar != NULL);
2707 
2708  *result = SCIP_DIDNOTFIND;
2709 
2710  if( inferinfo == -1 )
2711  {
2712  /* we have to resolve a fixing of a binary variable which was done due to fixed binary variables */
2713  assert(SCIPvarIsBinary(infervar));
2714  assert(SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, FALSE)));
2715  assert(SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, FALSE)));
2716 
2717  if( boundtype == SCIP_BOUNDTYPE_UPPER )
2718  {
2719  /* we fixed the binary variable to zero since one of the other binary variable was fixed to one (set
2720  * partitioning condition)
2721  */
2722  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
2723 
2724  for( v = 0; v < consdata->nbinvars; ++v )
2725  {
2726  if( SCIPgetVarLbAtIndex(scip, consdata->binvars[v], bdchgidx, FALSE) > 0.5 )
2727  {
2728  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvars[v]) );
2729  break;
2730  }
2731  }
2732  assert(v < consdata->nbinvars);
2733  }
2734  else
2735  {
2736  /* we fixed the binary variable to one since all other binary variable were fixed to zero */
2737  assert(boundtype == SCIP_BOUNDTYPE_LOWER);
2738  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
2739 
2740  for( v = 0; v < consdata->nbinvars; ++v )
2741  {
2742  if( consdata->binvars[v] != infervar )
2743  {
2744  /* the reason variable must be assigned to zero */
2745  assert(SCIPgetVarUbAtIndex(scip, consdata->binvars[v], bdchgidx, FALSE) < 0.5);
2746  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvars[v]) );
2747  }
2748  }
2749  }
2750  }
2751  else if( inferinfo == -2 )
2752  {
2753  /* we have to resolve a fixing of a binary variable which was done due to the integer variable lower bound */
2754  assert(SCIPvarIsBinary(infervar));
2755  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
2756  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5); /*@repair: neu*/
2757  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5); /*@repair: neu*/
2758  assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2759  assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2760 
2761 
2762  SCIP_CALL( SCIPaddConflictLb( scip, intvar, bdchgidx) );
2763  }
2764  else if( inferinfo == -3 )
2765  {
2766  /* we have to resolve a fixing of a binary variable which was done due to the integer variable upper bound */
2767  assert(SCIPvarIsBinary(infervar));
2768  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
2769  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
2770  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5);
2771  assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2772  assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2773 
2774  SCIP_CALL( SCIPaddConflictUb( scip, intvar, bdchgidx) );
2775  }
2776  else if( inferinfo == -4 )
2777  {
2778  SCIP_VAR** binvars;
2779  int* vals;
2780  int nbinvars;
2781  int lb;
2782  int b;
2783 
2784  /* we tightened the lower bound of the integer variable due the fixing of the corresponding binary variable to zero */
2785  assert(infervar == intvar);
2786  assert(boundtype == SCIP_BOUNDTYPE_LOWER);
2787 
2788  binvars = consdata->binvars;
2789  nbinvars = consdata->nbinvars;
2790  vals = consdata->vals;
2791 
2792  /* get propagated lower bound */
2793  lb = SCIPconvertRealToInt(scip, SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, TRUE));
2794 
2795  for( b = 0; b < nbinvars; ++b )
2796  {
2797  if( vals[b] >= lb )
2798  break;
2799 
2800  assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
2801  SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
2802  }
2803  }
2804  else if( inferinfo == -5 )
2805  {
2806  SCIP_VAR** binvars;
2807  int* vals;
2808  int nbinvars;
2809  int ub;
2810  int b;
2811 
2812  /* we tightened the upper bound of the integer variable due the fixing of the corresponding binary variable two zero */
2813 
2814  assert(infervar == intvar);
2815  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
2816 
2817  binvars = consdata->binvars;
2818  nbinvars = consdata->nbinvars;
2819  vals = consdata->vals;
2820 
2821  /* get old and new upper bound */
2822  ub = SCIPconvertRealToInt(scip, SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, TRUE));
2823 
2824  /* resolve tightening of upper bound of the integer variable by binary variables */
2825  for( b = nbinvars - 1; b >= 0; --b )
2826  {
2827  if( vals[b] <= ub )
2828  break;
2829 
2830  assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
2831  SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
2832  }
2833  }
2834  else if( inferinfo == -6 )
2835  {
2836  /* we fixed a binary variable to one since the integer variable was fixed */
2837  assert(SCIPvarIsBinary(infervar));
2838  assert(boundtype == SCIP_BOUNDTYPE_LOWER);
2839  assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2840  assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2841  assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2842  assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, intvar, bdchgidx, FALSE)) );
2843 
2844  assert( !SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, FALSE)) );
2845 
2846  SCIP_CALL( SCIPaddConflictLb( scip, intvar, bdchgidx) );
2847  SCIP_CALL( SCIPaddConflictUb( scip, intvar, bdchgidx) );
2848  }
2849  else
2850  {
2851  /* we fixed the integer variable to (vals[inferinfo]) since the corresponding binary variable was fixed to one */
2852  assert(infervar == intvar);
2853  assert(inferinfo >= 0);
2854  assert(inferinfo < consdata->nbinvars);
2855  assert(consdata->vals[inferinfo] == SCIPconvertRealToInt(scip, SCIPgetVarUbAtIndex(scip, consdata->intvar, bdchgidx, TRUE))
2856  || consdata->vals[inferinfo] == SCIPconvertRealToInt(scip, SCIPgetVarLbAtIndex(scip, consdata->intvar, bdchgidx, TRUE)));
2857 
2858  assert(SCIPgetVarLbAtIndex(scip, consdata->binvars[inferinfo], bdchgidx, FALSE) > 0.5);
2859  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvars[inferinfo]) );
2860  }
2861 
2862  *result = SCIP_SUCCESS;
2863 
2864  return SCIP_OKAY;
2865 }
2866 
2867 /** variable rounding lock method of constraint handler */
2868 static
2869 SCIP_DECL_CONSLOCK(consLockLinking)
2870 { /*lint --e{715}*/
2871  SCIP_CONSDATA* consdata;
2872  int b;
2873 
2874  consdata = SCIPconsGetData(cons);
2875  assert(consdata != NULL);
2876 
2877  /* look integer variable in both directions */
2878  SCIP_CALL( SCIPaddVarLocks(scip, consdata->intvar, nlockspos + nlocksneg, nlockspos + nlocksneg) );
2879 
2880  /* look binary variables in both directions */
2881  for( b = 0; b < consdata->nbinvars; ++b )
2882  {
2883  SCIP_CALL( SCIPaddVarLocks(scip, consdata->binvars[b], nlockspos + nlocksneg, nlockspos + nlocksneg) );
2884  }
2885 
2886  return SCIP_OKAY;
2887 }
2888 
2889 /** constraint enabling notification method of constraint handler */
2890 static
2891 SCIP_DECL_CONSENABLE(consEnableLinking)
2892 { /*lint --e{715}*/
2893 #if 0
2894  SCIP_CONSHDLRDATA* conshdlrdata;
2895  SCIP_CONSDATA* consdata;
2896 
2897  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2898  assert(conshdlrdata != NULL);
2899 
2900  consdata = SCIPconsGetData(cons);
2901  assert(consdata != NULL);
2902 
2903  if( consdata->nbinvars <= 1 )
2904  {
2905  SCIP_CALL( SCIPdisableCons(scip, cons) );
2906  assert(consdata->nbinvars == 0 || SCIPvarGetLbGlobal(consdata->binvars[0]) > 0.5);
2907  }
2908  else if( conshdlrdata->linearize )
2909  {
2910  SCIP_CALL( consdataLinearize(scip, cons, consdata) );
2911  SCIP_CALL( SCIPdelCons(scip, cons) );
2912  }
2913 #endif
2914  return SCIP_OKAY;
2915 }
2916 
2917 /** constraint display method of constraint handler */
2918 static
2919 SCIP_DECL_CONSPRINT(consPrintLinking)
2920 { /*lint --e{715}*/
2921  assert(scip != NULL);
2922  assert(conshdlr != NULL);
2923  assert(cons != NULL);
2924 
2925  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
2926 
2927  return SCIP_OKAY;
2928 }
2929 
2930 
2931 /** constraint copying method of constraint handler */
2932 static
2933 SCIP_DECL_CONSCOPY(consCopyLinking)
2934 { /*lint --e{715}*/
2935  SCIP_CONSDATA* sourceconsdata;
2936  SCIP_VAR** binvars;
2937  SCIP_VAR* intvar;
2938  int* vals;
2939  const char* consname;
2940  int nbinvars;
2941  int v;
2942 
2943  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(sourcecons)), CONSHDLR_NAME) != 0 )
2944  {
2945  SCIPerrorMessage("constraint is not a linking constraint\n");
2946  SCIPABORT();
2947  return SCIP_INVALIDDATA; /*lint !e527*/
2948  }
2949 
2950  (*valid) = TRUE;
2951 
2952  sourceconsdata = SCIPconsGetData(sourcecons);
2953  assert(sourceconsdata != NULL);
2954 
2955  /* get number of binary variables, integer variables */
2956  nbinvars = sourceconsdata->nbinvars;
2957  intvar = sourceconsdata->intvar;
2958 
2959  /* duplicate variable array */
2960  if( nbinvars > 0 )
2961  {
2962  SCIP_CALL( SCIPduplicateBufferArray(scip, &binvars, sourceconsdata->binvars, nbinvars) );
2963  SCIP_CALL( SCIPduplicateBufferArray(scip, &vals, sourceconsdata->vals, nbinvars) );
2964  }
2965  else
2966  {
2967  binvars = NULL;
2968  vals = NULL;
2969  }
2970 
2971  /* get copy for the binary variables */
2972  for( v = 0; v < nbinvars && *valid; ++v )
2973  {
2974  assert(binvars != NULL); /* for flexelint */
2975  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, binvars[v], &binvars[v], varmap, consmap, global, valid) );
2976  assert(!(*valid) || binvars[v] != NULL);
2977  }
2978 
2979  /* copy the integer variable */
2980  if( *valid )
2981  {
2982  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, intvar, &intvar, varmap, consmap, global, valid) );
2983  assert(!(*valid) || intvar != NULL);
2984  }
2985 
2986  /* only create the target constraint, if all variables could be copied */
2987  if( *valid )
2988  {
2989  if( name != NULL )
2990  consname = name;
2991  else
2992  consname = SCIPconsGetName(sourcecons);
2993 
2994  SCIP_CALL( SCIPcreateConsLinking(scip, cons, consname, intvar, binvars, vals, nbinvars,
2995  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2996  }
2997 
2998  /* free buffer array */
2999  if( nbinvars > 0 )
3000  {
3001  SCIPfreeBufferArrayNull(scip, &vals);
3002  SCIPfreeBufferArrayNull(scip, &binvars);
3003  }
3004 
3005  return SCIP_OKAY;
3006 }
3007 
3008 /** constraint parsing method of constraint handler */
3009 static
3010 SCIP_DECL_CONSPARSE(consParseLinking)
3011 { /*lint --e{715}*/
3012  SCIP_VAR** binvars;
3013  SCIP_VAR* intvar;
3014  int* intvals;
3015  char* endptr;
3016  int varssize;
3017  int nbinvars;
3018 
3019  assert(scip != NULL);
3020  assert(success != NULL);
3021  assert(str != NULL);
3022  assert(name != NULL);
3023  assert(cons != NULL);
3024 
3025  *success = TRUE;
3026 
3027  /* parse integer variables */
3028  SCIP_CALL( SCIPparseVarName(scip, str, &intvar, &endptr) );
3029 
3030  if( intvar == NULL )
3031  {
3032  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable name at '%s'\n", str);
3033  *success = FALSE;
3034  return SCIP_OKAY;
3035  }
3036  str = endptr;
3037 
3038  nbinvars = 0;
3039  varssize = 16;
3040 
3041  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, varssize) );
3042  SCIP_CALL( SCIPallocBufferArray(scip, &intvals, varssize) );
3043 
3044  while( *str != '=' )
3045  ++str;
3046 
3047  /* skip '=' */
3048  ++str;
3049 
3050  /* skip whitespace */
3051  while( isspace((int)*str) )
3052  ++str;
3053 
3054  /* check for the string "no binary variables yet" */
3055  if( strncmp(str, "no binary variables yet", 24) != 0 )
3056  {
3057  SCIP_Real* vals;
3058  int requsize;
3059  int v;
3060 
3061  SCIP_CALL( SCIPallocBufferArray(scip, &vals, varssize) );
3062 
3063  /* parse linear sum to get variables and coefficients */
3064  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, binvars, vals, &nbinvars, varssize, &requsize, &endptr, success) );
3065 
3066  if( *success && requsize > varssize )
3067  {
3068  /* realloc buffers and try again */
3069  varssize = requsize;
3070  SCIP_CALL( SCIPreallocBufferArray(scip, &binvars, varssize) );
3071  SCIP_CALL( SCIPreallocBufferArray(scip, &intvals, varssize) );
3072  SCIP_CALL( SCIPreallocBufferArray(scip, &vals, varssize) );
3073 
3074  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, binvars, vals, &nbinvars, varssize, &requsize, &endptr, success) );
3075  assert(!*success || requsize <= varssize); /* if successful, then should have had enough space now */
3076  }
3077 
3078  /* check coefficients */
3079  if( *success )
3080  {
3081  /* convert SCIP_Real to integer */
3082  for( v = 0; v < nbinvars; ++v )
3083  {
3084  assert(SCIPisIntegral(scip, vals[v]));
3085 
3086  /* check that the coefficients is integral */
3087  *success = *success && SCIPisIntegral(scip, vals[v]);
3088 
3089  intvals[v] = SCIPconvertRealToInt(scip, vals[v]);
3090  }
3091  }
3092 
3093  SCIPfreeBufferArray(scip, &vals);
3094  }
3095 
3096  if( *success )
3097  {
3098  SCIP_CALL( SCIPcreateConsLinking(scip, cons, name, intvar, binvars, intvals, nbinvars,
3099  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3100  }
3101 
3102  SCIPfreeBufferArray(scip, &intvals);
3103  SCIPfreeBufferArray(scip, &binvars);
3104 
3105  return SCIP_OKAY;
3106 }
3107 
3108 /** constraint method of constraint handler which returns the variables (if possible) */
3109 static
3110 SCIP_DECL_CONSGETVARS(consGetVarsLinking)
3111 { /*lint --e{715}*/
3112  SCIP_CONSDATA* consdata;
3113 
3114  consdata = SCIPconsGetData(cons);
3115  assert(consdata != NULL);
3116 
3117  if( varssize < consdata->nbinvars + 1)
3118  (*success) = FALSE;
3119  else
3120  {
3121  assert(vars != NULL);
3122 
3123  BMScopyMemoryArray(vars, consdata->binvars, consdata->nbinvars);
3124  vars[consdata->nbinvars] = consdata->intvar;
3125  (*success) = TRUE;
3126  }
3127 
3128  return SCIP_OKAY;
3129 }
3130 
3131 /** constraint method of constraint handler which returns the number of variables (if possible) */
3132 static
3133 SCIP_DECL_CONSGETNVARS(consGetNVarsLinking)
3134 { /*lint --e{715}*/
3135  SCIP_CONSDATA* consdata;
3136 
3137  consdata = SCIPconsGetData(cons);
3138  assert(consdata != NULL);
3139 
3140  (*nvars) = consdata->nbinvars + 1;
3141  (*success) = TRUE;
3142 
3143  return SCIP_OKAY;
3144 }
3145 
3146 /*
3147  * Callback methods of event handler
3148  */
3149 
3150 /** execution method of event handler */
3151 static
3152 SCIP_DECL_EVENTEXEC(eventExecBinvar)
3153 { /*lint --e{715}*/
3154  SCIP_CONSDATA* consdata;
3155  SCIP_EVENTTYPE eventtype;
3156 
3157  assert(eventhdlr != NULL);
3158  assert(eventdata != NULL);
3159  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
3160  assert(event != NULL);
3161 
3162  consdata = (SCIP_CONSDATA*)eventdata;
3163  assert(consdata != NULL);
3164 
3165  eventtype = SCIPeventGetType(event);
3166  switch( eventtype )
3167  {
3169  consdata->nfixedones++;
3170  break;
3172  consdata->nfixedones--;
3173  consdata->firstnonfixed = 0;
3174  consdata->lastnonfixed = consdata->nbinvars - 1;
3175  break;
3177  consdata->nfixedzeros++;
3178  break;
3180  consdata->firstnonfixed = 0;
3181  consdata->lastnonfixed = consdata->nbinvars - 1;
3182  consdata->nfixedzeros--;
3183  break;
3184  default:
3185  SCIPerrorMessage("invalid event type\n");
3186  return SCIP_INVALIDDATA;
3187  }
3188  assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nbinvars);
3189  assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nbinvars);
3190 
3191  /*debugMsg(scip, " -> constraint has %d zero-fixed and %d one-fixed of %d variables\n",
3192  consdata->nfixedzeros, consdata->nfixedones, consdata->nvars);*/
3193 
3194  return SCIP_OKAY;
3195 }
3196 
3197 /*
3198  * constraint specific interface methods
3199  */
3200 
3201 /** creates the handler for linking constraints and includes it in SCIP */
3203  SCIP* scip /**< SCIP data structure */
3204  )
3205 {
3206  SCIP_CONSHDLRDATA* conshdlrdata;
3207  SCIP_CONSHDLR* conshdlr;
3208  SCIP_EVENTHDLR* eventhdlr;
3209 
3210  /* create event handler for bound change events */
3212  eventExecBinvar, NULL) );
3213 
3214  /* create linking constraint handler data */
3215  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
3216 
3217  /* include constraint handler */
3220  consEnfolpLinking, consEnfopsLinking, consCheckLinking, consLockLinking,
3221  conshdlrdata) );
3222 
3223  assert(conshdlr != NULL);
3224 
3225  /* set non-fundamental callbacks via specific setter functions */
3226  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinking, consCopyLinking) );
3227  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinking) );
3228  SCIP_CALL( SCIPsetConshdlrEnable(scip, conshdlr, consEnableLinking) );
3229  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinking) );
3230  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinking) );
3231  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinking) );
3232  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinking) );
3233  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLinking) );
3234  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinking) );
3235  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinking) );
3236  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinking, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
3237  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinking) );
3238  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinking, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
3240  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinking) );
3241  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinking, consSepasolLinking, CONSHDLR_SEPAFREQ,
3243  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinking) );
3244  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinking) );
3245 
3246  /* include the linear constraint to linking constraint upgrade in the linear constraint handler */
3247  /* SCIP_CALL( SCIPincludeLinconsUpgrade(scip, linconsUpgdLinking, LINCONSUPGD_PRIORITY, CONSHDLR_NAME) ); */
3248 
3249  /* add linking constraint handler parameters */
3251  "constraints/" CONSHDLR_NAME "/linearize", "this constraint will not propagate or separate, linear and setppc are used?",
3252  &conshdlrdata->linearize, FALSE, DEFAULT_LINEARIZE, NULL, NULL) );
3253 
3254  return SCIP_OKAY;
3255 }
3256 
3257 /** creates and captures a linking constraint
3258  *
3259  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3260  */
3262  SCIP* scip, /**< SCIP data structure */
3263  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3264  const char* name, /**< name of constraint */
3265  SCIP_VAR* intvar, /**< integer variable which should be linked */
3266  SCIP_VAR** binvars, /**< binary variables, or NULL */
3267  int* vals, /**< coefficients of the binary variables */
3268  int nbinvars, /**< number of binary variables */
3269  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3270  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3271  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3272  * Usually set to TRUE. */
3273  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3274  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3275  SCIP_Bool check, /**< should the constraint be checked for feasibility?
3276  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3277  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3278  * Usually set to TRUE. */
3279  SCIP_Bool local, /**< is constraint only valid locally?
3280  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3281  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3282  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3283  * adds coefficients to this constraint. */
3284  SCIP_Bool dynamic, /**< is constraint subject to aging?
3285  * Usually set to FALSE. Set to TRUE for own cuts which
3286  * are separated as constraints. */
3287  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3288  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3289  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3290  * if it may be moved to a more global node?
3291  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3292  )
3293 {
3294  SCIP_CONSHDLR* conshdlr;
3295  SCIP_CONSDATA* consdata;
3296  SCIP_CONSHDLRDATA* conshdlrdata;
3297 
3298  assert(scip != NULL);
3299  assert(!SCIPisInfinity(scip, -SCIPvarGetLbGlobal(intvar)));
3300  assert(!SCIPisInfinity(scip, SCIPvarGetUbGlobal(intvar)));
3301 
3302  /* find the linking constraint handler */
3303  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3304  if( conshdlr == NULL )
3305  {
3306  SCIPerrorMessage("linking constraint handler not found\n");
3307  return SCIP_PLUGINNOTFOUND;
3308  }
3309 
3310  SCIPdebugMsg(scip, "create linking constraint for variable <%s> with %d binary variable (SCIP stage %d)\n",
3311  SCIPvarGetName(intvar), nbinvars, SCIPgetStage(scip));
3312 
3313  /* get constraint handler data */
3314  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3315  assert(conshdlrdata != NULL);
3316 
3317  if( conshdlrdata->varmap == NULL )
3318  {
3319  SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varmap, SCIPblkmem(scip), HASHSIZE_BINVARSCONS) );
3320  }
3321  assert(conshdlrdata->varmap != NULL);
3322 
3323  /* check if the linking for the requests integer variable already exists */
3324  assert(!SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey(intvar)));
3325 
3326  /* create the constraint specific data */
3327  SCIP_CALL( consdataCreate(scip, conshdlrdata->eventhdlr, &consdata, intvar, binvars, vals, nbinvars) );
3328 
3329  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata,
3330  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3331 
3332  /* insert linking constraint into the hash map */
3333  SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varmap, getHashmapKey(intvar), *cons) );
3334  assert(SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey(intvar)));
3335 
3336  return SCIP_OKAY;
3337 }
3338 
3339 /** creates and captures a linking constraint
3340  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3341  * method SCIPcreateConsLinking(); all flags can be set via SCIPsetCons<Flagname>-methods in scip.h
3342  *
3343  * @see SCIPcreateConsLinking() for information about the basic constraint flag configuration
3344  *
3345  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3346  */
3348  SCIP* scip, /**< SCIP data structure */
3349  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3350  const char* name, /**< name of constraint */
3351  SCIP_VAR* intvar, /**< integer variable which should be linked */
3352  SCIP_VAR** binvars, /**< binary variables, or NULL */
3353  int* vals, /**< coefficients of the binary variables */
3354  int nbinvars /**< number of binary variables */
3355  )
3356 {
3357  assert(scip != NULL);
3358 
3359  SCIP_CALL( SCIPcreateConsLinking(scip, cons, name, intvar, binvars, vals, nbinvars,
3360  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
3361 
3362  return SCIP_OKAY;
3363 }
3364 
3365 /** checks if for the given integer variable a linking constraint exists */
3367  SCIP* scip, /**< SCIP data structure */
3368  SCIP_VAR* intvar /**< integer variable which should be linked */
3369  )
3370 {
3371  SCIP_CONSHDLR* conshdlr;
3372  SCIP_CONSHDLRDATA* conshdlrdata;
3373 
3374  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3375  assert(conshdlr != NULL);
3376 
3377  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3378  assert(conshdlrdata != NULL);
3379 
3380  return (conshdlrdata->varmap != NULL) && SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey(intvar));
3381 }
3382 
3383 /** returns the linking constraint belonging to the given integer variable or NULL if it does not exist yet */
3385  SCIP* scip, /**< SCIP data structure */
3386  SCIP_VAR* intvar /**< integer variable which should be linked */
3387  )
3388 {
3389  SCIP_CONSHDLR* conshdlr;
3390  SCIP_CONSHDLRDATA* conshdlrdata;
3391 
3392  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3393  assert(conshdlr != NULL);
3394 
3395  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3396  assert(conshdlrdata != NULL);
3397 
3398  if( conshdlrdata->varmap != NULL )
3399  return (SCIP_CONS*) SCIPhashmapGetImage(conshdlrdata->varmap, getHashmapKey(intvar));
3400  else
3401  return NULL;
3402 }
3403 
3404 /** returns the integer variable of the linking constraint */
3406  SCIP* scip, /**< SCIP data structure */
3407  SCIP_CONS* cons /**< linking constraint */
3408  )
3409 {
3410  SCIP_CONSDATA* consdata;
3411 
3412  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3413  {
3414  SCIPerrorMessage("constraint is not a " CONSHDLR_NAME " constraint\n");
3415  SCIPABORT();
3416  return NULL; /*lint !e527*/
3417  }
3418 
3419  consdata = SCIPconsGetData(cons);
3420  assert(consdata != NULL);
3421 
3422  return consdata->intvar;
3423 
3424 }
3425 
3426 /** returns the binary variables of the linking constraint */
3428  SCIP* scip, /**< SCIP data structure */
3429  SCIP_CONS* cons, /**< linking constraint */
3430  SCIP_VAR*** binvars, /**< pointer to store the binary variables array pointer */
3431  int* nbinvars /**< pointer to store the number of returned binary variables */
3432  )
3433 {
3434  SCIP_CONSDATA* consdata;
3435 
3436  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3437  {
3438  SCIPerrorMessage("constraint is not a " CONSHDLR_NAME " constraint\n");
3439  SCIPABORT();
3440  return SCIP_INVALIDDATA; /*lint !e527*/
3441  }
3442 
3443  consdata = SCIPconsGetData(cons);
3444  assert(consdata != NULL);
3445 
3446  if( consdata->binvars == NULL )
3447  {
3448  SCIP_CONSHDLR* conshdlr;
3449  SCIP_CONSHDLRDATA* conshdlrdata;
3450 
3451  conshdlr = SCIPconsGetHdlr(cons);
3452  assert(conshdlr != NULL);
3453 
3454  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3455  assert(conshdlrdata != NULL);
3456 
3457  SCIP_CALL( consdataCreateBinvars(scip, cons, consdata, conshdlrdata->eventhdlr, conshdlrdata->linearize) );
3458  }
3459 
3460  assert(consdata->binvars != NULL);
3461 
3462  if( binvars != NULL )
3463  (*binvars) = consdata->binvars;
3464  if( nbinvars != NULL )
3465  (*nbinvars) = consdata->nbinvars;
3466 
3467  return SCIP_OKAY;
3468 }
3469 
3470 /** returns the number of binary variables of the linking constraint */
3472  SCIP* scip, /**< SCIP data structure */
3473  SCIP_CONS* cons /**< linking constraint */
3474  )
3475 {
3476  SCIP_CONSDATA* consdata;
3477 
3478  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3479  {
3480  SCIPerrorMessage("constraint is not a " CONSHDLR_NAME " constraint\n");
3481  SCIPABORT();
3482  return -1; /*lint !e527*/
3483  }
3484 
3485  consdata = SCIPconsGetData(cons);
3486  assert(consdata != NULL);
3487 
3488  return consdata->nbinvars;
3489 }
3490 
3491 /** returns the coefficients of the binary variables */
3493  SCIP* scip, /**< SCIP data structure */
3494  SCIP_CONS* cons /**< linking constraint */
3495  )
3496 {
3497  SCIP_CONSDATA* consdata;
3498 
3499  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3500  {
3501  SCIPerrorMessage("constraint is not a " CONSHDLR_NAME " constraint\n");
3502  SCIPABORT();
3503  return NULL; /*lint !e527*/
3504  }
3505 
3506  consdata = SCIPconsGetData(cons);
3507  assert(consdata != NULL);
3508  assert(consdata->sorted);
3509 
3510  return consdata->vals;
3511 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition: scip.c:30740
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47363
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28372
SCIP_RETCODE SCIPincludeConshdlrLinking(SCIP *scip)
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6291
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:41459
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:46443
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition: cons.c:8083
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19649
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:821
#define CONSHDLR_DELAYPROP
Definition: cons_linking.c:63
static SCIP_DECL_EVENTEXEC(eventExecBinvar)
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8245
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6314
static SCIP_RETCODE consFixInteger(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff)
Definition: cons_linking.c:671
static SCIP_DECL_CONSTRANS(consTransLinking)
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19509
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linking.c:197
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41226
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linking.c:56
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
static SCIP_RETCODE removeFixedBinvars(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
Definition: cons_linking.c:977
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6544
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6036
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28400
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12663
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30668
#define DEFAULT_LINEARIZE
Definition: cons_linking.c:71
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinking)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:27388
static SCIP_DECL_CONSPRINT(consPrintLinking)
int * SCIPgetValsLinking(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:8355
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18957
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:18038
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *intvar, SCIP_VAR *binvar, SCIP_Bool lbintvar, SCIP_Bool ubintvar)
Definition: cons_linking.c:628
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
Definition: scip.c:6205
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47387
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47350
#define CONSHDLR_EAGERFREQ
Definition: cons_linking.c:60
#define CONSHDLR_NEEDSCONS
Definition: cons_linking.c:64
static SCIP_RETCODE createRows(SCIP *scip, SCIP_CONS *cons)
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10289
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5894
static SCIP_DECL_CONSSEPASOL(consSepasolLinking)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27251
SCIP_Bool SCIPexistsConsLinking(SCIP *scip, SCIP_VAR *intvar)
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21660
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8265
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linking.c:577
#define CONSHDLR_NAME
Definition: cons_linking.c:49
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17022
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8295
static SCIP_Bool checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:27155
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
#define CONSHDLR_PROP_TIMING
Definition: cons_linking.c:66
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5948
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
static SCIP_RETCODE dropAllEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linking.c:338
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8255
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6337
int SCIPgetNBinvarsLinking(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSDATA **consdata, SCIP_VAR *intvar, SCIP_VAR **binvars, int *vals, int nbinvars)
Definition: cons_linking.c:497
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff, SCIP_Bool *separated, int *nchgbds)
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18998
static SCIP_DECL_CONSINITLP(consInitlpLinking)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6521
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8047
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:27584
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip.c:18214
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27184
static void * getHashmapKey(SCIP_VAR *var)
Definition: cons_linking.c:109
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16695
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3025
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:64
void SCIPsortIntPtr(int *intarray, void **ptrarray, int len)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:27133
SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28425
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:24222
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:22599
static SCIP_DECL_CONSENFOLP(consEnfolpLinking)
static SCIP_DECL_CONSGETVARS(consGetVarsLinking)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **binvars, int nbinvars)
Definition: cons_linking.c:135
static SCIP_DECL_CONSLOCK(consLockLinking)
SCIP_VAR * SCIPgetIntvarLinking(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:6060
#define CONSHDLR_DELAYSEPA
Definition: cons_linking.c:62
#define EVENTHDLR_DESC
Definition: cons_linking.c:53
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
static SCIP_DECL_CONSPARSE(consParseLinking)
static SCIP_RETCODE tightenedIntvar(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *cutoff, int *nchgbds)
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13297
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinking)
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:22633
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21788
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:25932
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17033
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8205
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:9034
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6085
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
#define CONSHDLR_PROPFREQ
Definition: cons_linking.c:59
#define REALABS(x)
Definition: def.h:173
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:66
#define SCIP_CALL(x)
Definition: def.h:350
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_RETCODE consdataLinearize(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata)
Definition: cons_linking.c:363
static SCIP_RETCODE catchEvent(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linking.c:251
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip.c:13802
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47324
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27535
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1360
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8225
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6360
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28459
static SCIP_RETCODE catchAllEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linking.c:314
#define HASHSIZE_BINVARSCONS
Definition: cons_linking.c:70
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:29208
static SCIP_DECL_CONSRESPROP(consRespropLinking)
static SCIP_DECL_CONSDELETE(consDeleteLinking)
static SCIP_DECL_CONSINITPRE(consInitpreLinking)
constraint handler for linking binary variables to an integer variable
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
#define SCIP_Bool
Definition: def.h:61
static SCIP_DECL_CONSPRESOL(consPresolLinking)
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
static SCIP_DECL_CONSCHECK(consCheckLinking)
static SCIP_RETCODE processIntegerBoundChg(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool *mustcheck)
Definition: cons_linking.c:728
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30402
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43045
#define EVENTHDLR_NAME
Definition: cons_linking.c:52
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:29091
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_DECL_CONSPROP(consPropLinking)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
#define CONSHDLR_DESC
Definition: cons_linking.c:50
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8155
static SCIP_DECL_CONSFREE(consFreeLinking)
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17011
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17619
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:25575
#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.c:21714
static SCIP_DECL_CONSENFOPS(consEnfopsLinking)
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6498
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
int SCIPconvertRealToInt(SCIP *scip, SCIP_Real real)
Definition: scip.c:47806
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22819
SCIP_RETCODE SCIPsetConshdlrEnable(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENABLE((*consenable)))
Definition: scip.c:6429
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:35836
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linking.c:57
static void consdataSort(SCIP_CONSDATA *consdata)
Definition: cons_linking.c:119
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip.c:17848
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinking)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons, int pos)
Definition: cons_linking.c:919
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3041
SCIP_RETCODE SCIPcreateConsLinking(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *intvar, SCIP_VAR **binvars, int *vals, int nbinvars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47112
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1920
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11492
static SCIP_DECL_CONSENABLE(consEnableLinking)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8016
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22932
SCIP_RETCODE SCIPgetBinvarsLinking(SCIP *scip, SCIP_CONS *cons, SCIP_VAR ***binvars, int *nbinvars)
static SCIP_DECL_CONSEXITSOL(consExitsolLinking)
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6253
static SCIP_RETCODE processBinvarFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool *addcut, SCIP_Bool *mustcheck)
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30977
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16781
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:25684
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18732
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8235
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6567
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linking.c:154
#define CONSHDLR_PRESOLTIMING
Definition: cons_linking.c:67
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8175
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8165
static SCIP_DECL_CONSSEPALP(consSepalpLinking)
#define CONSHDLR_SEPAFREQ
Definition: cons_linking.c:58
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16959
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16804
static SCIP_DECL_CONSCOPY(consCopyLinking)
SCIP_CONS * SCIPgetConsLinking(SCIP *scip, SCIP_VAR *intvar)
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2874
static SCIP_RETCODE addCuts(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
static SCIP_RETCODE enforcePseudo(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, SCIP_Bool *infeasible, int *nchgbds, SCIP_Bool *solvelp)
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6181
#define SCIPABORT()
Definition: def.h:322
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:17735
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linking.c:55
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
SCIP_RETCODE SCIPcreateConsBasicLinking(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *intvar, SCIP_VAR **binvars, int *vals, int nbinvars)
SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:23039
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linking.c:61
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
static SCIP_RETCODE dropEvent(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linking.c:283
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:22624
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5994
static SCIP_RETCODE conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linking.c:177
static SCIP_RETCODE consdataCreateBinvars(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool linearize)
Definition: cons_linking.c:402