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