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