Scippy

SCIP

Solving Constraint Integer Programs

cons_xor.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-2014 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_xor.c
17  * @brief Constraint handler for "xor" constraints, \f$rhs = x_1 \oplus x_2 \oplus \dots \oplus x_n\f$
18  * @author Tobias Achterberg
19  * @author Stefan Heinz
20  * @author Marc Pfetsch
21  * @author Michael Winkler
22  *
23  * This constraint handler deals with "xor" constraint. These are constraint of the form:
24  *
25  * \f[
26  * rhs = x_1 \oplus x_2 \oplus \dots \oplus x_n
27  * \f]
28  *
29  * where \f$x_i\f$ is a binary variable for all \f$i\f$ and \f$rhs\f$ is bool. The variables \f$x\f$'s are called
30  * operators. This constraint is satisfied if \f$rhs\f$ is TRUE and an odd number of the operators are TRUE or if the
31  * \f$rhs\f$ is FALSE and a even number of operators are TRUE. Hence, if the sum of \f$rhs\f$ and operators is even.
32  */
33 
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35 
36 #include <assert.h>
37 #include <string.h>
38 
39 #include "scip/pub_misc.h"
40 #include "scip/cons_xor.h"
41 #include "scip/cons_setppc.h"
42 #include "scip/cons_linear.h"
43 #include "scip/heur_trysol.h"
44 #include "scip/debug.h"
45 
46 
47 /* constraint handler properties */
48 #define CONSHDLR_NAME "xor"
49 #define CONSHDLR_DESC "constraint handler for xor constraints: r = xor(x1, ..., xn)"
50 #define CONSHDLR_SEPAPRIORITY +850200 /**< priority of the constraint handler for separation */
51 #define CONSHDLR_ENFOPRIORITY -850200 /**< priority of the constraint handler for constraint enforcing */
52 #define CONSHDLR_CHECKPRIORITY -850200 /**< priority of the constraint handler for checking feasibility */
53 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
54 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
55 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
56  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
57 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
58 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
59 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
60 #define CONSHDLR_DELAYPRESOL FALSE /**< should presolving method be delayed, if other presolvers found reductions? */
61 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
62 
63 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
64 
65 #define EVENTHDLR_NAME "xor"
66 #define EVENTHDLR_DESC "event handler for xor constraints"
67 
68 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
69 #define DEFAULT_ADDEXTENDEDFORM FALSE /**< should the extended formulation be added in presolving? */
70 #define DEFAULT_ADDFLOWEXTENDED FALSE /**< should the extended flow formulation be added (nonsymmetric formulation otherwise)? */
71 #define DEFAULT_SEPARATEPARITY FALSE /**< should parity inequalities be separated? */
72 #define DEFAULT_GAUSSPROPFREQ 5 /**< frequency for applying the Gauss propagator */
73 #define HASHSIZE_XORCONS 131101 /**< minimal size of hash table in logicor constraint tables */
74 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
75 #define NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
76 #define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
77 #define MAXXORCONSSSYSTEM 1000 /**< maximal number of active constraints for which checking the system over GF2 is performed */
78 #define MAXXORVARSSYSTEM 1000 /**< maximal number of variables in xor constraints for which checking the system over GF2 is performed */
79 
80 #define NROWS 4
81 
82 
83 /*
84  * Data structures
85  */
86 
87 /** type used for matrix entries in function checkGauss() */
88 typedef unsigned short Type;
89 
90 /** constraint data for xor constraints */
91 struct SCIP_ConsData
92 {
93  SCIP_VAR** vars; /**< variables in the xor operation */
94  SCIP_VAR* intvar; /**< internal variable for LP relaxation */
95  SCIP_VAR** extvars; /**< variables in extended (flow|asymmetric) formulation (order for flow formulation: nn, ns, sn, ss) */
96  SCIP_ROW* rows[NROWS]; /**< rows for linear relaxation of xor constraint */
97  int nvars; /**< number of variables in xor operation */
98  int nextvars; /**< number of variables in extended flow formulation */
99  int varssize; /**< size of vars array */
100  int extvarssize; /**< size of extvars array */
101  int watchedvar1; /**< position of first watched operator variable */
102  int watchedvar2; /**< position of second watched operator variable */
103  int filterpos1; /**< event filter position of first watched operator variable */
104  int filterpos2; /**< event filter position of second watched operator variable */
105  SCIP_Bool rhs; /**< right hand side of the constraint */
106  unsigned int deleteintvar:1; /**< should artificial variable be deleted */
107  unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
108  unsigned int sorted:1; /**< are the constraint's variables sorted? */
109  unsigned int changed:1; /**< was constraint changed since last pair preprocessing round? */
110 };
111 
112 /** constraint handler data */
113 struct SCIP_ConshdlrData
114 {
115  SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
116  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
117  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance? */
118  SCIP_Bool addextendedform; /**< should the extended formulation be added in presolving? */
119  SCIP_Bool addflowextended; /**< should the extended flow formulation be added (nonsymmetric formulation otherwise)? */
120  SCIP_Bool separateparity; /**< should parity inequalities be separated? */
121  int gausspropfreq; /**< frequency for applying the Gauss propagator */
122 };
123 
124 
125 /*
126  * Propagation rules
127  */
128 
129 enum Proprule
130 {
131  PROPRULE_0, /**< all variables are fixed => fix integral variable */
132  PROPRULE_1, /**< all except one variable fixed => fix remaining variable */
133  PROPRULE_INTLB, /**< lower bound propagation of integral variable */
134  PROPRULE_INTUB, /**< upper bound propagation of integral variable */
135  PROPRULE_INVALID /**< propagation was applied without a specific propagation rule */
136 };
137 typedef enum Proprule PROPRULE;
139 
140 /*
141  * Local methods
142  */
143 
144 /** installs rounding locks for the given variable in the given xor constraint */
145 static
147  SCIP* scip, /**< SCIP data structure */
148  SCIP_CONS* cons, /**< xor constraint */
149  SCIP_VAR* var /**< variable of constraint entry */
150  )
151 {
152  /* rounding in both directions may violate the constraint */
153  SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
154 
155  return SCIP_OKAY;
156 }
157 
158 /** removes rounding locks for the given variable in the given xor constraint */
159 static
161  SCIP* scip, /**< SCIP data structure */
162  SCIP_CONS* cons, /**< xor constraint */
163  SCIP_VAR* var /**< variable of constraint entry */
164  )
165 {
166  /* rounding in both directions may violate the constraint */
167  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
168 
169  return SCIP_OKAY;
170 }
171 
172 /** creates constraint handler data */
173 static
175  SCIP* scip, /**< SCIP data structure */
176  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
177  SCIP_EVENTHDLR* eventhdlr /**< event handler */
178  )
179 {
180  assert(scip != NULL);
181  assert(conshdlrdata != NULL);
182  assert(eventhdlr != NULL);
183 
184  SCIP_CALL( SCIPallocMemory(scip, conshdlrdata) );
185 
186  /* set event handler for catching events on watched variables */
187  (*conshdlrdata)->eventhdlr = eventhdlr;
188 
189  return SCIP_OKAY;
190 }
191 
192 /** frees constraint handler data */
193 static
195  SCIP* scip, /**< SCIP data structure */
196  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
197  )
198 {
199  assert(conshdlrdata != NULL);
200  assert(*conshdlrdata != NULL);
201 
202  SCIPfreeMemory(scip, conshdlrdata);
203 
204  return SCIP_OKAY;
205 }
206 
207 /** stores the given variable numbers as watched variables, and updates the event processing */
208 static
210  SCIP* scip, /**< SCIP data structure */
211  SCIP_CONSDATA* consdata, /**< xor constraint data */
212  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
213  int watchedvar1, /**< new first watched variable */
214  int watchedvar2 /**< new second watched variable */
215  )
216 {
217  assert(consdata != NULL);
218  assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
219  assert(watchedvar1 != -1 || watchedvar2 == -1);
220  assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
221  assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
222 
223  /* if one watched variable is equal to the old other watched variable, just switch positions */
224  if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
225  {
226  int tmp;
227 
228  tmp = consdata->watchedvar1;
229  consdata->watchedvar1 = consdata->watchedvar2;
230  consdata->watchedvar2 = tmp;
231  tmp = consdata->filterpos1;
232  consdata->filterpos1 = consdata->filterpos2;
233  consdata->filterpos2 = tmp;
234  }
235  assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
236  assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
237 
238  /* drop events on old watched variables */
239  if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
240  {
241  assert(consdata->filterpos1 != -1);
242  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar1], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
243  (SCIP_EVENTDATA*)consdata, consdata->filterpos1) );
244  }
245  if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
246  {
247  assert(consdata->filterpos2 != -1);
248  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[consdata->watchedvar2], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
249  (SCIP_EVENTDATA*)consdata, consdata->filterpos2) );
250  }
251 
252  /* catch events on new watched variables */
253  if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
254  {
255  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar1], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
256  (SCIP_EVENTDATA*)consdata, &consdata->filterpos1) );
257  }
258  if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
259  {
260  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[watchedvar2], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr,
261  (SCIP_EVENTDATA*)consdata, &consdata->filterpos2) );
262  }
263 
264  /* set the new watched variables */
265  consdata->watchedvar1 = watchedvar1;
266  consdata->watchedvar2 = watchedvar2;
267 
268  return SCIP_OKAY;
269 }
270 
271 /** ensures, that the vars array can store at least num entries */
272 static
274  SCIP* scip, /**< SCIP data structure */
275  SCIP_CONSDATA* consdata, /**< linear constraint data */
276  int num /**< minimum number of entries to store */
277  )
278 {
279  assert(consdata != NULL);
280  assert(consdata->nvars <= consdata->varssize);
281 
282  if( num > consdata->varssize )
283  {
284  int newsize;
285 
286  newsize = SCIPcalcMemGrowSize(scip, num);
287  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
288  consdata->varssize = newsize;
289  }
290  assert(num <= consdata->varssize);
291 
292  return SCIP_OKAY;
293 }
294 
295 /** creates constraint data for xor constraint */
296 static
298  SCIP* scip, /**< SCIP data structure */
299  SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
300  SCIP_Bool rhs, /**< right hand side of the constraint */
301  int nvars, /**< number of variables in the xor operation */
302  SCIP_VAR** vars, /**< variables in xor operation */
303  SCIP_VAR* intvar /**< artificial integer variable for linear relaxation */
304  )
305 {
306  int r;
307 
308  assert(consdata != NULL);
309  assert(nvars == 0 || vars != NULL);
310 
311  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
312  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
313 
314  (*consdata)->rhs = rhs;
315  (*consdata)->intvar = intvar;
316  for( r = 0; r < NROWS; ++r )
317  (*consdata)->rows[r] = NULL;
318  (*consdata)->nvars = nvars;
319  (*consdata)->varssize = nvars;
320  (*consdata)->watchedvar1 = -1;
321  (*consdata)->watchedvar2 = -1;
322  (*consdata)->filterpos1 = -1;
323  (*consdata)->filterpos2 = -1;
324  (*consdata)->deleteintvar = (intvar == NULL);
325  (*consdata)->propagated = FALSE;
326  (*consdata)->sorted = FALSE;
327  (*consdata)->changed = TRUE;
328  (*consdata)->extvars = NULL;
329  (*consdata)->nextvars = 0;
330  (*consdata)->extvarssize = 0;
331 
332  /* get transformed variables, if we are in the transformed problem */
333  if( SCIPisTransformed(scip) )
334  {
335  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
336 
337  if( (*consdata)->intvar != NULL )
338  {
339  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->intvar, &((*consdata)->intvar)) );
340  }
341  }
342 
343  if( (*consdata)->intvar != NULL )
344  {
345  /* capture artificial variable */
346  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->intvar) );
347  }
348 
349  return SCIP_OKAY;
350 }
351 
352 /** releases LP row of constraint data */
353 static
355  SCIP* scip, /**< SCIP data structure */
356  SCIP_CONSDATA* consdata /**< constraint data */
357  )
358 {
359  int r;
360 
361  assert(consdata != NULL);
362 
363  for( r = 0; r < NROWS; ++r )
364  {
365  if( consdata->rows[r] != NULL )
366  {
367  SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
368  }
369  }
370 
371  return SCIP_OKAY;
372 }
373 
374 /** frees constraint data for xor constraint */
375 static
377  SCIP* scip, /**< SCIP data structure */
378  SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
379  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
380  )
381 {
382  assert(consdata != NULL);
383  assert(*consdata != NULL);
384 
385  if( SCIPisTransformed(scip) )
386  {
387  int j;
388 
389  /* drop events for watched variables */
390  SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
391 
392  /* release flow variables */
393  if ( (*consdata)->nextvars > 0 )
394  {
395  assert( (*consdata)->extvars != NULL );
396  for (j = 0; j < (*consdata)->extvarssize; ++j)
397  {
398  if ( (*consdata)->extvars[j] != NULL )
399  {
400  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->extvars[j])) );
401  }
402  }
403 
404  SCIPfreeBlockMemoryArray(scip, &((*consdata)->extvars), (*consdata)->extvarssize);
405  (*consdata)->nextvars = 0;
406  (*consdata)->extvarssize = 0;
407  }
408  }
409  else
410  {
411  assert((*consdata)->watchedvar1 == -1);
412  assert((*consdata)->watchedvar2 == -1);
413  }
414 
415  /* release LP row */
416  SCIP_CALL( consdataFreeRows(scip, *consdata) );
417 
418  /* release internal variable */
419  if( (*consdata)->intvar != NULL )
420  {
421  /* if the constraint is deleted and the integral variable is present, it should be fixed */
422  assert( SCIPisEQ(scip, SCIPvarGetLbGlobal((*consdata)->intvar), SCIPvarGetLbGlobal((*consdata)->intvar)) );
423 
424  /* We do not delete the integral variable, but leave the handling to SCIP, because it might happen that the
425  integral variable is stored in some basis information somewhere. */
426  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->intvar) );
427  }
428 
429  SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
430  SCIPfreeBlockMemory(scip, consdata);
431 
432  return SCIP_OKAY;
433 }
434 
435 /** prints xor constraint to file stream */
436 static
438  SCIP* scip, /**< SCIP data structure */
439  SCIP_CONSDATA* consdata, /**< xor constraint data */
440  FILE* file, /**< output file (or NULL for standard output) */
441  SCIP_Bool endline /**< should an endline be set? */
442  )
443 {
444  assert(consdata != NULL);
445 
446  /* start variable list */
447  SCIPinfoMessage(scip, file, "xor(");
448 
449  /* print variable list */
450  SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
451 
452  /* close variable list and write right hand side */
453  SCIPinfoMessage(scip, file, ") = %d", consdata->rhs);
454 
455  if( endline )
456  SCIPinfoMessage(scip, file, "\n");
457 
458  return SCIP_OKAY;
459 }
460 
461 /** adds coefficient to xor constraint */
462 static
464  SCIP* scip, /**< SCIP data structure */
465  SCIP_CONS* cons, /**< linear constraint */
466  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
467  SCIP_VAR* var /**< variable to add to the constraint */
468  )
469 { /*lint --e{715}*/
470  SCIP_CONSDATA* consdata;
471  SCIP_Bool transformed;
472 
473  assert(var != NULL);
474 
475  consdata = SCIPconsGetData(cons);
476  assert(consdata != NULL);
477  assert(consdata->rows[0] == NULL);
478 
479  /* are we in the transformed problem? */
480  transformed = SCIPconsIsTransformed(cons);
481 
482  /* always use transformed variables in transformed constraints */
483  if( transformed )
484  {
485  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
486  }
487  assert(var != NULL);
488  assert(transformed == SCIPvarIsTransformed(var));
489 
490  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
491  consdata->vars[consdata->nvars] = var;
492  consdata->nvars++;
493  consdata->sorted = (consdata->nvars == 1);
494  consdata->changed = TRUE;
495 
496  /* install the rounding locks for the new variable */
497  SCIP_CALL( lockRounding(scip, cons, var) );
498 
499  /**@todo update LP rows */
500  if( consdata->rows[0] != NULL )
501  {
502  SCIPerrorMessage("cannot add coefficients to xor constraint after LP relaxation was created\n");
503  return SCIP_INVALIDCALL;
504  }
505 
506  return SCIP_OKAY;
507 }
508 
509 /** deletes coefficient at given position from xor constraint data */
510 static
512  SCIP* scip, /**< SCIP data structure */
513  SCIP_CONS* cons, /**< xor constraint */
514  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
515  int pos /**< position of coefficient to delete */
516  )
517 {
518  SCIP_CONSDATA* consdata;
519 
520  assert(eventhdlr != NULL);
521 
522  consdata = SCIPconsGetData(cons);
523  assert(consdata != NULL);
524  assert(0 <= pos && pos < consdata->nvars);
525  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
526 
527  /* remove the rounding locks of the deleted variable */
528  SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
529 
530  if( SCIPconsIsTransformed(cons) )
531  {
532  /* if the position is watched, stop watching the position */
533  if( consdata->watchedvar1 == pos )
534  {
535  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
536  }
537  if( consdata->watchedvar2 == pos )
538  {
539  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
540  }
541  }
542  assert(pos != consdata->watchedvar1);
543  assert(pos != consdata->watchedvar2);
544 
545  /* move the last variable to the free slot */
546  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
547  consdata->nvars--;
548 
549  /* if the last variable (that moved) was watched, update the watched position */
550  if( consdata->watchedvar1 == consdata->nvars )
551  consdata->watchedvar1 = pos;
552  if( consdata->watchedvar2 == consdata->nvars )
553  consdata->watchedvar2 = pos;
554 
555  consdata->propagated = FALSE;
556  consdata->sorted = FALSE;
557  consdata->changed = TRUE;
558 
559  return SCIP_OKAY;
560 }
561 
562 /** sorts and constraint's variables by non-decreasing variable index */
563 static
564 void consdataSort(
565  SCIP_CONSDATA* consdata /**< constraint data */
566  )
567 {
568  assert(consdata != NULL);
569 
570  if( !consdata->sorted )
571  {
572  if( consdata->nvars <= 1 )
573  consdata->sorted = TRUE;
574  else
575  {
576  SCIP_VAR* var1 = NULL;
577  SCIP_VAR* var2 = NULL;
578 
579  /* remember watch variables */
580  if( consdata->watchedvar1 != -1 )
581  {
582  var1 = consdata->vars[consdata->watchedvar1];
583  assert(var1 != NULL);
584  consdata->watchedvar1 = -1;
585  if( consdata->watchedvar2 != -1 )
586  {
587  var2 = consdata->vars[consdata->watchedvar2];
588  assert(var2 != NULL);
589  consdata->watchedvar2 = -1;
590  }
591  }
592  assert(consdata->watchedvar1 == -1);
593  assert(consdata->watchedvar2 == -1);
594  assert(var1 != NULL || var2 == NULL);
595 
596  /* sort variables after index */
597  SCIPsortPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, consdata->nvars);
598  consdata->sorted = TRUE;
599 
600  /* correct watched variables */
601  if( var1 != NULL )
602  {
603  int pos;
604 #ifndef NDEBUG
605  SCIP_Bool found;
606 
607  found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, (void*)var1, consdata->nvars, &pos);
608  assert(found);
609 #else
610  SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, (void*)var1, consdata->nvars, &pos);
611 #endif
612  assert(pos >= 0 && pos < consdata->nvars);
613  consdata->watchedvar1 = pos;
614 
615  if( var2 != NULL )
616  {
617 #ifndef NDEBUG
618  found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, (void*)var2, consdata->nvars, &pos);
619  assert(found);
620 #else
621  SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, (void*)var2, consdata->nvars, &pos);
622 #endif
623  assert(pos >= 0 && pos < consdata->nvars);
624  consdata->watchedvar2 = pos;
625  }
626  }
627  }
628  }
629 
630 #ifdef SCIP_DEBUG
631  /* check sorting */
632  {
633  int v;
634 
635  for( v = 0; v < consdata->nvars; ++v )
636  {
637  assert(v == consdata->nvars-1 || SCIPvarCompareActiveAndNegated(consdata->vars[v], consdata->vars[v+1]) <= 0);
638  }
639  }
640 #endif
641 }
642 
643 
644 /** gets the key of the given element */
645 static
646 SCIP_DECL_HASHGETKEY(hashGetKeyXorcons)
647 { /*lint --e{715}*/
648  /* the key is the element itself */
649  return elem;
650 }
651 
652 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
653 static
654 SCIP_DECL_HASHKEYEQ(hashKeyEqXorcons)
655 {
656  SCIP_CONSDATA* consdata1;
657  SCIP_CONSDATA* consdata2;
658  int i;
659 #ifndef NDEBUG
660  SCIP* scip;
661 
662  scip = (SCIP*)userptr;
663  assert(scip != NULL);
664 #endif
665 
666  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
667  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
668 
669  /* checks trivial case */
670  if( consdata1->nvars != consdata2->nvars )
671  return FALSE;
672 
673  /* sorts the constraints */
674  consdataSort(consdata1);
675  consdataSort(consdata2);
676  assert(consdata1->sorted);
677  assert(consdata2->sorted);
678 
679  for( i = 0; i < consdata1->nvars ; ++i )
680  {
681  /* tests if variables are equal */
682  if( consdata1->vars[i] != consdata2->vars[i] )
683  {
684  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
685  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
686  return FALSE;
687  }
688  assert(SCIPvarCompareActiveAndNegated(consdata1->vars[i], consdata2->vars[i]) == 0);
689  }
690 
691  return TRUE;
692 }
693 
694 /** returns the hash value of the key */
695 static
696 SCIP_DECL_HASHKEYVAL(hashKeyValXorcons)
697 { /*lint --e{715}*/
698  SCIP_CONSDATA* consdata;
699  unsigned int hashval;
700  int minidx;
701  int mididx;
702  int maxidx;
703 
704  consdata = SCIPconsGetData((SCIP_CONS*)key);
705  assert(consdata != NULL);
706  assert(consdata->sorted);
707  assert(consdata->nvars > 0);
708 
709  /* only active, fixed or negated variables are allowed */
710  assert(consdata->vars[0] != NULL);
711  assert(consdata->vars[consdata->nvars / 2] != NULL);
712  assert(consdata->vars[consdata->nvars - 1] != NULL);
713  assert(SCIPvarIsActive(consdata->vars[0]) || SCIPvarGetStatus(consdata->vars[0]) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(consdata->vars[0]) == SCIP_VARSTATUS_FIXED);
714  assert(SCIPvarIsActive(consdata->vars[consdata->nvars / 2]) || SCIPvarGetStatus(consdata->vars[consdata->nvars / 2]) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(consdata->vars[consdata->nvars / 2]) == SCIP_VARSTATUS_FIXED);
715  assert(SCIPvarIsActive(consdata->vars[consdata->nvars - 1]) || SCIPvarGetStatus(consdata->vars[consdata->nvars - 1]) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(consdata->vars[consdata->nvars - 1]) == SCIP_VARSTATUS_FIXED);
716 
717  minidx = SCIPvarGetIndex(consdata->vars[0]);
718  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
719  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
720  /* note that for all indices it does not hold that they are sorted, because variables are sorted with
721  * SCIPvarCompareActiveAndNegated (see var.c)
722  */
723 
724  hashval = (consdata->nvars << 29) + (minidx << 22) + (mididx << 11) + maxidx; /*lint !e701*/
725 
726  return hashval;
727 }
728 
729 /** deletes all fixed variables and all pairs equal variables variables */
730 static
732  SCIP* scip, /**< SCIP data structure */
733  SCIP_CONS* cons, /**< xor constraint */
734  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
735  int* nchgcoefs /**< pointer to add up the number of changed coefficients */
736  )
737 {
738  SCIP_CONSDATA* consdata;
739  int v;
740 
741  consdata = SCIPconsGetData(cons);
742  assert(consdata != NULL);
743  assert(consdata->nvars == 0 || consdata->vars != NULL);
744  assert(nchgcoefs != NULL);
745 
746  SCIPdebugMessage("before fixings: ");
747  SCIPdebug( SCIP_CALL(consdataPrint(scip, consdata, NULL, TRUE)) );
748 
749  v = 0;
750  while( v < consdata->nvars )
751  {
752  SCIP_VAR* var;
753 
754  var = consdata->vars[v];
755  assert(SCIPvarIsBinary(var));
756 
757  if( SCIPvarGetUbGlobal(var) < 0.5 )
758  {
759  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
760  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
761  (*nchgcoefs)++;
762  }
763  else if( SCIPvarGetLbGlobal(var) > 0.5 )
764  {
765  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
766  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
767  consdata->rhs = !consdata->rhs;
768  (*nchgcoefs)++;
769  }
770  else
771  {
772  SCIP_VAR* repvar;
773  SCIP_Bool negated;
774 
775  /* get binary representative of variable */
776  SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
777 
778  /* remove all negations by replacing them with the active variable
779  * it holds that xor(x1, ~x2) = 0 <=> xor(x1, x2) = 1
780  */
781  if( negated )
782  {
783  assert(SCIPvarIsNegated(repvar));
784 
785  repvar = SCIPvarGetNegationVar(repvar);
786  consdata->rhs = !consdata->rhs;
787  }
788 
789  /* check, if the variable should be replaced with the representative */
790  if( repvar != var )
791  {
792  /* delete old (aggregated) variable */
793  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
794 
795  /* add representative instead */
796  SCIP_CALL( addCoef(scip, cons, eventhdlr, repvar) );
797  }
798  else
799  ++v;
800  }
801  }
802 
803  /* sort the variables in the constraint */
804  consdataSort(consdata);
805  assert(consdata->sorted);
806 
807  SCIPdebugMessage("after sort : ");
808  SCIPdebug( SCIP_CALL(consdataPrint(scip, consdata, NULL, TRUE)) );
809 
810  /* delete pairs of equal or negated variables; scan from back to front because deletion doesn't affect the
811  * order of the front variables
812  */
813  v = consdata->nvars-2;
814  while ( v >= 0 )
815  {
816  if( consdata->vars[v] == consdata->vars[v+1] ) /*lint !e679*/
817  {
818  /* delete both variables */
819  SCIPdebugMessage("xor constraint <%s>: deleting pair of equal variables <%s>\n",
820  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]));
821  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v+1) );
822  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
823  (*nchgcoefs) += 2;
824  v = MIN(v, consdata->nvars-1);
825  }
826  else if( consdata->vars[v] == SCIPvarGetNegatedVar(consdata->vars[v+1]) ) /*lint !e679*/
827  {
828  /* delete both variables and negate the rhs */
829  SCIPdebugMessage("xor constraint <%s>: deleting pair of negated variables <%s> and <%s>\n",
830  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v]), SCIPvarGetName(consdata->vars[v+1])); /*lint !e679*/
831  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v+1) );
832  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
833  (*nchgcoefs) += 2;
834  consdata->rhs = !consdata->rhs;
835  v = MIN(v, consdata->nvars-1);
836  }
837  else
838  assert(SCIPvarGetProbvar(consdata->vars[v]) != SCIPvarGetProbvar(consdata->vars[v+1])); /*lint !e679*/
839  --v;
840  }
841 
842  SCIPdebugMessage("after fixings : ");
843  SCIPdebug( SCIP_CALL(consdataPrint(scip, consdata, NULL, TRUE)) );
844 
845  return SCIP_OKAY;
846 }
847 
848 /** adds extended flow formulation
849  *
850  * The extended flow formulation is built as follows: Let \f$x_1, \dots, x_k\f$ be the variables contained in the given
851  * XOR constraint. We construct a two layered flow network. The upper layer is called the north layer and the lower is
852  * called the south layer. For each \f$x_i,\; i = 2, \ldots, k-1\f$, we add arcs that stay in the north and south layer
853  * (denoted by 'nn' and 'ss', respectively), as well as arcs that change the layers (denoted by 'ns' and 'sn'). For
854  * \f$x_1\f$, we only add two arcs from the source to the two layers. The source is located on the north layer. For
855  * \f$x_k\f$, we add two arcs connecting the two layers to the sink. Depending on the rhs of the constraint the sink is
856  * located on the north or south layer. A change in the layers corresponds to a parity change, i.e., the corresponding
857  * variable \f$x_i\f$ is 1 (and 0 otherwise).
858  */
859 static
861  SCIP* scip, /**< SCIP data structure */
862  SCIP_CONS* cons, /**< constraint to check */
863  int* naddedconss /**< number of added constraints */
864  )
865 {
866  char name[SCIP_MAXSTRLEN];
867  SCIP_CONSDATA* consdata;
868  SCIP_VAR* varprevnn = NULL;
869  SCIP_VAR* varprevns = NULL;
870  SCIP_VAR* varprevsn = NULL;
871  SCIP_VAR* varprevss = NULL;
872  SCIP_VAR* vars[4];
873  SCIP_Real vals[4];
874  int i;
875 
876  assert( scip != NULL );
877  assert( cons != NULL );
878  assert( naddedconss != NULL );
879  *naddedconss = 0;
880 
881  /* exit if contraints is modifiable */
882  if ( SCIPconsIsModifiable(cons) )
883  return SCIP_OKAY;
884 
885  consdata = SCIPconsGetData(cons);
886  assert( consdata != NULL );
887 
888  /* exit if extended formulation has been added already */
889  if ( consdata->extvars != NULL )
890  return SCIP_OKAY;
891 
892  /* xor constraints with at most 3 variables are handled directly through rows for the convex hull */
893  if ( consdata->nvars <= 3 )
894  return SCIP_OKAY;
895 
896  SCIPdebugMessage("Add extended formulation for xor constraint <%s> ...\n", SCIPconsGetName(cons));
897  assert( consdata->extvars == NULL );
898  assert( consdata->nextvars == 0 );
899  assert( consdata->extvarssize == 0 );
900 
901  /* get storage for auxiliary variables */
902  consdata->extvarssize = 4 * (consdata->nvars);
903  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->extvars), consdata->extvarssize) );
904 
905  /* pass through components */
906  for (i = 0; i < consdata->nvars; ++i)
907  {
908  /* variables: n - north, s - south */
909  SCIP_VAR* varnn = NULL;
910  SCIP_VAR* varns = NULL;
911  SCIP_VAR* varsn = NULL;
912  SCIP_VAR* varss = NULL;
913  SCIP_CONS* newcons;
914  SCIP_Real rhs = 0.0;
915  SCIP_Bool infeasible = FALSE;
916  SCIP_Bool redundant = FALSE;
917  SCIP_Bool aggregated = FALSE;
918  int cnt = 0;
919 
920  /* create variables */
921  if ( i == 0 )
922  {
923  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_nn", SCIPconsGetName(cons), i);
924  SCIP_CALL( SCIPcreateVar(scip, &varnn, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
925  SCIP_CALL( SCIPaddVar(scip, varnn) );
926 
927  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ns", SCIPconsGetName(cons), i);
928  SCIP_CALL( SCIPcreateVar(scip, &varns, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
929  SCIP_CALL( SCIPaddVar(scip, varns) );
930 
931  /* need to lock variables, because we aggregate them */
932  SCIP_CALL( SCIPlockVarCons(scip, varnn, cons, TRUE, TRUE) );
933  SCIP_CALL( SCIPlockVarCons(scip, varns, cons, TRUE, TRUE) );
934 
935  /* aggregate ns variable with original variable */
936  SCIP_CALL( SCIPaggregateVars(scip, varns, consdata->vars[0], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
937  assert( ! infeasible );
938  assert( redundant );
939  assert( aggregated );
940  }
941  else
942  {
943  if ( i == consdata->nvars-1 )
944  {
945  if ( consdata->rhs )
946  {
947  /* if the rhs is 1 (true) the flow goes to the bottom level */
948  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ns", SCIPconsGetName(cons), i);
949  SCIP_CALL( SCIPcreateVar(scip, &varns, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
950  SCIP_CALL( SCIPaddVar(scip, varns) );
951 
952  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ss", SCIPconsGetName(cons), i);
953  SCIP_CALL( SCIPcreateVar(scip, &varss, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
954  SCIP_CALL( SCIPaddVar(scip, varss) );
955 
956  /* need to lock variables, because we aggregate them */
957  SCIP_CALL( SCIPlockVarCons(scip, varns, cons, TRUE, TRUE) );
958  SCIP_CALL( SCIPlockVarCons(scip, varss, cons, TRUE, TRUE) );
959 
960  /* aggregate ns variable with original variable */
961  SCIP_CALL( SCIPaggregateVars(scip, varns, consdata->vars[i], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
962  assert( ! infeasible );
963  assert( redundant );
964  assert( aggregated );
965  }
966  else
967  {
968  /* if the rhs is 0 (false) the flow stays on the top level */
969  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_nn", SCIPconsGetName(cons), i);
970  SCIP_CALL( SCIPcreateVar(scip, &varnn, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
971  SCIP_CALL( SCIPaddVar(scip, varnn) );
972 
973  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_sn", SCIPconsGetName(cons), i);
974  SCIP_CALL( SCIPcreateVar(scip, &varsn, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
975  SCIP_CALL( SCIPaddVar(scip, varsn) );
976 
977  /* need to lock variables, because we aggregate them */
978  SCIP_CALL( SCIPlockVarCons(scip, varnn, cons, TRUE, TRUE) );
979  SCIP_CALL( SCIPlockVarCons(scip, varsn, cons, TRUE, TRUE) );
980 
981  /* aggregate sn variable with original variable */
982  SCIP_CALL( SCIPaggregateVars(scip, varsn, consdata->vars[i], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
983  assert( ! infeasible );
984  assert( redundant );
985  assert( aggregated );
986  }
987  }
988  else
989  {
990  /* add the four flow variables */
991  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_nn", SCIPconsGetName(cons), i);
992  SCIP_CALL( SCIPcreateVar(scip, &varnn, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
993  SCIP_CALL( SCIPaddVar(scip, varnn) );
994 
995  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ns", SCIPconsGetName(cons), i);
996  SCIP_CALL( SCIPcreateVar(scip, &varns, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
997  SCIP_CALL( SCIPaddVar(scip, varns) );
998 
999  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_sn", SCIPconsGetName(cons), i);
1000  SCIP_CALL( SCIPcreateVar(scip, &varsn, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
1001  SCIP_CALL( SCIPaddVar(scip, varsn) );
1002 
1003  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_ss", SCIPconsGetName(cons), i);
1004  SCIP_CALL( SCIPcreateVar(scip, &varss, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
1005  SCIP_CALL( SCIPaddVar(scip, varss) );
1006 
1007  SCIP_CALL( SCIPlockVarCons(scip, varnn, cons, TRUE, TRUE) );
1008  SCIP_CALL( SCIPlockVarCons(scip, varns, cons, TRUE, TRUE) );
1009  SCIP_CALL( SCIPlockVarCons(scip, varsn, cons, TRUE, TRUE) );
1010  SCIP_CALL( SCIPlockVarCons(scip, varss, cons, TRUE, TRUE) );
1011 
1012  /* add coupling constraint */
1013  cnt = 0;
1014  if ( varns != NULL )
1015  {
1016  vars[cnt] = varns;
1017  vals[cnt++] = 1.0;
1018  }
1019  if ( varsn != NULL )
1020  {
1021  vars[cnt] = varsn;
1022  vals[cnt++] = 1.0;
1023  }
1024  assert( SCIPvarIsTransformed(consdata->vars[i]) );
1025  vars[cnt] = consdata->vars[i];
1026  vals[cnt++] = -1.0;
1027 
1028  assert( cnt >= 2 );
1029  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_couple", SCIPconsGetName(cons));
1030  /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
1031  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, cnt, vars, vals, 0.0, 0.0,
1033  SCIP_CALL( SCIPaddCons(scip, newcons) );
1034  SCIPdebugPrintCons(scip, newcons, NULL);
1035  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1036  ++(*naddedconss);
1037  }
1038 
1039  /* add south flow conservation constraint */
1040 
1041  /* incoming variables */
1042  cnt = 0;
1043  if ( varprevss != NULL )
1044  {
1045  vars[cnt] = varprevss;
1046  vals[cnt++] = 1.0;
1047  }
1048  if ( varprevns != NULL )
1049  {
1050  vars[cnt] = varprevns;
1051  vals[cnt++] = 1.0;
1052  }
1053 
1054  /* outgoing variables */
1055  if ( varss != NULL )
1056  {
1057  vars[cnt] = varss;
1058  vals[cnt++] = -1.0;
1059  }
1060  if ( varsn != NULL )
1061  {
1062  vars[cnt] = varsn;
1063  vals[cnt++] = -1.0;
1064  }
1065 
1066  assert( cnt >= 2 );
1067  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_south", SCIPconsGetName(cons));
1068  /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
1069  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, cnt, vars, vals, 0.0, 0.0,
1071  SCIP_CALL( SCIPaddCons(scip, newcons) );
1072  SCIPdebugPrintCons(scip, newcons, NULL);
1073  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1074  ++(*naddedconss);
1075  }
1076 
1077  /* add north flow conservation constraint */
1078 
1079  /* incoming variables */
1080  cnt = 0;
1081  if ( varprevnn != NULL )
1082  {
1083  vars[cnt] = varprevnn;
1084  vals[cnt++] = 1.0;
1085  }
1086  if ( varprevsn != NULL )
1087  {
1088  vars[cnt] = varprevsn;
1089  vals[cnt++] = 1.0;
1090  }
1091 
1092  /* outgoing variables */
1093  if ( varnn != NULL )
1094  {
1095  vars[cnt] = varnn;
1096  vals[cnt++] = -1.0;
1097  }
1098  if ( varns != NULL )
1099  {
1100  vars[cnt] = varns;
1101  vals[cnt++] = -1.0;
1102  }
1103 
1104  assert( cnt >= 2 );
1105  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_north", SCIPconsGetName(cons));
1106  if ( i == 0 )
1107  rhs = -1.0;
1108  else
1109  rhs = 0.0;
1110 
1111  /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
1112  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, cnt, vars, vals, rhs, rhs,
1114  SCIP_CALL( SCIPaddCons(scip, newcons) );
1115  SCIPdebugPrintCons(scip, newcons, NULL);
1116  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1117  ++(*naddedconss);
1118 
1119  /* store variables */
1120  consdata->extvars[4*i] = varnn; /*lint !e679*/
1121  consdata->extvars[4*i + 1] = varns; /*lint !e679*/
1122  consdata->extvars[4*i + 2] = varsn; /*lint !e679*/
1123  consdata->extvars[4*i + 3] = varss; /*lint !e679*/
1124 
1125  if ( varnn != NULL )
1126  ++(consdata->nextvars);
1127  if ( varns != NULL )
1128  ++(consdata->nextvars);
1129  if ( varsn != NULL )
1130  ++(consdata->nextvars);
1131  if ( varss != NULL )
1132  ++(consdata->nextvars);
1133 
1134  /* store previous variables */
1135  varprevnn = varnn;
1136  varprevns = varns;
1137  varprevsn = varsn;
1138  varprevss = varss;
1139  }
1140 
1141  return SCIP_OKAY;
1142 }
1143 
1144 /** adds extended asymmetric formulation
1145  *
1146  * The extended asymmetric formulation is constructed as follows: Let \f$x_1, \dots, x_k\f$ be the variables contained
1147  * in the given XOR constraint. We introduce variables \f$p_1, \ldots, p_k\f$ with the following constraints: \f$p_1 =
1148  * x_1\f$, \f$p_k = 1\f$, and for \f$i = 2, \ldots, k-1\f$:
1149  * \f[
1150  * \begin{array}{ll}
1151  * p_i & \leq p_{i-1} + x_i\\
1152  * p_i & \leq 2 - (p_{i-1} + x_i)\\
1153  * p_i & \geq p_{i-1} - x_i\\
1154  * p_i & \geq x_i - p_{i-1}.
1155  * \end{array}
1156  * \f]
1157  * This formulation is described in
1158  *
1159  * Robert D. Carr and Goran Konjevod@n
1160  * Polyhedral combinatorics@n
1161  * In Harvey Greenberg, editor, Tutorials on emerging methodologies and applications in Operations Research,@n
1162  * Chapter 2, pages (2-1)-(2-48). Springer, 2004.
1163  */
1164 static
1166  SCIP* scip, /**< SCIP data structure */
1167  SCIP_CONS* cons, /**< constraint to check */
1168  int* naddedconss /**< number of added constraints */
1169  )
1170 {
1171  char name[SCIP_MAXSTRLEN];
1172  SCIP_CONSDATA* consdata;
1173  SCIP_VAR* vars[3];
1174  SCIP_Real vals[3];
1175  SCIP_VAR* prevvar = NULL;
1176  int i;
1177 
1178  assert( scip != NULL );
1179  assert( cons != NULL );
1180  assert( naddedconss != NULL );
1181  *naddedconss = 0;
1182 
1183  /* exit if contraints is modifiable */
1184  if ( SCIPconsIsModifiable(cons) )
1185  return SCIP_OKAY;
1186 
1187  consdata = SCIPconsGetData(cons);
1188  assert( consdata != NULL );
1189 
1190  /* exit if extended formulation has been added already */
1191  if ( consdata->extvars != NULL )
1192  return SCIP_OKAY;
1193 
1194  /* xor constraints with at most 3 variables are handled directly through rows for the convex hull */
1195  if ( consdata->nvars <= 3 )
1196  return SCIP_OKAY;
1197 
1198  SCIPdebugMessage("Add extended formulation for xor constraint <%s> ...\n", SCIPconsGetName(cons));
1199  assert( consdata->extvars == NULL );
1200  assert( consdata->nextvars == 0 );
1201 
1202  /* get storage for auxiliary variables */
1203  consdata->extvarssize = consdata->nvars;
1204  consdata->nextvars = consdata->nvars;
1205  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->extvars), consdata->extvarssize ) );
1206 
1207  /* pass through components */
1208  for (i = 0; i < consdata->nvars; ++i)
1209  {
1210  SCIP_Bool infeasible = FALSE;
1211  SCIP_Bool redundant = FALSE;
1212  SCIP_Bool aggregated = FALSE;
1213  SCIP_CONS* newcons;
1214  SCIP_VAR* artvar = NULL;
1215  SCIP_Real lb = 0.0;
1216  SCIP_Real ub = 1.0;
1217 
1218  /* determine fixing for last variables */
1219  if ( i == consdata->nvars-1 )
1220  {
1221  if ( consdata->rhs )
1222  {
1223  lb = 1.0;
1224  ub = 1.0;
1225  }
1226  else
1227  {
1228  lb = 0.0;
1229  ub = 0.0;
1230  }
1231  }
1232 
1233  /* create variable */
1234  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "p_%s_%d", SCIPconsGetName(cons), i);
1235  SCIP_CALL( SCIPcreateVar(scip, &artvar, name, lb, ub, 0.0, SCIP_VARTYPE_IMPLINT, SCIPconsIsInitial(cons), SCIPconsIsRemovable(cons), NULL, NULL, NULL, NULL, NULL) );
1236  SCIP_CALL( SCIPaddVar(scip, artvar) );
1237  SCIP_CALL( SCIPlockVarCons(scip, artvar, cons, TRUE, TRUE) );
1238 
1239  /* create constraints */
1240  if ( i == 0 )
1241  {
1242  /* aggregate artificial variable with original variable */
1243  SCIP_CALL( SCIPaggregateVars(scip, artvar, consdata->vars[0], 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
1244  assert( ! infeasible );
1245  assert( redundant );
1246  assert( aggregated );
1247  }
1248  else
1249  {
1250  assert( SCIPvarIsTransformed(consdata->vars[i]) );
1251 
1252  /* add first constraint */
1253  vars[0] = artvar;
1254  vals[0] = 1.0;
1255  vars[1] = prevvar;
1256  vals[1] = -1.0;
1257  vars[2] = consdata->vars[i];
1258  vals[2] = -1.0;
1259 
1260  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_1", SCIPconsGetName(cons), i);
1261  /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
1262  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 0.0,
1264  SCIP_CALL( SCIPaddCons(scip, newcons) );
1265  SCIPdebugPrintCons(scip, newcons, NULL);
1266  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1267  ++(*naddedconss);
1268 
1269  /* add second constraint */
1270  vars[0] = artvar;
1271  vals[0] = 1.0;
1272  vars[1] = prevvar;
1273  vals[1] = 1.0;
1274  vars[2] = consdata->vars[i];
1275  vals[2] = 1.0;
1276 
1277  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_2", SCIPconsGetName(cons), i);
1278  /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
1279  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 2.0,
1281  SCIP_CALL( SCIPaddCons(scip, newcons) );
1282  SCIPdebugPrintCons(scip, newcons, NULL);
1283  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1284  ++(*naddedconss);
1285 
1286  /* add third constraint */
1287  vars[0] = artvar;
1288  vals[0] = -1.0;
1289  vars[1] = prevvar;
1290  vals[1] = 1.0;
1291  vars[2] = consdata->vars[i];
1292  vals[2] = -1.0;
1293 
1294  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_3", SCIPconsGetName(cons), i);
1295  /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
1296  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 0.0,
1298  SCIP_CALL( SCIPaddCons(scip, newcons) );
1299  SCIPdebugPrintCons(scip, newcons, NULL);
1300  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1301  ++(*naddedconss);
1302 
1303  /* add fourth constraint */
1304  vars[0] = artvar;
1305  vals[0] = -1.0;
1306  vars[1] = prevvar;
1307  vals[1] = -1.0;
1308  vars[2] = consdata->vars[i];
1309  vals[2] = 1.0;
1310 
1311  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_%d_4", SCIPconsGetName(cons), i);
1312  /* not initial, separate, do not enforce, do not check, propagate, not local, not modifiable, dynamic, removable, not sticking */
1313  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, 3, vars, vals, -SCIPinfinity(scip), 0.0,
1315  SCIP_CALL( SCIPaddCons(scip, newcons) );
1316  SCIPdebugPrintCons(scip, newcons, NULL);
1317  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1318  ++(*naddedconss);
1319  }
1320 
1321  /* store variable */
1322  consdata->extvars[i] = artvar;
1323  prevvar = artvar;
1324  }
1325 
1326  return SCIP_OKAY;
1327 }
1328 
1329 /** creates LP row corresponding to xor constraint:
1330  * x1 + ... + xn - 2q == rhs
1331  * with internal integer variable q;
1332  * in the special case of 3 variables and c = 0, the following linear system is created:
1333  * + x - y - z <= 0
1334  * - x + y - z <= 0
1335  * - x - y + z <= 0
1336  * + x + y + z <= 2
1337  * in the special case of 3 variables and c = 1, the following linear system is created:
1338  * - x + y + z <= 1
1339  * + x - y + z <= 1
1340  * + x + y - z <= 1
1341  * - x - y - z <= -1
1342  */
1343 static
1345  SCIP* scip, /**< SCIP data structure */
1346  SCIP_CONS* cons /**< constraint to check */
1347  )
1348 {
1349  SCIP_CONSDATA* consdata;
1350  char varname[SCIP_MAXSTRLEN];
1351 
1352  consdata = SCIPconsGetData(cons);
1353  assert(consdata != NULL);
1354  assert(consdata->rows[0] == NULL);
1355 
1356  if( SCIPconsIsModifiable(cons) || consdata->nvars != 3 )
1357  {
1358  SCIP_Real rhsval;
1359 
1360  /* create internal variable, if not yet existing */
1361  if( consdata->intvar == NULL )
1362  {
1363  int ub;
1364 
1365  (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "XOR_artificial_%s_int", SCIPconsGetName(cons));
1366  ub = consdata->nvars/2;
1367  SCIP_CALL( SCIPcreateVar(scip, &consdata->intvar, varname, 0.0, (SCIP_Real)ub, 0.0,
1368  consdata->nvars >= 4 ? SCIP_VARTYPE_INTEGER : SCIP_VARTYPE_BINARY,
1370  SCIP_CALL( SCIPaddVar(scip, consdata->intvar) );
1371 
1372 #ifdef SCIP_DEBUG_SOLUTION
1373  if( SCIPdebugIsMainscip(scip) )
1374  {
1375  SCIP_Real solval;
1376  int count = 0;
1377  int v;
1378 
1379  for( v = consdata->nvars - 1; v >= 0; --v )
1380  {
1381  SCIP_CALL( SCIPdebugGetSolVal(scip, consdata->vars[v], &solval) );
1382  count += (solval > 0.5 ? 1 : 0);
1383  }
1384  assert((count - consdata->rhs) % 2 == 0);
1385  solval = (SCIP_Real) ((count - consdata->rhs) / 2);
1386 
1387  /* store debug sol value of artificial integer variable */
1388  SCIP_CALL( SCIPdebugAddSolVal(scip, consdata->intvar, solval) );
1389  }
1390 #endif
1391 
1392  /* install the rounding locks for the internal variable */
1393  SCIP_CALL( lockRounding(scip, cons, consdata->intvar) );
1394  }
1395 
1396  /* create LP row */
1397  rhsval = (consdata->rhs ? 1.0 : 0.0);
1398  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[0], SCIPconsGetHdlr(cons), SCIPconsGetName(cons), rhsval, rhsval,
1400  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[0], consdata->intvar, -2.0) );
1401  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[0], consdata->nvars, consdata->vars, 1.0) );
1402  }
1403  else if( !consdata->rhs )
1404  {
1405  char rowname[SCIP_MAXSTRLEN];
1406  int r;
1407 
1408  /* create the <= 0 rows with one positive sign */
1409  for( r = 0; r < 3; ++r )
1410  {
1411  int v;
1412 
1413  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), r);
1414  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[r], SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 0.0,
1416  for( v = 0; v < 3; ++v )
1417  {
1418  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[r], consdata->vars[v], v == r ? +1.0 : -1.0) );
1419  }
1420  }
1421 
1422  /* create the <= 2 row with all positive signs */
1423  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_3", SCIPconsGetName(cons));
1424  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[3], SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 2.0,
1426  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[3], consdata->nvars, consdata->vars, 1.0) );
1427  }
1428  else
1429  {
1430  char rowname[SCIP_MAXSTRLEN];
1431  int r;
1432 
1433  /* create the <= 1 rows with one negative sign */
1434  for( r = 0; r < 3; ++r )
1435  {
1436  int v;
1437 
1438  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), r);
1439  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[r], SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 1.0,
1441  for( v = 0; v < 3; ++v )
1442  {
1443  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[r], consdata->vars[v], v == r ? -1.0 : +1.0) );
1444  }
1445  }
1446 
1447  /* create the <= -1 row with all negative signs */
1448  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_3", SCIPconsGetName(cons));
1449  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[3], SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), -1.0,
1451  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[3], consdata->nvars, consdata->vars, -1.0) );
1452  }
1453 
1454  return SCIP_OKAY;
1455 }
1456 
1457 /** adds linear relaxation of or constraint to the LP */
1458 static
1460  SCIP* scip, /**< SCIP data structure */
1461  SCIP_CONS* cons /**< constraint to check */
1462  )
1463 {
1464  SCIP_CONSDATA* consdata;
1465  SCIP_Bool infeasible;
1466  int r;
1467 
1468  consdata = SCIPconsGetData(cons);
1469  assert(consdata != NULL);
1470 
1471  if( consdata->rows[0] == NULL )
1472  {
1473  SCIP_CALL( createRelaxation(scip, cons) );
1474  }
1475  assert(consdata->rows[0] != NULL);
1476  for( r = 0; r < NROWS; ++r )
1477  {
1478  if( consdata->rows[r] != NULL && !SCIProwIsInLP(consdata->rows[r]) )
1479  {
1480  SCIP_CALL( SCIPaddCut(scip, NULL, consdata->rows[r], FALSE, &infeasible) );
1481  assert( ! infeasible ); /* function is only called from initlp -> row should be feasible */
1482  }
1483  }
1484 
1485  return SCIP_OKAY;
1486 }
1487 
1488 /** returns whether all rows of the LP relaxation are in the current LP */
1489 static
1491  SCIP_CONSDATA* consdata /**< constraint data */
1492  )
1493 {
1494  assert(consdata != NULL);
1495 
1496  if( consdata->rows[0] == NULL ) /* LP relaxation does not exist */
1497  return FALSE;
1498  else
1499  {
1500  int r;
1501  for( r = 0; r < NROWS; ++r )
1502  {
1503  if( consdata->rows[r] != NULL && !SCIProwIsInLP(consdata->rows[r]) )
1504  return FALSE;
1505  }
1506  return TRUE;
1507  }
1508 }
1509 
1510 /** checks xor constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
1511 static
1513  SCIP* scip, /**< SCIP data structure */
1514  SCIP_CONS* cons, /**< constraint to check */
1515  SCIP_SOL* sol, /**< solution to check, NULL for current solution */
1516  SCIP_Bool checklprows, /**< should LP rows be checked? */
1517  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
1518  )
1519 {
1520  SCIP_CONSDATA* consdata;
1521 
1522  assert(violated != NULL);
1523 
1524  consdata = SCIPconsGetData(cons);
1525  assert(consdata != NULL);
1526 
1527  *violated = FALSE;
1528 
1529  /* check feasibility of constraint if necessary */
1530  if( checklprows || !allRowsInLP(consdata) )
1531  {
1532  SCIP_Real solval;
1533  int i;
1534  SCIP_Bool odd;
1535 
1536  /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
1537  * enforcement
1538  */
1539  if( sol == NULL )
1540  {
1541  SCIP_CALL( SCIPincConsAge(scip, cons) );
1542  }
1543 
1544  /* check, if all variables and the rhs sum up to an even value */
1545  odd = consdata->rhs;
1546  for( i = 0; i < consdata->nvars; ++i )
1547  {
1548  solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
1549  assert(SCIPisFeasIntegral(scip, solval));
1550  odd = (odd != (solval > 0.5));
1551  }
1552  if( odd )
1553  {
1554  *violated = TRUE;
1555 
1556  /* only reset constraint age if we are in enforcement */
1557  if( sol == NULL )
1558  {
1559  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1560  }
1561  }
1562  }
1563 
1564  return SCIP_OKAY;
1565 }
1566 
1567 /** separates current LP solution
1568  *
1569  * Consider a XOR-constraint
1570  * \f[
1571  * x_1 \oplus x_2 \oplus \dots \oplus x_n = b
1572  * \f]
1573  * with \f$b \in \{0,1\}\f$ and a solution \f$x^*\f$ to be cut off. Small XOR constraints are handled by adding the
1574  * inequalities of the convex hull.
1575  *
1576  * The separation of larger XOR constraints has been described by @n
1577  * Xiaojie Zhang and Paul H. Siegel@n
1578  * "Adaptive Cut Generation Algorithm for Improved Linear Programming Decoding of Binary Linear Codes"@n
1579  * IEEE Transactions on Information Theory, vol. 58, no. 10, 2012
1580  *
1581  * We separate the inequalities
1582  * \f[
1583  * \sum_{j \in S} (1 - x_j) + \sum_{j \notin S} x_j \geq 1
1584  * \f]
1585  * with \f$|S| \equiv (b+1) \mbox{ mod } 2\f$ as follows. That these inequalities are valid can be seen as follows: Let
1586  * \f$x\f$ be a feasible solution and suppose that the inequality is violated for some \f$S\f$. Then \f$x_j = 1\f$ for
1587  * all \f$j \in S\f$ and \f$x_j = 0\f$ for all \f$j \notin S\f$. Thus we should have
1588  * \f[
1589  * \oplus_{j \in S} x_j = |S| \mbox{ mod } 2 = b+1 \mbox{ mod } 2,
1590  * \f]
1591  * which is not equal to \f$b\f$ as required by the XOR-constraint.
1592  *
1593  * Let \f$L= \{j \;:\; x^*_j > \frac{1}{2}\}\f$. Suppose that \f$|L|\f$ has @em not the same parity as \f$b\f$ rhs. Then
1594  * \f[
1595  * \sum_{j \in L} (1 - x_j) + \sum_{j \notin L} x_j \geq 1
1596  * \f]
1597  * is the only inequality that can be violated. We rewrite the inequality as
1598  * \f[
1599  * \sum_{j \in L} x_j - \sum_{j \notin L} x_j \leq |L| - 1.
1600  * \f]
1601  * These inequalities are added.
1602  *
1603  * Otherwise let \f$k = \mbox{argmin}\{x^*_j \;:\; j \in L\}\f$ and check the inequality for \f$L \setminus \{k\}\f$
1604  * and similarly for \f$k = \mbox{argmax}\{x^*_j \;:\; j \in L\}\f$.
1605  */
1606 static
1608  SCIP* scip, /**< SCIP data structure */
1609  SCIP_CONS* cons, /**< constraint to check */
1610  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1611  SCIP_Bool separateparity, /**< should parity inequalities be separated? */
1612  SCIP_Bool* separated, /**< pointer to store whether a cut was found */
1613  SCIP_Bool* cutoff /**< whether a cutoff has been detected */
1614  )
1615 {
1616  SCIP_CONSDATA* consdata;
1617  SCIP_Real feasibility;
1618  int r;
1619 
1620  assert( separated != NULL );
1621  assert( cutoff != NULL );
1622  *cutoff = FALSE;
1623 
1624  consdata = SCIPconsGetData(cons);
1625  assert(consdata != NULL);
1626 
1627  *separated = FALSE;
1628 
1629  /* create row for the linear relaxation */
1630  if( consdata->rows[0] == NULL )
1631  {
1632  SCIP_CALL( createRelaxation(scip, cons) );
1633  }
1634  assert(consdata->rows[0] != NULL);
1635 
1636  /* test rows for feasibility and add it, if it is infeasible */
1637  for( r = 0; r < NROWS; ++r )
1638  {
1639  if( consdata->rows[r] != NULL && ((sol == NULL && !SCIProwIsInLP(consdata->rows[r])) || sol != NULL) )
1640  {
1641  feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
1642  if( SCIPisFeasNegative(scip, feasibility) )
1643  {
1644  SCIP_CALL( SCIPaddCut(scip, sol, consdata->rows[r], FALSE, cutoff) );
1645  if ( *cutoff )
1646  return SCIP_OKAY;
1647  *separated = TRUE;
1648  }
1649  }
1650  }
1651 
1652  /* separate parity inequalities if required */
1653  if ( separateparity && consdata->nvars > 3 )
1654  {
1655  char name[SCIP_MAXSTRLEN];
1656  SCIP_Real maxval = -1.0;
1657  SCIP_Real minval = 2.0;
1658  SCIP_Real sum = 0.0;
1659  int maxidx = -1;
1660  int minidx = -1;
1661  int ngen = 0;
1662  int cnt = 0;
1663  int j;
1664 
1665  SCIPdebugMessage("separating parity inequalities ...\n");
1666 
1667  /* compute value */
1668  for (j = 0; j < consdata->nvars; ++j)
1669  {
1670  SCIP_Real val;
1671 
1672  val = SCIPgetSolVal(scip, sol, consdata->vars[j]);
1673  if ( SCIPisFeasGT(scip, val, 0.5) )
1674  {
1675  if ( val < minval )
1676  {
1677  minval = val;
1678  minidx = j;
1679  }
1680  ++cnt;
1681  sum += (1.0 - val);
1682  }
1683  else
1684  {
1685  if ( val > maxval )
1686  {
1687  maxval = val;
1688  maxidx = j;
1689  }
1690  sum += val;
1691  }
1692  }
1693 
1694  /* if size of set does not have the same parity as rhs (e.g., size is odd if rhs is 0) */
1695  if ( (cnt - consdata->rhs) % 2 == 1 )
1696  {
1697  if ( SCIPisEfficacious(scip, 1.0 - sum) )
1698  {
1699  SCIP_ROW* row;
1700 
1701  SCIPdebugMessage("found violated parity cut (efficiacy: %f)\n", 1.0 - sum);
1702 
1703  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "parity#%s", SCIPconsGetName(cons));
1704  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), (SCIP_Real) (cnt - 1), FALSE, FALSE, TRUE) );
1705  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
1706 
1707  /* fill in row */
1708  for (j = 0; j < consdata->nvars; ++j)
1709  {
1710  if ( SCIPisFeasGT(scip, SCIPgetSolVal(scip, sol, consdata->vars[j]), 0.5) )
1711  {
1712  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
1713  }
1714  else
1715  {
1716  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
1717  }
1718  }
1719  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
1720  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
1721  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, cutoff) );
1722  assert( SCIPisGT(scip, SCIPgetRowLPActivity(scip, row), (SCIP_Real) (cnt-1)) );
1723  SCIP_CALL( SCIPreleaseRow(scip, &row) );
1724  ++ngen;
1725  }
1726  }
1727  else
1728  {
1729  /* If the parity is equal: check removing the element with smallest value from the set and adding the
1730  * element with largest value to the set. If we remove the element with smallest value, we have to subtract (1
1731  * - minval) and add minval to correct the sum. */
1732  if ( SCIPisEfficacious(scip, 1.0 - (sum - 1.0 + 2.0 * minval)) )
1733  {
1734  SCIP_ROW* row;
1735 
1736  SCIPdebugMessage("found violated parity cut (efficiacy: %f, minval: %f)\n", 1.0 - (sum - 1.0 + 2.0 * minval), minval);
1737 
1738  /* the rhs of the inequality is the corrected set size minus 1 */
1739  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "parity#%s", SCIPconsGetName(cons));
1740  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), (SCIP_Real) (cnt - 2), FALSE, FALSE, TRUE) );
1741  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
1742 
1743  /* fill in row */
1744  for (j = 0; j < consdata->nvars; ++j)
1745  {
1746  if ( SCIPisFeasGT(scip, SCIPgetSolVal(scip, sol, consdata->vars[j]), 0.5) )
1747  {
1748  /* if the index corresponds to the smallest element, we reverse the sign */
1749  if ( j == minidx )
1750  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
1751  else
1752  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
1753  }
1754  else
1755  {
1756  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
1757  }
1758  }
1759  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
1760  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
1761  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, cutoff) );
1762  assert( SCIPisGT(scip, SCIPgetRowLPActivity(scip, row), (SCIP_Real) (cnt-2)) );
1763  SCIP_CALL( SCIPreleaseRow(scip, &row) );
1764  ++ngen;
1765  }
1766 
1767  /* If we add the element with largest value, we have to add (1 - maxval) and subtract maxval to get the correct sum. */
1768  if ( SCIPisEfficacious(scip, 1.0 - (sum + 1.0 - 2.0 * maxval)) )
1769  {
1770  SCIP_ROW* row;
1771 
1772  SCIPdebugMessage("found violated parity cut (efficiacy: %f, maxval: %f)\n", 1.0 - (sum + 1.0 - 2.0 * maxval), maxval);
1773 
1774  /* the rhs of the inequality is the size of the corrected set */
1775  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "parity#%s", SCIPconsGetName(cons));
1776  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), (SCIP_Real) cnt, FALSE, FALSE, TRUE) );
1777  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
1778 
1779  /* fill in row */
1780  for (j = 0; j < consdata->nvars; ++j)
1781  {
1782  if ( SCIPisFeasGT(scip, SCIPgetSolVal(scip, sol, consdata->vars[j]), 0.5) )
1783  {
1784  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
1785  }
1786  else
1787  {
1788  /* if the index corresponds to the largest element, we reverse the sign */
1789  if ( j == maxidx )
1790  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], 1.0) );
1791  else
1792  SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->vars[j], -1.0) );
1793  }
1794  }
1795  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
1796  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
1797  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, cutoff) );
1798  assert( *cutoff || SCIPisGT(scip, SCIPgetRowLPActivity(scip, row), (SCIP_Real)(j-1)) );
1799  SCIP_CALL( SCIPreleaseRow(scip, &row) );
1800  ++ngen;
1801  }
1802  }
1803 
1804  SCIPdebugMessage("separated parity inequalites: %d\n", ngen);
1805  if ( ngen > 0 )
1806  *separated = TRUE;
1807  }
1808 
1809  return SCIP_OKAY;
1810 }
1811 
1812 /** Transform linear system \f$A x = b\f$ into row echolon form via the Gauss algorithm with row pivoting over GF2
1813  * @returns the rank of @p A
1814  *
1815  * Here, \f$A \in R^{m \times n},\; b \in R^m\f$. On exit, the vector @p p contains a permutation of the row indices
1816  * used for pivoting and the function returns the rank @p r of @p A. For each row \f$i = 1, \ldots, r\f$, the entry @p
1817  * s[i] contains the column index of the first nonzero in row @p i.
1818  */
1819 static
1821  SCIP* scip, /**< SCIP data structure */
1822  int m, /**< number of rows */
1823  int n, /**< number of columns */
1824  int* p, /**< row permutation */
1825  int* s, /**< steps indicators of the row echolon form */
1826  Type** A, /**< matrix */
1827  Type* b /**< rhs */
1828  )
1829 {
1830  int pi;
1831  int i;
1832  int j;
1833  int k;
1834 
1835  assert( A != NULL );
1836  assert( b != NULL );
1837  assert( p != NULL );
1838  assert( s != NULL );
1839 
1840  /* init permutation and step indicators */
1841  for (i = 0; i < m; ++i)
1842  {
1843  p[i] = i;
1844  s[i] = i;
1845  }
1846 
1847  /* loop through possible steps in echolon form (stop at min {n, m}) */
1848  for (i = 0; i < m && i < n; ++i)
1849  {
1850  assert( s[i] == i );
1851 
1852  /* init starting column */
1853  if ( i == 0 )
1854  j = 0;
1855  else
1856  j = s[i-1] + 1;
1857 
1858  /* find pivot row (i.e., first nonzero entry), if all entries in current row are 0 we search the next column */
1859  do
1860  {
1861  /* search in current column j */
1862  k = i;
1863  while ( k < m && A[p[k]][j] == 0 )
1864  ++k;
1865 
1866  /* found pivot */
1867  if ( k < m )
1868  break;
1869 
1870  /* otherwise search next column */
1871  ++j;
1872  }
1873  while ( j < n );
1874 
1875  /* if not pivot entry was found (checked all columns), the rank of A is equal to the current index i; in this case
1876  * all entries in and below row i are 0 */
1877  if ( j >= n )
1878  return i;
1879 
1880  /* at this place: we have found a pivot entry (p[k], j) */
1881  assert( k < m );
1882 
1883  /* store step index */
1884  s[i] = j;
1885  assert( A[p[k]][j] != 0 );
1886 
1887  /* swap row indices */
1888  if ( k != i )
1889  {
1890  int h = p[i];
1891  p[i] = p[k];
1892  p[k] = h;
1893  }
1894  pi = p[i];
1895  assert( A[pi][s[i]] != 0 );
1896 
1897  /* do elimination */
1898  for (k = i+1; k < m; ++k)
1899  {
1900  int pk = p[k];
1901  /* if entry in leading column is nonzero (otherwise we already have a 0) */
1902  if ( A[pk][s[i]] != 0 )
1903  {
1904  for (j = s[i]; j < n; ++j)
1905  A[pk][j] = A[pk][j] ^ A[pi][j];
1906  b[pk] = b[pk] ^ b[pi];
1907  }
1908  }
1909 
1910  /* check stopped (only every 100 rows in order to save time */
1911  if ( i % 100 == 99 )
1912  {
1913  if ( SCIPisStopped(scip) )
1914  return -1;
1915  }
1916  }
1917 
1918  /* at this point we have treated all rows in which a step can occur; the rank is the minimum of the number of rows or
1919  * columns min {n,m}. */
1920  if ( n <= m )
1921  return n;
1922  return m;
1923 }
1924 
1925 /** Construct solution from matrix in row echolon form over GF2
1926  *
1927  * Compute solution of \f$A x = b\f$, which is already in row echolon form (@see computeRowEcholonGF2()) */
1928 static
1929 void solveRowEcholonGF2(
1930  int m, /**< number of rows */
1931  int n, /**< number of columns */
1932  int r, /**< rank of matrix */
1933  int* p, /**< row permutation */
1934  int* s, /**< steps indicators of the row echolon form */
1935  Type** A, /**< matrix */
1936  Type* b, /**< rhs */
1937  Type* x /**< solution vector on exit */
1938  )
1939 {
1940  int i;
1941  int k;
1942 
1943  assert( A != NULL );
1944  assert( b != NULL );
1945  assert( s != NULL );
1946  assert( p != NULL );
1947  assert( x != NULL );
1948  assert( r <= m && r <= n );
1949 
1950  /* init solution vector to 0 */
1951  for (k = 0; k < n; ++k)
1952  x[k] = 0;
1953 
1954  /* init last entry */
1955  x[s[r-1]] = b[p[r-1]];
1956 
1957  /* loop backwards through solution vector */
1958  for (i = r-2; i >= 0; --i)
1959  {
1960  Type val;
1961 
1962  assert( i <= s[i] && s[i] <= n );
1963 
1964  /* init val with rhs and then add the contributions of the components of x already computed */
1965  val = b[p[i]];
1966  for (k = i+1; k < r; ++k)
1967  {
1968  assert( i <= s[k] && s[k] <= n );
1969  if ( A[p[i]][s[k]] != 0 )
1970  val = val ^ x[s[k]];
1971  }
1972 
1973  /* store solution */
1974  x[s[i]] = val;
1975  }
1976 }
1977 
1978 /** solve equation system over GF 2 by Gauss algorithm and create solution out of it or return cutoff
1979  *
1980  * Collect all information in xor constraints into a linear system over GF2. Then solve the system by computing a row
1981  * echolon form. If the system is infeasible, the current node is infeasible. Otherwise, we can compute a solution for
1982  * the xor constraints given. We check whether this gives a solution for the whole problem.
1983  *
1984  * We sort the columns with respect to the product of the objective coefficients and 1 minus the current LP solution
1985  * value. The idea is that columns that are likely to provide the steps in the row echolon form should appear towards
1986  * the front of the matrix. The smaller the product, the more it makes sense to set the variable to 1 (because the
1987  * solution value is already close to 1 and the objective function is small).
1988  *
1989  * Note that this function is called from propagation where usually no solution is available. However, the solution is
1990  * only used for sorting the columns. Thus, the procedure stays correct even with nonsense solutions.
1991  */
1992 static
1994  SCIP* scip, /**< SCIP data structure */
1995  SCIP_CONS** conss, /**< xor constraints */
1996  int nconss, /**< number of xor constraints */
1997  SCIP_SOL* currentsol, /**< current solution (maybe NULL) */
1998  SCIP_RESULT* result /**< result of propagation (possibly cutoff, no change if primal solution has been tried) */
1999  )
2000 {
2001  SCIP_CONSDATA* consdata;
2002  SCIP_HASHMAP* varhash;
2003  SCIP_Bool* xoractive;
2004  SCIP_Real* xorvals;
2005  SCIP_VAR** xorvars;
2006 #ifndef NDEBUG
2007  SCIP_Bool noaggr = TRUE;
2008 #endif
2009  Type** A;
2010  Type* b;
2011  int* s;
2012  int* p;
2013  int* xoridx;
2014  int* xorbackidx;
2015  int nconssactive = 0;
2016  int nconssmat = 0;
2017  int nvarsmat = 0;
2018  int nvars;
2019  int rank;
2020  int i;
2021  int j;
2022 
2023  assert( scip != NULL );
2024  assert( conss != NULL );
2025  assert( result != NULL );
2026 
2027  if ( *result == SCIP_CUTOFF )
2028  return SCIP_OKAY;
2029 
2030  SCIPdebugMessage("Checking feasibility via the linear equation system over GF2 using Gauss.\n");
2031 
2032  nvars = SCIPgetNVars(scip);
2033 
2034  /* set up hash map from variable to column index */
2035  SCIP_CALL( SCIPhashmapCreate(&varhash, SCIPblkmem(scip), SCIPcalcHashtableSize(10 * nvars)) );
2036  SCIP_CALL( SCIPallocBufferArray(scip, &xoractive, nconss) );
2037  SCIP_CALL( SCIPallocBufferArray(scip, &xorvars, nvars) );
2038  SCIP_CALL( SCIPallocBufferArray(scip, &xoridx, nvars) );
2039  SCIP_CALL( SCIPallocBufferArray(scip, &xorvals, nvars) );
2040 
2041  /* collect variables */
2042  for (i = 0; i < nconss; ++i)
2043  {
2044  int cnt = 0;
2045 
2046  xoractive[i] = FALSE;
2047 
2048  assert( conss[i] != NULL );
2049  consdata = SCIPconsGetData(conss[i]);
2050  assert( consdata != NULL );
2051 
2052  /* count nonfixed variables in constraint */
2053  for (j = 0; j < consdata->nvars; ++j)
2054  {
2055  SCIP_VAR* var;
2056 
2057  var = consdata->vars[j];
2058  assert( var != NULL );
2059  assert( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY );
2060 
2061  /* replace negated variables */
2062  if ( SCIPvarIsNegated(var) )
2063  var = SCIPvarGetNegatedVar(var);
2064  assert( var != NULL );
2065 
2066  /* consider nonfixed variables */
2067  if ( SCIPcomputeVarLbLocal(scip, var) < 0.5 && SCIPcomputeVarUbLocal(scip, var) > 0.5 )
2068  {
2069  /* consider active variables and collect only new ones */
2070  if ( SCIPvarIsActive(var) && ! SCIPhashmapExists(varhash, var) )
2071  {
2072  /* add variable in map */
2073  SCIP_CALL( SCIPhashmapInsert(varhash, var, (void*) (size_t) nvarsmat) );
2074  assert( nvarsmat == (int) (size_t) SCIPhashmapGetImage(varhash, var) );
2075  xorvals[nvarsmat] = SCIPvarGetObj(var) * (1.0 - SCIPgetSolVal(scip, currentsol, var));
2076  xorvars[nvarsmat++] = var;
2077  }
2078  ++cnt;
2079  }
2080  }
2081 
2082  if ( cnt > 0 )
2083  {
2084  xoractive[i] = TRUE;
2085  ++nconssactive;
2086  }
2087 #ifdef SCIP_DISABLED_CODE
2088  /* The following can save time, if there are constraints with all variables fixed that are infeasible; this
2089  * should, however, be detected somewhere else, e.g., in propagateCons(). */
2090  else
2091  {
2092  /* all variables are fixed - check whether constraint is feasible (could be that the constraint is not propagated) */
2093  assert( cnt == 0 );
2094  for (j = 0; j < consdata->nvars; ++j)
2095  {
2096  /* count variables fixed to 1 */
2097  if ( SCIPcomputeVarLbLocal(scip, consdata->vars[j]) > 0.5 )
2098  ++cnt;
2099  else
2100  assert( SCIPcomputeVarUbLocal(scip, consdata->vars[j]) < 0.5 );
2101  }
2102  if ( ( cnt - consdata->rhs ) % 2 != 0 )
2103  {
2104  SCIPdebugMessage("constraint <%s> with all variables fixed is violated.\n", SCIPconsGetName(conss[i]));
2105  *result = SCIP_CUTOFF;
2106  break;
2107  }
2108  }
2109 #endif
2110  }
2111  assert( nvarsmat <= nvars );
2112  assert( nconssactive <= nconss );
2113 
2114  if ( nconssactive > MAXXORCONSSSYSTEM || nvarsmat > MAXXORVARSSYSTEM || *result == SCIP_CUTOFF )
2115  {
2116  SCIPdebugMessage("Skip checking the xor system over GF2 (%d conss, %d vars).\n", nconssactive, nvarsmat);
2117  SCIPfreeBufferArray(scip, &xorvals);
2118  SCIPfreeBufferArray(scip, &xoridx);
2119  SCIPfreeBufferArray(scip, &xorvars);
2120  SCIPfreeBufferArray(scip, &xoractive);
2121  SCIPhashmapFree(&varhash);
2122  return SCIP_OKAY;
2123  }
2124 
2125  /* init index */
2126  for (j = 0; j < nvarsmat; ++j)
2127  xoridx[j] = j;
2128 
2129  /* Sort variables non-decreasingly with respect to product of objective and 1 minus the current solution value: the
2130  * smaller the value the better it would be to set the variable to 1. This is more likely if the variable appears
2131  * towards the front of the matrix, because only the entries on the steps in the row echolon form will have the
2132  * chance to be nonzero.
2133  */
2134  SCIPsortRealIntPtr(xorvals, xoridx, (void**) xorvars, nvarsmat);
2135  SCIPfreeBufferArray(scip, &xorvals);
2136 
2137  /* build back index */
2138  SCIP_CALL( SCIPallocBufferArray(scip, &xorbackidx, nvarsmat) );
2139  for (j = 0; j < nvarsmat; ++j)
2140  {
2141  assert( 0 <= xoridx[j] && xoridx[j] < nvarsmat );
2142  xorbackidx[xoridx[j]] = j;
2143  }
2144 
2145  /* init matrix and rhs */
2146  SCIP_CALL( SCIPallocBufferArray(scip, &b, nconssactive) );
2147  SCIP_CALL( SCIPallocBufferArray(scip, &A, nconssactive) );
2148  for (i = 0; i < nconss; ++i)
2149  {
2150  if ( ! xoractive[i] )
2151  continue;
2152 
2153  assert( conss[i] != NULL );
2154  consdata = SCIPconsGetData(conss[i]);
2155  assert( consdata != NULL );
2156  assert( consdata->nvars > 0 );
2157 
2158  SCIP_CALL( SCIPallocBufferArray(scip, &(A[nconssmat]), nvarsmat) ); /*lint !e866*/
2159  BMSclearMemoryArray(A[nconssmat], nvarsmat); /*lint !e866*/
2160 
2161  /* correct rhs w.r.t. to fixed variables and count nonfixed variables in constraint */
2162  b[nconssmat] = (Type) consdata->rhs;
2163  for (j = 0; j < consdata->nvars; ++j)
2164  {
2165  SCIP_VAR* var;
2166  int idx;
2167 
2168  var = consdata->vars[j];
2169  assert( var != NULL );
2170 
2171  /* replace negated variables */
2172  if ( SCIPvarIsNegated(var) )
2173  {
2174  var = SCIPvarGetNegatedVar(var);
2175  assert( var != NULL );
2176  b[nconssmat] = ! b[nconssmat];
2177  }
2178 
2179  /* If the constraint contains (multi-)aggregated variables, the solution might not be valid, since the
2180  * implications are not represented in the matrix. */
2181 #ifndef NDEBUG
2183  noaggr = FALSE;
2184 #endif
2185  /** @todo possibly treat aggregated variables here */
2186 
2187  if ( SCIPcomputeVarLbLocal(scip, var) > 0.5 )
2188  {
2189  /* variable is fixed to 1, invert rhs */
2190  b[nconssmat] = ! b[nconssmat];
2191  assert( ! SCIPhashmapExists(varhash, var) );
2192  }
2193  else
2194  {
2195  if ( SCIPvarIsActive(var) && SCIPcomputeVarUbLocal(scip, var) > 0.5 )
2196  {
2197  assert( SCIPhashmapExists(varhash, var) );
2198  idx = (int) (size_t) SCIPhashmapGetImage(varhash, var);
2199  assert( idx < nvarsmat );
2200  assert( 0 <= xorbackidx[idx] && xorbackidx[idx] < nvarsmat );
2201  A[nconssmat][xorbackidx[idx]] = 1;
2202  }
2203  }
2204  }
2205  ++nconssmat;
2206  }
2207  SCIPdebugMessage("Found %d non-fixed variables in %d nonempty xor constraints.\n", nvarsmat, nconssmat);
2208  assert( nconssmat == nconssactive );
2209 
2210  /* perform Gauss algorithm */
2211  SCIP_CALL( SCIPallocBufferArray(scip, &p, nconssmat) );
2212  SCIP_CALL( SCIPallocBufferArray(scip, &s, nconssmat) );
2213 
2214 #ifdef SCIP_OUTPUT
2215  SCIPinfoMessage(scip, NULL, "Matrix before Gauss (size: %d x %d):\n", nconssmat, nvarsmat);
2216  for (i = 0; i < nconssmat; ++i)
2217  {
2218  for (j = 0; j < nvarsmat; ++j)
2219  SCIPinfoMessage(scip, NULL, "%d ", A[i][j]);
2220  SCIPinfoMessage(scip, NULL, " = %d\n", b[i]);
2221  }
2222  SCIPinfoMessage(scip, NULL, "\n");
2223 #endif
2224 
2225  rank = -1;
2226  if ( ! SCIPisStopped(scip) )
2227  {
2228  rank = computeRowEcholonGF2(scip, nconssmat, nvarsmat, p, s, A, b);
2229  assert( rank <= nconssmat && rank <= nvarsmat );
2230  }
2231 
2232  /* rank is < 0 if the solution process has been stopped */
2233  if ( rank >= 0 )
2234  {
2235 #ifdef SCIP_OUTPUT
2236  SCIPinfoMessage(scip, NULL, "Matrix after Gauss (rank: %d):\n", rank);
2237  for (i = 0; i < nconssmat; ++i)
2238  {
2239  for (j = 0; j < nvarsmat; ++j)
2240  SCIPinfoMessage(scip, NULL, "%d ", A[p[i]][j]);
2241  SCIPinfoMessage(scip, NULL, " = %d\n", b[p[i]]);
2242  }
2243  SCIPinfoMessage(scip, NULL, "\n");
2244 #endif
2245 
2246  /* check whether system is feasible */
2247  for (i = rank; i < nconssmat; ++i)
2248  {
2249  if ( b[p[i]] != 0 )
2250  break;
2251  }
2252  /* did not find nonzero entry in b -> equation system is feasible */
2253  if ( i >= nconssmat )
2254  {
2255  SCIP_HEUR* heurtrysol;
2256 
2257  SCIPdebugMessage("Found solution.\n");
2258 
2259  /* try solution */
2260  heurtrysol = SCIPfindHeur(scip, "trysol");
2261 
2262  if ( heurtrysol != NULL )
2263  {
2264  SCIP_Bool success;
2265  SCIP_VAR** vars;
2266  SCIP_SOL* sol;
2267  Type* x;
2268 
2269  /* construct solution */
2270  SCIP_CALL( SCIPallocBufferArray(scip, &x, nvarsmat) );
2271  solveRowEcholonGF2(nconssmat, nvarsmat, rank, p, s, A, b, x);
2272 
2273 #ifdef SCIP_OUTPUT
2274  SCIPinfoMessage(scip, NULL, "Solution:\n");
2275  for (j = 0; j < nvarsmat; ++j)
2276  SCIPinfoMessage(scip, NULL, "%d ", x[j]);
2277  SCIPinfoMessage(scip, NULL, "\n");
2278 #endif
2279 
2280  /* create solution */
2281  SCIP_CALL( SCIPcreateSol(scip, &sol, heurtrysol) );
2282 
2283  /* transfer solution */
2284  for (j = 0; j < nvarsmat; ++j)
2285  {
2286  if ( x[j] != 0 )
2287  {
2288  assert( (int) (size_t) SCIPhashmapGetImage(varhash, xorvars[j]) < nvars );
2289  assert( xorbackidx[(int) (size_t) SCIPhashmapGetImage(varhash, xorvars[j])] == j );
2290  assert( SCIPcomputeVarLbLocal(scip, xorvars[j]) < 0.5 );
2291  SCIP_CALL( SCIPsetSolVal(scip, sol, xorvars[j], 1.0) );
2292  }
2293  }
2294  SCIPfreeBufferArray(scip, &x);
2295 
2296  /* add *all* variables fixed to 1 */
2297  vars = SCIPgetVars(scip);
2298  for (j = 0; j < nvars; ++j)
2299  {
2300  if ( SCIPcomputeVarLbLocal(scip, vars[j]) > 0.5 )
2301  {
2302  SCIP_CALL( SCIPsetSolVal(scip, sol, vars[j], 1.0) );
2303  SCIPdebugMessage("Added fixed variable <%s>.\n", SCIPvarGetName(vars[j]));
2304  }
2305  }
2306 
2307  /* correct integral variables if necessary */
2308  for (i = 0; i < nconss; ++i)
2309  {
2310  consdata = SCIPconsGetData(conss[i]);
2311  assert(consdata != NULL);
2312 
2313  if ( xoractive[i] && consdata->intvar != NULL )
2314  {
2315  SCIP_Real val;
2316  int nones = 0;
2317 
2318  for (j = 0; j < consdata->nvars; ++j)
2319  {
2320  if ( SCIPgetSolVal(scip, sol, consdata->vars[j]) > 0.5 )
2321  ++nones;
2322  }
2323  /* if there are aggregated variables, the solution might not be feasible */
2324  assert( ! noaggr || nones % 2 == (int) consdata->rhs );
2325  if ( (unsigned int) nones != consdata->rhs )
2326  {
2327  val = (SCIP_Real) (nones - consdata->rhs)/2;
2328  if ( SCIPisGE(scip, val, SCIPvarGetLbGlobal(consdata->intvar)) && SCIPisLE(scip, val, SCIPvarGetUbGlobal(consdata->intvar)) )
2329  {
2330  SCIP_CALL( SCIPsetSolVal(scip, sol, consdata->intvar, val) );
2331  }
2332  }
2333  }
2334  }
2335  SCIPdebug( SCIP_CALL( SCIPprintSol(scip, sol, NULL, FALSE) ) );
2336 
2337  /* check feasibility of new solution and pass it to trysol heuristic */
2338  SCIP_CALL( SCIPcheckSol(scip, sol, FALSE, TRUE, TRUE, TRUE, &success) );
2339  if ( success )
2340  {
2341  SCIP_CALL( SCIPheurPassSolAddSol(scip, heurtrysol, sol) );
2342  SCIPdebugMessage("Creating solution was successful.\n");
2343  }
2344 #ifdef SCIP_DEBUG
2345  else
2346  {
2347  /* the solution might not be feasible, because of additional constraints */
2348  SCIPdebugMessage("Creating solution was not successful.\n");
2349  }
2350 #endif
2351  SCIP_CALL( SCIPfreeSol(scip, &sol) );
2352  }
2353  }
2354  else
2355  {
2356  *result = SCIP_CUTOFF;
2357  SCIPdebugMessage("System not feasible.\n");
2358  }
2359  }
2360 
2361  /* free storage */
2362  SCIPfreeBufferArray(scip, &s);
2363  SCIPfreeBufferArray(scip, &p);
2364  SCIPfreeBufferArray(scip, &xorbackidx);
2365  j = 0;
2366  for (i = 0; i < nconss; ++i)
2367  {
2368  consdata = SCIPconsGetData(conss[i]);
2369  assert(consdata != NULL);
2370 
2371  if ( consdata->nvars == 0 )
2372  continue;
2373 
2374  if( !xoractive[i] )
2375  continue;
2376 
2377  SCIPfreeBufferArray(scip, &(A[j++]));
2378  }
2379  SCIPfreeBufferArray(scip, &A);
2380  SCIPfreeBufferArray(scip, &b);
2381  SCIPfreeBufferArray(scip, &xoridx);
2382  SCIPfreeBufferArray(scip, &xorvars);
2383  SCIPfreeBufferArray(scip, &xoractive);
2384  SCIPhashmapFree(&varhash);
2385 
2386  return SCIP_OKAY;
2387 }
2388 
2389 /** for each variable in the xor constraint, add it to conflict set; for integral variable add corresponding bound */
2390 static
2392  SCIP* scip, /**< SCIP data structure */
2393  SCIP_CONS* cons, /**< constraint that inferred the bound change */
2394  SCIP_VAR* infervar, /**< variable that was deduced, or NULL (not equal to integral variable) */
2395  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
2396  PROPRULE proprule /**< propagation rule */
2397  )
2398 {
2399  SCIP_CONSDATA* consdata;
2400  SCIP_VAR** vars;
2401  int nvars;
2402  int i;
2403 
2404  assert( cons != NULL );
2405 
2406  consdata = SCIPconsGetData(cons);
2407  assert(consdata != NULL);
2408  vars = consdata->vars;
2409  nvars = consdata->nvars;
2410 
2411  switch( proprule )
2412  {
2413  case PROPRULE_0:
2414  assert( infervar == NULL || infervar == consdata->intvar );
2415 
2416  /* the integral variable was fixed, because all variables were fixed */
2417  for (i = 0; i < nvars; ++i)
2418  {
2419  assert( SCIPisEQ(scip, SCIPvarGetLbAtIndex(vars[i], bdchgidx, FALSE), SCIPvarGetUbAtIndex(vars[i], bdchgidx, FALSE)) );
2420  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
2421  }
2422  break;
2423 
2424  case PROPRULE_1:
2425  /* the variable was inferred, because all other variables were fixed */
2426  for (i = 0; i < nvars; ++i)
2427  {
2428  /* add variables that were fixed to 1 before */
2429  if ( SCIPvarGetLbAtIndex(vars[i], bdchgidx, FALSE) > 0.5 )
2430  {
2431  assert( SCIPvarGetLbAtIndex(vars[i], bdchgidx, TRUE) > 0.5 );
2432  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
2433  }
2434  /* add variables that were fixed to 0 */
2435  else if ( SCIPvarGetUbAtIndex(vars[i], bdchgidx, FALSE) < 0.5 )
2436  {
2437  assert( SCIPvarGetUbAtIndex(vars[i], bdchgidx, TRUE) < 0.5 );
2438  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
2439  }
2440  else
2441  {
2442  /* check changed variable (changed variable is 0 or 1 afterwards) */
2443  assert( vars[i] == infervar );
2444  }
2445  }
2446  break;
2447 
2448  case PROPRULE_INTLB:
2449  assert( consdata->intvar != NULL );
2450 
2451  if( infervar != consdata->intvar )
2452  {
2453  /* the variable was fixed, because of the lower bound of the integral variable */
2454  SCIP_CALL( SCIPaddConflictLb(scip, consdata->intvar, NULL) );
2455  }
2456  /* to many and the other fixed variables */
2457  for (i = 0; i < nvars; ++i)
2458  {
2459  /* add variables that were fixed to 0 */
2460  if ( SCIPvarGetUbAtIndex(vars[i], bdchgidx, FALSE) < 0.5 )
2461  {
2462  assert( SCIPvarGetUbAtIndex(vars[i], bdchgidx, TRUE) < 0.5 );
2463  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
2464  }
2465  }
2466  break;
2467 
2468  case PROPRULE_INTUB:
2469  assert( consdata->intvar != NULL );
2470 
2471  if( infervar != consdata->intvar )
2472  {
2473  /* the variable was fixed, because of upper bound of the integral variable and the other fixed variables */
2474  SCIP_CALL( SCIPaddConflictUb(scip, consdata->intvar, NULL) );
2475  }
2476  for (i = 0; i < nvars; ++i)
2477  {
2478  /* add variables that were fixed to 1 */
2479  if ( SCIPvarGetLbAtIndex(vars[i], bdchgidx, FALSE) > 0.5 )
2480  {
2481  assert( SCIPvarGetLbAtIndex(vars[i], bdchgidx, TRUE) > 0.5 );
2482  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
2483  }
2484  }
2485  break;
2486 
2487  case PROPRULE_INVALID:
2488  default:
2489  SCIPerrorMessage("invalid inference information %d in xor constraint <%s>\n", proprule, SCIPconsGetName(cons));
2490  SCIPABORT();
2491  return SCIP_INVALIDDATA; /*lint !e527*/
2492  }
2493 
2494  return SCIP_OKAY;
2495 }
2496 
2497 /** analyzes conflicting assignment on given constraint, and adds conflict constraint to problem */
2498 static
2500  SCIP* scip, /**< SCIP data structure */
2501  SCIP_CONS* cons, /**< xor constraint that detected the conflict */
2502  SCIP_VAR* infervar, /**< variable that was deduced, or NULL (not equal to integral variable) */
2503  PROPRULE proprule /**< propagation rule */
2504  )
2505 {
2506  /* conflict analysis can only be applied in solving stage and if it is applicable */
2508  return SCIP_OKAY;
2509 
2510  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
2512 
2513  /* add bound changes */
2514  SCIP_CALL( addConflictBounds(scip, cons, infervar, NULL, proprule) );
2515 
2516  /* analyze the conflict */
2517  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
2518 
2519  return SCIP_OKAY;
2520 }
2521 
2522 /** propagates constraint with the following rules:
2523  * (0) all variables are fixed => can fix integral variable
2524  * (1) all except one variable fixed => fix remaining variable and integral variable
2525  * (2) depending on the amount of fixed binary variables we can tighten the integral variable
2526  * (3) depending on the lower bound of the integral variable one can fix variables to 1
2527  * (4) depending on the upper bound of the integral variable one can fix variables to 0
2528  */
2529 static
2531  SCIP* scip, /**< SCIP data structure */
2532  SCIP_CONS* cons, /**< xor constraint to be processed */
2533  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2534  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2535  int* nfixedvars, /**< pointer to add up the number of fixed variables */
2536  int* nchgbds /**< pointer to add up the number of found domain reductions */
2537  )
2538 {
2539  SCIP_CONSDATA* consdata;
2540  SCIP_VAR** vars;
2541  SCIP_Bool infeasible;
2542  SCIP_Bool tightened;
2543  SCIP_Bool odd;
2544  int nvars;
2545  int nfixedones;
2546  int nfixedzeros;
2547  int watchedvar1;
2548  int watchedvar2;
2549  int i;
2550 
2551  assert(scip != NULL);
2552  assert(cons != NULL);
2553  assert(eventhdlr != NULL);
2554  assert(cutoff != NULL);
2555  assert(nfixedvars != NULL);
2556  assert(nchgbds != NULL);
2557 
2558  /* propagation can only be applied, if we know all operator variables */
2559  if( SCIPconsIsModifiable(cons) )
2560  return SCIP_OKAY;
2561 
2562  consdata = SCIPconsGetData(cons);
2563  assert(consdata != NULL);
2564 
2565  vars = consdata->vars;
2566  nvars = consdata->nvars;
2567 
2568  /* don't process the constraint, if the watched variables weren't fixed to any value since last propagation call */
2569  if( consdata->propagated )
2570  return SCIP_OKAY;
2571 
2572  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
2573  if( !SCIPinRepropagation(scip) )
2574  {
2575  SCIP_CALL( SCIPincConsAge(scip, cons) );
2576  }
2577 
2578  /* propagation cannot be applied, if we have at least two unfixed variables left;
2579  * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
2580  * if these ones get fixed
2581  */
2582  watchedvar1 = consdata->watchedvar1;
2583  watchedvar2 = consdata->watchedvar2;
2584 
2585  /* check, if watched variables are still unfixed */
2586  if( watchedvar1 != -1 )
2587  {
2588  if( SCIPvarGetLbLocal(vars[watchedvar1]) > 0.5 || SCIPvarGetUbLocal(vars[watchedvar1]) < 0.5 )
2589  watchedvar1 = -1;
2590  }
2591  if( watchedvar2 != -1 )
2592  {
2593  if( SCIPvarGetLbLocal(vars[watchedvar2]) > 0.5 || SCIPvarGetUbLocal(vars[watchedvar2]) < 0.5 )
2594  watchedvar2 = -1;
2595  }
2596 
2597  /* if only one watched variable is still unfixed, make it the first one */
2598  if( watchedvar1 == -1 )
2599  {
2600  watchedvar1 = watchedvar2;
2601  watchedvar2 = -1;
2602  }
2603  assert(watchedvar1 != -1 || watchedvar2 == -1);
2604 
2605  /* if the watched variables are invalid (fixed), find new ones if existing; count the parity */
2606  odd = consdata->rhs;
2607  nfixedones = 0;
2608  nfixedzeros = 0;
2609  if( watchedvar2 == -1 )
2610  {
2611  for( i = 0; i < nvars; ++i )
2612  {
2613  if( SCIPvarGetLbLocal(vars[i]) > 0.5 )
2614  {
2615  odd = !odd;
2616  ++nfixedones;
2617  }
2618  else if( SCIPvarGetUbLocal(vars[i]) > 0.5 )
2619  {
2620  if( watchedvar1 == -1 )
2621  {
2622  assert(watchedvar2 == -1);
2623  watchedvar1 = i;
2624  }
2625  else if( watchedvar1 != i )
2626  {
2627  watchedvar2 = i;
2628  break;
2629  }
2630  }
2631  else if ( SCIPvarGetUbLocal(vars[i]) < 0.5 )
2632  ++nfixedzeros;
2633  }
2634  }
2635  assert(watchedvar1 != -1 || watchedvar2 == -1);
2636 
2637  /* if all variables are fixed, we can decide the feasibility of the constraint */
2638  if( watchedvar1 == -1 )
2639  {
2640  assert(watchedvar2 == -1);
2641 
2642  if( odd )
2643  {
2644  SCIPdebugMessage("constraint <%s>: all vars fixed, constraint is infeasible\n", SCIPconsGetName(cons));
2645 
2646  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
2647  SCIP_CALL( analyzeConflict(scip, cons, NULL, PROPRULE_0) );
2648  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2649 
2650  *cutoff = TRUE;
2651  }
2652  else
2653  {
2654  /* fix integral variable if present */
2655  if ( consdata->intvar != NULL )
2656  {
2657  int fixval;
2658 
2659  assert( ! *cutoff );
2660  assert( (nfixedones - consdata->rhs) % 2 == 0 );
2661 
2662  fixval = (nfixedones - consdata->rhs)/2; /*lint !e713*/
2663 
2664  SCIPdebugMessage("fix integral variable <%s> to %d\n", SCIPvarGetName(consdata->intvar), fixval);
2665 
2666  /* check whether value to fix is outside bounds */
2667  if ( fixval + 0.5 < SCIPvarGetLbLocal(consdata->intvar) )
2668  {
2669  /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
2670  SCIPdebugMessage("node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
2671  fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
2672 
2673  SCIP_CALL( analyzeConflict(scip, cons, NULL, PROPRULE_INTLB) );
2674  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2675 
2676  *cutoff = TRUE;
2677  }
2678  else if ( fixval - 0.5 > SCIPvarGetUbLocal(consdata->intvar) )
2679  {
2680  /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
2681  SCIPdebugMessage("node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
2682  fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
2683 
2684  SCIP_CALL( analyzeConflict(scip, cons, NULL, PROPRULE_INTUB) );
2685  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2686 
2687  *cutoff = TRUE;
2688  }
2689  else
2690  {
2691  if ( ! SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->intvar), (SCIP_Real) fixval) )
2692  {
2693  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_0, FALSE, &infeasible, &tightened) );
2694  assert( tightened );
2695  assert( ! infeasible );
2696  }
2697 
2698  if ( ! SCIPisEQ(scip, SCIPvarGetUbLocal(consdata->intvar), (SCIP_Real) fixval) )
2699  {
2700  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_0, FALSE, &infeasible, &tightened) );
2701  assert( tightened );
2702  assert( ! infeasible );
2703  }
2704 
2705  ++(*nfixedvars);
2706  }
2707  }
2708  else
2709  {
2710  SCIPdebugMessage("constraint <%s>: all vars fixed, constraint is feasible\n", SCIPconsGetName(cons));
2711  }
2712  }
2713  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2714 
2715  return SCIP_OKAY;
2716  }
2717 
2718  /* if only one variable is not fixed, this variable can be deduced */
2719  if( watchedvar2 == -1 )
2720  {
2721  assert(watchedvar1 != -1);
2722 
2723  SCIPdebugMessage("constraint <%s>: only one unfixed variable -> fix <%s> to %u\n",
2724  SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]), odd);
2725 
2726  SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], odd, cons, (int)PROPRULE_1, &infeasible, &tightened) );
2727  assert(!infeasible);
2728  assert(tightened);
2729 
2730  (*nfixedvars)++;
2731 
2732  /* fix integral variable if present */
2733  if ( consdata->intvar != NULL )
2734  {
2735  int fixval;
2736 
2737  /* if variable has been fixed to 1, adjust number of fixed variables */
2738  if ( odd )
2739  ++nfixedones;
2740 
2741  assert( (nfixedones - consdata->rhs) % 2 == 0 );
2742 
2743  fixval = (nfixedones - consdata->rhs)/2; /*lint !e713*/
2744  SCIPdebugMessage("should fix integral variable <%s> to %d\n", SCIPvarGetName(consdata->intvar), fixval);
2745 
2746  /* check whether value to fix is outside bounds */
2747  if ( fixval + 0.5 < SCIPvarGetLbLocal(consdata->intvar) )
2748  {
2749  /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
2750  SCIPdebugMessage("node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
2751  fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
2752 
2753  SCIP_CALL( analyzeConflict(scip, cons, NULL, PROPRULE_INTLB) );
2754  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2755 
2756  *cutoff = TRUE;
2757  }
2758  else if ( fixval - 0.5 > SCIPvarGetUbLocal(consdata->intvar) )
2759  {
2760  /* cannot fix auxiliary variable (maybe it has been branched on): we are infeasible */
2761  SCIPdebugMessage("node infeasible: activity is %d, bounds of integral variable are [%g,%g]\n",
2762  fixval, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar));
2763 
2764  SCIP_CALL( analyzeConflict(scip, cons, NULL, PROPRULE_INTUB) );
2765  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2766 
2767  *cutoff = TRUE;
2768  }
2769  else
2770  {
2771  if( SCIPvarGetLbLocal(consdata->intvar) + 0.5 < (SCIP_Real) fixval )
2772  {
2773  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_1, TRUE, &infeasible, &tightened) );
2774  assert( tightened );
2775  assert( ! infeasible );
2776  }
2777 
2778  if( SCIPvarGetUbLocal(consdata->intvar) - 0.5 > (SCIP_Real) fixval )
2779  {
2780  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->intvar, (SCIP_Real) fixval, cons, (int)PROPRULE_1, TRUE, &infeasible, &tightened) );
2781  assert( tightened );
2782  assert( ! infeasible );
2783  }
2784  assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->intvar), SCIPvarGetUbLocal(consdata->intvar)));
2785 
2786  ++(*nfixedvars);
2787  }
2788  }
2789 
2790  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2791  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2792 
2793  return SCIP_OKAY;
2794  }
2795 
2796  /* propagate w.r.t. integral variable */
2797  if ( consdata->intvar != NULL )
2798  {
2799  SCIP_Real newlb;
2800  SCIP_Real newub;
2801  int nonesmin;
2802  int nonesmax;
2803 
2804  assert( nfixedones + nfixedzeros < nvars );
2805 
2806  assert( SCIPisFeasIntegral(scip, SCIPvarGetLbLocal(consdata->intvar)) );
2807  assert( SCIPisFeasIntegral(scip, SCIPvarGetUbLocal(consdata->intvar)) );
2808 
2809  nonesmin = 2 * (int)(SCIPvarGetLbLocal(consdata->intvar) + 0.5) + consdata->rhs; /*lint !e713*/
2810  nonesmax = 2 * (int)(SCIPvarGetUbLocal(consdata->intvar) + 0.5) + consdata->rhs; /*lint !e713*/
2811 
2812  /* the number of possible variables that can get value 1 is less than the minimum bound */
2813  if ( nvars - nfixedzeros < nonesmin )
2814  {
2815  SCIPdebugMessage("constraint <%s>: at most %d variables can take value 1, but there should be at least %d.\n", SCIPconsGetName(cons), nvars - nfixedones, nonesmin);
2816 
2817  SCIP_CALL( analyzeConflict(scip, cons, NULL, PROPRULE_INTLB) );
2818  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2819 
2820  *cutoff = TRUE;
2821 
2822  return SCIP_OKAY;
2823  }
2824 
2825  /* the number of variables that are fixed to 1 is larger than the maximum bound */
2826  if ( nfixedones > nonesmax )
2827  {
2828  SCIPdebugMessage("constraint <%s>: at least %d variables are fixed to 1, but there should be at most %d.\n", SCIPconsGetName(cons), nfixedones, nonesmax);
2829 
2830  SCIP_CALL( analyzeConflict(scip, cons, NULL, PROPRULE_INTUB) );
2831  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2832 
2833  *cutoff = TRUE;
2834 
2835  return SCIP_OKAY;
2836  }
2837 
2838  /* compute new bounds on the integral variable */
2839  newlb = (SCIP_Real)((nfixedones + 1 - consdata->rhs) / 2); /*lint !e653*/
2840  newub = (SCIP_Real)((nvars - nfixedzeros - consdata->rhs) / 2); /*lint !e653*/
2841 
2842  /* new lower bound is better */
2843  if( newlb > SCIPvarGetLbLocal(consdata->intvar) + 0.5 )
2844  {
2845  SCIPdebugMessage("constraint <%s>: propagated lower bound of integral variable <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->intvar), newlb);
2846  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->intvar, newlb, cons, (int)PROPRULE_INTUB, TRUE, &infeasible, &tightened) );
2847  assert(tightened);
2848  assert(!infeasible);
2849 
2850  ++(*nchgbds);
2851 
2852  nonesmin = 2 * (int)(SCIPvarGetLbLocal(consdata->intvar) + 0.5) + consdata->rhs; /*lint !e713*/
2853  }
2854 
2855  /* new upper bound is better */
2856  if( newub < SCIPvarGetUbLocal(consdata->intvar) - 0.5 )
2857  {
2858  SCIPdebugMessage("constraint <%s>: propagated upper bound of integral variable <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->intvar), newub);
2859  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->intvar, newub, cons, (int)PROPRULE_INTLB, TRUE, &infeasible, &tightened) );
2860  assert(tightened);
2861  assert(!infeasible);
2862 
2863  ++(*nchgbds);
2864 
2865  nonesmax = 2 * (int)(SCIPvarGetUbLocal(consdata->intvar) + 0.5) + consdata->rhs; /*lint !e713*/
2866  }
2867 
2868  assert(nvars - nfixedzeros >= nonesmin);
2869  assert(nfixedones <= nonesmax);
2870 
2871  /* the number of variables that are free or fixed to 1 is exactly the minimum required -> fix free variables to 1 */
2872  if ( nvars - nfixedzeros == nonesmin )
2873  {
2874  SCIPdebugMessage("constraint <%s>: fix %d free variables to 1 to reach lower bound of %d\n", SCIPconsGetName(cons), nvars - nfixedzeros - nfixedones, nonesmin);
2875 
2876  for (i = 0; i < nvars; ++i)
2877  {
2878  if ( SCIPvarGetLbLocal(vars[i]) < 0.5 && SCIPvarGetUbLocal(vars[i]) > 0.5 )
2879  {
2880  SCIP_CALL( SCIPinferBinvarCons(scip, vars[i], TRUE, cons, (int)PROPRULE_INTLB, &infeasible, &tightened) );
2881  assert( !infeasible );
2882  assert( tightened );
2883 
2884  ++(*nfixedvars);
2885  }
2886  }
2887  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2888  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2889 
2890  return SCIP_OKAY;
2891  }
2892 
2893  /* the number of variables that are fixed to 1 is exactly the maximum required -> fix free variables to 0 */
2894  if ( nfixedones == nonesmax )
2895  {
2896  SCIPdebugMessage("constraint <%s>: fix %d free variables to 0 to guarantee upper bound of %d\n", SCIPconsGetName(cons), nvars - nfixedzeros - nfixedones, nonesmax);
2897 
2898  for (i = 0; i < nvars; ++i)
2899  {
2900  if ( SCIPvarGetLbLocal(vars[i]) < 0.5 && SCIPvarGetUbLocal(vars[i]) > 0.5 )
2901  {
2902  SCIP_CALL( SCIPinferBinvarCons(scip, vars[i], FALSE, cons, (int)PROPRULE_INTUB, &infeasible, &tightened) );
2903  assert(!infeasible);
2904  assert(tightened);
2905  ++(*nfixedvars);
2906  }
2907  }
2908  SCIP_CALL( SCIPresetConsAge(scip, cons) );
2909  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2910 
2911  return SCIP_OKAY;
2912  }
2913  }
2914 
2915  /* switch to the new watched variables */
2916  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
2917 
2918  /* mark the constraint propagated */
2919  consdata->propagated = TRUE;
2920 
2921  return SCIP_OKAY;
2922 }
2923 
2924 /** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
2925  * propagation rules (see propagateCons())
2926  */
2927 static
2929  SCIP* scip, /**< SCIP data structure */
2930  SCIP_CONS* cons, /**< constraint that inferred the bound change */
2931  SCIP_VAR* infervar, /**< variable that was deduced */
2932  PROPRULE proprule, /**< propagation rule that deduced the value */
2933  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
2934  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
2935  )
2936 {
2937  assert(result != NULL);
2938 
2939  SCIPdebugMessage("resolving fixations according to rule %d\n", (int) proprule);
2940 
2941  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, proprule) );
2942  *result = SCIP_SUCCESS;
2943 
2944  return SCIP_OKAY;
2945 }
2946 
2947 /** try to use clique information to delete a part of the xor constraint or even fix variables */
2948 static
2950  SCIP* scip, /**< SCIP data structure */
2951  SCIP_CONS* cons, /**< constraint that inferred the bound change */
2952  int* nfixedvars, /**< pointer to add up the number of found domain reductions */
2953  int* nchgcoefs, /**< pointer to add up the number of deleted entries */
2954  int* ndelconss, /**< pointer to add up the number of deleted constraints */
2955  int* naddconss, /**< pointer to add up the number of added constraints */
2956  SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
2957  )
2958 {
2959  SCIP_CONSDATA* consdata;
2960  SCIP_VAR** vars;
2961  int nvars;
2962  SCIP_Bool breaked;
2963  SCIP_Bool restart;
2964  int posnotinclq1;
2965  int posnotinclq2;
2966  int v;
2967  int v1;
2968 
2969  assert(scip != NULL);
2970  assert(cons != NULL);
2971  assert(nfixedvars != NULL);
2972  assert(nchgcoefs != NULL);
2973  assert(ndelconss != NULL);
2974  assert(naddconss != NULL);
2975  assert(cutoff != NULL);
2976 
2977  /* propagation can only be applied, if we know all operator variables */
2978  if( SCIPconsIsModifiable(cons) )
2979  return SCIP_OKAY;
2980 
2981  consdata = SCIPconsGetData(cons);
2982  assert(consdata != NULL);
2983 
2984  vars = consdata->vars;
2985  nvars = consdata->nvars;
2986 
2987  if( nvars < 3 )
2988  return SCIP_OKAY;
2989 
2990 #if 0 /* try to evaluate if clique presolving should only be done multiple times when the constraint changed */
2991  if( !consdata->changed )
2992  return SCIP_OKAY;
2993 #endif
2994 
2995  /* @todo: if clique information would have saved the type of the clique, like <= 1, or == 1 we could do more
2996  * presolving like:
2997  *
2998  * (xor(x1,x2,x3,x4) = 1 and clique(x1,x2) == 1) => xor(x3,x4) = 0
2999  * (xor(x1,x2,x3,x4) = 1 and clique(x1,x2,x3) == 1) => (x4 = 0 and delete xor constraint)
3000  */
3001 
3002  /* 1. we have only clique information "<=", so we can check if all variables are in the same clique
3003  *
3004  * (xor(x1,x2,x3) = 1 and clique(x1,x2,x3) <= 1) => (add set-partioning constraint x1 + x2 + x3 = 1 and delete old
3005  * xor-constraint)
3006  *
3007  * (xor(x1,x2,x3) = 0 and clique(x1,x2,x3) <= 1) => (fix all variables x1 = x2 = x3 = 0 and delete old xor-
3008  * constraint)
3009  */
3010 
3011  /* 2. we have only clique information "<=", so we can check if all but one variable are in the same clique
3012  *
3013  * (xor(x1,x2,x3,x4) = 1 and clique(x1,x2,x3) <= 1) => (add set-partioning constraint x1 + x2 + x3 + x4 = 1 and
3014  * delete old xor constraint)
3015  *
3016  * (xor(x1,x2,x3,x4) = 0 and clique(x1,x2,x3) <= 1) => (add set-partioning constraint x1 + x2 + x3 + ~x4 = 1 and
3017  * delete old xor constraint)
3018  */
3019 
3020  posnotinclq1 = -1; /* index of variable that is possible not in the clique */
3021  posnotinclq2 = -1; /* index of variable that is possible not in the clique */
3022  breaked = FALSE;
3023  restart = FALSE;
3024 
3025  v = nvars - 2;
3026  while( v >= 0 )
3027  {
3028  assert(SCIPvarIsActive(vars[v]));
3029 
3030  if( posnotinclq1 == v )
3031  {
3032  --v;
3033  continue;
3034  }
3035 
3036  for( v1 = v+1; v1 < nvars; ++v1 )
3037  {
3038  if( posnotinclq1 == v1 )
3039  continue;
3040 
3041  if( !SCIPvarsHaveCommonClique(vars[v], TRUE, vars[v1], TRUE, TRUE) )
3042  {
3043  /* if the position of the variable which is not in the clique with all other variables is not yet
3044  * initialized, than do now, one of both variables does not fit
3045  */
3046  if( posnotinclq1 == -1 )
3047  {
3048  posnotinclq1 = v;
3049  posnotinclq2 = v1;
3050  }
3051  else
3052  {
3053  /* no clique with exactly nvars-1 variables */
3054  if( restart || (posnotinclq2 != v && posnotinclq2 != v1) )
3055  {
3056  breaked = TRUE;
3057  break;
3058  }
3059 
3060  /* check the second variables for not fitting into the clique of (nvars - 1) variables */
3061  posnotinclq1 = posnotinclq2;
3062  restart = TRUE;
3063  v = nvars - 1;
3064  }
3065 
3066  break;
3067  }
3068  else
3069  assert(vars[v] != vars[v1]);
3070  }
3071 
3072  if( breaked )
3073  break;
3074 
3075  --v;
3076  }
3077 
3078  /* at least nvars-1 variables are in one clique */
3079  if( !breaked )
3080  {
3081  /* all variables are in one clique, case 1 */
3082  if( posnotinclq1 == -1 )
3083  {
3084  /* all variables of xor constraints <%s> (with rhs == 1) are in one clique, so create a setpartitioning
3085  * constraint with all variables and delete this xor-constraint
3086  */
3087  if( consdata->rhs )
3088  {
3089  SCIP_CONS* newcons;
3090  char consname[SCIP_MAXSTRLEN];
3091 
3092  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_complete_clq", SCIPconsGetName(cons));
3093  SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, consname, nvars, vars,
3098 
3099  SCIP_CALL( SCIPaddCons(scip, newcons) );
3100  SCIPdebugMessage("added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
3101  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, newcons, NULL) ) );
3102  ++(*naddconss);
3103 
3104  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3105  }
3106  /* all variables of xor constraints <%s> (with rhs == 0) are in one clique, so fixed all variables to 0 */
3107  else
3108  {
3109  SCIP_Bool infeasible;
3110  SCIP_Bool fixed;
3111 
3112  SCIPdebugMessage("all variables of xor constraints <%s> are in one clique, so fixed all variables to 0\n",
3113  SCIPconsGetName(cons));
3114  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
3115 
3116  for( v = nvars - 1; v >= 0; --v )
3117  {
3118  SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, &infeasible, &fixed) );
3119 
3120  assert(infeasible || fixed);
3121 
3122  if( infeasible )
3123  {
3124  *cutoff = infeasible;
3125 
3126  return SCIP_OKAY;
3127  }
3128  else
3129  ++(*nfixedvars);
3130  }
3131 
3132  }
3133  }
3134  /* all but one variable are in one clique, case 2 */
3135  else
3136  {
3137  SCIP_CONS* newcons;
3138  char consname[SCIP_MAXSTRLEN];
3139 
3140  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_completed_clq", SCIPconsGetName(cons));
3141 
3142  /* complete clique by creating a set partioning constraint over all variables */
3143 
3144  /* if rhs == FALSE we need to exchange the variable not appaering in the clique with the negated variables */
3145  if( !consdata->rhs )
3146  {
3147  SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, consname, 0, NULL,
3152 
3153  for( v = 0; v < nvars; ++v )
3154  {
3155  if( v == posnotinclq1 )
3156  {
3157  SCIP_VAR* var;
3158 
3159  SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &var) );
3160  assert(var != NULL);
3161 
3162  SCIP_CALL( SCIPaddCoefSetppc(scip, newcons, var) );
3163  }
3164  else
3165  {
3166  SCIP_CALL( SCIPaddCoefSetppc(scip, newcons, vars[v]) );
3167  }
3168  }
3169  }
3170  /* if rhs == TRUE we can add all variables to the clique constraint directly */
3171  else
3172  {
3173  SCIP_CALL( SCIPcreateConsSetpart(scip, &newcons, consname, nvars, vars,
3178  }
3179 
3180  SCIP_CALL( SCIPaddCons(scip, newcons) );
3181  SCIPdebugMessage("added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
3182  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, newcons, NULL) ) );
3183  ++(*naddconss);
3184 
3185  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3186  }
3187 
3188  /* delete old redundant xor-constraint */
3189  SCIP_CALL( SCIPdelCons(scip, cons) );
3190  ++(*ndelconss);
3191  }
3192 
3193  return SCIP_OKAY;
3194 }
3195 
3196 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
3197  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
3198  */
3199 static
3201  SCIP* scip, /**< SCIP data structure */
3202  BMS_BLKMEM* blkmem, /**< block memory */
3203  SCIP_CONS** conss, /**< constraint set */
3204  int nconss, /**< number of constraints in constraint set */
3205  int* firstchange, /**< pointer to store first changed constraint */
3206  int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
3207  int* ndelconss, /**< pointer to count number of deleted constraints */
3208  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
3209 )
3210 {
3211  SCIP_HASHTABLE* hashtable;
3212  int hashtablesize;
3213  int c;
3214 
3215  assert(conss != NULL);
3216  assert(ndelconss != NULL);
3217 
3218  /* create a hash table for the constraint set */
3219  hashtablesize = SCIPcalcHashtableSize(10*nconss);
3220  hashtablesize = MAX(hashtablesize, HASHSIZE_XORCONS);
3221  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
3222  hashGetKeyXorcons, hashKeyEqXorcons, hashKeyValXorcons, (void*) scip) );
3223 
3224  /* check all constraints in the given set for redundancy */
3225  for( c = 0; c < nconss; ++c )
3226  {
3227  SCIP_CONS* cons0;
3228  SCIP_CONS* cons1;
3229  SCIP_CONSDATA* consdata0;
3230  SCIP_CONSHDLR* conshdlr;
3231  SCIP_CONSHDLRDATA* conshdlrdata;
3232 
3233  cons0 = conss[c];
3234 
3235  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
3236  continue;
3237 
3238  /* get constraint handler data */
3239  conshdlr = SCIPconsGetHdlr(cons0);
3240  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3241  assert(conshdlrdata != NULL);
3242 
3243  /* it can happen that during preprocessing some variables got aggregated and a constraint now has not active
3244  * variables inside so we need to remove them for sorting
3245  */
3246  /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
3247  * merge multiple entries of the same or negated variables
3248  */
3249  SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs) );
3250 
3251  consdata0 = SCIPconsGetData(cons0);
3252  /* sort the constraint */
3253  consdataSort(consdata0);
3254  assert(consdata0->sorted);
3255 
3256  /* get constraint from current hash table with same variables as cons0 */
3257  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
3258 
3259  if( cons1 != NULL )
3260  {
3261  SCIP_CONSDATA* consdata1;
3262 
3263  assert(SCIPconsIsActive(cons1));
3264  assert(!SCIPconsIsModifiable(cons1));
3265 
3266  consdata1 = SCIPconsGetData(cons1);
3267 
3268  assert(consdata0 != NULL && consdata1 != NULL);
3269  assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
3270 
3271  assert(consdata0->sorted && consdata1->sorted);
3272  assert(consdata0->vars[0] == consdata1->vars[0]);
3273 
3274  if( consdata0->rhs != consdata1->rhs )
3275  {
3276  *cutoff = TRUE;
3277  goto TERMINATE;
3278  }
3279 
3280  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3281  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
3282 
3283  /* delete consdel */
3284  SCIP_CALL( SCIPdelCons(scip, cons0) );
3285  (*ndelconss)++;
3286 
3287  /* update the first changed constraint to begin the next aggregation round with */
3288  if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
3289  *firstchange = SCIPconsGetPos(cons1);
3290 
3291  assert(SCIPconsIsActive(cons1));
3292  }
3293  else
3294  {
3295  /* no such constraint in current hash table: insert cons0 into hash table */
3296  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
3297  }
3298  }
3299 
3300  TERMINATE:
3301  /* free hash table */
3302  SCIPhashtableFree(&hashtable);
3303 
3304  return SCIP_OKAY;
3305 }
3306 
3307 /** compares constraint with all prior constraints for possible redundancy or aggregation,
3308  * and removes or changes constraint accordingly
3309  */
3310 static
3312  SCIP* scip, /**< SCIP data structure */
3313  SCIP_CONS** conss, /**< constraint set */
3314  int firstchange, /**< first constraint that changed since last pair preprocessing round */
3315  int chkind, /**< index of constraint to check against all prior indices upto startind */
3316  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
3317  int* nfixedvars, /**< pointer to add up the number of found domain reductions */
3318  int* naggrvars, /**< pointer to count number of aggregated variables */
3319  int* ndelconss, /**< pointer to count number of deleted constraints */
3320  int* nchgcoefs /**< pointer to add up the number of changed coefficients */
3321  )
3322 {
3323  SCIP_CONSHDLR* conshdlr;
3324  SCIP_CONSHDLRDATA* conshdlrdata;
3325  SCIP_CONS* cons0;
3326  SCIP_CONSDATA* consdata0;
3327  SCIP_Bool cons0changed;
3328  int c;
3329 
3330  assert(conss != NULL);
3331  assert(firstchange <= chkind);
3332  assert(cutoff != NULL);
3333  assert(nfixedvars != NULL);
3334  assert(naggrvars != NULL);
3335  assert(ndelconss != NULL);
3336  assert(nchgcoefs != NULL);
3337 
3338  /* get the constraint to be checked against all prior constraints */
3339  cons0 = conss[chkind];
3340  assert(SCIPconsIsActive(cons0));
3341  assert(!SCIPconsIsModifiable(cons0));
3342 
3343  consdata0 = SCIPconsGetData(cons0);
3344  assert(consdata0 != NULL);
3345  assert(consdata0->nvars >= 1);
3346 
3347  /* get constraint handler data */
3348  conshdlr = SCIPconsGetHdlr(cons0);
3349  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3350  assert(conshdlrdata != NULL);
3351 
3352  /* it can happen that during preprocessing some variables got aggregated and a constraint now has not active
3353  * variables inside so we need to remove them for sorting
3354  */
3355  /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
3356  * merge multiple entries of the same or negated variables
3357  */
3358  SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs) );
3359 
3360  /* sort cons0 */
3361  consdataSort(consdata0);
3362  assert(consdata0->sorted);
3363 
3364  /* check constraint against all prior constraints */
3365  cons0changed = consdata0->changed;
3366  consdata0->changed = FALSE;
3367  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && SCIPconsIsActive(cons0) && !SCIPisStopped(scip); ++c )
3368  {
3369  SCIP_CONS* cons1;
3370  SCIP_CONSDATA* consdata1;
3371  SCIP_VAR* singlevar0;
3372  SCIP_VAR* singlevar1;
3373  SCIP_Bool parity;
3374  SCIP_Bool cons0hastwoothervars;
3375  SCIP_Bool cons1hastwoothervars;
3376  SCIP_Bool aborted;
3377  SCIP_Bool infeasible;
3378  SCIP_Bool fixed;
3379  SCIP_Bool redundant;
3380  SCIP_Bool aggregated;
3381  int v0;
3382  int v1;
3383 
3384  cons1 = conss[c];
3385 
3386  /* ignore inactive and modifiable constraints */
3387  if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
3388  continue;
3389 
3390  consdata1 = SCIPconsGetData(cons1);
3391  assert(consdata1 != NULL);
3392 
3393  /* it can happen that during preprocessing some variables got aggregated and a constraint now has not active
3394  * variables inside so we need to remove them for sorting
3395  */
3396  /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
3397  * merge multiple entries of the same or negated variables
3398  */
3399  SCIP_CALL( applyFixings(scip, cons1, conshdlrdata->eventhdlr, nchgcoefs) );
3400  assert(consdata1 == SCIPconsGetData(cons1));
3401 
3402  SCIPdebugMessage("preprocess xor constraint pair <%s>[chg:%u] and <%s>[chg:%u]\n",
3403  SCIPconsGetName(cons0), cons0changed, SCIPconsGetName(cons1), consdata1->changed);
3404 
3405  /* if both constraints were not changed since last round, we can ignore the pair */
3406  if( !cons0changed && !consdata1->changed )
3407  continue;
3408 
3409  /* applyFixings() led to an empty constraint */
3410  if( consdata1->nvars == 0 )
3411  {
3412  if( consdata1->rhs )
3413  {
3414  *cutoff = TRUE;
3415  break;
3416  }
3417  else
3418  {
3419  /* delete empty constraint */
3420  SCIP_CALL( SCIPdelCons(scip, cons1) );
3421  ++(*ndelconss);
3422 
3423  continue;
3424  }
3425  }
3426  else if( consdata1->nvars == 1 )
3427  {
3428  /* fix remaining variable */
3429  SCIP_CALL( SCIPfixVar(scip, consdata1->vars[0], (SCIP_Real) consdata1->rhs, &infeasible, &fixed) );
3430  assert(!infeasible);
3431 
3432  if( fixed )
3433  ++(*nfixedvars);
3434 
3435  SCIP_CALL( SCIPdelCons(scip, cons1) );
3436  ++(*ndelconss);
3437 
3438  /* check for fixed variable in cons0 and remove it */
3439  SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs) );
3440 
3441  /* sort cons0 */
3442  consdataSort(consdata0);
3443  assert(consdata0->sorted);
3444 
3445  continue;
3446  }
3447  else if( consdata1->nvars == 2 )
3448  {
3449  if( !(consdata1->rhs) )
3450  {
3451  /* aggregate var0 == var1 */
3452  SCIP_CALL( SCIPaggregateVars(scip, consdata1->vars[0], consdata1->vars[1], 1.0, -1.0, 0.0,
3453  &infeasible, &redundant, &aggregated) );
3454  }
3455  else
3456  {
3457  /* aggregate var0 == 1 - var1 */
3458  SCIP_CALL( SCIPaggregateVars(scip, consdata1->vars[0], consdata1->vars[1], 1.0, 1.0, 1.0,
3459  &infeasible, &redundant, &aggregated) );
3460  }
3461  assert(!infeasible);
3462  assert(redundant || SCIPdoNotAggr(scip));
3463 
3464  if( aggregated )
3465  {
3466  ++(*naggrvars);
3467 
3468  /* check for aggregated variable in cons0 and remove it */
3469  SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs) );
3470 
3471  /* sort cons0 */
3472  consdataSort(consdata0);
3473  assert(consdata0->sorted);
3474  }
3475 
3476  if( redundant )
3477  {
3478  SCIP_CALL( SCIPdelCons(scip, cons1) );
3479  ++(*ndelconss);
3480  }
3481 
3482  continue;
3483  }
3484  assert(consdata0->sorted);
3485 
3486  /* sort cons1 */
3487  consdataSort(consdata1);
3488  assert(consdata1->sorted);
3489 
3490  /* check whether
3491  * (a) one problem variable set is a subset of the other, or
3492  * (b) the problem variable sets are almost equal with only one variable in each constraint that is not
3493  * member of the other
3494  */
3495  aborted = FALSE;
3496  parity = (consdata0->rhs ^ consdata1->rhs);
3497  cons0hastwoothervars = FALSE;
3498  cons1hastwoothervars = FALSE;
3499  singlevar0 = NULL;
3500  singlevar1 = NULL;
3501  v0 = 0;
3502  v1 = 0;
3503  while( (v0 < consdata0->nvars || v1 < consdata1->nvars) && !aborted )
3504  {
3505  int cmp;
3506 
3507  assert(v0 <= consdata0->nvars);
3508  assert(v1 <= consdata1->nvars);
3509 
3510  if( v0 == consdata0->nvars )
3511  cmp = +1;
3512  else if( v1 == consdata1->nvars )
3513  cmp = -1;
3514  else
3515  cmp = SCIPvarCompareActiveAndNegated(consdata0->vars[v0], consdata1->vars[v1]);
3516 
3517  switch( cmp )
3518  {
3519  case -1:
3520  /* variable doesn't appear in cons1 */
3521  assert(v0 < consdata0->nvars);
3522  if( singlevar0 == NULL )
3523  {
3524  singlevar0 = consdata0->vars[v0];
3525  if( cons1hastwoothervars )
3526  aborted = TRUE;
3527  }
3528  else
3529  {
3530  cons0hastwoothervars = TRUE;
3531  if( singlevar1 != NULL )
3532  aborted = TRUE;
3533  }
3534  v0++;
3535  break;
3536 
3537  case +1:
3538  /* variable doesn't appear in cons0 */
3539  assert(v1 < consdata1->nvars);
3540  if( singlevar1 == NULL )
3541  {
3542  singlevar1 = consdata1->vars[v1];
3543  if( cons0hastwoothervars )
3544  aborted = TRUE;
3545  }
3546  else
3547  {
3548  cons1hastwoothervars = TRUE;
3549  if( singlevar0 != NULL )
3550  aborted = TRUE;
3551  }
3552  v1++;
3553  break;
3554 
3555  case 0:
3556  /* variable appears in both constraints */
3557  assert(v0 < consdata0->nvars);
3558  assert(v1 < consdata1->nvars);
3559  assert(SCIPvarGetProbvar(consdata0->vars[v0]) == SCIPvarGetProbvar(consdata1->vars[v1]));
3560  if( consdata0->vars[v0] != consdata1->vars[v1] )
3561  {
3562  assert(SCIPvarGetNegatedVar(consdata0->vars[v0]) == consdata1->vars[v1]);
3563  parity = !parity;
3564  }
3565  v0++;
3566  v1++;
3567  break;
3568 
3569  default:
3570  SCIPerrorMessage("invalid comparison result\n");
3571  SCIPABORT();
3572  return SCIP_INVALIDDATA; /*lint !e527*/
3573  }
3574  }
3575 
3576  /* check if a useful presolving is possible */
3577  if( (cons0hastwoothervars && singlevar1 != NULL) || (cons1hastwoothervars && singlevar0 != NULL) )
3578  continue;
3579 
3580  /* check if one problem variable set is a subset of the other */
3581  if( singlevar0 == NULL && singlevar1 == NULL )
3582  {
3583  /* both constraints are equal */
3584  if( !parity )
3585  {
3586  /* even parity: constraints are redundant */
3587  SCIPdebugMessage("xor constraints <%s> and <%s> are redundant: delete <%s>\n",
3588  SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPconsGetName(cons1));
3589  SCIPdebugPrintCons(scip, cons0, NULL);
3590  SCIPdebugPrintCons(scip, cons1, NULL);
3591  SCIP_CALL( SCIPdelCons(scip, cons1) );
3592  (*ndelconss)++;
3593  }
3594  else
3595  {
3596  /* odd parity: constraints are contradicting */
3597  SCIPdebugMessage("xor constraints <%s> and <%s> are contradicting\n",
3598  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
3599  SCIPdebugPrintCons(scip, cons0, NULL);
3600  SCIPdebugPrintCons(scip, cons1, NULL);
3601  *cutoff = TRUE;
3602  }
3603  }
3604  else if( singlevar1 == NULL )
3605  {
3606  /* cons1 is a subset of cons0 */
3607  if( !cons0hastwoothervars )
3608  {
3609  /* only one additional variable in cons0: fix this variable according to the parity */
3610  SCIPdebugMessage("xor constraints <%s> and <%s> yield sum %u == <%s>\n",
3611  SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity, SCIPvarGetName(singlevar0));
3612  SCIPdebugPrintCons(scip, cons0, NULL);
3613  SCIPdebugPrintCons(scip, cons1, NULL);
3614  SCIP_CALL( SCIPfixVar(scip, singlevar0, parity ? 1.0 : 0.0, &infeasible, &fixed) );
3615  *cutoff = *cutoff || infeasible;
3616  if ( fixed )
3617  (*nfixedvars)++;
3618  SCIP_CALL( SCIPdelCons(scip, cons1) );
3619  (*ndelconss)++;
3620  }
3621  else
3622  {
3623  int v;
3624 
3625  /* more than one additional variable in cons0: add cons1 to cons0, thus eliminating the equal variables */
3626  SCIPdebugMessage("xor constraint <%s> is superset of <%s> with parity %u\n",
3627  SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity);
3628  SCIPdebugPrintCons(scip, cons0, NULL);
3629  SCIPdebugPrintCons(scip, cons1, NULL);
3630  for( v = 0; v < consdata1->nvars; ++v )
3631  {
3632  SCIP_CALL( addCoef(scip, cons0, conshdlrdata->eventhdlr, consdata1->vars[v]) );
3633  }
3634  SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs) );
3635  assert(SCIPconsGetData(cons0) == consdata0);
3636  assert(consdata0->nvars >= 2); /* at least the two "other" variables should remain in the constraint */
3637 
3638  consdataSort(consdata0);
3639  assert(consdata0->sorted);
3640  }
3641  }
3642  else if( singlevar0 == NULL )
3643  {
3644  /* cons0 is a subset of cons1 */
3645  if( !cons1hastwoothervars )
3646  {
3647  /* only one additional variable in cons1: fix this variable according to the parity */
3648  SCIPdebugMessage("xor constraints <%s> and <%s> yield sum %u == <%s>\n",
3649  SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity, SCIPvarGetName(singlevar1));
3650  SCIPdebugPrintCons(scip, cons0, NULL);
3651  SCIPdebugPrintCons(scip, cons1, NULL);
3652  SCIP_CALL( SCIPfixVar(scip, singlevar1, parity ? 1.0 : 0.0, &infeasible, &fixed) );
3653  assert(infeasible || fixed);
3654  *cutoff = *cutoff || infeasible;
3655  (*nfixedvars)++;
3656  SCIP_CALL( SCIPdelCons(scip, cons1) );
3657  (*ndelconss)++;
3658  }
3659  else
3660  {
3661  int v;
3662 
3663  /* more than one additional variable in cons1: add cons0 to cons1, thus eliminating the equal variables */
3664  SCIPdebugMessage("xor constraint <%s> is subset of <%s> with parity %u\n",
3665  SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity);
3666  SCIPdebugPrintCons(scip, cons0, NULL);
3667  SCIPdebugPrintCons(scip, cons1, NULL);
3668  for( v = 0; v < consdata0->nvars; ++v )
3669  {
3670  SCIP_CALL( addCoef(scip, cons1, conshdlrdata->eventhdlr, consdata0->vars[v]) );
3671  }
3672  SCIP_CALL( applyFixings(scip, cons1, conshdlrdata->eventhdlr, nchgcoefs) );
3673  assert(SCIPconsGetData(cons1) == consdata1);
3674  assert(consdata1->nvars >= 2); /* at least the two "other" variables should remain in the constraint */
3675 
3676  consdataSort(consdata1);
3677  assert(consdata1->sorted);
3678  }
3679  }
3680  else
3681  {
3682  assert(!cons0hastwoothervars);
3683  assert(!cons1hastwoothervars);
3684 
3685  /* sum of constraints is parity == singlevar0 xor singlevar1: aggregate variables and delete cons1 */
3686  SCIPdebugMessage("xor constraints <%s> and <%s> yield sum %u == xor(<%s>,<%s>)\n",
3687  SCIPconsGetName(cons0), SCIPconsGetName(cons1), parity, SCIPvarGetName(singlevar0),
3688  SCIPvarGetName(singlevar1));
3689  if( !parity )
3690  {
3691  /* aggregate singlevar0 == singlevar1 */
3692  SCIP_CALL( SCIPaggregateVars(scip, singlevar1, singlevar0, 1.0, -1.0, 0.0,
3693  &infeasible, &redundant, &aggregated) );
3694  }
3695  else
3696  {
3697  /* aggregate singlevar0 == 1-singlevar1 */
3698  SCIP_CALL( SCIPaggregateVars(scip, singlevar1, singlevar0, 1.0, 1.0, 1.0,
3699  &infeasible, &redundant, &aggregated) );
3700  }
3701  assert(infeasible || redundant || SCIPdoNotAggr(scip));
3702 
3703  *cutoff = *cutoff || infeasible;
3704  if( aggregated )
3705  (*naggrvars)++;
3706 
3707  if( redundant )
3708  {
3709  SCIP_CALL( SCIPdelCons(scip, cons1) );
3710  (*ndelconss)++;
3711  }
3712 #if 0
3713  /* if aggregation in the core of SCIP is not changed we do not need to call applyFixing, this would be the correct
3714  * way
3715  */
3716  /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
3717  * merge multiple entries of the same or negated variables
3718  */
3719  SCIP_CALL( applyFixings(scip, cons0, conshdlrdata->eventhdlr, nchgcoefs) );
3720 #endif
3721 
3722  }
3723  }
3724 
3725  return SCIP_OKAY;
3726 }
3727 
3728 /** creates and captures a xor constraint x_0 xor ... xor x_{k-1} = rhs with a given artificial integer variable for the
3729  * linear relaxation
3730  *
3731  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3732  */
3733 static
3735  SCIP* scip, /**< SCIP data structure */
3736  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3737  const char* name, /**< name of constraint */
3738  SCIP_Bool rhs, /**< right hand side of the constraint */
3739  int nvars, /**< number of operator variables in the constraint */
3740  SCIP_VAR** vars, /**< array with operator variables of constraint */
3741  SCIP_VAR* intvar, /**< artificial integer variable for linear relaxation */
3742  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3743  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3744  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3745  * Usually set to TRUE. */
3746  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3747  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3748  SCIP_Bool check, /**< should the constraint be checked for feasibility?
3749  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3750  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3751  * Usually set to TRUE. */
3752  SCIP_Bool local, /**< is constraint only valid locally?
3753  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3754  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3755  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3756  * adds coefficients to this constraint. */
3757  SCIP_Bool dynamic, /**< is constraint subject to aging?
3758  * Usually set to FALSE. Set to TRUE for own cuts which
3759  * are separated as constraints. */
3760  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3761  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3762  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3763  * if it may be moved to a more global node?
3764  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3765  )
3766 {
3767  SCIP_CONSHDLR* conshdlr;
3768  SCIP_CONSDATA* consdata;
3769 
3770  /* find the xor constraint handler */
3771  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3772  if( conshdlr == NULL )
3773  {
3774  SCIPerrorMessage("xor constraint handler not found\n");
3775  return SCIP_PLUGINNOTFOUND;
3776  }
3777 
3778  /* create constraint data */
3779  SCIP_CALL( consdataCreate(scip, &consdata, rhs, nvars, vars, intvar) );
3780 
3781  /* create constraint */
3782  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3783  local, modifiable, dynamic, removable, stickingatnode) );
3784 
3785  return SCIP_OKAY;
3786 }
3787 
3788 
3789 /*
3790  * Callback methods of constraint handler
3791  */
3792 
3793 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
3794 static
3795 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyXor)
3796 { /*lint --e{715}*/
3797  assert(scip != NULL);
3798  assert(conshdlr != NULL);
3799  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3800 
3801  /* call inclusion method of constraint handler */
3803 
3804  *valid = TRUE;
3805 
3806  return SCIP_OKAY;
3807 }
3808 
3809 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
3810 static
3811 SCIP_DECL_CONSFREE(consFreeXor)
3812 { /*lint --e{715}*/
3813  SCIP_CONSHDLRDATA* conshdlrdata;
3814 
3815  /* free constraint handler data */
3816  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3817  assert(conshdlrdata != NULL);
3818 
3819  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
3820 
3821  SCIPconshdlrSetData(conshdlr, NULL);
3822 
3823  return SCIP_OKAY;
3824 }
3825 
3826 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
3827 static
3828 SCIP_DECL_CONSEXITSOL(consExitsolXor)
3829 { /*lint --e{715}*/
3830  SCIP_CONSDATA* consdata;
3831  int c;
3832 
3833  /* release and free the rows of all constraints */
3834  for( c = 0; c < nconss; ++c )
3835  {
3836  consdata = SCIPconsGetData(conss[c]);
3837  SCIP_CALL( consdataFreeRows(scip, consdata) );
3838  }
3839 
3840  return SCIP_OKAY;
3841 }
3842 
3843 
3844 /** frees specific constraint data */
3845 static
3846 SCIP_DECL_CONSDELETE(consDeleteXor)
3847 { /*lint --e{715}*/
3848  SCIP_CONSHDLRDATA* conshdlrdata;
3849 
3850  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3851  assert(conshdlrdata != NULL);
3852 
3853  SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
3854 
3855  return SCIP_OKAY;
3856 }
3857 
3858 
3859 /** transforms constraint data into data belonging to the transformed problem */
3860 static
3861 SCIP_DECL_CONSTRANS(consTransXor)
3862 { /*lint --e{715}*/
3863  SCIP_CONSDATA* sourcedata;
3864  SCIP_CONSDATA* targetdata;
3865 
3866  sourcedata = SCIPconsGetData(sourcecons);
3867  assert(sourcedata != NULL);
3868  assert(sourcedata->nvars >= 1);
3869  assert(sourcedata->vars != NULL);
3870 
3871  /* create target constraint data */
3872  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->rhs, sourcedata->nvars, sourcedata->vars, sourcedata->intvar) );
3873 
3874  /* create target constraint */
3875  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
3876  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
3877  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
3878  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
3879  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
3880 
3881  return SCIP_OKAY;
3882 }
3883 
3884 
3885 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
3886 static
3887 SCIP_DECL_CONSINITLP(consInitlpXor)
3888 { /*lint --e{715}*/
3889  int i;
3890 
3891  for( i = 0; i < nconss; i++ )
3892  {
3893  assert(SCIPconsIsInitial(conss[i]));
3894  SCIP_CALL( addRelaxation(scip, conss[i]) );
3895  }
3896 
3897  return SCIP_OKAY;
3898 }
3899 
3900 
3901 /** separation method of constraint handler for LP solutions */
3902 static
3903 SCIP_DECL_CONSSEPALP(consSepalpXor)
3904 { /*lint --e{715}*/
3905  SCIP_CONSHDLRDATA* conshdlrdata;
3906  SCIP_Bool separated;
3907  SCIP_Bool cutoff;
3908  int c;
3909 
3910  *result = SCIP_DIDNOTFIND;
3911 
3912  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3913  assert( conshdlrdata != NULL );
3914 
3915  /* separate all useful constraints */
3916  for( c = 0; c < nusefulconss; ++c )
3917  {
3918  SCIP_CALL( separateCons(scip, conss[c], NULL, conshdlrdata->separateparity, &separated, &cutoff) );
3919  if ( cutoff )
3920  *result = SCIP_CUTOFF;
3921  else if ( separated )
3922  *result = SCIP_SEPARATED;
3923  }
3924 
3925  /* combine constraints to get more cuts */
3926  /**@todo combine constraints to get further cuts */
3927 
3928  return SCIP_OKAY;
3929 }
3930 
3931 
3932 /** separation method of constraint handler for arbitrary primal solutions */
3933 static
3934 SCIP_DECL_CONSSEPASOL(consSepasolXor)
3935 { /*lint --e{715}*/
3936  SCIP_CONSHDLRDATA* conshdlrdata;
3937  SCIP_Bool separated;
3938  SCIP_Bool cutoff;
3939  int c;
3940 
3941  *result = SCIP_DIDNOTFIND;
3942 
3943  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3944  assert( conshdlrdata != NULL );
3945 
3946  /* separate all useful constraints */
3947  for( c = 0; c < nusefulconss; ++c )
3948  {
3949  SCIP_CALL( separateCons(scip, conss[c], sol, conshdlrdata->separateparity, &separated, &cutoff) );
3950  if ( cutoff )
3951  *result = SCIP_CUTOFF;
3952  else if ( separated )
3953  *result = SCIP_SEPARATED;
3954  }
3955 
3956  /* combine constraints to get more cuts */
3957  /**@todo combine constraints to get further cuts */
3958 
3959  return SCIP_OKAY;
3960 }
3961 
3962 
3963 /** constraint enforcing method of constraint handler for LP solutions */
3964 static
3965 SCIP_DECL_CONSENFOLP(consEnfolpXor)
3966 { /*lint --e{715}*/
3967  SCIP_CONSHDLRDATA* conshdlrdata;
3968  SCIP_Bool violated;
3969  SCIP_Bool cutoff;
3970  int i;
3971 
3972  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3973  assert( conshdlrdata != NULL );
3974 
3975  /* method is called only for integral solutions, because the enforcing priority is negative */
3976  for( i = 0; i < nconss; i++ )
3977  {
3978  SCIP_CALL( checkCons(scip, conss[i], NULL, FALSE, &violated) );
3979  if( violated )
3980  {
3981  SCIP_Bool separated;
3982 
3983  SCIP_CALL( separateCons(scip, conss[i], NULL, conshdlrdata->separateparity, &separated, &cutoff) );
3984  if ( cutoff )
3985  *result = SCIP_CUTOFF;
3986  else
3987  {
3988  assert(separated); /* because the solution is integral, the separation always finds a cut */
3989  *result = SCIP_SEPARATED;
3990  }
3991  return SCIP_OKAY;
3992  }
3993  }
3994  *result = SCIP_FEASIBLE;
3995 
3996  return SCIP_OKAY;
3997 }
3998 
3999 
4000 /** constraint enforcing method of constraint handler for pseudo solutions */
4001 static
4002 SCIP_DECL_CONSENFOPS(consEnfopsXor)
4003 { /*lint --e{715}*/
4004  SCIP_Bool violated;
4005  int i;
4006 
4007  /* method is called only for integral solutions, because the enforcing priority is negative */
4008  for( i = 0; i < nconss; i++ )
4009  {
4010  SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, &violated) );
4011  if( violated )
4012  {
4013  *result = SCIP_INFEASIBLE;
4014  return SCIP_OKAY;
4015  }
4016  }
4017  *result = SCIP_FEASIBLE;
4018 
4019  return SCIP_OKAY;
4020 }
4021 
4022 
4023 /** feasibility check method of constraint handler for integral solutions */
4024 static
4025 SCIP_DECL_CONSCHECK(consCheckXor)
4026 { /*lint --e{715}*/
4027  SCIP_Bool violated;
4028  int i;
4029 
4030  /* method is called only for integral solutions, because the enforcing priority is negative */
4031  for( i = 0; i < nconss; i++ )
4032  {
4033  SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, &violated) );
4034  if( violated )
4035  {
4036  *result = SCIP_INFEASIBLE;
4037 
4038  if( printreason )
4039  {
4040  int v;
4041  int sum = 0;
4042  SCIP_CONSDATA* consdata;
4043 
4044  consdata = SCIPconsGetData(conss[i]);
4045  assert( consdata != NULL );
4046 
4047  SCIP_CALL( SCIPprintCons(scip, conss[i], NULL) );
4048 
4049  for( v = 0; v < consdata->nvars; ++v )
4050  {
4051  if( SCIPgetSolVal(scip, sol, consdata->vars[v]) > 0.5 )
4052  sum++;
4053  }
4054  SCIPinfoMessage(scip, NULL, ";\nviolation: %d operands are set to TRUE\n", sum );
4055  }
4056 
4057  return SCIP_OKAY;
4058  }
4059  }
4060  *result = SCIP_FEASIBLE;
4061 
4062  return SCIP_OKAY;
4063 }
4064 
4065 
4066 /** domain propagation method of constraint handler */
4067 static
4068 SCIP_DECL_CONSPROP(consPropXor)
4069 { /*lint --e{715}*/
4070  SCIP_CONSHDLRDATA* conshdlrdata;
4071  SCIP_Bool cutoff;
4072  int nfixedvars;
4073  int nchgbds;
4074  int c;
4075 
4076  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4077  assert(conshdlrdata != NULL);
4078 
4079  cutoff = FALSE;
4080  nfixedvars = 0;
4081  nchgbds = 0;
4082 
4083  /* propagate all useful constraints */
4084  for( c = 0; c < nusefulconss && !cutoff; ++c )
4085  {
4086  SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars, &nchgbds) );
4087  }
4088 
4089  /* return the correct result */
4090  if( cutoff )
4091  *result = SCIP_CUTOFF;
4092  else if( nfixedvars > 0 || nchgbds > 0 )
4093  *result = SCIP_REDUCEDDOM;
4094  else
4095  {
4096  *result = SCIP_DIDNOTFIND;
4097  if ( ! SCIPinProbing(scip) )
4098  {
4099  int depth;
4100  int freq;
4101 
4102  depth = SCIPgetDepth(scip);
4103  freq = conshdlrdata->gausspropfreq;
4104  if ( (depth == 0 && freq == 0) || (freq > 0 && depth % freq == 0) )
4105  {
4106  /* take usefull constraints only - might improve success rate to take all */
4107  SCIP_CALL( checkSystemGF2(scip, conss, nusefulconss, NULL, result) );
4108  }
4109  }
4110  }
4111 
4112  return SCIP_OKAY;
4113 }
4114 
4115 
4116 /** presolving method of constraint handler */
4117 static
4118 SCIP_DECL_CONSPRESOL(consPresolXor)
4119 { /*lint --e{715}*/
4120  SCIP_CONSHDLRDATA* conshdlrdata;
4121  SCIP_CONS* cons;
4122  SCIP_CONSDATA* consdata;
4123  SCIP_Bool cutoff;
4124  SCIP_Bool delay;
4125  SCIP_Bool redundant;
4126  SCIP_Bool aggregated;
4127  int oldnfixedvars;
4128  int oldnchgbds;
4129  int oldnaggrvars;
4130  int oldndelconss;
4131  int oldnchgcoefs;
4132  int firstchange;
4133  int c;
4134 
4135  assert(result != NULL);
4136 
4137  oldnfixedvars = *nfixedvars;
4138  oldnchgbds = *nchgbds;
4139  oldnaggrvars = *naggrvars;
4140  oldndelconss = *ndelconss;
4141  oldnchgcoefs = *nchgcoefs;
4142 
4143  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4144  assert(conshdlrdata != NULL);
4145 
4146  /* process constraints */
4147  cutoff = FALSE;
4148  delay = FALSE;
4149  firstchange = INT_MAX;
4150  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
4151  {
4152  cons = conss[c];
4153  assert(cons != NULL);
4154  consdata = SCIPconsGetData(cons);
4155  assert(consdata != NULL);
4156 
4157  /* force presolving the constraint in the initial round */
4158  if( nrounds == 0 )
4159  consdata->propagated = FALSE;
4160 
4161  /* remember the first changed constraint to begin the next aggregation round with */
4162  if( firstchange == INT_MAX && consdata->changed )
4163  firstchange = c;
4164 
4165  /* remove all variables that are fixed to zero and all pairs of variables fixed to one;
4166  * merge multiple entries of the same or negated variables
4167  */
4168  SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, nchgcoefs) );
4169 
4170  /* propagate constraint */
4171  SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nchgbds) );
4172 
4173  if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
4174  {
4175  assert(consdata->nvars >= 2); /* otherwise, propagateCons() has deleted the constraint */
4176 
4177  /* if only two variables are left, both have to be equal or opposite, depending on the rhs */
4178  if( consdata->nvars == 2 )
4179  {
4180  SCIPdebugMessage("xor constraint <%s> has only two unfixed variables, rhs=%u\n",
4181  SCIPconsGetName(cons), consdata->rhs);
4182 
4183  assert(consdata->vars != NULL);
4184  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
4185  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
4186  assert(SCIPisEQ(scip, SCIPvarGetLbGlobal(consdata->vars[1]), 0.0));
4187  assert(SCIPisEQ(scip, SCIPvarGetUbGlobal(consdata->vars[1]), 1.0));
4188 
4189  if( !consdata->rhs )
4190  {
4191  /* aggregate variables: vars[0] - vars[1] == 0 */
4192  SCIPdebugMessage(" -> aggregate <%s> == <%s>\n", SCIPvarGetName(consdata->vars[0]),
4193  SCIPvarGetName(consdata->vars[1]));
4194  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], 1.0, -1.0, 0.0,
4195  &cutoff, &redundant, &aggregated) );
4196  }
4197  else
4198  {
4199  /* aggregate variables: vars[0] + vars[1] == 1 */
4200  SCIPdebugMessage(" -> aggregate <%s> == 1 - <%s>\n", SCIPvarGetName(consdata->vars[0]),
4201  SCIPvarGetName(consdata->vars[1]));
4202  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], 1.0, 1.0, 1.0,
4203  &cutoff, &redundant, &aggregated) );
4204  }
4205  assert(redundant || SCIPdoNotAggr(scip));
4206 
4207  if( aggregated )
4208  {
4209  assert(redundant);
4210  (*naggrvars)++;
4211  }
4212 
4213  if( redundant )
4214  {
4215  /* delete constraint */
4216  SCIP_CALL( SCIPdelCons(scip, cons) );
4217  (*ndelconss)++;
4218  }
4219  }
4220  else
4221  {
4222  /* try to use clique information to upgrade the constraint to a set-partitioning constraint or fix
4223  * variables
4224  */
4225  SCIP_CALL( cliquePresolve(scip, cons, nfixedvars, nchgcoefs, ndelconss, naddconss, &cutoff) );
4226  }
4227  }
4228  }
4229 
4230  /* process pairs of constraints: check them for equal operands;
4231  * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
4232  * (otherwise, we delay the presolving to be called again next time)
4233  */
4234  if( !cutoff )
4235  {
4236  if( *nfixedvars == oldnfixedvars && *nchgbds == oldnchgbds && *naggrvars == oldnaggrvars )
4237  {
4238  if( firstchange < nconss && conshdlrdata->presolusehashing )
4239  {
4240  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
4241  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, nchgcoefs, ndelconss, &cutoff) );
4242  }
4243  if( conshdlrdata->presolpairwise )
4244  {
4245  SCIP_Longint npaircomparisons;
4246  int lastndelconss;
4247  npaircomparisons = 0;
4248  lastndelconss = *ndelconss;
4249 
4250  for( c = firstchange; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
4251  {
4252  if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
4253  {
4254  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange);
4255 
4256  SCIP_CALL( preprocessConstraintPairs(scip, conss, firstchange, c,
4257  &cutoff, nfixedvars, naggrvars, ndelconss, nchgcoefs) );
4258 
4259  if( npaircomparisons > NMINCOMPARISONS )
4260  {
4261  if( ((SCIP_Real) (*ndelconss - lastndelconss)) / ((SCIP_Real) npaircomparisons) < MINGAINPERNMINCOMPARISONS )
4262  break;
4263  lastndelconss = *ndelconss;
4264  npaircomparisons = 0;
4265  }
4266  }
4267  }
4268  }
4269  }
4270  else
4271  delay = TRUE;
4272  }
4273 
4274  /* return the correct result code */
4275  if( cutoff )
4276  *result = SCIP_CUTOFF;
4277  else if( delay )
4278  *result = SCIP_DELAYED;
4279  else if( *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds || *naggrvars > oldnaggrvars
4280  || *ndelconss > oldndelconss || *nchgcoefs > oldnchgcoefs )
4281  *result = SCIP_SUCCESS;
4282  else
4283  *result = SCIP_DIDNOTFIND;
4284 
4285  /* add extended formulation at the end of presolving if required */
4286  if ( conshdlrdata->addextendedform && *result == SCIP_DIDNOTFIND && SCIPisPresolveFinished(scip) )
4287  {
4288  for (c = 0; c < nconss && ! SCIPisStopped(scip); ++c)
4289  {
4290  int naddedconss = 0;
4291 
4292  cons = conss[c];
4293  assert(cons != NULL);
4294  consdata = SCIPconsGetData(cons);
4295  assert(consdata != NULL);
4296 
4297  if ( consdata->extvars != NULL )
4298  break;
4299 
4300  if ( conshdlrdata->addflowextended )
4301  {
4302  SCIP_CALL( addExtendedFlowFormulation(scip, cons, &naddedconss) );
4303  }
4304  else
4305  {
4306  SCIP_CALL( addExtendedAsymmetricFormulation(scip, cons, &naddedconss) );
4307  }
4308  (*naddconss) += naddedconss;
4309  }
4310  }
4311 
4312  return SCIP_OKAY;
4313 }
4314 
4315 
4316 /** propagation conflict resolving method of constraint handler */
4317 static
4318 SCIP_DECL_CONSRESPROP(consRespropXor)
4319 { /*lint --e{715}*/
4320  SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
4321 
4322  return SCIP_OKAY;
4323 }
4324 
4325 
4326 /** variable rounding lock method of constraint handler */
4327 static
4328 SCIP_DECL_CONSLOCK(consLockXor)
4329 { /*lint --e{715}*/
4330  SCIP_CONSDATA* consdata;
4331  int i;
4332 
4333  consdata = SCIPconsGetData(cons);
4334  assert(consdata != NULL);
4335 
4336  /* external variables */
4337  for( i = 0; i < consdata->nvars; ++i )
4338  {
4339  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos + nlocksneg, nlockspos + nlocksneg) );
4340  }
4341 
4342  /* internal variable */
4343  if( consdata->intvar != NULL )
4344  {
4345  SCIP_CALL( SCIPaddVarLocks(scip, consdata->intvar, nlockspos + nlocksneg, nlockspos + nlocksneg) );
4346  }
4347 
4348  return SCIP_OKAY;
4349 }
4350 
4351 
4352 /** constraint display method of constraint handler */
4353 static
4354 SCIP_DECL_CONSPRINT(consPrintXor)
4355 { /*lint --e{715}*/
4356  assert( scip != NULL );
4357  assert( conshdlr != NULL );
4358  assert( cons != NULL );
4359 
4360  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file, FALSE) );
4361 
4362  return SCIP_OKAY;
4363 }
4364 
4365 /** constraint copying method of constraint handler */
4366 static
4367 SCIP_DECL_CONSCOPY(consCopyXor)
4368 { /*lint --e{715}*/
4369  SCIP_CONSDATA* sourceconsdata;
4370  SCIP_VAR** sourcevars;
4371  SCIP_VAR** targetvars;
4372  SCIP_VAR* intvar;
4373  SCIP_VAR* targetintvar;
4374  const char* consname;
4375  int nvars;
4376  int v;
4377 
4378  assert(scip != NULL);
4379  assert(sourcescip != NULL);
4380  assert(sourcecons != NULL);
4381 
4382  (*valid) = TRUE;
4383 
4384  sourceconsdata = SCIPconsGetData(sourcecons);
4385  assert(sourceconsdata != NULL);
4386 
4387  /* get variables and coefficients of the source constraint */
4388  sourcevars = sourceconsdata->vars;
4389  nvars = sourceconsdata->nvars;
4390  intvar = sourceconsdata->intvar;
4391  targetintvar = NULL;
4392 
4393  if( name != NULL )
4394  consname = name;
4395  else
4396  consname = SCIPconsGetName(sourcecons);
4397 
4398  if( nvars == 0 )
4399  {
4400  if( intvar != NULL )
4401  {
4402  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, intvar, &targetintvar, varmap, consmap, global, valid) );
4403  assert(!(*valid) || targetintvar != NULL);
4404 
4405  SCIPdebugMessage("Copied integral variable <%s> (bounds: [%g,%g])\n", SCIPvarGetName(targetintvar),
4406  global ? SCIPvarGetLbGlobal(intvar) : SCIPvarGetLbLocal(intvar),
4407  global ? SCIPvarGetUbGlobal(intvar) : SCIPvarGetUbLocal(intvar));
4408  }
4409 
4410  if( *valid )
4411  {
4412  SCIP_CALL( createConsXorIntvar(scip, cons, consname, SCIPgetRhsXor(sourcescip, sourcecons), 0, NULL,
4413  targetintvar,
4414  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4415  }
4416 
4417  return SCIP_OKAY;
4418  }
4419 
4420  /* duplicate variable array */
4421  SCIP_CALL( SCIPallocBufferArray(scip, &targetvars, nvars) );
4422 
4423  /* map variables of the source constraint to variables of the target SCIP */
4424  for( v = 0; v < nvars && *valid; ++v )
4425  {
4426  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &targetvars[v], varmap, consmap, global, valid) );
4427  assert(!(*valid) || targetvars[v] != NULL);
4428  }
4429 
4430  /* map artificial relaxation variable of the source constraint to variable of the target SCIP */
4431  if( *valid && intvar != NULL )
4432  {
4433  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, intvar, &targetintvar, varmap, consmap, global, valid) );
4434  assert(!(*valid) || targetintvar != NULL);
4435 
4436  SCIPdebugMessage("Copied integral variable <%s> (bounds: [%g,%g])\n", SCIPvarGetName(targetintvar),
4437  global ? SCIPvarGetLbGlobal(intvar) : SCIPvarGetLbLocal(intvar),
4438  global ? SCIPvarGetUbGlobal(intvar) : SCIPvarGetUbLocal(intvar));
4439  }
4440 
4441  /* only create the target constraints, if all variables could be copied */
4442  if( *valid )
4443  {
4444  SCIP_CALL( createConsXorIntvar(scip, cons, consname, SCIPgetRhsXor(sourcescip, sourcecons), nvars, targetvars,
4445  targetintvar,
4446  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4447  }
4448 
4449  /* free buffer array */
4450  SCIPfreeBufferArray(scip, &targetvars);
4451 
4452  return SCIP_OKAY;
4453 }
4454 
4455 
4456 /** constraint parsing method of constraint handler */
4457 static
4458 SCIP_DECL_CONSPARSE(consParseXor)
4459 { /*lint --e{715}*/
4460  SCIP_VAR** vars;
4461  char* endptr;
4462  int requiredsize;
4463  int varssize;
4464  int nvars;
4465 
4466  SCIPdebugMessage("parse <%s> as xor constraint\n", str);
4467 
4468  varssize = 100;
4469  nvars = 0;
4470 
4471  /* allocate buffer array for variables */
4472  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
4473 
4474  /* parse string */
4475  SCIP_CALL( SCIPparseVarsList(scip, str, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4476 
4477  if( *success )
4478  {
4479  SCIP_Real rhs;
4480 
4481  /* check if the size of the variable array was big enough */
4482  if( varssize < requiredsize )
4483  {
4484  /* reallocate memory */
4485  varssize = requiredsize;
4486  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
4487 
4488  /* parse string again with the correct size of the variable array */
4489  SCIP_CALL( SCIPparseVarsList(scip, str, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4490  }
4491 
4492  assert(*success);
4493  assert(varssize >= requiredsize);
4494 
4495  SCIPdebugMessage("successfully parsed %d variables\n", nvars);
4496 
4497  str = endptr;
4498 
4499  /* search for the equal symbol */
4500  while( *str != '=' && *str != '\0' )
4501  str++;
4502 
4503  /* if the string end has been reached without finding the '=' */
4504  if ( *str == '\0' )
4505  {
4506  SCIPerrorMessage("Could not find terminating '='.\n");
4507  *success = FALSE;
4508  }
4509  else
4510  {
4511  /* skip '=' character */
4512  ++str;
4513 
4514  if( SCIPstrToRealValue(str, &rhs, &endptr) )
4515  {
4516  assert(SCIPisZero(scip, rhs) || SCIPisEQ(scip, rhs, 1.0));
4517 
4518  /* create or constraint */
4519  SCIP_CALL( SCIPcreateConsXor(scip, cons, name, (rhs > 0.5 ? TRUE : FALSE), nvars, vars,
4520  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4521 
4522  SCIPdebugPrintCons(scip, *cons, NULL);
4523  }
4524  else
4525  *success = FALSE;
4526  }
4527  }
4528 
4529  /* free variable buffer */
4530  SCIPfreeBufferArray(scip, &vars);
4531 
4532  return SCIP_OKAY;
4533 }
4534 
4535 /** constraint method of constraint handler which returns the variables (if possible) */
4536 static
4537 SCIP_DECL_CONSGETVARS(consGetVarsXor)
4538 { /*lint --e{715}*/
4539  SCIP_CONSDATA* consdata;
4540  int nintvar = 0;
4541  int cnt;
4542  int j;
4543 
4544  consdata = SCIPconsGetData(cons);
4545  assert(consdata != NULL);
4546 
4547  if ( consdata->intvar != NULL )
4548  nintvar = 1;
4549 
4550  if ( varssize < consdata->nvars + nintvar + consdata->nextvars )
4551  (*success) = FALSE;
4552  else
4553  {
4554  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
4555 
4556  if ( consdata->intvar != NULL )
4557  vars[consdata->nvars] = consdata->intvar;
4558 
4559  if ( consdata->nextvars > 0 )
4560  {
4561  assert( consdata->extvars != NULL );
4562  cnt = consdata->nvars + nintvar;
4563  for (j = 0; j < consdata->extvarssize; ++j)
4564  {
4565  if ( consdata->extvars[j] != NULL )
4566  vars[cnt++] = consdata->extvars[j];
4567  }
4568  assert( cnt == consdata->nvars + nintvar + consdata->nextvars );
4569  }
4570 
4571  (*success) = TRUE;
4572  }
4573 
4574  return SCIP_OKAY;
4575 }
4576 
4577 /** constraint method of constraint handler which returns the number of variable (if possible) */
4578 static
4579 SCIP_DECL_CONSGETNVARS(consGetNVarsXor)
4580 { /*lint --e{715}*/
4581  SCIP_CONSDATA* consdata;
4582 
4583  assert(cons != NULL);
4584 
4585  consdata = SCIPconsGetData(cons);
4586  assert(consdata != NULL);
4587 
4588  if( consdata->intvar == NULL )
4589  (*nvars) = consdata->nvars + consdata->nextvars;
4590  else
4591  (*nvars) = consdata->nvars + 1 + consdata->nextvars;
4592 
4593  (*success) = TRUE;
4594 
4595  return SCIP_OKAY;
4596 }
4597 
4598 /*
4599  * Callback methods of event handler
4600  */
4601 
4602 static
4603 SCIP_DECL_EVENTEXEC(eventExecXor)
4604 { /*lint --e{715}*/
4605  SCIP_CONSDATA* consdata;
4606 
4607  assert(eventhdlr != NULL);
4608  assert(eventdata != NULL);
4609  assert(event != NULL);
4610 
4611  consdata = (SCIP_CONSDATA*)eventdata;
4612  assert(consdata != NULL);
4613 
4614  consdata->propagated = FALSE;
4615 
4616  return SCIP_OKAY;
4617 }
4618 
4619 
4620 /*
4621  * constraint specific interface methods
4622  */
4623 
4624 /** creates the handler for xor constraints and includes it in SCIP */
4626  SCIP* scip /**< SCIP data structure */
4627  )
4628 {
4629  SCIP_CONSHDLRDATA* conshdlrdata;
4630  SCIP_CONSHDLR* conshdlr;
4631  SCIP_EVENTHDLR* eventhdlr;
4632 
4633  /* create event handler for events on variables */
4635  eventExecXor, NULL) );
4636 
4637  /* create constraint handler data */
4638  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
4639 
4640  /* include constraint handler */
4643  consEnfolpXor, consEnfopsXor, consCheckXor, consLockXor,
4644  conshdlrdata) );
4645  assert(conshdlr != NULL);
4646 
4647  /* set non-fundamental callbacks via specific setter functions */
4648  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyXor, consCopyXor) );
4649  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteXor) );
4650  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolXor) );
4651  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeXor) );
4652  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsXor) );
4653  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsXor) );
4654  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpXor) );
4655  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseXor) );
4656  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolXor, CONSHDLR_MAXPREROUNDS, CONSHDLR_DELAYPRESOL) );
4657  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintXor) );
4658  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropXor, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
4660  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropXor) );
4661  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpXor, consSepasolXor, CONSHDLR_SEPAFREQ,
4663  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransXor) );
4664 
4665  /* add xor constraint handler parameters */
4667  "constraints/xor/presolpairwise",
4668  "should pairwise constraint comparison be performed in presolving?",
4669  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
4670 
4672  "constraints/xor/presolusehashing",
4673  "should hash table be used for detecting redundant constraints in advance?",
4674  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
4675 
4677  "constraints/xor/addextendedform",
4678  "should the extended formulation be added in presolving?",
4679  &conshdlrdata->addextendedform, TRUE, DEFAULT_ADDEXTENDEDFORM, NULL, NULL) );
4680 
4682  "constraints/xor/addflowextended",
4683  "should the extended flow formulation be added (nonsymmetric formulation otherwise)?",
4684  &conshdlrdata->addflowextended, TRUE, DEFAULT_ADDFLOWEXTENDED, NULL, NULL) );
4685 
4687  "constraints/xor/separateparity",
4688  "should parity inequalities be separated?",
4689  &conshdlrdata->separateparity, TRUE, DEFAULT_SEPARATEPARITY, NULL, NULL) );
4690 
4691  SCIP_CALL( SCIPaddIntParam(scip,
4692  "constraints/xor/gausspropfreq",
4693  "frequency for applying the Gauss propagator",
4694  &conshdlrdata->gausspropfreq, TRUE, DEFAULT_GAUSSPROPFREQ, -1, INT_MAX, NULL, NULL) );
4695 
4696  return SCIP_OKAY;
4697 }
4698 
4699 /** creates and captures a xor constraint x_0 xor ... xor x_{k-1} = rhs
4700  *
4701  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
4702  */
4704  SCIP* scip, /**< SCIP data structure */
4705  SCIP_CONS** cons, /**< pointer to hold the created constraint */
4706  const char* name, /**< name of constraint */
4707  SCIP_Bool rhs, /**< right hand side of the constraint */
4708  int nvars, /**< number of operator variables in the constraint */
4709  SCIP_VAR** vars, /**< array with operator variables of constraint */
4710  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
4711  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
4712  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
4713  * Usually set to TRUE. */
4714  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
4715  * TRUE for model constraints, FALSE for additional, redundant constraints. */
4716  SCIP_Bool check, /**< should the constraint be checked for feasibility?
4717  * TRUE for model constraints, FALSE for additional, redundant constraints. */
4718  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
4719  * Usually set to TRUE. */
4720  SCIP_Bool local, /**< is constraint only valid locally?
4721  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
4722  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
4723  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
4724  * adds coefficients to this constraint. */
4725  SCIP_Bool dynamic, /**< is constraint subject to aging?
4726  * Usually set to FALSE. Set to TRUE for own cuts which
4727  * are separated as constraints. */
4728  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
4729  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
4730  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
4731  * if it may be moved to a more global node?
4732  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
4733  )
4734 {
4735  SCIP_CONSHDLR* conshdlr;
4736  SCIP_CONSDATA* consdata;
4737 
4738  /* find the xor constraint handler */
4739  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
4740  if( conshdlr == NULL )
4741  {
4742  SCIPerrorMessage("xor constraint handler not found\n");
4743  return SCIP_PLUGINNOTFOUND;
4744  }
4745 
4746  /* create constraint data */
4747  SCIP_CALL( consdataCreate(scip, &consdata, rhs, nvars, vars, NULL) );
4748 
4749  /* create constraint */
4750  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
4751  local, modifiable, dynamic, removable, stickingatnode) );
4752 
4753  return SCIP_OKAY;
4754 }
4755 
4756 /** creates and captures a xor constraint x_0 xor ... xor x_{k-1} = rhs
4757  * with all constraint flags set to their default values
4758  *
4759  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
4760  */
4762  SCIP* scip, /**< SCIP data structure */
4763  SCIP_CONS** cons, /**< pointer to hold the created constraint */
4764  const char* name, /**< name of constraint */
4765  SCIP_Bool rhs, /**< right hand side of the constraint */
4766  int nvars, /**< number of operator variables in the constraint */
4767  SCIP_VAR** vars /**< array with operator variables of constraint */
4768  )
4769 {
4770  SCIP_CALL( SCIPcreateConsXor(scip,cons, name, rhs, nvars, vars,
4771  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
4772 
4773  return SCIP_OKAY;
4774 }
4775 
4776 /** gets number of variables in xor constraint */
4777 int SCIPgetNVarsXor(
4778  SCIP* scip, /**< SCIP data structure */
4779  SCIP_CONS* cons /**< constraint data */
4780  )
4781 {
4782  SCIP_CONSDATA* consdata;
4783 
4784  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4785  {
4786  SCIPerrorMessage("constraint is not an xor constraint\n");
4787  SCIPABORT();
4788  return -1; /*lint !e527*/
4789  }
4790 
4791  consdata = SCIPconsGetData(cons);
4792  assert(consdata != NULL);
4793 
4794  return consdata->nvars;
4795 }
4796 
4797 /** gets array of variables in xor constraint */
4799  SCIP* scip, /**< SCIP data structure */
4800  SCIP_CONS* cons /**< constraint data */
4801  )
4802 {
4803  SCIP_CONSDATA* consdata;
4804 
4805  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4806  {
4807  SCIPerrorMessage("constraint is not an xor constraint\n");
4808  SCIPABORT();
4809  return NULL; /*lint !e527*/
4810  }
4811 
4812  consdata = SCIPconsGetData(cons);
4813  assert(consdata != NULL);
4814 
4815  return consdata->vars;
4816 }
4817 
4818 /** gets the right hand side of the xor constraint */
4820  SCIP* scip, /**< SCIP data structure */
4821  SCIP_CONS* cons /**< constraint data */
4822  )
4823 {
4824  SCIP_CONSDATA* consdata;
4825 
4826  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4827  {
4828  SCIPerrorMessage("constraint is not an xor constraint\n");
4829  SCIPABORT();
4830  }
4831 
4832  consdata = SCIPconsGetData(cons);
4833  assert(consdata != NULL);
4834 
4835  return consdata->rhs;
4836 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
enum Proprule PROPRULE
Definition: cons_xor.c:138
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:20784
#define NROWS
Definition: cons_xor.c:81
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38254
#define EVENTHDLR_NAME
Definition: cons_xor.c:66
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file, SCIP_Bool endline)
Definition: cons_xor.c:438
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition: scip.c:25608
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16205
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:38397
static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
Definition: cons_xor.c:1345
static SCIP_DECL_EVENTEXEC(eventExecXor)
Definition: cons_xor.c:4604
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:25984
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10071
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5600
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:5332
static int computeRowEcholonGF2(SCIP *scip, int m, int n, int *p, int *s, Type **A, Type *b)
Definition: cons_xor.c:1821
static SCIP_DECL_CONSCOPY(consCopyXor)
Definition: cons_xor.c:4368
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:23286
static SCIP_DECL_CONSFREE(consFreeXor)
Definition: cons_xor.c:3812
#define MAXXORCONSSSYSTEM
Definition: cons_xor.c:78
primal heuristic that tries a given solution
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
static SCIP_DECL_CONSINITLP(consInitlpXor)
Definition: cons_xor.c:3888
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:20892
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
Definition: cons_xor.c:2531
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1374
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:19206
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:8894
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:9751
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:10913
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:15968
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:13986
SCIP_Bool SCIPgetRhsXor(SCIP *scip, SCIP_CONS *cons)
Definition: cons_xor.c:4820
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10026
#define SCIP_MAXSTRLEN
Definition: def.h:196
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:5378
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip.c:28166
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:4990
static SCIP_DECL_CONSSEPASOL(consSepasolXor)
Definition: cons_xor.c:3935
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule)
Definition: cons_xor.c:2500
#define NULL
Definition: lpi_spx.cpp:129
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:16426
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1111
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:7786
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_xor.c:161
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7618
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5078
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16380
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:31639
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:22044
SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19452
static SCIP_DECL_CONSPROP(consPropXor)
Definition: cons_xor.c:4069
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5562
SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
Definition: scip.c:14164
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_xor.c:75
static SCIP_RETCODE conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_xor.c:195
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip.c:7110
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:7846
#define FALSE
Definition: def.h:52
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:1864
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7209
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:7579
#define TRUE
Definition: def.h:51
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7577
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_DECL_CONSPRESOL(consPresolXor)
Definition: cons_xor.c:4119
enum Proprule PROPRULE
static void solveRowEcholonGF2(int m, int n, int r, int *p, int *s, Type **A, Type *b, Type *x)
Definition: cons_xor.c:1930
static SCIP_DECL_CONSENFOLP(consEnfolpXor)
Definition: cons_xor.c:3966
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:5539
#define DEFAULT_ADDFLOWEXTENDED
Definition: cons_xor.c:71
#define CONSHDLR_CHECKPRIORITY
Definition: cons_xor.c:52
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_Bool delaypresol)
Definition: scip.c:5271
#define MINGAINPERNMINCOMPARISONS
Definition: cons_xor.c:77
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:38779
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:19185
static SCIP_DECL_CONSSEPALP(consSepalpXor)
Definition: cons_xor.c:3904
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15141
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:31775
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:19214
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16227
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_xor.c:377
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:1923
#define CONSHDLR_SEPAPRIORITY
Definition: cons_xor.c:50
#define CONSHDLR_PROP_TIMING
Definition: cons_xor.c:64
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING timingmask)
Definition: scip.c:5036
SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_setppc.c:9067
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7776
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7716
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:23934
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:28256
Constraint handler for the set partitioning / packing / covering constraints .
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:22651
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
static SCIP_DECL_CONSTRANS(consTransXor)
Definition: cons_xor.c:3862
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:99
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:19215
static SCIP_DECL_CONSLOCK(consLockXor)
Definition: cons_xor.c:4329
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11177
static SCIP_DECL_CONSENFOPS(consEnfopsXor)
Definition: cons_xor.c:4003
SCIP_RETCODE SCIPincludeConshdlrXor(SCIP *scip)
Definition: cons_xor.c:4626
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:5103
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:7706
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:18686
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1287
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:22424
#define EVENTHDLR_DESC
Definition: cons_xor.c:67
SCIP_RETCODE SCIPcreateConsXor(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Bool rhs, 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_xor.c:4704
SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
Definition: scip.c:14482
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:3388
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons)
Definition: cons_xor.c:1460
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:15907
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:1966
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3414
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3893
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:33378
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:15475
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:22066
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:15930
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:23258
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:1690
#define CONSHDLR_ENFOPRIORITY
Definition: cons_xor.c:51
static SCIP_DECL_CONSDELETE(consDeleteXor)
Definition: cons_xor.c:3847
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:19183
#define HASHSIZE_XORCONS
Definition: cons_xor.c:74
static SCIP_DECL_CONSPRINT(consPrintXor)
Definition: cons_xor.c:4355
SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
Definition: scip.c:33181
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:15319
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:7816
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:19159
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
Definition: cons_xor.c:464
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:19221
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:17713
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:23000
#define DEFAULT_SEPARATEPARITY
Definition: cons_xor.c:72
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:38767
#define CONSHDLR_MAXPREROUNDS
Definition: cons_xor.c:58
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3873
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:964
static SCIP_DECL_CONSGETVARS(consGetVarsXor)
Definition: cons_xor.c:4538
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15233
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:21051
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38292
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:15406
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:30856
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:37940
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7557
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38648
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:18848
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:15943
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
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:18783
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:1882
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:19189
#define CONSHDLR_NEEDSCONS
Definition: cons_xor.c:62
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:38349
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define SCIP_CALL(x)
Definition: def.h:258
#define DEFAULT_GAUSSPROPFREQ
Definition: cons_xor.c:73
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:4936
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10713
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:29454
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38705
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:246
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:49
static SCIP_DECL_CONSPARSE(consParseXor)
Definition: cons_xor.c:4459
static void consdataSort(SCIP_CONSDATA *consdata)
Definition: cons_xor.c:565
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7587
#define CONSHDLR_DELAYSEPA
Definition: cons_xor.c:59
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:15130
static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_xor.c:355
static SCIP_DECL_CONSGETNVARS(consGetNVarsXor)
Definition: cons_xor.c:4580
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11453
#define CONSHDLR_DELAYPRESOL
Definition: cons_xor.c:61
static SCIP_DECL_CONSRESPROP(consRespropXor)
Definition: cons_xor.c:4319
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:15360
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38311
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16195
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:15097
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:16436
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:983
public data structures and miscellaneous methods
#define CONSHDLR_PROPFREQ
Definition: cons_xor.c:54
#define DEFAULT_ADDEXTENDEDFORM
Definition: cons_xor.c:70
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip.c:1020
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:22476
static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
Definition: cons_xor.c:210
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16062
#define SCIP_Bool
Definition: def.h:49
SCIP_VAR ** SCIPgetVarsXor(SCIP *scip, SCIP_CONS *cons)
Definition: cons_xor.c:4799
#define CONSHDLR_SEPAFREQ
Definition: cons_xor.c:53
#define NMINCOMPARISONS
Definition: cons_xor.c:76
SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19472
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_xor.c:175
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:790
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7796
unsigned short Type
Definition: cons_xor.c:89
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:25487
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:7650
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22093
int SCIPgetNVarsXor(SCIP *scip, SCIP_CONS *cons)
Definition: cons_xor.c:4778
methods for debugging
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, PROPRULE proprule)
Definition: cons_xor.c:2392
static SCIP_RETCODE addExtendedAsymmetricFormulation(SCIP *scip, SCIP_CONS *cons, int *naddedconss)
Definition: cons_xor.c:1166
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:7806
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:7676
static SCIP_DECL_HASHKEYVAL(hashKeyValXorcons)
Definition: cons_xor.c:697
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:7567
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:5355
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:102
Constraint handler for linear constraints in their most general form, .
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:1434
static SCIP_RETCODE checkSystemGF2(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_SOL *currentsol, SCIP_RESULT *result)
Definition: cons_xor.c:1994
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:19204
Proprule
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:34833
#define CONSHDLR_DESC
Definition: cons_xor.c:49
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_Bool rhs, int nvars, SCIP_VAR **vars, SCIP_VAR *intvar)
Definition: cons_xor.c:298
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38330
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1317
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:18583
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:33424
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:5309
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:10850
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:15953
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool separateparity, SCIP_Bool *separated, SCIP_Bool *cutoff)
Definition: cons_xor.c:1608
Constraint handler for "xor" constraints, .
#define CONSHDLR_EAGERFREQ
Definition: cons_xor.c:55
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:19176
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16370
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:5516
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:25510
static SCIP_DECL_CONSEXITSOL(consExitsolXor)
Definition: cons_xor.c:3829
#define CONSHDLR_NAME
Definition: cons_xor.c:48
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1239
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)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_xor.c:147
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:5199
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:17642
static SCIP_RETCODE addExtendedFlowFormulation(SCIP *scip, SCIP_CONS *cons, int *naddedconss)
Definition: cons_xor.c:861
static SCIP_DECL_CONSCHECK(consCheckXor)
Definition: cons_xor.c:4026
#define SCIP_Real
Definition: def.h:123
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7736
static SCIP_RETCODE createConsXorIntvar(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Bool rhs, int nvars, SCIP_VAR **vars, SCIP_VAR *intvar, 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_xor.c:3735
#define MIN(x, y)
Definition: memory.c:59
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition: cons_xor.c:2929
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int *nchgcoefs)
Definition: cons_xor.c:732
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool *violated)
Definition: cons_xor.c:1513
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:25276
static SCIP_DECL_HASHKEYEQ(hashKeyEqXorcons)
Definition: cons_xor.c:655
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:26010
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:19198
#define CONSHDLR_DELAYPROP
Definition: cons_xor.c:60
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:25414
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, int *nchgcoefs, int *ndelconss, SCIP_Bool *cutoff)
Definition: cons_xor.c:3201
#define SCIP_Longint
Definition: def.h:107
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:245
static SCIP_Bool allRowsInLP(SCIP_CONSDATA *consdata)
Definition: cons_xor.c:1491
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:17590
SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:25810
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:48
SCIP_RETCODE SCIPheurPassSolAddSol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
Definition: heur_trysol.c:277
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16052
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:22285
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_xor.c:512
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyXor)
Definition: cons_xor.c:3796
SCIP_RETCODE SCIPcreateConsBasicXor(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_Bool rhs, int nvars, SCIP_VAR **vars)
Definition: cons_xor.c:4762
static SCIP_DECL_HASHGETKEY(hashGetKeyXorcons)
Definition: cons_xor.c:647
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22156
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:38001
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:1901
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:98
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_xor.c:274
#define MAXXORVARSSYSTEM
Definition: cons_xor.c:79
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:371
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_xor.c:69
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5585
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11452
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:25540
#define SCIPABORT()
Definition: def.h:230
void SCIPsortRealIntPtr(SCIP_Real *realarray, int *intarray, void **ptrarray, int len)
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7726
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7756
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:3903
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:33573
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss, int *nchgcoefs)
Definition: cons_xor.c:3312
static SCIP_RETCODE cliquePresolve(SCIP *scip, SCIP_CONS *cons, int *nfixedvars, int *nchgcoefs, int *ndelconss, int *naddconss, SCIP_Bool *cutoff)
Definition: cons_xor.c:2950
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip.c:32161
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:31403
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11139