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