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