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