Scippy

SCIP

Solving Constraint Integer Programs

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