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-2020 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  SCIP_CALL( SCIPcreateConsPseudobooleanWithConss(targetscip, targetcons, consname,
4008  targetlincons, targetlinconstype, targetandconss, targetandcoefs, ntargetandconss,
4009  indvar, sourceconsdata->weight, sourceconsdata->issoftcons, intvar, targetlhs, targetrhs,
4010  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4011  }
4012  }
4013 
4014  if( !(*valid) && !SCIPisConsCompressionEnabled(sourcescip) )
4015  {
4016  SCIPverbMessage(sourcescip, SCIP_VERBLEVEL_MINIMAL, NULL, "could not copy constraint <%s>\n", SCIPconsGetName(sourcecons));
4017  }
4018 
4019  /* release copied linear constraint */
4020  if( targetlincons != NULL )
4021  {
4022  SCIP_CALL( SCIPreleaseCons(targetscip, &targetlincons) );
4023  }
4024 
4025  /* release copied and constraint */
4026  if( targetandconss != NULL )
4027  {
4028  int c;
4029 
4030  assert(ntargetandconss <= sourceconsdata->nconsanddatas);
4031 
4032  for( c = 0 ; c < ntargetandconss; ++c )
4033  {
4034  if( targetandconss[c] != NULL )
4035  {
4036  SCIP_CALL( SCIPreleaseCons(targetscip, &targetandconss[c]) );
4037  }
4038  }
4039  }
4040 
4041  /* free temporary memory */
4042  SCIPfreeBufferArrayNull(sourcescip, &targetandcoefs);
4043  SCIPfreeBufferArrayNull(sourcescip, &targetandconss);
4044  }
4045  else
4046  *valid = FALSE;
4047 
4048  return SCIP_OKAY;
4049 }
4050 
4051 /** compute all changes in consanddatas array */
4052 static
4054  SCIP*const scip, /**< SCIP data structure */
4055  SCIP_CONSHDLRDATA*const conshdlrdata /**< pseudoboolean constraint handler data */
4056  )
4057 {
4058  CONSANDDATA** allconsanddatas;
4059  CONSANDDATA* consanddata;
4060  int c;
4061 
4062  assert(scip != NULL);
4063  assert(conshdlrdata != NULL);
4064 
4065  allconsanddatas = conshdlrdata->allconsanddatas;
4066  assert(allconsanddatas != NULL);
4067  assert(conshdlrdata->nallconsanddatas > 0);
4068  assert(conshdlrdata->nallconsanddatas <= conshdlrdata->sallconsanddatas);
4069 
4070  for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c )
4071  {
4072  SCIP_CONS* cons;
4073  SCIP_VAR** vars;
4074  int nvars;
4075  SCIP_VAR** newvars;
4076  int nnewvars;
4077  int v;
4078 
4079  consanddata = allconsanddatas[c];
4080 
4081  if( !consanddata->istransformed )
4082  continue;
4083 
4084  if( consanddata->nuses == 0 )
4085  continue;
4086 
4087  vars = consanddata->vars;
4088  nvars = consanddata->nvars;
4089  assert(nvars == 0 || vars != NULL);
4090  assert(consanddata->nnewvars == 0 && ((consanddata->snewvars > 0) == (consanddata->newvars != NULL)));
4091 
4092  if( nvars == 0 )
4093  {
4094 #ifndef NDEBUG
4095  /* if an old consanddata-object has no variables left there should be no new variables */
4096  if( consanddata->cons != NULL )
4097  assert(SCIPgetNVarsAnd(scip, consanddata->cons) == 0);
4098 #endif
4099  continue;
4100  }
4101 
4102  cons = consanddata->cons;
4103  assert(cons != NULL);
4104 
4105  if( SCIPconsIsDeleted(cons) )
4106  continue;
4107 
4108  /* sort and-variables */
4109  if( !SCIPisAndConsSorted(scip, consanddata->cons) )
4110  {
4111  SCIP_CALL( SCIPsortAndCons(scip, consanddata->cons) );
4112  assert(SCIPisAndConsSorted(scip, consanddata->cons));
4113  }
4114 
4115  /* get new and-variables */
4116  nnewvars = SCIPgetNVarsAnd(scip, consanddata->cons);
4117  newvars = SCIPgetVarsAnd(scip, consanddata->cons);
4118 
4119  /* stop if the constraint has no variables or there was an error (coverity issue) */
4120  if( nnewvars <= 0 )
4121  continue;
4122 
4123 #ifndef NDEBUG
4124  /* check that old variables are sorted */
4125  for( v = nvars - 1; v > 0; --v )
4126  assert(SCIPvarGetIndex(vars[v]) >= SCIPvarGetIndex(vars[v - 1]));
4127  /* check that new variables are sorted */
4128  for( v = nnewvars - 1; v > 0; --v )
4129  assert(SCIPvarGetIndex(newvars[v]) >= SCIPvarGetIndex(newvars[v - 1]));
4130 #endif
4131 
4132  /* check for changings, if and-constraint did not change we do not need to copy all variables */
4133  if( nvars == nnewvars )
4134  {
4135  SCIP_Bool changed;
4136 
4137  changed = FALSE;
4138 
4139  /* check each variable */
4140  for( v = nvars - 1; v >= 0; --v )
4141  {
4142  if( vars[v] != newvars[v] )
4143  {
4144  changed = TRUE;
4145  break;
4146  }
4147  }
4148 
4149  if( !changed )
4150  continue;
4151  }
4152 
4153  /* resize newvars array if necessary */
4154  if( nnewvars > consanddata->snewvars )
4155  {
4156  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(consanddata->newvars), &(consanddata->snewvars), nnewvars) );
4157  }
4158 
4159  /* copy all variables */
4160  BMScopyMemoryArray(consanddata->newvars, newvars, nnewvars);
4161  consanddata->nnewvars = nnewvars;
4162 
4163  /* capture all variables */
4164  for( v = consanddata->nnewvars - 1; v >= 0; --v )
4165  {
4166  /* in original problem the variables was already deleted */
4167  assert(consanddata->newvars[v] != NULL);
4168  SCIP_CALL( SCIPcaptureVar(scip, consanddata->newvars[v]) );
4169  }
4170  }
4171 
4172  return SCIP_OKAY;
4173 }
4174 
4175 /** remove old locks */
4176 static
4178  SCIP*const scip, /**< SCIP data structure */
4179  SCIP_CONS*const cons, /**< pseudoboolean constraint */
4180  CONSANDDATA*const consanddata, /**< CONSANDDATA object for which we want to delete the locks and the
4181  * capture of the corresponding and-constraint */
4182  SCIP_Real const coef, /**< coefficient which led to old locks */
4183  SCIP_Real const lhs, /**< left hand side which led to old locks */
4184  SCIP_Real const rhs /**< right hand side which led to old locks */
4185  )
4186 {
4187  assert(scip != NULL);
4188  assert(cons != NULL);
4189  assert(consanddata != NULL);
4190  assert(!SCIPisInfinity(scip, coef) && !SCIPisInfinity(scip, -coef));
4191  assert(!SCIPisInfinity(scip, lhs));
4192  assert(!SCIPisInfinity(scip, -rhs));
4193  assert(SCIPisLE(scip, lhs, rhs));
4194 
4195  /* remove rounding locks */
4196  SCIP_CALL( unlockRoundingAndCons(scip, cons, consanddata, coef, lhs, rhs) );
4197 
4198  assert(consanddata->cons != NULL);
4199 
4200  return SCIP_OKAY;
4201 }
4202 
4203 /** add new locks */
4204 static
4206  SCIP*const scip, /**< SCIP data structure */
4207  SCIP_CONS*const cons, /**< pseudoboolean constraint */
4208  CONSANDDATA*const consanddata, /**< CONSANDDATA object for which we want to delete the locks and the
4209  * capture of the corresponding and-constraint */
4210  SCIP_Real const coef, /**< coefficient which lead to new locks */
4211  SCIP_Real const lhs, /**< left hand side which lead to new locks */
4212  SCIP_Real const rhs /**< right hand side which lead to new locks */
4213  )
4214 {
4215  assert(scip != NULL);
4216  assert(cons != NULL);
4217  assert(consanddata != NULL);
4218  assert(!SCIPisInfinity(scip, coef) && !SCIPisInfinity(scip, -coef));
4219  assert(!SCIPisInfinity(scip, lhs));
4220  assert(!SCIPisInfinity(scip, -rhs));
4221  assert(SCIPisLE(scip, lhs, rhs));
4222 
4223  /* add rounding locks due to old variables in consanddata object */
4224  SCIP_CALL( lockRoundingAndCons(scip, cons, consanddata, coef, lhs, rhs) );
4225 
4226  assert(consanddata->cons != NULL);
4227 
4228  return SCIP_OKAY;
4229 }
4230 
4231 /** update all locks inside this constraint and all captures on all and-constraints */
4232 static
4234  SCIP*const scip, /**< SCIP data structure */
4235  SCIP_CONS*const cons, /**< pseudoboolean constraint */
4236  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
4237  SCIP_Real const newlhs, /**< new left hand side of pseudoboolean constraint */
4238  SCIP_Real const newrhs, /**< new right hand side of pseudoboolean constraint */
4239  SCIP_VAR**const andress, /**< current and-resultants in pseudoboolean constraint */
4240  SCIP_Real*const andcoefs, /**< current and-resultants-coeffcients in pseudoboolean constraint */
4241  SCIP_Bool*const andnegs, /**< current negation status of and-resultants in pseudoboolean constraint */
4242  int const nandress /**< number of current and-resultants in pseudoboolean constraint */
4243  )
4244 {
4245  CONSANDDATA** newconsanddatas;
4246  int nnewconsanddatas;
4247  int snewconsanddatas;
4248  SCIP_Real* newandcoefs;
4249  SCIP_Real* oldandcoefs;
4250  SCIP_Bool* newandnegs;
4251  SCIP_Bool* oldandnegs;
4252  CONSANDDATA** consanddatas;
4253  int nconsanddatas;
4254  SCIP_CONSDATA* consdata;
4255  int oldnvars;
4256  int c;
4257  int c1;
4258 
4259  assert(scip != NULL);
4260  assert(cons != NULL);
4261  assert(conshdlrdata != NULL);
4262  assert(conshdlrdata->hashmap != NULL);
4263  assert(nandress == 0 || (andress != NULL && andcoefs != NULL));
4264  assert(!SCIPisInfinity(scip, newlhs));
4265  assert(!SCIPisInfinity(scip, -newrhs));
4266  assert(SCIPisLE(scip, newlhs, newrhs));
4267 
4268  consdata = SCIPconsGetData(cons);
4269  assert(consdata != NULL);
4270 
4271  /* sort and-constraints after indices of corresponding and-resultants */
4272  SCIPsortPtrRealBool((void**)(consdata->consanddatas), consdata->andcoefs, consdata->andnegs, resvarCompWithInactive, consdata->nconsanddatas);
4273 
4274  consanddatas = consdata->consanddatas;
4275  oldandcoefs = consdata->andcoefs;
4276  oldandnegs = consdata->andnegs;
4277  nconsanddatas = consdata->nconsanddatas;
4278  assert(nconsanddatas == 0 || (consanddatas != NULL && oldandcoefs != NULL));
4279 
4280 #ifndef NDEBUG
4281  /* check that and-resultants are sorted, and coefficents are not zero */
4282  for( c = nandress - 1; c > 0; --c )
4283  {
4284  assert(!SCIPisZero(scip, andcoefs[c]));
4285  assert(SCIPvarGetIndex(andress[c]) > SCIPvarGetIndex(andress[c - 1]));
4286  }
4287  /* check that consanddata objects are sorted due to the index of the corresponding resultants, and coefficents are
4288  * not zero
4289  */
4290  for( c = nconsanddatas - 1; c > 0; --c )
4291  {
4292  SCIP_VAR* res1;
4293  SCIP_VAR* res2;
4294 
4295  assert(consanddatas[c] != NULL);
4296 
4297  if( !consanddatas[c]->istransformed )
4298  continue;
4299 
4300  assert(!SCIPisZero(scip, oldandcoefs[c]));
4301  assert(consanddatas[c - 1] != NULL);
4302 
4303  if( !consanddatas[c - 1]->istransformed )
4304  continue;
4305 
4306  assert(!SCIPisZero(scip, oldandcoefs[c - 1]));
4307 
4308  if( SCIPconsIsDeleted(consanddatas[c]->cons) || SCIPconsIsDeleted(consanddatas[c - 1]->cons) )
4309  continue;
4310 
4311  assert(consanddatas[c]->cons != NULL);
4312  res1 = SCIPgetResultantAnd(scip, consanddatas[c]->cons);
4313  assert(res1 != NULL);
4314  assert(consanddatas[c - 1]->cons != NULL);
4315  res2 = SCIPgetResultantAnd(scip, consanddatas[c - 1]->cons);
4316  assert(res2 != NULL);
4317 
4318  assert(SCIPvarGetIndex(res1) >= SCIPvarGetIndex(res2));
4319  }
4320 #endif
4321 
4322  snewconsanddatas = nconsanddatas + nandress;
4323 
4324  /* allocate new block memory arrays */
4325  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newconsanddatas, snewconsanddatas) );
4326  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newandcoefs, snewconsanddatas) );
4327  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &newandnegs, snewconsanddatas) );
4328 
4329  nnewconsanddatas = 0;
4330 
4331  /* collect new consanddata objects and update locks and captures */
4332  for( c = 0, c1 = 0; c < nconsanddatas && c1 < nandress; )
4333  {
4334  SCIP_CONS* andcons;
4335  SCIP_VAR* res1;
4336  SCIP_VAR* res2;
4337 
4338  assert(consanddatas[c] != NULL);
4339 
4340  /* consanddata object could have been deleted in the last presolving round */
4341  if( !consanddatas[c]->istransformed )
4342  {
4343  ++c;
4344  consdata->changed = TRUE;
4345  consdata->upgradetried = FALSE;
4346  continue;
4347  }
4348 
4349  andcons = consanddatas[c]->cons;
4350  assert(andcons != NULL);
4351 
4352  if( andcons == NULL ) /*lint !e774*/
4353  {
4354  ++c;
4355  consdata->changed = TRUE;
4356  consdata->upgradetried = FALSE;
4357  continue;
4358  }
4359  else if( SCIPconsIsDeleted(andcons) )
4360  {
4361  /* remove rounding locks, because the and constraint was deleted */
4362  SCIP_CALL( unlockRoundingAndCons(scip, cons, consanddatas[c],
4363  oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c], consdata->lhs, consdata->rhs) );
4364  ++c;
4365  consdata->changed = TRUE;
4366  consdata->upgradetried = FALSE;
4367  continue;
4368  }
4369  assert(andcons != NULL);
4370 
4371  /* get and-resultants of consanddata object in constraint data */
4372  res1 = SCIPgetResultantAnd(scip, andcons);
4373  assert(res1 != NULL);
4374  assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res1) == consanddatas[c]);
4375 
4376  /* get and-resultants in new corresponding linear constraint */
4377  res2 = andress[c1];
4378  assert(res2 != NULL);
4379  assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2) != NULL);
4380 
4381  /* collect new consanddata objects in sorted order due to the variable index of corresponding and-resultants */
4382  if( SCIPvarGetIndex(res1) < SCIPvarGetIndex(res2) )
4383  {
4384  assert(consanddatas[c]->nuses > 0);
4385  --(consanddatas[c]->nuses);
4386 
4387  /* remove old locks */
4388  SCIP_CALL( removeOldLocks(scip, cons, consanddatas[c], oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c],
4389  consdata->lhs, consdata->rhs) );
4390  ++c;
4391  consdata->changed = TRUE;
4392  consdata->upgradetried = FALSE;
4393  consdata->propagated = FALSE;
4394  consdata->presolved = FALSE;
4395  }
4396  else if( SCIPvarGetIndex(res1) > SCIPvarGetIndex(res2) )
4397  {
4398  assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res2));
4399  newconsanddatas[nnewconsanddatas] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2);
4400  newandcoefs[nnewconsanddatas] = andcoefs[c1];
4401  newandnegs[nnewconsanddatas] = andnegs[c1];
4402  ++(newconsanddatas[nnewconsanddatas]->nuses);
4403 
4404  /* add new locks */
4405  SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ?
4406  -newandcoefs[nnewconsanddatas] : newandcoefs[nnewconsanddatas], newlhs, newrhs) );
4407  ++c1;
4408  consdata->changed = TRUE;
4409  consdata->upgradetried = FALSE;
4410  consdata->cliquesadded = FALSE;
4411  consdata->propagated = FALSE;
4412  consdata->presolved = FALSE;
4413 
4414  ++nnewconsanddatas;
4415  }
4416  else
4417  {
4418  SCIP_Bool coefsignchanged;
4419  SCIP_Bool lhschanged;
4420  SCIP_Bool rhschanged;
4421 
4422  assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2) == consanddatas[c]);
4423 
4424  /* copy old consanddata object and new coefficent */
4425  newconsanddatas[nnewconsanddatas] = consanddatas[c];
4426 
4427  newandcoefs[nnewconsanddatas] = andcoefs[c1];
4428  newandnegs[nnewconsanddatas] = andnegs[c1];
4429 
4430  if( ((oldandnegs[c] == andnegs[c1]) && !SCIPisEQ(scip, oldandcoefs[c], newandcoefs[c1]))
4431  || ((oldandnegs[c] != newandnegs[c1]) && !SCIPisEQ(scip, oldandcoefs[c], -newandcoefs[c1])) )
4432  consdata->upgradetried = FALSE;
4433 
4434  coefsignchanged = (oldandnegs[c] == andnegs[c1]) &&
4435  ((oldandcoefs[c] < 0 && andcoefs[c1] > 0) || (oldandcoefs[c] > 0 && andcoefs[c1] < 0));
4436  coefsignchanged = coefsignchanged || ((oldandnegs[c] != andnegs[c1]) &&
4437  ((oldandcoefs[c] < 0 && andcoefs[c1] < 0) || (oldandcoefs[c] > 0 && andcoefs[c1] > 0)));
4438  lhschanged = (SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -newlhs)) || (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -newlhs))
4439  || (consdata->lhs < 0 && newlhs > 0) || (consdata->lhs > 0 && newlhs < 0);
4440  rhschanged = (SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, newrhs)) || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, newrhs))
4441  || (consdata->rhs < 0 && newrhs > 0) || (consdata->rhs > 0 && newrhs < 0);
4442 
4443  /* update or renew locks */
4444  if( coefsignchanged || lhschanged || rhschanged || newconsanddatas[nnewconsanddatas]->nnewvars > 0)
4445  {
4446  /* renew locks */
4447  SCIP_CALL( removeOldLocks(scip, cons, newconsanddatas[nnewconsanddatas], oldandnegs[c] ?
4448  -oldandcoefs[c] : oldandcoefs[c], consdata->lhs, consdata->rhs) );
4449  SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ?
4450  -newandcoefs[nnewconsanddatas] : newandcoefs[nnewconsanddatas], newlhs, newrhs) );
4451 
4452  consdata->changed = TRUE;
4453  consdata->upgradetried = FALSE;
4454  consdata->cliquesadded = FALSE;
4455  consdata->propagated = FALSE;
4456  consdata->presolved = FALSE;
4457  }
4458 
4459  ++c;
4460  ++c1;
4461  ++nnewconsanddatas;
4462  }
4463  }
4464 
4465  /* add all remaining consanddatas and update locks and captures */
4466  if( c < nconsanddatas )
4467  {
4468  assert(c1 == nandress);
4469 
4470  for( ; c < nconsanddatas; ++c )
4471  {
4472  SCIP_CONS* andcons;
4473 #ifndef NDEBUG
4474  SCIP_VAR* res1;
4475 
4476  assert(consanddatas[c] != NULL);
4477 #endif
4478  andcons = consanddatas[c]->cons;
4479 #ifndef NDEBUG
4480  if( andcons != NULL )
4481  {
4482  res1 = SCIPgetResultantAnd(scip, andcons);
4483  assert(res1 != NULL);
4484  assert(SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res1) == consanddatas[c]);
4485  }
4486 #endif
4487  if( andcons == NULL )
4488  {
4489  consdata->changed = TRUE;
4490  consdata->upgradetried = FALSE;
4491  continue;
4492  }
4493 
4494  assert(consanddatas[c]->nuses > 0);
4495  --(consanddatas[c]->nuses);
4496 
4497  /* remove old locks */
4498  SCIP_CALL( removeOldLocks(scip, cons, consanddatas[c], oldandnegs[c] ? -oldandcoefs[c] : oldandcoefs[c],
4499  consdata->lhs, consdata->rhs) );
4500  consdata->changed = TRUE;
4501  consdata->upgradetried = FALSE;
4502  consdata->propagated = FALSE;
4503  consdata->presolved = FALSE;
4504  }
4505  }
4506  else if( c1 < nandress )
4507  {
4508  for( ; c1 < nandress; ++c1 )
4509  {
4510  SCIP_VAR* res2;
4511 
4512  res2 = andress[c1];
4513  assert(res2 != NULL);
4514  assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res2));
4515  newconsanddatas[nnewconsanddatas] = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)res2);
4516  newandcoefs[nnewconsanddatas] = andcoefs[c1];
4517  newandnegs[nnewconsanddatas] = andnegs[c1];
4518  ++(newconsanddatas[nnewconsanddatas]->nuses);
4519 
4520  /* add new locks */
4521  SCIP_CALL( addNewLocks(scip, cons, newconsanddatas[nnewconsanddatas], newandnegs[nnewconsanddatas] ?
4522  -newandcoefs[nnewconsanddatas] : newandcoefs[nnewconsanddatas], newlhs, newrhs) );
4523 
4524  ++nnewconsanddatas;
4525  consdata->changed = TRUE;
4526  consdata->upgradetried = FALSE;
4527  consdata->cliquesadded = FALSE;
4528  consdata->propagated = FALSE;
4529  consdata->presolved = FALSE;
4530  }
4531  }
4532  assert(c == nconsanddatas && c1 == nandress);
4533 
4534  /* delete old and-coefficients and consanddata objects */
4535  SCIPfreeBlockMemoryArray(scip, &(consdata->andcoefs), consdata->sconsanddatas);
4536  SCIPfreeBlockMemoryArray(scip, &(consdata->andnegs), consdata->sconsanddatas);
4537  SCIPfreeBlockMemoryArray(scip, &(consdata->consanddatas), consdata->sconsanddatas);
4538 
4539  if( !SCIPisEQ(scip, consdata->lhs, newlhs) || !SCIPisEQ(scip, consdata->rhs, newrhs) )
4540  {
4541  consdata->upgradetried = FALSE;
4542  consdata->lhs = newlhs;
4543  consdata->rhs = newrhs;
4544  }
4545 
4546  consdata->consanddatas = newconsanddatas;
4547  consdata->andcoefs = newandcoefs;
4548  consdata->andnegs = newandnegs;
4549  consdata->nconsanddatas = nnewconsanddatas;
4550  consdata->sconsanddatas = snewconsanddatas;
4551 
4552  oldnvars = consdata->nlinvars;
4553  /* update number of linear variables without and-resultants */
4554  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &(consdata->nlinvars)) );
4555  consdata->nlinvars -= nnewconsanddatas;
4556 
4557  if( oldnvars != consdata->nlinvars )
4558  {
4559  consdata->changed = TRUE;
4560  consdata->upgradetried = FALSE;
4561  consdata->cliquesadded = FALSE;
4562  consdata->propagated = FALSE;
4563  consdata->presolved = FALSE;
4564  }
4565 
4566  /* we need to re-sort and-constraints after indices of corresponding and-resultants, since we might have replaced
4567  * negated variables
4568  */
4569  SCIPsortPtrRealBool((void**)(consdata->consanddatas), consdata->andcoefs, consdata->andnegs, resvarCompWithInactive, consdata->nconsanddatas);
4570 
4571 #ifndef NDEBUG
4572  consanddatas = consdata->consanddatas;
4573  nconsanddatas = consdata->nconsanddatas;
4574  assert(nconsanddatas == 0 || consanddatas != NULL);
4575 
4576  /* check that consanddata objects are sorted with respect to the index of the corresponding resultants */
4577  for( c = nconsanddatas - 1; c > 0; --c )
4578  {
4579  SCIP_VAR* res1;
4580  SCIP_VAR* res2;
4581 
4582  assert(consanddatas[c] != NULL);
4583  assert(consanddatas[c]->cons != NULL);
4584  res1 = SCIPgetResultantAnd(scip, consanddatas[c]->cons);
4585  assert(res1 != NULL);
4586  assert(consanddatas[c - 1] != NULL);
4587  assert(consanddatas[c - 1]->cons != NULL);
4588  res2 = SCIPgetResultantAnd(scip, consanddatas[c - 1]->cons);
4589  assert(res2 != NULL);
4590 
4591  assert(SCIPvarGetIndex(res1) > SCIPvarGetIndex(res2));
4592  }
4593 #endif
4594 
4595  return SCIP_OKAY;
4596 }
4597 
4598 /** adds cliques of the pseudoboolean constraint to the global clique table */
4599 static
4601  SCIP*const scip, /**< SCIP data structure */
4602  SCIP_CONS*const cons, /**< pseudoboolean constraint */
4603  SCIP_Bool*const cutoff, /**< pointer to store whether the node can be cut off */
4604  int*const naggrvars, /**< pointer to count the number of aggregated variables */
4605  int*const nchgbds /**< pointer to count the number of performed bound changes */
4606  )
4607 {
4608  SCIP_CONSDATA* consdata;
4609  SCIP_VAR** vars;
4610  int nvars;
4611  SCIP_VAR** linvars;
4612  SCIP_VAR* andres;
4613  SCIP_VAR* andres2;
4614  int nlinvars;
4615  int nandress;
4616  int c;
4617  int v2;
4618  int v1;
4619  int nchgbdslocal;
4620 
4621  assert(scip != NULL);
4622  assert(cons != NULL);
4623  assert(cutoff != NULL);
4624  assert(naggrvars != NULL);
4625  assert(nchgbds != NULL);
4626  assert(SCIPconsIsActive(cons));
4627 
4628  *cutoff = FALSE;
4629 
4630  consdata = SCIPconsGetData(cons);
4631  assert(consdata != NULL);
4632  /* if we have no and-constraints left, we should not be here and this constraint should be deleted (only the linaer should survive) */
4633  assert(consdata->nconsanddatas > 0);
4634 
4635  /* check whether the cliques have already been added */
4636  if( consdata->cliquesadded )
4637  return SCIP_OKAY;
4638 
4639  consdata->cliquesadded = TRUE;
4640 
4641  checkConsConsistency(scip, cons);
4642 
4643  /* check standard pointers and sizes */
4644  assert(consdata->lincons != NULL);
4645  assert(SCIPconsIsActive(consdata->lincons));
4646  assert(consdata->linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
4647  assert(consdata->consanddatas != NULL);
4648  assert(consdata->nconsanddatas > 0);
4649  assert(consdata->nconsanddatas <= consdata->sconsanddatas);
4650 
4651  /* check number of linear variables */
4652  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
4653  assert(nvars == consdata->nlinvars + consdata->nconsanddatas);
4654 
4655  /* get temporary memory */
4656  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
4657  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
4658 
4659  /* get variables and coefficients */
4660  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, NULL, &nvars) );
4661 
4662  /* calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the
4663  * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array
4664  * afterwards
4665  * @todo should we take into accout the negation status of the cliques?
4666  */
4667  SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, NULL, nvars, linvars, NULL, &nlinvars,
4668  NULL, NULL, NULL, &nandress) );
4669 
4670  assert(nandress == consdata->nconsanddatas);
4671  assert(consdata->consanddatas != NULL);
4672 
4673  /* find cliques from linear variable to and-resultant */
4674  for( c = nandress - 1; c >= 0; --c )
4675  {
4676  CONSANDDATA* consanddata;
4677  SCIP_VAR** andvars;
4678  int nandvars;
4679 
4680  consanddata = consdata->consanddatas[c];
4681  assert(consanddata != NULL);
4682 
4683  andres = SCIPgetResultantAnd(scip, consanddata->cons);
4684 
4685  /* choose correct variable array */
4686  if( consanddata->nnewvars > 0 )
4687  {
4688  andvars = consanddata->newvars;
4689  nandvars = consanddata->nnewvars;
4690  }
4691  else
4692  {
4693  andvars = consanddata->vars;
4694  nandvars = consanddata->nvars;
4695  }
4696 
4697  for( v1 = nandvars - 1; v1 >= 0; --v1 )
4698  {
4699  SCIP_VAR* var1;
4700  SCIP_Bool values[2];
4701 
4702  var1 = andvars[v1];
4703  if( !SCIPvarIsActive(var1) && (!SCIPvarIsNegated(var1) || !SCIPvarIsActive(SCIPvarGetNegationVar(var1))) )
4704  continue;
4705 
4706  /* get active counterpart to check for common cliques */
4708  {
4709  var1 = SCIPvarGetNegationVar(var1);
4710  values[0] = FALSE;
4711  }
4712  else
4713  values[0] = TRUE;
4714 
4715  for( v2 = nlinvars - 1; v2 >= 0; --v2 )
4716  {
4717  SCIP_VAR* var2;
4718 
4719  var2 = linvars[v2];
4720  if( !SCIPvarIsActive(var2) && (!SCIPvarIsNegated(var2) || !SCIPvarIsActive(SCIPvarGetNegationVar(var2))) )
4721  continue;
4722 
4723  /* get active counterpart to check for common cliques */
4725  {
4726  var2 = SCIPvarGetNegationVar(var2);
4727  values[1] = FALSE;
4728  }
4729  else
4730  values[1] = TRUE;
4731 
4732  /* if variable in and-constraint1 is the negated variable of a normal linear variable, than we can add a
4733  * clique between the and-resultant and the normal linear variable, negated variables are not save in
4734  * cliquetables
4735  *
4736  * set r_1 = var1 * z; (z is some product)
4737  * var1 == ~var2
4738  *
4739  * if:
4740  * var1 + ~var1 <= 1; r_1
4741  * 0 + 1 <= 1 0 \
4742  * 1 + 0 <= 1 ==> 1 or 0 > ==> r_1 + var2 <= 1
4743  * 0 + 0 <= 1 0 /
4744  */
4745  if( values[0] != values[1] && var1 == var2 )
4746  {
4747  SCIP_CONS* newcons;
4748  SCIP_VAR* clqvars[2];
4749  char consname[SCIP_MAXSTRLEN];
4750 
4751  clqvars[0] = andres;
4752  clqvars[1] = values[1] ? var2 : SCIPvarGetNegatedVar(var2);
4753  assert(clqvars[1] != NULL);
4754 
4755  /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
4756 
4757  /* add clique */
4758  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
4759  if( *cutoff )
4760  goto TERMINATE;
4761 
4762  *nchgbds += nchgbdslocal;
4763 
4764  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
4765  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
4767  FALSE, SCIPconsIsPropagated(cons),
4770 
4771  SCIP_CALL( SCIPaddCons(scip, newcons) );
4772  SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
4773  SCIPdebugPrintCons(scip, newcons, NULL);
4774 
4775  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
4776  }
4777  /* if a variable in an and-constraint is in a clique with another normal linear variable, we can add the
4778  * clique between the linear variable and the and-resultant
4779  *
4780  * set r_1 = var1 * z; (z is some product)
4781  *
4782  * if:
4783  * var1 + var2 <= 1; r_1
4784  * 0 + 1 <= 1 0 \
4785  * 1 + 0 <= 1 ==> 1 or 0 > ==> r_1 + var2 <= 1
4786  * 0 + 0 <= 1 0 /
4787  */
4788  if( (var1 != var2) && SCIPvarsHaveCommonClique(var1, values[0], var2, values[1], TRUE) )
4789  {
4790  SCIP_CONS* newcons;
4791  SCIP_VAR* clqvars[2];
4792  char consname[SCIP_MAXSTRLEN];
4793 
4794  clqvars[0] = andres;
4795  clqvars[1] = values[1] ? var2 : SCIPvarGetNegatedVar(var2);
4796  assert(clqvars[1] != NULL);
4797 
4798  /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
4799 
4800  /* add clique */
4801  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
4802  if( *cutoff )
4803  goto TERMINATE;
4804 
4805  *nchgbds += nchgbdslocal;
4806 
4807  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
4808  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
4810  FALSE, SCIPconsIsPropagated(cons),
4813 
4814  SCIP_CALL( SCIPaddCons(scip, newcons) );
4815  SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
4816  SCIPdebugPrintCons(scip, newcons, NULL);
4817 
4818  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
4819  }
4820  }
4821  }
4822  }
4823 
4824  /* find cliques over variables which are in different and-constraints */
4825  for( c = nandress - 1; c > 0; --c )
4826  {
4827  CONSANDDATA* consanddata1;
4828  CONSANDDATA* consanddata2;
4829  SCIP_VAR** andvars1;
4830  int nandvars1;
4831  SCIP_VAR** andvars2;
4832  int nandvars2;
4833 
4834  consanddata1 = consdata->consanddatas[c];
4835  assert(consanddata1 != NULL);
4836  consanddata2 = consdata->consanddatas[c - 1];
4837  assert(consanddata2 != NULL);
4838 
4839  andres = SCIPgetResultantAnd(scip, consanddata1->cons);
4840  andres2 = SCIPgetResultantAnd(scip, consanddata2->cons);
4841 
4842  /* choose correct variable array of consanddata object 1 */
4843  if( consanddata1->nnewvars > 0 )
4844  {
4845  andvars1 = consanddata1->newvars;
4846  nandvars1 = consanddata1->nnewvars;
4847  }
4848  else
4849  {
4850  andvars1 = consanddata1->vars;
4851  nandvars1 = consanddata1->nvars;
4852  }
4853 
4854  /* choose correct variable array of consanddata object 2 */
4855  if( consanddata2->nnewvars > 0 )
4856  {
4857  andvars2 = consanddata2->newvars;
4858  nandvars2 = consanddata2->nnewvars;
4859  }
4860  else
4861  {
4862  andvars2 = consanddata2->vars;
4863  nandvars2 = consanddata2->nvars;
4864  }
4865 
4866  /* compare both terms for finding new aggregated variables and new cliques */
4867  for( v1 = nandvars1 - 1; v1 >= 0; --v1 )
4868  {
4869  SCIP_VAR* var1;
4870  SCIP_Bool values[2];
4871 
4872  var1 = andvars1[v1];
4873  if( !SCIPvarIsActive(var1) && (!SCIPvarIsNegated(var1) || !SCIPvarIsActive(SCIPvarGetNegationVar(var1))) )
4874  continue;
4875 
4876  /* get active counterpart to check for common cliques */
4878  {
4879  var1 = SCIPvarGetNegationVar(var1);
4880  values[0] = FALSE;
4881  }
4882  else
4883  values[0] = TRUE;
4884 
4885  for( v2 = nandvars2 - 1; v2 >= 0; --v2 )
4886  {
4887  SCIP_VAR* var2;
4888 
4889  var2 = andvars2[v2];
4890  if( !SCIPvarIsActive(var2) && (!SCIPvarIsNegated(var2) || !SCIPvarIsActive(SCIPvarGetNegationVar(var2))) )
4891  continue;
4892 
4893  /* get active counterpart to check for common cliques */
4895  {
4896  var2 = SCIPvarGetNegationVar(var2);
4897  values[1] = FALSE;
4898  }
4899  else
4900  values[1] = TRUE;
4901 
4902  /* if a variable in and-constraint1 is the negated variable of a variable in and-constraint2, than we can
4903  * add a clique between both and-resultants, negated variables are not save in cliquetables
4904  *
4905  * set r_1 = var1 * z_1; (z_1 is some product)
4906  * set r_2 = var2 * z_2; (z_2 is some product)
4907  * var1 == ~var2
4908  *
4909  * if:
4910  * var1 + ~var1 <= 1; r_1 r_2
4911  * 0 + 1 <= 1 0 1 or 0 \
4912  * 1 + 0 <= 1 ==> 1 or 0 0 > ==> r_1 + r_2 <= 1
4913  * 0 + 0 <= 1 0 0 /
4914  */
4915  if( values[0] != values[1] && var1 == var2 )
4916  {
4917  SCIP_CONS* newcons;
4918  SCIP_VAR* clqvars[2];
4919  char consname[SCIP_MAXSTRLEN];
4920 
4921  clqvars[0] = andres;
4922  clqvars[1] = andres2;
4923 
4924  /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
4925 
4926  /* add clique */
4927  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
4928  if( *cutoff )
4929  goto TERMINATE;
4930 
4931  *nchgbds += nchgbdslocal;
4932 
4933  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
4934  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
4936  FALSE, SCIPconsIsPropagated(cons),
4939 
4940  SCIP_CALL( SCIPaddCons(scip, newcons) );
4941  SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
4942  SCIPdebugPrintCons(scip, newcons, NULL);
4943 
4944  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
4945  }
4946  /* if a variable in an and-constraint is in a clique with a variable in another and-constraint, we can add
4947  * the clique between both and-resultant
4948  *
4949  * let r_1 = var1 * z_1; (z_1 is some product)
4950  * let r_2 = var2 * z_2; (z_2 is some product)
4951  *
4952  * if:
4953  * var1 + var2 <= 1; r_1 r_2
4954  * 0 + 1 <= 1 0 1 or 0 \
4955  * 1 + 0 <= 1 ==> 1 or 0 0 > ==> r_1 + r_2 <= 1
4956  * 0 + 0 <= 1 0 0 /
4957  */
4958  else if( SCIPvarsHaveCommonClique(var1, values[0], var2, values[1], TRUE) && (var1 != var2) )
4959  {
4960  SCIP_CONS* newcons;
4961  SCIP_VAR* clqvars[2];
4962  char consname[SCIP_MAXSTRLEN];
4963 
4964  clqvars[0] = andres;
4965  clqvars[1] = values[1] ? var2 : SCIPvarGetNegatedVar(var2);
4966  assert(clqvars[1] != NULL);
4967 
4968  /* @todo: check whether it is better to only add the clique or to add the setppc constraint or do both */
4969 
4970  /* add clique */
4971  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, 2, FALSE, cutoff, &nchgbdslocal) );
4972  if( *cutoff )
4973  goto TERMINATE;
4974 
4975  *nchgbds += nchgbdslocal;
4976 
4977  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_clq_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(clqvars[0]), SCIPvarGetName(clqvars[1]) );
4978  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, consname, 2, clqvars,
4980  FALSE, SCIPconsIsPropagated(cons),
4983 
4984  SCIP_CALL( SCIPaddCons(scip, newcons) );
4985  SCIPdebugMsg(scip, "added a clique/setppc constraint <%s> \n", SCIPconsGetName(newcons));
4986  SCIPdebugPrintCons(scip, newcons, NULL);
4987 
4988  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
4989  }
4990  }
4991  }
4992  }
4993 
4994  TERMINATE:
4995  /* free temporary memory */
4996  SCIPfreeBufferArray(scip, &linvars);
4997  SCIPfreeBufferArray(scip, &vars);
4998 
4999  return SCIP_OKAY;
5000 }
5001 
5002 /** propagation method for pseudoboolean constraints */
5003 static
5005  SCIP*const scip, /**< SCIP data structure */
5006  SCIP_CONS*const cons, /**< knapsack constraint */
5007  SCIP_Bool*const cutoff, /**< pointer to store whether the node can be cut off */
5008  int*const ndelconss /**< pointer to count number of deleted constraints */
5009  )
5010 {
5011  SCIP_CONSDATA* consdata;
5012 
5013  assert(scip != NULL);
5014  assert(cons != NULL);
5015  assert(cutoff != NULL);
5016  assert(ndelconss != NULL);
5017 
5018  *cutoff = FALSE;
5019 
5020  consdata = SCIPconsGetData(cons);
5021  assert(consdata != NULL);
5022  assert(consdata->lincons != NULL);
5023 
5024  /* if linear constraint is redundant, than pseudoboolean constraint is redundant too */
5025  if( SCIPconsIsDeleted(consdata->lincons) )
5026  {
5027  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
5028  ++(*ndelconss);
5029  }
5030 
5031  /* check if the constraint was already propagated */
5032  if( consdata->propagated )
5033  return SCIP_OKAY;
5034 
5035  /* mark the constraint propagated */
5036  consdata->propagated = TRUE;
5037 
5038  return SCIP_OKAY;
5039 }
5040 
5041 /** update and-constraint flags due to pseudoboolean constraint flags */
5042 static
5044  SCIP*const scip, /**< SCIP data structure */
5045  SCIP_CONS*const cons /**< pseudoboolean constraint */
5046  )
5047 {
5048  CONSANDDATA** consanddatas;
5049  int nconsanddatas;
5050  SCIP_CONSDATA* consdata;
5051  int c;
5052 
5053  assert(scip != NULL);
5054  assert(cons != NULL);
5055 
5056  consdata = SCIPconsGetData(cons);
5057  assert(consdata != NULL);
5058 
5059  consanddatas = consdata->consanddatas;
5060  nconsanddatas = consdata->nconsanddatas;
5061  assert(nconsanddatas == 0 || consanddatas != NULL);
5062 
5063  if( !SCIPconsIsActive(cons) )
5064  return SCIP_OKAY;
5065 
5066  /* release and-constraints and change check flag of and-constraint */
5067  for( c = nconsanddatas - 1; c >= 0; --c )
5068  {
5069  SCIP_CONS* andcons;
5070 
5071  assert(consanddatas[c] != NULL);
5072 
5073  if( !consanddatas[c]->istransformed )
5074  continue;
5075 
5076  andcons = consanddatas[c]->cons;
5077  assert(andcons != NULL);
5078 
5079  SCIP_CALL( SCIPsetConsChecked(scip, andcons, SCIPconsIsChecked(cons)) );
5080  }
5081 
5082  return SCIP_OKAY;
5083 }
5084 
5085 /** delete unused information in constraint handler data */
5086 static
5088  SCIP*const scip, /**< SCIP data structure */
5089  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
5090  int*const ndelconss /**< pointer to count number of deleted constraints */
5091  )
5092 {
5093  CONSANDDATA** allconsanddatas;
5094  CONSANDDATA* consanddata;
5095  int c;
5096 
5097  assert(scip != NULL);
5098  assert(conshdlrdata != NULL);
5099  assert(ndelconss != NULL);
5100 
5101  allconsanddatas = conshdlrdata->allconsanddatas;
5102  assert(allconsanddatas != NULL);
5103  assert(conshdlrdata->nallconsanddatas > 0);
5104  assert(conshdlrdata->nallconsanddatas <= conshdlrdata->sallconsanddatas);
5105 
5106  for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c )
5107  {
5108  SCIP_VAR** tmpvars;
5109  int stmpvars;
5110  SCIP_CONS* cons;
5111  int v;
5112 
5113  consanddata = allconsanddatas[c];
5114 
5115  assert(consanddata->nvars == 0 || (consanddata->vars != NULL && consanddata->svars > 0));
5116  assert(consanddata->nnewvars == 0 || (consanddata->newvars != NULL && consanddata->snewvars > 0));
5117 
5118  if( !consanddata->istransformed )
5119  {
5120  assert(consanddata->vars == NULL || consanddata->origcons != NULL);
5121  assert(consanddata->nvars == 0 || consanddata->origcons != NULL);
5122  assert(consanddata->svars == 0 || consanddata->origcons != NULL);
5123  assert(consanddata->newvars == NULL);
5124  assert(consanddata->nnewvars == 0);
5125  assert(consanddata->snewvars == 0);
5126 
5127  continue;
5128  }
5129 
5130  /* if no variables are left, delete variables arrays */
5131  if( consanddata->nvars == 0 )
5132  {
5133  SCIP_VAR* resvar = SCIPgetResultantAnd(scip, consanddata->cons);
5134 
5135  /* if we have no old variables, than also no new variables */
5136  assert(consanddata->nnewvars == 0);
5137  assert(consanddata->nuses > 0);
5138  assert(resvar != NULL);
5139 
5140  /* delete and-constraint */
5141  SCIP_CALL( SCIPdelCons(scip, consanddata->cons) );
5142  ++(*ndelconss);
5143 
5144  SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
5145 
5146  /* release and-constraint */
5147  SCIP_CALL( SCIPreleaseCons(scip, &consanddata->cons) );
5148  consanddata->nuses = 0;
5149 
5150  /* remove consanddata from hashtable, if it existed only in transformed space */
5151  if( consanddata->origcons == NULL )
5152  {
5153  assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
5154  SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
5155  }
5156  assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)resvar));
5157  SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)resvar) );
5158 
5159  continue;
5160  }
5161 
5162  /* the consanddata object is not used anymore, so extract the and constraint and delete other data */
5163  if( consanddata->nuses == 0 )
5164  {
5165  SCIP_Bool looseorcolumn;
5166  SCIP_VARSTATUS varstatus;
5167 
5168  if( consanddata->cons == NULL )
5169  {
5170  assert(!consanddata->istransformed || consanddata->noriguses > 0);
5171  assert((consanddata->noriguses > 0) == (consanddata->origcons != NULL));
5172  assert(consanddata->vars == NULL || consanddata->origcons != NULL);
5173  assert(consanddata->nvars == 0 || consanddata->origcons != NULL);
5174  assert(consanddata->svars == 0 || consanddata->origcons != NULL);
5175  assert(consanddata->newvars == NULL);
5176  assert(consanddata->nnewvars == 0);
5177  assert(consanddata->snewvars == 0);
5178 
5179  continue;
5180  }
5181 
5182  SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
5183 
5184  varstatus = SCIPvarGetStatus(SCIPgetResultantAnd(scip, consanddata->cons));
5185  looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN);
5186 
5187 #if 1
5188  /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only
5189  * delete the and-constraint if the resultant is of column or loose status
5190  * and is not an active variable of another (multi-)aggregated/negated variable
5191  */
5192  if( looseorcolumn )
5193  {
5194  SCIP_Bool del = TRUE;
5195  int nfixedvars = SCIPgetNFixedVars(scip);
5196 
5197  if( nfixedvars > 0 )
5198  {
5199  SCIP_VAR** fixedvars;
5200  SCIP_VAR** scipfixedvars;
5201  SCIP_VAR** activevars = NULL;
5202  SCIP_Real* activescalars = NULL;
5203  SCIP_Real activeconstant;
5204  int nactivevars;
5205  int requiredsize;
5206  int pos;
5207  int w;
5208 
5209  scipfixedvars = SCIPgetFixedVars(scip);
5210  SCIP_CALL( SCIPduplicateBufferArray(scip, &fixedvars, scipfixedvars, nfixedvars) );
5211 
5212  SCIPvarsGetProbvar(fixedvars, nfixedvars);
5213 
5214  /* all inactive variables have a loose, column, fixed or multi-aggregated variable as counterpart,
5215  * for multi-aggregated variables, we need to check all active representatives
5216  * @todo move this outside of the consanddata loop
5217  */
5218  for( w = nfixedvars - 1; w >= 0; --w )
5219  {
5220  if( SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_MULTAGGR )
5221  {
5222  if( activevars == NULL )
5223  {
5224  SCIP_CALL( SCIPallocBufferArray(scip, &activevars, SCIPgetNVars(scip)) );
5225  SCIP_CALL( SCIPallocBufferArray(scip, &activescalars, SCIPgetNVars(scip)) );
5226  }
5227  assert(activevars != NULL);
5228  assert(activescalars != NULL);
5229 
5230  activevars[0] = fixedvars[w];
5231  activescalars[0] = 1.0;
5232  activeconstant = 0.0;
5233  nactivevars = 1;
5234 
5235  SCIP_CALL( SCIPgetProbvarLinearSum(scip, activevars, activescalars, &nactivevars, SCIPgetNVars(scip),
5236  &activeconstant, &requiredsize, TRUE) );
5237  assert(requiredsize <= SCIPgetNVars(scip));
5238 
5239  if( nactivevars == 0 )
5240  {
5241  --nfixedvars;
5242  fixedvars[w] = fixedvars[nfixedvars];
5243  }
5244  else
5245  {
5246  fixedvars[w] = activevars[0];
5247 
5248  if( nactivevars > 1 )
5249  {
5250  int i;
5251 
5252  SCIP_CALL( SCIPreallocBufferArray(scip, &fixedvars, nfixedvars + nactivevars - 1) );
5253  for( i = 1; i < nactivevars; ++i )
5254  {
5255  assert(SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(activevars[i]) == SCIP_VARSTATUS_FIXED);
5256  fixedvars[nfixedvars] = activevars[i];
5257  ++nfixedvars;
5258  }
5259  }
5260  }
5261  }
5262 
5263  assert(SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_FIXED);
5264  }
5265 
5266  if( activevars != NULL )
5267  {
5268  SCIPfreeBufferArray(scip, &activevars);
5269  SCIPfreeBufferArray(scip, &activescalars);
5270  }
5271 
5272  SCIPsortPtr((void**)fixedvars, SCIPvarComp, nfixedvars);
5273 
5274  if( SCIPsortedvecFindPtr((void**)fixedvars, SCIPvarComp, SCIPgetResultantAnd(scip, consanddata->cons), nfixedvars, &pos) )
5275  del = FALSE;
5276 
5277  SCIPfreeBufferArray(scip, &fixedvars);
5278  }
5279 
5280  if( del )
5281  {
5282  SCIP_CALL( SCIPdelCons(scip, consanddata->cons) );
5283  }
5284  }
5285 #endif
5286 
5287  if( !SCIPconsIsDeleted(consanddata->cons) )
5288  {
5289  /* change flags */
5290  if( !looseorcolumn )
5291  {
5292  SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) );
5293 #if 0
5294  SCIP_CALL( SCIPsetConsSeparated(scip, consanddata->cons, FALSE) );
5295 #endif
5296  }
5297  SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) );
5298  }
5299 
5300  /* remove consanddata from hashtable, if it existed only in transformed space */
5301  if( consanddata->origcons == NULL )
5302  {
5303  assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
5304  SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
5305  }
5306  assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)));
5307  SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)) );
5308 
5309  SCIP_CALL( SCIPreleaseCons(scip, &(consanddata->cons)) );
5310  ++(*ndelconss);
5311 
5312  continue;
5313  }
5314 
5315  cons = consanddata->cons;
5316  assert(cons != NULL);
5317 
5318  /* if and-constraint is deleted, delete variables arrays */
5319  if( SCIPconsIsDeleted(cons) )
5320  {
5321  SCIP_VAR* resvar = SCIPgetResultantAnd(scip, consanddata->cons);
5322 
5323  assert(consanddata->nuses > 0);
5324  assert(resvar != NULL);
5325 
5326  SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
5327 
5328  /* release and-constraint */
5329  SCIP_CALL( SCIPreleaseCons(scip, &consanddata->cons) );
5330  consanddata->nuses = 0;
5331 
5332  /* remove consanddata from hashtable, if it existed only in transformed space */
5333  if( consanddata->origcons == NULL )
5334  {
5335  assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
5336  SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
5337  }
5338  assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)resvar));
5339  SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)resvar) );
5340 
5341  continue;
5342  }
5343 
5344  /* if no new variables exist, we do not need to do anything here */
5345  if( consanddata->nnewvars == 0 )
5346  continue;
5347 
5348  tmpvars = consanddata->vars;
5349  /* release all variables */
5350  for( v = consanddata->nvars - 1; v >= 0; --v )
5351  {
5352  /* in original problem the variables was already deleted */
5353  assert(tmpvars[v] != NULL);
5354  SCIP_CALL( SCIPreleaseVar(scip, &tmpvars[v]) );
5355  }
5356 
5357  /* exchange newvars with old vars array */
5358  tmpvars = consanddata->vars;
5359  stmpvars = consanddata->svars;
5360  consanddata->vars = consanddata->newvars;
5361  consanddata->svars = consanddata->snewvars;
5362  consanddata->nvars = consanddata->nnewvars;
5363  consanddata->newvars = tmpvars;
5364  consanddata->snewvars = stmpvars;
5365  /* reset number of variables in newvars array */
5366  consanddata->nnewvars = 0;
5367  }
5368 
5369  return SCIP_OKAY;
5370 }
5371 
5372 /** update the uses counter of consandata objects which are used in pseudoboolean constraint, that were deleted and
5373  * probably delete and-constraints
5374  */
5375 static
5377  SCIP*const scip, /**< SCIP data structure */
5378  SCIP_CONS*const cons, /**< pseudoboolean constraint */
5379  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
5380  int*const ndelconss /**< pointer to store number of deleted constraints */
5381  )
5382 {
5383  CONSANDDATA** consanddatas;
5384  int nconsanddatas;
5385  SCIP_CONSDATA* consdata;
5386  int c;
5387 
5388  assert(scip != NULL);
5389  assert(cons != NULL);
5390  assert(conshdlrdata != NULL);
5391  assert(ndelconss != NULL);
5392 
5393  /* can only be called when constraint was deleted */
5394  assert(SCIPconsIsDeleted(cons));
5395 
5396  consdata = SCIPconsGetData(cons);
5397  assert(consdata != NULL);
5398 
5399  consanddatas = consdata->consanddatas;
5400  nconsanddatas = consdata->nconsanddatas;
5401  assert(nconsanddatas > 0 && consanddatas != NULL);
5402  assert(consdata->andcoefs != NULL);
5403 
5404  /* remove old locks */
5405  for( c = nconsanddatas - 1; c >= 0; --c )
5406  {
5407  CONSANDDATA* consanddata;
5408 
5409  consanddata = consanddatas[c];
5410  assert(consanddata != NULL);
5411 
5412  if( !consanddata->istransformed )
5413  continue;
5414 
5415  SCIP_CALL( removeOldLocks(scip, cons, consanddata, consdata->andcoefs[c], consdata->lhs, consdata->rhs) );
5416  }
5417 
5418  /* correct consandata usage counters and data */
5419  for( c = nconsanddatas - 1; c >= 0; --c )
5420  {
5421  CONSANDDATA* consanddata;
5422 
5423  consanddata = consanddatas[c];
5424  assert(consanddata != NULL);
5425  assert(consanddatas[c]->istransformed);
5426 
5427  assert(consanddata->nuses > 0);
5428 
5429  if( consanddata->nuses > 0 )
5430  --(consanddata->nuses);
5431 
5432  /* if data object is not used anymore, delete it */
5433  if( consanddata->nuses == 0 )
5434  {
5435  SCIP_VAR* resvar;
5436  SCIP_VARSTATUS varstatus;
5437  SCIP_Bool looseorcolumn;
5438 
5439  SCIP_CALL( transformToOrig(scip, consanddata, conshdlrdata) );
5440 
5441  resvar = SCIPgetResultantAnd(scip, consanddata->cons);
5442  assert(resvar != NULL);
5443 
5444  varstatus = SCIPvarGetStatus(resvar);
5445  looseorcolumn = (varstatus == SCIP_VARSTATUS_LOOSE || varstatus == SCIP_VARSTATUS_COLUMN);
5446 
5447 #if 1
5448  /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only
5449  * delete the and-constraint if the resultant is of column or loose status
5450  * and is not an active variable of another (multi-)aggregated/negated variable
5451  */
5452  if( looseorcolumn )
5453  {
5454  SCIP_Bool delcons = TRUE;
5455 #if 0
5456  const int nfixedvars = SCIPgetNFixedVars(scip);
5457 
5458  if( nfixedvars > 0 )
5459  {
5460  SCIP_VAR** fixedvars;
5461  SCIP_Bool foundmultiaggrvar = FALSE; /* workaround for multi-aggregated variables */
5462  int pos;
5463  int w;
5464 
5465  SCIP_CALL( SCIPduplicateBufferArray(scip, &fixedvars, SCIPgetFixedVars(scip), nfixedvars) );
5466 
5467  SCIPvarsGetProbvar(fixedvars, nfixedvars);
5468 
5469  /* all inactive variables have a loose, column, fixed or multi-aggregated variable as counterpart, but
5470  * because we have only binary variables (in pseudobbolean contest) there should also be no
5471  * multi-aggregated variable
5472  *
5473  * @todo for multi-aggregated variables check also all active representatives for this resultant
5474  */
5475  for( w = nfixedvars - 1; w >= 0; --w )
5476  {
5477  if( SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_MULTAGGR )
5478  foundmultiaggrvar = TRUE;
5479  else
5480  assert(SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(fixedvars[w]) == SCIP_VARSTATUS_FIXED);
5481  }
5482 
5483  SCIPsortPtr((void**)fixedvars, SCIPvarComp, nfixedvars);
5484 
5485  if( foundmultiaggrvar )
5486  delcons = FALSE;
5487  else if( SCIPsortedvecFindPtr((void**)fixedvars, SCIPvarComp, resvar, nfixedvars, &pos) )
5488  delcons = FALSE;
5489 
5490  SCIPfreeBufferArray(scip, &fixedvars);
5491  }
5492 #endif
5493  /* we can only delete and constraints if the resultant is an artificial variable and also active, because
5494  * then the assigned value is not of interest and the artificial and constraint does not need to be
5495  * fulfilled
5496  *
5497  * if this variable is not such an artificial variable we need the IRRELEVANT vartype which should be the
5498  * correct way to fix this
5499  */
5500  if( delcons
5501 #if 0
5502  && strlen(SCIPvarGetName(resvar)) > strlen(ARTIFICIALVARNAMEPREFIX) &&
5503  strncmp(SCIPvarGetName(resvar)+2, ARTIFICIALVARNAMEPREFIX, strlen(ARTIFICIALVARNAMEPREFIX)) == 0
5504 #endif
5505  ) /*lint !e774*/
5506  {
5507  assert(!SCIPconsIsChecked(consanddata->cons));
5508  SCIP_CALL( SCIPdelCons(scip, consanddata->cons) );
5509  }
5510  }
5511 #endif
5512 
5513 #if 0
5514  /* @note due to aggregations or fixings the resultant may need to be propagated later on, so we can only
5515  * delete the and-constraint if the resultant is of column or loose status
5516  * and is not an active variable of another (multi-)aggregated/negated variable
5517  */
5518  if( looseorcolumn )
5519  {
5520  SCIP_CALL( SCIPdelCons(scip, consanddata->cons) );
5521  }
5522 #endif
5523 
5524  if( !SCIPconsIsDeleted(consanddata->cons) )
5525  {
5526  /* change flags */
5527  if( !looseorcolumn )
5528  {
5529  SCIP_CALL( SCIPsetConsInitial(scip, consanddata->cons, FALSE) );
5530 #if 0
5531  SCIP_CALL( SCIPsetConsSeparated(scip, consanddata->cons, FALSE) );
5532 #endif
5533  }
5534  SCIP_CALL( SCIPsetConsChecked(scip, consanddata->cons, TRUE) );
5535  }
5536 
5537  /* remove consanddata from hashtable, if it existed only in transformed space */
5538  if( consanddata->origcons == NULL )
5539  {
5540  assert(SCIPhashtableExists(conshdlrdata->hashtable, (void*)consanddata));
5541  SCIP_CALL( SCIPhashtableRemove(conshdlrdata->hashtable, (void*)consanddata) );
5542  }
5543  assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)));
5544  SCIP_CALL( SCIPhashmapRemove(conshdlrdata->hashmap, (void*)SCIPgetResultantAnd(scip, consanddata->cons)) );
5545 
5546  SCIP_CALL( SCIPreleaseCons(scip, &(consanddata->cons)) );
5547  ++(*ndelconss);
5548  }
5549  }
5550 
5551  consdata->nconsanddatas = 0;
5552 
5553  return SCIP_OKAY;
5554 }
5555 
5556 
5557 /* maximal number to enumerate solutions for one pseudoboolean constraint to check for an upgrade to an XOR constraint */
5558 #define MAXNVARS 10 /* note that this cannot be bigger than 31 */
5560 /** calculate result for a given pseudoboolean constraint with given values, this is used to decide whether a
5561  * pseudoboolean constraint can be upgrade to an XOR constraint
5562  */
5563 static
5565  SCIP*const scip, /**< SCIP data structure */
5566  SCIP_VAR**const vars, /**< all variables which occur */
5567  int const nvars, /**< number of all variables which appear in the pseudoboolean
5568  * constraint
5569  */
5570  SCIP_Bool*const values, /**< values of all variables which appear in the pseudoboolean
5571  * constraint
5572  */
5573  SCIP_VAR**const linvars, /**< linear variables */
5574  SCIP_Real*const lincoefs, /**< linear coefficients */
5575  int const nlinvars, /**< number of linear variables */
5576  SCIP_Real const constant, /**< offset to the linear part */
5577  SCIP_Real const side, /**< side of pseudoboolean constraint */
5578  CONSANDDATA**const consanddatas, /**< all consanddata objects in a constraint */
5579  SCIP_Real*const consanddatacoefs, /**< nonlinear coefficients */
5580  SCIP_Bool*const consanddatanegs, /**< negation status of and resultants in pseudo-boolean constraint */
5581  int const nconsanddatas, /**< number of all consanddata objects */
5582  int const cnt, /**< number of variables set to 1 */
5583  int*const xortype /**< pointer to save the possible xor type if a solution was valid and does
5584  * not violate the old xortype
5585  */
5586  )
5587 {
5588  CONSANDDATA* consanddata;
5589  SCIP_VAR** termvars;
5590  SCIP_VAR** repvars;
5591  int ntermvars;
5592  SCIP_Bool* negated;
5593  SCIP_Real value;
5594  int pos;
5595  int v;
5596  int c;
5597 
5598  assert(scip != NULL);
5599  assert(vars != NULL);
5600  assert(nvars > 0);
5601  assert(values != NULL);
5602  assert(linvars != NULL || nlinvars == 0);
5603  assert(lincoefs != NULL || nlinvars == 0);
5604  assert(nvars >= nlinvars);
5605  assert(SCIPisEQ(scip, side, 1.0) || SCIPisZero(scip, side));
5606  assert(consanddatas != NULL);
5607  assert(consanddatacoefs != NULL);
5608  assert(nconsanddatas > 0);
5609  assert(*xortype >= -1 && *xortype <= 1);
5610 
5611  /* order the variables after index, to compare them easier */
5612  SCIPsortPtr((void**)linvars, SCIPvarCompActiveAndNegated, nlinvars);
5613  SCIPsortPtr((void**)vars, SCIPvarCompActiveAndNegated, nvars);
5614 
5615  value = constant;
5616  for( v = nlinvars - 1; v >= 0; --v )
5617  {
5618  if( SCIPsortedvecFindPtr((void**)vars, SCIPvarCompActiveAndNegated, linvars[v], nvars, &pos) ) /*lint !e613*/
5619  {
5620  if( values[pos] )
5621  value += lincoefs[v]; /*lint !e613*/
5622  }
5623  else
5624  {
5625  /* this cannot happen, all linear variables should be a part of 'vars' */
5626  SCIPABORT();
5627 
5628  *xortype = -1; /*lint !e527*/
5629  return SCIP_OKAY;
5630  }
5631  }
5632 
5633  SCIP_CALL( SCIPallocBufferArray(scip, &repvars, MAXNVARS) );
5634  SCIP_CALL( SCIPallocBufferArray(scip, &negated, MAXNVARS) );
5635 
5636  for( c = nconsanddatas - 1; c >= 0; --c )
5637  {
5638  SCIP_Bool val = TRUE;
5639 
5640  consanddata = consanddatas[c];
5641  assert(consanddata != NULL);
5642  assert(consanddata->istransformed);
5643 
5644  /* choose correct variable array to add locks for, we only add locks for now valid variables */
5645  if( consanddata->nnewvars > 0 )
5646  {
5647  termvars = consanddata->newvars;
5648  ntermvars = consanddata->nnewvars;
5649  }
5650  else
5651  {
5652  termvars = consanddata->vars;
5653  ntermvars = consanddata->nvars;
5654  }
5655  assert(ntermvars > 0 && termvars != NULL);
5656 
5657  BMSclearMemoryArray(negated, MAXNVARS);
5658 
5659  /* get linear active representation */
5660  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, ntermvars, termvars, repvars, negated) );
5661  SCIPsortPtrBool((void**)repvars, negated, SCIPvarCompActiveAndNegated, ntermvars);
5662 
5663  for( v = ntermvars - 1; v >= 0; --v )
5664  {
5665  SCIP_VAR* var;
5666 
5667  assert(!negated[v] || (SCIPvarIsNegated(repvars[v]) && SCIPvarGetNegatedVar(repvars[v]) != NULL));
5668 
5669  var = ( negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]);
5670  if( SCIPsortedvecFindPtr((void**)vars, SCIPvarCompActiveAndNegated, var, nvars, &pos) )
5671  {
5672  if( (negated[v] && values[pos]) || (!negated[v] && !values[pos]) )
5673  {
5674  val = FALSE;
5675  break;
5676  }
5677  }
5678  else
5679  {
5680  /* this cannot happen, all non-linear variables should be a part of 'vars' */
5681  SCIPABORT();
5682 
5683  *xortype = -1; /*lint !e527*/
5684  goto TERMINATE;
5685  }
5686  }
5687 
5688  if( val != consanddatanegs[c] )
5689  value += consanddatacoefs[c];
5690  }
5691 
5692  if( SCIPisEQ(scip, value, side) )
5693  {
5694  /* first solution is checked, so determine the possible xor upgrade */
5695  if( *xortype == -1 )
5696  {
5697  if( cnt % 2 == 0 )
5698  *xortype = 0;
5699  else
5700  *xortype = 1;
5701  }
5702  /* check if this solution does not fit in all possible xor solutions */
5703  else if( *xortype == 1 && cnt % 2 == 0 )
5704  *xortype = -1;
5705  else if( *xortype == 0 && cnt % 2 == 1 )
5706  *xortype = -1;
5707  }
5708  else
5709  {
5710  /* first not-solution is checked, so determine the possible xor upgrade */
5711  if( *xortype == -1 )
5712  {
5713  if( cnt % 2 == 0 )
5714  *xortype = 1;
5715  else
5716  *xortype = 0;
5717  }
5718  /* check if this had to be a solution for an upgrade to an xor */
5719  else if( *xortype == 1 && cnt % 2 == 1 )
5720  *xortype = -1;
5721  else if( *xortype == 0 && cnt % 2 == 0 )
5722  *xortype = -1;
5723  }
5724 
5725  TERMINATE:
5726  SCIPfreeBufferArray(scip, &negated);
5727  SCIPfreeBufferArray(scip, &repvars);
5728 
5729  return SCIP_OKAY;
5730 }
5731 
5732 /** try upgrading pseudoboolean linear constraint to an XOR constraint and/or remove possible and-constraints
5733  *
5734  * @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
5735  * trying to upgrade
5736  */
5737 static
5739  SCIP*const scip, /**< SCIP data structure */
5740  SCIP_CONS*const cons, /**< pseudoboolean constraint */
5741  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
5742  int*const ndelconss, /**< pointer to store number of deleted constraints */
5743  int*const naddconss, /**< pointer to count number of added constraints */
5744  int*const nfixedvars, /**< pointer to store number of fixed variables */
5745  int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
5746  int*const nchgsides, /**< pointer to store number of changed sides constraints */
5747  SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
5748  )
5749 {
5750  SCIP_CONSDATA* consdata;
5751  CONSANDDATA** consanddatas;
5752  int nconsanddatas;
5753  CONSANDDATA* consanddata;
5754  SCIP_VAR** allvars;
5755  SCIP_Real* allcoefs;
5756  int nallvars;
5757  SCIP_VAR** linvars;
5758  SCIP_Real* lincoefs;
5759  int nlinvars;
5760  SCIP_Real* andcoefs;
5761  SCIP_Bool* andnegs;
5762  int nandress;
5763  SCIP_VAR** vars;
5764  int nvars;
5765  SCIP_VAR** repvars;
5766  SCIP_Bool* negated;
5767  SCIP_VAR** activelinvars;
5768  SCIP_Bool* values;
5769  SCIP_CONS* lincons;
5770  SCIP_CONS* newcons;
5771  char newname[SCIP_MAXSTRLEN];
5772  SCIP_Real constant;
5773  int requiredsize;
5774  int firstnlinvars;
5775  int oldnlinvars;
5776  int xortype;
5777  int v;
5778  int v1;
5779  int c;
5780 
5781  assert(scip != NULL);
5782  assert(cons != NULL);
5783  assert(conshdlrdata != NULL);
5784  assert(ndelconss != NULL);
5785  assert(nfixedvars != NULL);
5786  assert(nchgcoefs != NULL);
5787  assert(nchgsides != NULL);
5788  assert(cutoff != NULL);
5789  assert(SCIPconsIsActive(cons));
5790 
5791  consdata = SCIPconsGetData(cons);
5792  assert(consdata != NULL);
5793 
5794  consanddatas = consdata->consanddatas;
5795  andcoefs = consdata->andcoefs;
5796  andnegs = consdata->andnegs;
5797  nconsanddatas = consdata->nconsanddatas;
5798  assert(nconsanddatas > 0 && consanddatas != NULL);
5799 
5800  assert(consdata->lincons != NULL);
5801  assert(consdata->linconstype == SCIP_LINEARCONSTYPE_LINEAR || consdata->linconstype == SCIP_LINEARCONSTYPE_SETPPC);
5802 
5803  /* only equations can be updated */
5804  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || (!SCIPisEQ(scip, consdata->lhs, 1.0) && !SCIPisZero(scip, consdata->lhs)) )
5805  return SCIP_OKAY;
5806 
5807  assert(consanddatas[0] != NULL);
5808  assert(consanddatas[0]->cons != NULL);
5809 
5810  lincons = consdata->lincons;
5811 
5812  /* check number of linear variables */
5813  SCIP_CALL( getLinearConsNVars(scip, lincons, consdata->linconstype, &nallvars) );
5814  assert(nallvars - nconsanddatas == consdata->nlinvars);
5815  nlinvars = consdata->nlinvars;
5816 
5817  if( nlinvars > MAXNVARS )
5818  return SCIP_OKAY;
5819 
5820  checkConsConsistency(scip, cons);
5821 
5822  /* allocate temporary memory */
5823  SCIP_CALL( SCIPallocBufferArray(scip, &allvars, nallvars) );
5824  SCIP_CALL( SCIPallocBufferArray(scip, &allcoefs, nallvars) );
5825  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, MAXNVARS) );
5826  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, MAXNVARS) );
5827  SCIP_CALL( SCIPallocBufferArray(scip, &repvars, MAXNVARS) );
5828  SCIP_CALL( SCIPallocBufferArray(scip, &negated, MAXNVARS) );
5829 
5830  /* get variables and coefficients */
5831  SCIP_CALL( getLinearConsVarsData(scip, lincons, consdata->linconstype, allvars, allcoefs, &nallvars) );
5832  assert(nallvars > 0);
5833 
5834  /* calculate all not artificial linear variables */
5835  SCIP_CALL( getLinVarsAndAndRess(scip, cons, allvars, allcoefs, nallvars, linvars, lincoefs, &nlinvars,
5836  NULL, NULL, NULL, &nandress) );
5837  assert(nlinvars == consdata->nlinvars);
5838  assert(nandress == nallvars-nlinvars);
5839 
5840  constant = 0;
5841 
5842  /* get linear active representation */
5843  SCIP_CALL( SCIPgetProbvarLinearSum(scip, linvars, lincoefs, &nlinvars, MAXNVARS, &constant, &requiredsize, TRUE) );
5844  SCIP_CALL( SCIPduplicateBufferArray(scip, &activelinvars, linvars, nlinvars) );
5845 
5846  if( requiredsize > MAXNVARS )
5847  goto TERMINATE;
5848 
5849  firstnlinvars = nlinvars;
5850 
5851  /* order the variables after index, to compare them easier */
5852  SCIPsortPtr((void**)linvars, SCIPvarCompActiveAndNegated, nlinvars);
5853 
5854  for( c = nconsanddatas - 1; c >= 0; --c )
5855  {
5856  consanddata = consanddatas[c];
5857  assert(consanddata != NULL);
5858  assert(consanddata->istransformed);
5859 
5860  /* choose correct variable array */
5861  if( consanddata->nnewvars > 0 )
5862  {
5863  vars = consanddata->newvars;
5864  nvars = consanddata->nnewvars;
5865  }
5866  else
5867  {
5868  vars = consanddata->vars;
5869  nvars = consanddata->nvars;
5870  }
5871  assert(nvars > 0 && vars != NULL);
5872 
5873  if( nvars > MAXNVARS )
5874  goto TERMINATE;
5875 
5876  BMSclearMemoryArray(negated, MAXNVARS);
5877 
5878  /* get linear active representation */
5879  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, vars, repvars, negated) );
5880  SCIPsortPtr((void**)repvars, SCIPvarCompActiveAndNegated, nvars);
5881 
5882  oldnlinvars = nlinvars;
5883 
5884  /* determine all different variables over the linear variables and all variables in all and constraints */
5885  for( v = nvars - 1, v1 = nlinvars - 1; v >= 0 && v1 >= 0; )
5886  {
5887  SCIP_VAR* var;
5888 
5889  /* it appears that some fixed variables were not yet deleted */
5890  if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
5891  goto TERMINATE;
5892 
5893  assert(SCIPvarIsActive(linvars[v1]));
5894  assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
5895 
5896  if( SCIPvarIsActive(repvars[v]) )
5897  var = repvars[v];
5898  else
5899  var = SCIPvarGetNegationVar(repvars[v]);
5900 
5901  if( SCIPvarGetIndex(var) > SCIPvarGetIndex(linvars[v1]) )
5902  {
5903  if( nlinvars + 1 < MAXNVARS )
5904  {
5905  linvars[nlinvars] = var;
5906  ++nlinvars;
5907  }
5908  else
5909  goto TERMINATE;
5910 
5911  --v;
5912  }
5913  else if( SCIPvarGetIndex(var) < SCIPvarGetIndex(linvars[v1]) )
5914  --v1;
5915  else
5916  {
5917  --v;
5918  --v1;
5919  }
5920  }
5921 
5922  /* add the rest of variables */
5923  if( v >= 0 )
5924  {
5925  SCIP_VAR* var;
5926 
5927  for( ; v >= 0; --v )
5928  {
5929  /* it appears that some fixed variables were not yet deleted */
5930  if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
5931  goto TERMINATE;
5932 
5933  assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
5934 
5935  if( SCIPvarIsActive(repvars[v]) )
5936  var = repvars[v];
5937  else
5938  var = SCIPvarGetNegationVar(repvars[v]);
5939 
5940  if( nlinvars + 1 < MAXNVARS )
5941  {
5942  linvars[nlinvars] = var;
5943  ++nlinvars;
5944  }
5945  else
5946  goto TERMINATE;
5947  }
5948  }
5949 
5950  /* if some new variables were inserted we need to reorder the array */
5951  if( nlinvars > oldnlinvars )
5952  {
5953  /* order the variables after index, to compare them easier */
5954  SCIPsortPtr((void**)linvars, SCIPvarCompActiveAndNegated, nlinvars);
5955  }
5956  }
5957 
5958  SCIP_CALL( SCIPallocBufferArray(scip, &values, nlinvars) );
5959  xortype = -1;
5960 
5961  /* check values for variables which result in solutions which in the end lead to an XOR upgrade */
5962  for( v = (1 << nlinvars) - 1; v >= 0; --v ) /*lint !e701*/
5963  {
5964  int cnt = 0;
5965  for( v1 = nlinvars - 1; v1 >= 0; --v1 )
5966  if( v & (1 << v1) ) /*lint !e701*/
5967  {
5968  values[v1] = TRUE;
5969  ++cnt;
5970  }
5971  else
5972  values[v1] = FALSE;
5973 
5974  /* at maximum nlinvars values could be set to TRUE */
5975  assert(cnt <= nlinvars);
5976 
5977  SCIP_CALL( checkSolution(scip, linvars, nlinvars, values, activelinvars, lincoefs, firstnlinvars, constant,
5978  consdata->lhs, consanddatas, andcoefs, andnegs, nconsanddatas, cnt, &xortype) );
5979  if( xortype == -1 )
5980  break;
5981  }
5982 
5983  SCIPfreeBufferArray(scip, &values);
5984 
5985  assert(xortype >= -1 && xortype <= 1);
5986 
5987  if( xortype >= 0 )
5988  {
5989  (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
5990 
5991  SCIP_CALL( SCIPcreateConsXor(scip, &newcons, newname, (unsigned int) xortype, nlinvars, linvars,
5992  SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
5993  SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
5994  SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
5995 
5996  /* add and release new constraint */
5997  SCIP_CALL( SCIPaddCons(scip, newcons) );
5998 
5999  SCIPdebugMsg(scip, "created upgraded XOR constraint:\n");
6000  SCIPdebugMsg(scip, "old -> ");
6001  SCIPdebugPrintCons(scip, lincons, NULL);
6002  SCIPdebugMsg(scip, "new -> ");
6003  SCIPdebugPrintCons(scip, newcons, NULL);
6004 
6005  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6006  ++(*naddconss);
6007 
6008  /* delete old constraints */
6009  SCIP_CALL( SCIPdelCons(scip, lincons) );
6010  SCIP_CALL( SCIPdelCons(scip, cons) );
6011  (*ndelconss) += 2;
6012  }
6013 
6014  TERMINATE:
6015  /* delete temporary memory */
6016  SCIPfreeBufferArray(scip, &activelinvars);
6017  SCIPfreeBufferArray(scip, &negated);
6018  SCIPfreeBufferArray(scip, &repvars);
6019  SCIPfreeBufferArray(scip, &lincoefs);
6020  SCIPfreeBufferArray(scip, &linvars);
6021  SCIPfreeBufferArray(scip, &allcoefs);
6022  SCIPfreeBufferArray(scip, &allvars);
6023 
6024  return SCIP_OKAY;
6025 }
6026 
6027 /** try upgrading pseudoboolean logicor constraint to a linear constraint and/or remove possible and-constraints */
6028 static
6030  SCIP*const scip, /**< SCIP data structure */
6031  SCIP_CONS*const cons, /**< pseudoboolean constraint */
6032  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
6033  int*const ndelconss, /**< pointer to store number of deleted constraints */
6034  int*const naddconss, /**< pointer to count number of added constraints */
6035  int*const nfixedvars, /**< pointer to store number of fixed variables */
6036  int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
6037  int*const nchgsides, /**< pointer to store number of changed sides constraints */
6038  SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
6039  )
6040 {
6041  CONSANDDATA** consanddatas;
6042  int nconsanddatas;
6043  SCIP_CONSDATA* consdata;
6044  int c;
6045  int v;
6046  int v2;
6047  SCIP_VAR** eqvars;
6048  int neqvars;
6049  int nminvars;
6050  int nmaxvars;
6051 
6052  assert(scip != NULL);
6053  assert(cons != NULL);
6054  assert(conshdlrdata != NULL);
6055  assert(ndelconss != NULL);
6056  assert(nfixedvars != NULL);
6057  assert(nchgcoefs != NULL);
6058  assert(nchgsides != NULL);
6059  assert(cutoff != NULL);
6060  assert(SCIPconsIsActive(cons));
6061 
6062  consdata = SCIPconsGetData(cons);
6063  assert(consdata != NULL);
6064 
6065  consanddatas = consdata->consanddatas;
6066  nconsanddatas = consdata->nconsanddatas;
6067  assert(nconsanddatas > 0 && consanddatas != NULL);
6068 
6069  assert(consdata->lincons != NULL);
6070  assert(consdata->linconstype == SCIP_LINEARCONSTYPE_LOGICOR);
6071 
6072  assert(consanddatas[0] != NULL);
6073  assert(consanddatas[0]->cons != NULL);
6074 
6075  if( nconsanddatas == 1 )
6076  {
6077  CONSANDDATA* consanddata;
6078  SCIP_VAR** allvars;
6079  SCIP_Real* allcoefs;
6080  int nallvars;
6081  SCIP_VAR** linvars;
6082  SCIP_Real* lincoefs;
6083  int nlinvars;
6084  SCIP_VAR** vars;
6085  int nvars;
6086  SCIP_CONS* lincons;
6087  SCIP_CONS* newcons;
6088  char newname[SCIP_MAXSTRLEN];
6089  SCIP_Real lhs;
6090  SCIP_Real rhs;
6091 
6092  /* if we have only one term left in the logicor constraint, the presolving should be done by the logicor
6093  * constraint handler
6094  */
6095  if( consdata->nlinvars == 0 )
6096  {
6097  return SCIP_OKAY;
6098  }
6099 
6100  /* for every old logicor constraint: sum_i (x_i) + res >= 1 , with an and-constraint of res as the resultant,
6101  * which looks like 'res = y_1 * ... * y_n' => sum_i (n * x_i) + sum_j=1^n y_j >= n
6102  *
6103  * i.e. x_1 + x_2 + x_3 + x_4 * x_5 * x_6 >= 1
6104  * => 3x_1 + 3x_2 + 3x_3 + x_4 + x_5 + x_6 >= 3
6105  */
6106 
6107  lincons = consdata->lincons;
6108 
6109  consanddata = consanddatas[0];
6110  assert(consanddata != NULL);
6111  assert(consanddata->istransformed);
6112 
6113  /* choose correct variable array to add locks for, we only add locks for now valid variables */
6114  if( consanddata->nnewvars > 0 )
6115  {
6116  vars = consanddata->newvars;
6117  nvars = consanddata->nnewvars;
6118  }
6119  else
6120  {
6121  vars = consanddata->vars;
6122  nvars = consanddata->nvars;
6123  }
6124  assert(nvars > 0 && vars != NULL);
6125 
6126  lhs = nvars;
6127  rhs = SCIPinfinity(scip);
6128 
6129  (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
6130 
6131  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, newname, 0, NULL, NULL, lhs, rhs,
6132  SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
6133  SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
6134  SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
6135 
6136  /* check number of linear variables */
6137  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nallvars) );
6138  assert(nallvars == consdata->nlinvars + 1);
6139 
6140  nlinvars = consdata->nlinvars;
6141 
6142  /* allocate temporary memory */
6143  SCIP_CALL( SCIPallocBufferArray(scip, &allvars, nallvars) );
6144  SCIP_CALL( SCIPallocBufferArray(scip, &allcoefs, nallvars) );
6145  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinvars) );
6146  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nlinvars) );
6147 
6148  /* get variables and coefficients */
6149  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, allvars, allcoefs, &nallvars) );
6150  assert(allcoefs != NULL);
6151 
6152  /* calculate all not artificial linear variables */
6153  SCIP_CALL( getLinVarsAndAndRess(scip, cons, allvars, allcoefs, nallvars, linvars, lincoefs, &nlinvars,
6154  NULL, NULL, NULL, NULL) );
6155  assert(nlinvars == consdata->nlinvars);
6156 
6157  /* add linear part to new constraint */
6158  for( v = 0; v < nlinvars; ++v )
6159  {
6160  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, linvars[v], (SCIP_Real) nvars) );
6161  }
6162 
6163  /* add non-linear part to new constraint */
6164  for( v = 0; v < nvars; ++v )
6165  {
6166  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v], 1.0) );
6167  }
6168 
6169  /* add and release new constraint */
6170  SCIP_CALL( SCIPaddCons(scip, newcons) );
6171 
6172  SCIPdebugMsg(scip, "created upgraded linear constraint:\n");
6173  SCIPdebugMsg(scip, "old -> ");
6174  SCIPdebugPrintCons(scip, lincons, NULL);
6175  SCIPdebugMsg(scip, "new -> ");
6176  SCIPdebugPrintCons(scip, newcons, NULL);
6177 
6178  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6179  ++(*naddconss);
6180 
6181  /* delete old constraints */
6182  SCIP_CALL( SCIPdelCons(scip, lincons) );
6183  SCIP_CALL( SCIPdelCons(scip, cons) );
6184  (*ndelconss) += 2;
6185 
6186  /* delete temporary memory */
6187  SCIPfreeBufferArray(scip, &lincoefs);
6188  SCIPfreeBufferArray(scip, &linvars);
6189  SCIPfreeBufferArray(scip, &allcoefs);
6190  SCIPfreeBufferArray(scip, &allvars);
6191 
6192  return SCIP_OKAY;
6193  }
6194 
6195  /* initializing array for variables which can appear in all consanddata objects */
6196  c = nconsanddatas - 1;
6197  assert(consanddatas[c]->istransformed);
6198 
6199  /* choose correct variable array */
6200  if( consanddatas[c]->nnewvars > 0 )
6201  {
6202  neqvars = consanddatas[c]->nnewvars;
6203  /* allocate temporary memory */
6204  SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->newvars, neqvars) );
6205  }
6206  else
6207  {
6208  neqvars = consanddatas[c]->nvars;
6209  /* allocate temporary memory */
6210  SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->vars, neqvars) );
6211  }
6212  nminvars = neqvars;
6213  nmaxvars = neqvars;
6214  assert(neqvars > 0 && eqvars != NULL);
6215 
6216 #ifndef NDEBUG
6217  /* check that variables are sorted */
6218  for( v = neqvars - 1; v > 0; --v )
6219  assert(SCIPvarGetIndex(eqvars[v]) > SCIPvarGetIndex(eqvars[v - 1]));
6220 #endif
6221  /* computing all variables which appear in all consanddata objects */
6222  for( --c ; c >= 0; --c )
6223  {
6224  CONSANDDATA* consanddata;
6225  SCIP_VAR** vars;
6226  int nvars;
6227  int nneweqvars;
6228 
6229  consanddata = consanddatas[c];
6230  assert(consanddata != NULL);
6231  assert(consanddatas[c]->istransformed);
6232 
6233  /* choose correct variable array to add locks for, we only add locks for now valid variables */
6234  if( consanddata->nnewvars > 0 )
6235  {
6236  vars = consanddata->newvars;
6237  nvars = consanddata->nnewvars;
6238  }
6239  else
6240  {
6241  vars = consanddata->vars;
6242  nvars = consanddata->nvars;
6243  }
6244  assert(nvars > 0 && vars != NULL);
6245 
6246 #ifndef NDEBUG
6247  /* check that variables are sorted */
6248  for( v = nvars - 1; v > 0; --v )
6249  assert(SCIPvarGetIndex(vars[v]) > SCIPvarGetIndex(vars[v - 1]));
6250 #endif
6251 
6252  /* update minimal number of variables in and-constraint */
6253  if( nvars < nminvars )
6254  nminvars = nvars;
6255  /* update maximal number of variables in and-constraint */
6256  else if( nvars > nmaxvars )
6257  nmaxvars = nvars;
6258  assert(nminvars > 0);
6259  assert(nminvars <= nmaxvars);
6260 
6261  nneweqvars = 0;
6262  for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
6263  {
6264  int index1;
6265  int index2;
6266 
6267  assert(eqvars[v] != NULL);
6268  assert(vars[v2] != NULL);
6269  index1 = SCIPvarGetIndex(eqvars[v]);
6270  index2 = SCIPvarGetIndex(vars[v2]);
6271 
6272  /* check which variables are still in all and-constraints */
6273  if( index1 < index2 )
6274  ++v;
6275  else if( index1 > index2 )
6276  ++v2;
6277  else
6278  {
6279  assert(index1 == index2);
6280  assert(nneweqvars <= v);
6281 
6282  if( nneweqvars < v )
6283  eqvars[nneweqvars] = eqvars[v];
6284  ++nneweqvars;
6285  ++v;
6286  ++v2;
6287  }
6288  }
6289  neqvars = nneweqvars;
6290 
6291  /* now we only want to handle the easy case where nminvars == neqvars + 1
6292  * @todo: implement for the othercase too
6293  */
6294  if( nminvars > neqvars + 1 )
6295  break;
6296 
6297  /* if no variables overlap we have to stop */
6298  if( neqvars == 0 )
6299  break;
6300  }
6301 
6302  /* if all and-constraints in pseudoboolean constraint have some equal variables we can extract them and create a new
6303  * linear constraint; iff the number of equal variables is equal to the number of variables - 1 in all consanddata
6304  * objects then the new constraint will not contain any products; if no normal linear variables exist we can fix all
6305  * equal variables to 1
6306  *
6307  * e.g. x1 * x2 + x1 * x3 + x1 * x4 >= 1
6308  * => x1 = 1 /\ x2 + x3 + x4 >= 1
6309  *
6310  * e.g. x1 * x2 * x3 + x1 * x2 * x4 + x5 >= 1
6311  * => 2x1 + 2x2 + x3 + x4 + 5x5 >= 5
6312  *
6313  * e.g. x1 * x2 * x3 + x1 * x4 >= 1
6314  * => x1 = 1 /\ x2 * x3 + x4 >= 1 (constraint is created indirectly, caused by the fixing of x1)
6315  *
6316  * @todo: implement the next cases
6317  *
6318  * e.g. x1 * x2 * x3 + x1 * x4 + x5 >= 1
6319  * => 2x1 + x2 * x3 + x4 + 3x5 >= 3 (x2 * x3 will be a new and-constraint)
6320  *
6321  * e.g. x1 * x2 + x1 * x2 * x3 + x4 >= 1
6322  * => x1 + x2 + 2x4 >= 2
6323  *
6324  * e.g. x1 * x2 + x1 * x3 + x2 * x3 + sum_i x_i >= 1
6325  * => x1 + x2 + x3 + 2 * sum_i x_i >= 2
6326  *
6327  */
6328 
6329  /* Extract additional information ???
6330  *
6331  * e.g. x1 * x2 * x4 + x1 * x3 * x5 + x2 * x3 * x6 >= 1
6332  * => extract x1 + x2 + x3 >= 2
6333  */
6334 
6335  /* if we have no normal linear variable in the logicor constraint, we can fix all equal variables */
6336  if( neqvars > 0 && consdata->nlinvars == 0 )
6337  {
6338  SCIP_Bool infeasible;
6339  SCIP_Bool fixed;
6340 
6341  /* fix all equal variable in logicor constraints which have to be one to fulfill the constraint */
6342  for( v = 0; v < neqvars; ++v )
6343  {
6344  /* fix the variable which cannot be one */
6345  SCIP_CALL( SCIPfixVar(scip, eqvars[v], 1.0, &infeasible, &fixed) );
6346  if( infeasible )
6347  {
6348  SCIPdebugMsg(scip, " -> infeasible fixing\n");
6349  *cutoff = TRUE;
6350  goto TERMINATE;
6351  }
6352  if( fixed )
6353  ++(*nfixedvars);
6354  }
6355 
6356  /* if a complete consanddata object have all variables in common with all other consanddata objects, than we can
6357  * delete this constraint after fixing all equal variables
6358  */
6359  if( nminvars == neqvars )
6360  {
6361  /* delete old constraints */
6362  SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
6363  SCIP_CALL( SCIPdelCons(scip, cons) );
6364  (*ndelconss) += 2;
6365 
6366  goto TERMINATE;
6367  }
6368  }
6369 
6370  /* now the following condition grant us that we can linearize the whole constraint */
6371  if( neqvars > 0 && nminvars == nmaxvars && nminvars == neqvars + 1 )
6372  {
6373  SCIP_CONS* lincons;
6374  SCIP_CONS* newcons;
6375  char newname[SCIP_MAXSTRLEN];
6376  SCIP_Real lhs;
6377  SCIP_Real rhs;
6378 
6379  lhs = 1.0;
6380  rhs = SCIPinfinity(scip);
6381 
6382  lincons = consdata->lincons;
6383 
6384  (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
6385 
6386  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, newname, 0, NULL, NULL, lhs, rhs,
6387  SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
6388  SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
6389  SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
6390 
6391  /* if createcons == TRUE add all variables which are not in the eqvars array to the new constraint with
6392  * coefficient 1.0
6393  */
6394  for( c = nconsanddatas - 1; c >= 0; --c )
6395  {
6396  CONSANDDATA* consanddata;
6397  SCIP_VAR** vars;
6398  int nvars;
6399 
6400  consanddata = consanddatas[c];
6401  assert(consanddata != NULL);
6402  assert(consanddatas[c]->istransformed);
6403 
6404  /* choose correct variable array to add locks for, we only add locks for now valid variables */
6405  if( consanddata->nnewvars > 0 )
6406  {
6407  vars = consanddata->newvars;
6408  nvars = consanddata->nnewvars;
6409  }
6410  else
6411  {
6412  vars = consanddata->vars;
6413  nvars = consanddata->nvars;
6414  }
6415  assert(nvars > 0 && vars != NULL);
6416 
6417  for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
6418  {
6419  int index1;
6420  int index2;
6421 
6422  assert(eqvars[v] != NULL);
6423  assert(vars[v2] != NULL);
6424  index1 = SCIPvarGetIndex(eqvars[v]);
6425  index2 = SCIPvarGetIndex(vars[v2]);
6426 
6427  /* all variables in eqvars array must exist in all and-constraints */
6428  assert(index1 >= index2);
6429 
6430  if( index1 > index2 )
6431  {
6432  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
6433  ++v2;
6434  }
6435  else
6436  {
6437  assert(index1 == index2);
6438  ++v;
6439  ++v2;
6440  }
6441  }
6442 
6443  /* if we did not loop over all variables in the and-constraint, go on and fix variables */
6444  if( v2 < nvars )
6445  {
6446  assert(v == neqvars);
6447  for( ; v2 < nvars; ++v2)
6448  {
6449  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
6450  }
6451  }
6452  assert(v == neqvars && v2 == nvars);
6453  }
6454 
6455  /* if we have normal linear variable in the logicor constraint, we did not fix all equal variables and we have to
6456  * add them with a coefficient of 'nconsanddatas'
6457  * we have to add also all normal linear variables with a coefficient of 'nconsanddatas * neqvars + 1'
6458  */
6459  if( consdata->nlinvars > 0 )
6460  {
6461  SCIP_VAR** vars;
6462  SCIP_Real* coefs;
6463  int nvars;
6464  SCIP_VAR** linvars;
6465  SCIP_Real* lincoefs;
6466  int nlinvars;
6467 
6468  /* add all equal variables */
6469  for( v = 0; v < neqvars; ++v )
6470  {
6471  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, eqvars[v], (SCIP_Real)nconsanddatas) );
6472  }
6473 
6474  /* check number of linear variables */
6475  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
6476  assert(nvars == consdata->nlinvars + consdata->nconsanddatas);
6477 
6478  /* allocate temporary memory */
6479  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
6480  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
6481  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
6482  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) );
6483 
6484  /* get variables and coefficients */
6485  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
6486  assert(nvars == 0 || (coefs != NULL));
6487 
6488 #ifndef NDEBUG
6489  /* all coefficients have to be 1 */
6490  for( v = 0; v < nvars; ++v )
6491  assert(SCIPisEQ(scip, coefs[v], 1.0));
6492 #endif
6493  /* calculate all not artificial linear variables */
6494  SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars,
6495  NULL, NULL, NULL, NULL) );
6496  assert(nlinvars == consdata->nlinvars);
6497 
6498  /* add all old normal linear variables */
6499  for( v = 0; v < nlinvars; ++v )
6500  {
6501  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, linvars[v], (SCIP_Real)(nconsanddatas * neqvars + 1)) ); /*lint !e732 !e790*/
6502  }
6503 
6504  /* reset left hand side to correct value */
6505  SCIP_CALL( SCIPchgLhsLinear(scip, newcons, (SCIP_Real)(nconsanddatas * neqvars + 1)) ); /*lint !e732 !e790*/
6506 
6507  /* free temporary memory */
6508  SCIPfreeBufferArray(scip, &lincoefs);
6509  SCIPfreeBufferArray(scip, &linvars);
6510  SCIPfreeBufferArray(scip, &coefs);
6511  SCIPfreeBufferArray(scip, &vars);
6512  }
6513 
6514  /* add and release new constraint */
6515  SCIP_CALL( SCIPaddCons(scip, newcons) );
6516 
6517  SCIPdebugMsg(scip, "created upgraded linear constraint:\n");
6518  SCIPdebugMsg(scip, "old -> ");
6519  SCIPdebugPrintCons(scip, lincons, NULL);
6520  SCIPdebugMsg(scip, "new -> ");
6521  SCIPdebugPrintCons(scip, newcons, NULL);
6522 
6523  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6524  ++(*naddconss);
6525 
6526  /* delete old constraints */
6527  SCIP_CALL( SCIPdelCons(scip, lincons) );
6528  SCIP_CALL( SCIPdelCons(scip, cons) );
6529  (*ndelconss) += 2;
6530  }
6531 
6532  TERMINATE:
6533  /* free temporary memory */
6534  SCIPfreeBufferArray(scip, &eqvars);
6535 
6536  return SCIP_OKAY;
6537 }
6538 
6539 /** try upgrading pseudoboolean setppc constraint to a linear constraint and/or remove possible and-constraints */
6540 static
6542  SCIP*const scip, /**< SCIP data structure */
6543  SCIP_CONS*const cons, /**< pseudoboolean constraint */
6544  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
6545  int*const ndelconss, /**< pointer to store number of deleted constraints */
6546  int*const naddconss, /**< pointer to count number of added constraints */
6547  int*const nfixedvars, /**< pointer to store number of fixed variables */
6548  int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
6549  int*const nchgsides, /**< pointer to store number of changed sides constraints */
6550  SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
6551  )
6552 {
6553  CONSANDDATA** consanddatas;
6554  int nconsanddatas;
6555  SCIP_CONSDATA* consdata;
6556  SCIP_SETPPCTYPE type;
6557  int c;
6558  int v;
6559  int v2;
6560  SCIP_VAR** eqvars;
6561  int neqvars;
6562  int nminvars;
6563  int nmaxvars;
6564 
6565  assert(scip != NULL);
6566  assert(cons != NULL);
6567  assert(conshdlrdata != NULL);
6568  assert(ndelconss != NULL);
6569  assert(nfixedvars != NULL);
6570  assert(nchgcoefs != NULL);
6571  assert(nchgsides != NULL);
6572  assert(cutoff != NULL);
6573  assert(SCIPconsIsActive(cons));
6574 
6575  consdata = SCIPconsGetData(cons);
6576  assert(consdata != NULL);
6577 
6578  consanddatas = consdata->consanddatas;
6579  nconsanddatas = consdata->nconsanddatas;
6580  assert(nconsanddatas > 0 && consanddatas != NULL);
6581 
6582  assert(consdata->lincons != NULL);
6583  assert(consdata->linconstype == SCIP_LINEARCONSTYPE_SETPPC);
6584 
6585  type = SCIPgetTypeSetppc(scip, consdata->lincons);
6586 
6587  switch( type )
6588  {
6591  break;
6593  return SCIP_OKAY;
6594  default:
6595  SCIPerrorMessage("unknown setppc type\n");
6596  return SCIP_INVALIDDATA;
6597  }
6598 
6599  assert(consanddatas[0] != NULL);
6600  assert(consanddatas[0]->cons != NULL);
6601 
6602  if( nconsanddatas == 1 )
6603  {
6604  /* if we have only one term left in the setppc constraint, the presolving should be done by the setppc constraint handler */
6605  if( consdata->nlinvars == 0 )
6606  {
6607  return SCIP_OKAY;
6608  }
6609 
6610  /* @todo: implement the following */
6611 
6612  /* for each set packing constraint:
6613  * sum_i (x_i) + res <= 1 , with and-constraint of res as the resultant like res = y_1 * ... * y_n
6614  * => sum_i (n * x_i) + sum_j=1^n y_j <= n + n-1
6615  *
6616  * i.e. x_1 + x_2 + x_3 + x_4*x_5*x_6 <= 1
6617  * => 3x_1 + 3x_2 + 3x_3 + x_4 + x_5 + x_6 <= 5
6618  */
6619 
6620  /* for each set partitioning constraint:
6621  * sum_i (x_i) + res = 1 , with the corresponding and-constraint of res like
6622  * res = y_1 * ... * y_n
6623  *
6624  * => n <= sum_i (n * x_i) + sum_j=1^n y_j <= 2 * n - 1
6625  *
6626  * i.e. x_1 + x_2 + x_3 + x_4*x_5*x_6 = 1
6627  * => 3 <= 3x_1 + 3x_2 + 3x_3 + x_4 + x_5 + x_6 <= 5
6628  *
6629  */
6630 
6631  return SCIP_OKAY;
6632  }
6633 
6634  if( consdata->nlinvars > 0 )
6635  {
6636  /* @todo: */
6637  return SCIP_OKAY;
6638  }
6639  assert(consdata->nlinvars == 0 && nconsanddatas > 1);
6640 
6641  c = nconsanddatas - 1;
6642  assert(consanddatas[c]->istransformed);
6643 
6644  /* initializing array for variables which can appear in all consanddata objects */
6645  if( consanddatas[c]->nnewvars > 0 )
6646  {
6647  neqvars = consanddatas[c]->nnewvars;
6648  /* allocate temporary memory */
6649  SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->newvars, neqvars) );
6650  }
6651  else
6652  {
6653  neqvars = consanddatas[c]->nvars;
6654  /* allocate temporary memory */
6655  SCIP_CALL( SCIPduplicateBufferArray(scip, &eqvars, consanddatas[c]->vars, neqvars) );
6656  }
6657  nminvars = neqvars;
6658  nmaxvars = neqvars;
6659  assert(neqvars > 0 && eqvars != NULL);
6660 
6661 #ifndef NDEBUG
6662  /* check that variables are sorted */
6663  for( v = neqvars - 1; v > 0; --v )
6664  assert(SCIPvarGetIndex(eqvars[v]) > SCIPvarGetIndex(eqvars[v - 1]));
6665 #endif
6666 
6667  for( --c ; c >= 0; --c )
6668  {
6669  CONSANDDATA* consanddata;
6670  SCIP_VAR** vars;
6671  int nvars;
6672  int nneweqvars;
6673 
6674  consanddata = consanddatas[c];
6675  assert(consanddata != NULL);
6676  assert(consanddatas[c]->istransformed);
6677 
6678  /* choose correct variable array to add locks for, we only add locks for now valid variables */
6679  if( consanddata->nnewvars > 0 )
6680  {
6681  vars = consanddata->newvars;
6682  nvars = consanddata->nnewvars;
6683  }
6684  else
6685  {
6686  vars = consanddata->vars;
6687  nvars = consanddata->nvars;
6688  }
6689  assert(nvars > 0 && vars != NULL);
6690 
6691 #ifndef NDEBUG
6692  /* check that variables are sorted */
6693  for( v = nvars - 1; v > 0; --v )
6694  assert(SCIPvarGetIndex(vars[v]) > SCIPvarGetIndex(vars[v - 1]));
6695 #endif
6696 
6697  /* update minimal number of variables in and-constraint */
6698  if( nvars < nminvars )
6699  nminvars = nvars;
6700  /* update maximal number of variables in and-constraint */
6701  else if( nvars > nmaxvars )
6702  nmaxvars = nvars;
6703  assert(nminvars > 0);
6704  assert(nminvars <= nmaxvars);
6705 
6706  nneweqvars = 0;
6707  for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
6708  {
6709  int index1;
6710  int index2;
6711 
6712  assert(eqvars[v] != NULL);
6713  assert(vars[v2] != NULL);
6714  index1 = SCIPvarGetIndex(eqvars[v]);
6715  index2 = SCIPvarGetIndex(vars[v2]);
6716 
6717  /* check which variables are still in all and-constraints */
6718  if( index1 < index2 )
6719  ++v;
6720  else if( index1 > index2 )
6721  ++v2;
6722  else
6723  {
6724  assert(index1 == index2);
6725  assert(nneweqvars <= v);
6726 
6727  if( nneweqvars < v )
6728  eqvars[nneweqvars] = eqvars[v];
6729  ++nneweqvars;
6730  ++v;
6731  ++v2;
6732  }
6733  }
6734  neqvars = nneweqvars;
6735 
6736  /* now we only want to handle the easy case where nminvars == neqvars + 1
6737  * @todo: implement for the othercase too
6738  */
6739  if( nminvars > neqvars + 1 && type != SCIP_SETPPCTYPE_PARTITIONING)
6740  break;
6741 
6742  if( neqvars == 0 )
6743  break;
6744  }
6745 
6746  /* if all and-constraints in pseudoboolean constraint have the same length and some equal variables we can upgrade
6747  * the linear constraint and fix some variables in setpartitioning case
6748  *
6749  * e.g. x1 * x2 + x1 * x3 + x1 * x4 <= 1
6750  * => 3x1 + x2 + x3 + x4 <= 4
6751  *
6752  * e.g. x1 * x2 * x3 + x1 * x2 * x4 <= 1
6753  * => 2x1 + 2x2 + x3 + x4 <= 5
6754  *
6755  * e.g. x1 * x2 + x1 * x2 * x3 + x1 * x2 * x4 <= 1
6756  * => 3x1 + 3x2 + x3 + x4 <= 6
6757  *
6758  * e.g. x1 * x2 + x1 * x3 == 1
6759  * => x1 = 1 /\ x2 + x3 == 1
6760  *
6761  * e.g. x1 * x2 * x3 + x1 * x4 == 1
6762  * => x1 = 1 /\ x2 * x3 + x4 == 1 (constraint is created indirectly, caused by the fixing of x1)
6763  *
6764  * e.g. x1 * x2 + x1 * x2 * x3 + x1 * x2 * x4 == 1
6765  * => x1 = 1, x2 = 1, x3 = 0, x4 = 0
6766  *
6767  * e.g. x1 * x2 + x1 * x2 * x3 + x1 * x2 * x4 * x5 == 1
6768  * => x1 = 1, x2 = 1, x3 = 0 /\ x4 * x5 == 0
6769  *
6770  * @todo: implement the next cases
6771  *
6772  * e.g. x1 * x2 * x3 + x1 * x2 * x4 + x5 <= 1
6773  * => 2x1 + 2x2 + x3 + x4 + x5 <= 5
6774  *
6775  */
6776  if( neqvars > 0 && ((nminvars == nmaxvars && nminvars == neqvars + 1) || (nminvars == neqvars) || (type == SCIP_SETPPCTYPE_PARTITIONING)) )
6777  {
6778  SCIP_CONS* lincons;
6779  SCIP_CONS* newcons;
6780  char newname[SCIP_MAXSTRLEN];
6781  SCIP_Real lhs;
6782  SCIP_Real rhs;
6783  SCIP_Bool infeasible;
6784  SCIP_Bool fixed;
6785  SCIP_Bool createcons;
6786  SCIP_Bool deletecons;
6787 
6788  newcons = NULL;
6789 
6790  /* determine new sides of linear constraint */
6791  if( type == SCIP_SETPPCTYPE_PARTITIONING )
6792  {
6793  lhs = 1.0;
6794  rhs = 1.0;
6795  }
6796  else
6797  {
6798  assert(type == SCIP_SETPPCTYPE_PACKING);
6799  lhs = -SCIPinfinity(scip);
6800  rhs = 1.0;
6801  }
6802 
6803  /* if one and-constraint was completely contained in all other and-constraints, we have to reduced the right hand
6804  * side by 1
6805  */
6806  if( neqvars == nminvars )
6807  rhs -= 1.0;
6808 
6809  createcons = (SCIPisLE(scip, lhs, rhs) && ((nminvars == nmaxvars && nminvars == neqvars + 1) || (nminvars == neqvars)));
6810  assert(createcons || type == SCIP_SETPPCTYPE_PARTITIONING);
6811 
6812  deletecons = (type == SCIP_SETPPCTYPE_PARTITIONING && nminvars == neqvars);
6813 
6814  lincons = consdata->lincons;
6815 
6816  if( createcons )
6817  {
6818  (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "%s_upgraded", SCIPconsGetName(lincons));
6819 
6820  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, newname, 0, NULL, NULL, lhs, rhs,
6821  SCIPconsIsInitial(lincons), SCIPconsIsSeparated(lincons), SCIPconsIsEnforced(lincons), SCIPconsIsChecked(lincons),
6822  SCIPconsIsPropagated(lincons), SCIPconsIsLocal(lincons), SCIPconsIsModifiable(lincons),
6823  SCIPconsIsDynamic(lincons), SCIPconsIsRemovable(lincons), SCIPconsIsStickingAtNode(lincons)) );
6824  }
6825 
6826  /* if createcons == TRUE add all variables which are not in the eqvars array to the new constraint with
6827  * coefficient 1.0
6828  *
6829  * otherwise (if createcons == FALSE) fix all variables to zero which are not in the eqvars array and if we have a
6830  * set partitioning constraint
6831  */
6832  for( c = nconsanddatas - 1; c >= 0; --c )
6833  {
6834  CONSANDDATA* consanddata;
6835  SCIP_VAR** vars;
6836  int nvars;
6837 
6838  consanddata = consanddatas[c];
6839  assert(consanddata != NULL);
6840  assert(consanddatas[c]->istransformed);
6841 
6842  /* choose correct variable array to add locks for, we only add locks for now valid variables */
6843  if( consanddata->nnewvars > 0 )
6844  {
6845  vars = consanddata->newvars;
6846  nvars = consanddata->nnewvars;
6847  }
6848  else
6849  {
6850  vars = consanddata->vars;
6851  nvars = consanddata->nvars;
6852  }
6853  assert(nvars > 0 && vars != NULL);
6854 
6855  /* if the consanddata object has at least two more different variables then the equal variables we have to fix the resultant to zero */
6856  if( deletecons && neqvars + 1 < nvars )
6857  {
6858  assert(SCIPgetResultantAnd(scip, consanddata->cons) != NULL);
6859 
6860  /* fix the resultant variable which have to be zero */
6861  SCIP_CALL( SCIPfixVar(scip, SCIPgetResultantAnd(scip, consanddata->cons), 0.0, &infeasible, &fixed) );
6862  if( infeasible )
6863  {
6864  SCIPdebugMsg(scip, " -> infeasible fixing\n");
6865  *cutoff = TRUE;
6866  goto TERMINATE;
6867  }
6868  if( fixed )
6869  ++(*nfixedvars);
6870 
6871  continue;
6872  }
6873 
6874  /* if the consanddata object has at exactly one more different variable then the equal variables we have to fix it to zero */
6875  for( v = 0, v2 = 0; v < neqvars && v2 < nvars; )
6876  {
6877  int index1;
6878  int index2;
6879 
6880  assert(eqvars[v] != NULL);
6881  assert(vars[v2] != NULL);
6882  index1 = SCIPvarGetIndex(eqvars[v]);
6883  index2 = SCIPvarGetIndex(vars[v2]);
6884 
6885  /* all variables in eqvars array must exist in all and-constraints */
6886  assert(index1 >= index2);
6887 
6888  if( index1 > index2 )
6889  {
6890  if( createcons )
6891  {
6892  assert(newcons != NULL);
6893  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
6894  }
6895  else if( deletecons )
6896  {
6897  /* fix the variable which cannot be one */
6898  SCIP_CALL( SCIPfixVar(scip, vars[v2], 0.0, &infeasible, &fixed) );
6899  if( infeasible )
6900  {
6901  SCIPdebugMsg(scip, " -> infeasible fixing\n");
6902  *cutoff = TRUE;
6903  goto TERMINATE;
6904  }
6905  if( fixed )
6906  ++(*nfixedvars);
6907  }
6908  ++v2;
6909  }
6910  else
6911  {
6912  assert(index1 == index2);
6913 
6914  ++v;
6915  ++v2;
6916  }
6917  }
6918 
6919  /* if we did not loop over all variables in the and-constraint, go on and fix variables */
6920  if( v2 < nvars )
6921  {
6922  assert(v == neqvars);
6923  for( ; v2 < nvars; ++v2)
6924  {
6925  if( createcons )
6926  {
6927  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, vars[v2], 1.0) );
6928  }
6929  else if( deletecons )
6930  {
6931  /* fix the variable which cannot be one */
6932  SCIP_CALL( SCIPfixVar(scip, vars[v2], 0.0, &infeasible, &fixed) );
6933  if( infeasible )
6934  {
6935  SCIPdebugMsg(scip, " -> infeasible fixing\n");
6936  *cutoff = TRUE;
6937  goto TERMINATE;
6938  }
6939  if( fixed )
6940  ++(*nfixedvars);
6941  }
6942  }
6943  }
6944  assert(v == neqvars && v2 == nvars);
6945  }
6946 
6947  /* fix all equal variable in set-partitioning constraints which have to be one, in set-packing constraint we have
6948  * to add these variable with a coeffcient as big as (nconsanddatas - 1)
6949  */
6950  for( v = 0; v < neqvars; ++v )
6951  {
6952  if( type == SCIP_SETPPCTYPE_PARTITIONING )
6953  {
6954  /* fix the variable which have to be one */
6955  SCIP_CALL( SCIPfixVar(scip, eqvars[v], 1.0, &infeasible, &fixed) );
6956  if( infeasible )
6957  {
6958  SCIPdebugMsg(scip, " -> infeasible fixing\n");
6959  *cutoff = TRUE;
6960  goto TERMINATE;
6961  }
6962  if( fixed )
6963  ++(*nfixedvars);
6964  }
6965  else
6966  {
6967  assert(type == SCIP_SETPPCTYPE_PACKING);
6968  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, eqvars[v], (SCIP_Real)(nconsanddatas - 1)) );
6969  }
6970  }
6971 
6972  /* correct right hand side for set packing constraint */
6973  if( type == SCIP_SETPPCTYPE_PACKING )
6974  {
6975  assert(createcons);
6976  assert(newcons != NULL);
6977 
6978  SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs + (SCIP_Real)((nconsanddatas - 1) * neqvars)) ); /*lint !e790*/
6979  }
6980 
6981  /* add and release new constraint */
6982  if( createcons )
6983  {
6984  SCIP_CALL( SCIPaddCons(scip, newcons) );
6985 
6986  SCIPdebugMsg(scip, "created upgraded linear constraint:\n");
6987  SCIPdebugMsg(scip, "old -> ");
6988  SCIPdebugPrintCons(scip, lincons, NULL);
6989  SCIPdebugMsg(scip, "new -> ");
6990  SCIPdebugPrintCons(scip, newcons, NULL);
6991 
6992  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6993  ++(*naddconss);
6994 
6995  assert(!deletecons);
6996  deletecons = TRUE;
6997  }
6998 
6999  if( deletecons )
7000  {
7001  /* delete old constraints */
7002  SCIP_CALL( SCIPdelCons(scip, lincons) );
7003  SCIP_CALL( SCIPdelCons(scip, cons) );
7004  (*ndelconss) += 2;
7005  }
7006  }
7007 
7008  TERMINATE:
7009  /* free temporary memory */
7010  SCIPfreeBufferArray(scip, &eqvars);
7011 
7012  return SCIP_OKAY;
7013 }
7014 
7015 /** try upgrading pseudoboolean constraint to a linear constraint and/or remove possible and-constraints */
7016 static
7018  SCIP*const scip, /**< SCIP data structure */
7019  SCIP_CONS*const cons, /**< pseudoboolean constraint */
7020  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
7021  int*const ndelconss, /**< pointer to store number of upgraded constraints */
7022  int*const naddconss, /**< pointer to count number of added constraints */
7023  int*const nfixedvars, /**< pointer to store number of fixed variables */
7024  int*const nchgcoefs, /**< pointer to store number of changed coefficients constraints */
7025  int*const nchgsides, /**< pointer to store number of changed sides constraints */
7026  SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
7027  )
7028 {
7029 #ifndef NDEBUG
7030  CONSANDDATA** consanddatas;
7031 #endif
7032  SCIP_CONSDATA* consdata;
7033  int nvars;
7034 
7035  assert(scip != NULL);
7036  assert(cons != NULL);
7037  assert(conshdlrdata != NULL);
7038  assert(ndelconss != NULL);
7039  assert(nfixedvars != NULL);
7040  assert(nchgcoefs != NULL);
7041  assert(nchgsides != NULL);
7042  assert(cutoff != NULL);
7043  assert(SCIPconsIsActive(cons));
7044 
7045  consdata = SCIPconsGetData(cons);
7046  assert(consdata != NULL);
7047  assert(consdata->lincons != NULL);
7048 
7049 #ifndef NDEBUG
7050  consanddatas = consdata->consanddatas;
7051  assert(consdata->nconsanddatas == 0 || consanddatas != NULL);
7052 #endif
7053 
7054  /* if no consanddata-objects in pseudoboolean constraint are left, create the corresponding linear constraint */
7055  if( consdata->nconsanddatas == 0 )
7056  {
7057  SCIPconsAddUpgradeLocks(consdata->lincons, -1);
7058  assert(SCIPconsGetNUpgradeLocks(consdata->lincons) == 0);
7059 
7060  /* @TODO: maybe it is better to create everytime a standard linear constraint instead of letting the special
7061  * linear constraint stay
7062  */
7063  SCIP_CALL( SCIPdelCons(scip, cons) );
7064  ++(*ndelconss);
7065 
7066  return SCIP_OKAY;
7067  }
7068 
7069  /* check number of linear variables */
7070  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
7071  assert(consdata->nlinvars + consdata->nconsanddatas == nvars);
7072 
7073  switch( consdata->linconstype )
7074  {
7076  SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
7077  break;
7079  SCIP_CALL( tryUpgradingLogicor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
7080  break;
7082  break;
7084  SCIP_CALL( tryUpgradingSetppc(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
7085  if( !SCIPconsIsDeleted(cons) )
7086  {
7087  SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
7088  }
7089  break;
7090 #ifdef WITHEQKNAPSACK
7091  case SCIP_LINEARCONSTYPE_EQKNAPSACK:
7092  SCIP_CALL( tryUpgradingXor(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, cutoff) );
7093 #endif
7095  default:
7096  SCIPerrorMessage("unknown linear constraint type\n");
7097  return SCIP_INVALIDDATA;
7098  }
7099 
7100  if( SCIPconsIsDeleted(cons) )
7101  {
7102  /* update the uses counter of consandata objects which are used in pseudoboolean constraint, which was deleted and
7103  * probably delete and-constraints
7104  */
7105  SCIP_CALL( updateConsanddataUses(scip, cons, conshdlrdata, ndelconss) );
7106  }
7107 
7108  consdata->upgradetried = TRUE;
7109 
7110  return SCIP_OKAY;
7111 }
7112 
7113 /** check if we can aggregated some variables */
7114 static
7116  SCIP*const scip, /**< SCIP data structure */
7117  SCIP_CONS*const cons, /**< pseudoboolean constraint */
7118  SCIP_CONSHDLRDATA*const conshdlrdata, /**< pseudoboolean constraint handler data */
7119  int*const ndelconss, /**< pointer to store number of upgraded constraints */
7120  int*const naggrvars, /**< pointer to store number of aggregated variables */
7121  SCIP_Bool*const cutoff /**< pointer to store if a cutoff happened */
7122  )
7123 {
7124  CONSANDDATA** consanddatas;
7125  SCIP_CONSDATA* consdata;
7126  SCIP_VAR** allvars;
7127  int* varcount[2];
7128  SCIP_VAR** repvars;
7129  SCIP_Bool* negated;
7130  SCIP_VAR** vars;
7131  int nconsanddatas;
7132  int nvars;
7133  int zerocount;
7134  int onecount;
7135  int twocount;
7136  int othercount;
7137  int c;
7138  int v;
7139  int i;
7140 
7141  assert(scip != NULL);
7142  assert(cons != NULL);
7143  assert(conshdlrdata != NULL);
7144  assert(ndelconss != NULL);
7145  assert(naggrvars != NULL);
7146  assert(cutoff != NULL);
7147  assert(SCIPconsIsActive(cons));
7148 
7149  if( SCIPconsIsModifiable(cons) )
7150  return SCIP_OKAY;
7151 
7152  consdata = SCIPconsGetData(cons);
7153  assert(consdata != NULL);
7154  assert(consdata->lincons != NULL);
7155 
7156  consanddatas = consdata->consanddatas;
7157  nconsanddatas = consdata->nconsanddatas;
7158  assert(nconsanddatas == 0 || consanddatas != NULL);
7159 
7160  /* we have only one special case for aggregations, a set-partinioning constraint */
7161  if( consdata->linconstype != SCIP_LINEARCONSTYPE_SETPPC || SCIPgetTypeSetppc(scip, consdata->lincons) != SCIP_SETPPCTYPE_PARTITIONING )
7162  return SCIP_OKAY;
7163 
7164  assert(SCIPisEQ(scip, consdata->rhs, consdata->lhs));
7165  assert(SCIPisEQ(scip, consdata->rhs, 1.0));
7166 
7167  if( nconsanddatas < 2 || nconsanddatas > 3 )
7168  return SCIP_OKAY;
7169 
7170 #ifndef NDEBUG
7171  /* check number of linear variables */
7172  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
7173  assert(consdata->nlinvars + nconsanddatas == nvars);
7174 #endif
7175 
7176  if( consdata->nlinvars != 1 )
7177  return SCIP_OKAY;
7178 
7179  /* check valid number of variables */
7180  if( consanddatas[0]->nnewvars > 0 )
7181  nvars = consanddatas[0]->nnewvars;
7182  else
7183  nvars = consanddatas[0]->nvars;
7184 
7185  if( consanddatas[1]->nnewvars > 0 )
7186  {
7187  if( nvars != consanddatas[1]->nnewvars )
7188  return SCIP_OKAY;
7189  }
7190  else if( nvars != consanddatas[1]->nvars )
7191  return SCIP_OKAY;
7192 
7193  /* allocate temporary memory */
7194  SCIP_CALL( SCIPallocBufferArray(scip, &allvars, nvars) );
7195  SCIP_CALL( SCIPallocBufferArray(scip, &(varcount[0]), nvars) );
7196  BMSclearMemoryArray(varcount[0], nvars);
7197  SCIP_CALL( SCIPallocBufferArray(scip, &(varcount[1]), nvars) );
7198  BMSclearMemoryArray(varcount[1], nvars);
7199 
7200  SCIP_CALL( SCIPallocBufferArray(scip, &repvars, nvars) );
7201  SCIP_CALL( SCIPallocBufferArray(scip, &negated, nvars) );
7202  BMSclearMemoryArray(negated, nvars);
7203 
7204  /* get valid variables */
7205  if( consanddatas[nconsanddatas - 1]->nnewvars > 0 )
7206  vars = consanddatas[nconsanddatas - 1]->newvars;
7207  else
7208  vars = consanddatas[nconsanddatas - 1]->vars;
7209 
7210  /* get linear active representation */
7211  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, vars, repvars, negated) );
7212  SCIPsortPtrBool((void**)repvars, negated, SCIPvarCompActiveAndNegated, nvars);
7213 
7214 #ifndef NDEBUG
7215  /* and-constraints have to be merged in order to check for aggregation */
7216  for( v = 1; v < nvars; ++v )
7217  {
7218  SCIP_VAR* var1;
7219  SCIP_VAR* var2;
7220 
7221  /* it appears that some fixed variables were not yet deleted */
7222  if( SCIPvarGetLbGlobal(repvars[v-1]) > 0.5 || SCIPvarGetUbGlobal(repvars[v-1]) < 0.5 )
7223  goto TERMINATE;
7224 
7225  /* it appears that some fixed variables were not yet deleted */
7226  if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
7227  goto TERMINATE;
7228 
7229  assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
7230  assert(SCIPvarIsActive(repvars[v-1]) || (SCIPvarIsNegated(repvars[v-1]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v-1]))));
7231  assert(SCIPvarIsActive(repvars[v]) != negated[v]);
7232  assert(SCIPvarIsActive(repvars[v-1]) != negated[v-1]);
7233 
7234  var1 = (negated[v-1] ? SCIPvarGetNegationVar(repvars[v-1]) : repvars[v-1]);
7235  var2 = (negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]);
7236  assert(var1 != var2);
7237  }
7238 #endif
7239 
7240  /* initializing the statuses of all appearing variables */
7241  for( v = nvars - 1; v >= 0; --v )
7242  {
7243  /* it appears that some fixed variables were not yet deleted */
7244  if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
7245  goto TERMINATE;
7246 
7247  assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
7248  assert(SCIPvarIsActive(repvars[v]) != negated[v]);
7249 
7250  allvars[v] = negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v];
7251 
7252  ++(varcount[negated[v]][v]);
7253  }
7254 
7255  for( c = nconsanddatas - 2; c >= 0; --c )
7256  {
7257  int pos = -1;
7258 
7259  /* get valid variables */
7260  if( consanddatas[nconsanddatas - 1]->nnewvars > 0 )
7261  vars = consanddatas[c]->newvars;
7262  else
7263  vars = consanddatas[c]->vars;
7264 
7265  /* need to reset the negated flags */
7266  BMSclearMemoryArray(negated, nvars);
7267 
7268  /* get linear active representation */
7269  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, vars, repvars, negated) );
7270  SCIPsortPtrBool((void**)repvars, negated, SCIPvarCompActiveAndNegated, nvars);
7271 
7272 #ifndef NDEBUG
7273  /* and-constraints have to be merged in order to check for aggregation */
7274  for( v = 1; v < nvars; ++v )
7275  {
7276  SCIP_VAR* var1;
7277  SCIP_VAR* var2;
7278 
7279  /* it appears that some fixed variables were not yet deleted */
7280  if( SCIPvarGetLbGlobal(repvars[v-1]) > 0.5 || SCIPvarGetUbGlobal(repvars[v-1]) < 0.5 )
7281  goto TERMINATE;
7282 
7283  /* it appears that some fixed variables were not yet deleted */
7284  if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
7285  goto TERMINATE;
7286 
7287  assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
7288  assert(SCIPvarIsActive(repvars[v-1]) || (SCIPvarIsNegated(repvars[v-1]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v-1]))));
7289  assert(SCIPvarIsActive(repvars[v]) != negated[v]);
7290  assert(SCIPvarIsActive(repvars[v-1]) != negated[v-1]);
7291 
7292  var1 = (negated[v-1] ? SCIPvarGetNegationVar(repvars[v-1]) : repvars[v-1]);
7293  var2 = (negated[v] ? SCIPvarGetNegationVar(repvars[v]) : repvars[v]);
7294  assert(var1 != var2);
7295  }
7296 #endif
7297 
7298  /* update the statuses of all appearing variables */
7299  for( v = nvars - 1; v >= 0; --v )
7300  {
7301  /* it appears that some fixed variables were not yet deleted */
7302  if( SCIPvarGetLbGlobal(repvars[v]) > 0.5 || SCIPvarGetUbGlobal(repvars[v]) < 0.5 )
7303  goto TERMINATE;
7304 
7305  assert(SCIPvarIsActive(repvars[v]) || (SCIPvarIsNegated(repvars[v]) && SCIPvarIsActive(SCIPvarGetNegationVar(repvars[v]))));
7306  assert(SCIPvarIsActive(repvars[v]) != negated[v]);
7307 
7308  /* we can only find an aggregation if all and constraints have the same variables */
7309  if( SCIPsortedvecFindPtr((void**)allvars, SCIPvarCompActiveAndNegated, repvars[v], nvars, &pos) )
7310  {
7311  assert(pos >= 0 && pos < nvars);
7312 
7313  ++(varcount[negated[v]][pos]);
7314  }
7315  else
7316  goto TERMINATE;
7317  }
7318  }
7319 
7320  zerocount = 0;
7321  onecount = 0;
7322  twocount = 0;
7323  othercount = 0;
7324 
7325  /* count number of multiple appearances of a variable */
7326  for( i = 1; i >= 0; --i )
7327  {
7328  for( v = nvars - 1; v >= 0; --v )
7329  {
7330  assert(SCIPvarIsActive(allvars[v]));
7331 
7332  if( varcount[i][v] == 0 )
7333  ++zerocount;
7334  else if( varcount[i][v] == 1 )
7335  ++onecount;
7336  else if( varcount[i][v] == 2 )
7337  ++twocount;
7338  else
7339  ++othercount;
7340  }
7341  }
7342 
7343  /* exactly one variable in all and-constraints appears as active and as negated variable */
7344  if( othercount == 0 )
7345  {
7346  /* we have a constraint in the form of: x1 + x2 * x3 * ... * x_n + ~x2 * x3 * ... * x_n == 1
7347  * this leads to the aggregation x1 = 1 - x3 * ... * x_n
7348  */
7349  if( nconsanddatas == 2 && twocount == nvars - 1 && onecount == 2 && zerocount == 1 )
7350  {
7351  SCIP_VAR** consvars;
7352  SCIP_Real* conscoefs;
7353  int nconsvars;
7354  SCIP_VAR* linvar;
7355  SCIP_Real lincoef;
7356  int nlinvars;
7357 
7358  /* allocate temporary memory */
7359  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) );
7360  SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) );
7361 
7362  /* get variables and coefficients */
7363  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) );
7364  assert(nconsvars == consdata->nlinvars + nconsanddatas);
7365  assert(conscoefs != NULL);
7366 
7367 #ifndef NDEBUG
7368  /* all coefficients have to be 1 */
7369  for( v = 0; v < nconsvars; ++v )
7370  assert(SCIPisEQ(scip, conscoefs[v], 1.0));
7371 #endif
7372  linvar = NULL;
7373 
7374  /* calculate all not artificial linear variables */
7375  SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars,
7376  NULL, NULL, NULL, NULL) );
7377  assert(nlinvars == 1);
7378  assert(linvar != NULL);
7379 
7380  SCIPfreeBufferArray(scip, &conscoefs);
7381  SCIPfreeBufferArray(scip, &consvars);
7382 
7383  /* if all and-constraints have exactly two variables */
7384  if( nvars == 2 )
7385  {
7386  SCIP_VAR* var;
7387  SCIP_Bool breaked;
7388  SCIP_Bool redundant;
7389  SCIP_Bool infeasible;
7390  SCIP_Bool aggregated;
7391 
7392  var = NULL;
7393  breaked = FALSE;
7394 
7395  /* find necessary variables, which only occur once */
7396  for( i = 1; i >= 0; --i )
7397  {
7398  for( v = nvars - 1; v >= 0; --v )
7399  {
7400  assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL);
7401  if( varcount[i][v] == 2 )
7402  {
7403  var = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v];
7404 
7405  breaked = TRUE;
7406  break;
7407  }
7408  }
7409 
7410  if( breaked )
7411  break;
7412  }
7413  assert(var != NULL);
7414 
7415  SCIPdebugMsg(scip, "aggregating variables <%s> == 1 - <%s> in pseudoboolean <%s>\n", SCIPvarGetName(linvar), SCIPvarGetName(var), SCIPconsGetName(cons));
7416 
7417  SCIP_CALL( SCIPaggregateVars(scip, linvar, var, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
7418 
7419  SCIPdebugPrintCons(scip, cons, NULL);
7420  SCIPdebugMsg(scip, "aggregation of variables: <%s> == 1 - <%s>, infeasible = %u, aggregated = %u\n", SCIPvarGetName(linvar), SCIPvarGetName(var), infeasible, aggregated);
7421 
7422  if( infeasible )
7423  *cutoff = TRUE;
7424  else
7425  {
7426  if( aggregated )
7427  ++(*naggrvars);
7428 
7429  /* delete old constraints */
7430  SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
7431  SCIP_CALL( SCIPdelCons(scip, cons) );
7432  (*ndelconss) += 2;
7433  }
7434  }
7435 #if 0
7436  else
7437  {
7438  /* @todo */
7439  /* delete allvars[samepos] from all and-constraints which appear in this pseudoboolean constraint, and delete
7440  * all but one of the remaining and-constraint
7441  *
7442  * it is the same like aggregating linvar with the resultant of the product, which is the same in all and-
7443  * constraints without allvars[samepos]
7444  *
7445  * e.g. x1 + x2*x_3*...x_n + ~x2*x_3*...x_n = 1 => x1 = 1 - x_3*...x_n
7446  */
7447  }
7448 #endif
7449  } /*lint !e438*/
7450  /* we have a constraint in the form of: x1 + x2 * x3 + ~x2 * x3 + ~x2 * ~x3 == 1
7451  * this leads to the aggregation x1 = x2 * ~x3
7452  *
7453  * @todo: implement more general step, that one combination of the variables in the and constraints is missing in
7454  * the pseudoboolean constraint, which leads to the same result, that the only linear variable is the
7455  * resultant of the missing and-constraint
7456  */
7457  else if( nvars == 2 && nconsanddatas == 3 && twocount == 2 && onecount == 2 && zerocount == 0)
7458  {
7459  SCIP_VAR** consvars;
7460  SCIP_Real* conscoefs;
7461  int nconsvars;
7462  SCIP_VAR* linvar;
7463  SCIP_Real lincoef;
7464  int nlinvars;
7465  SCIP_VAR* newandvars[2];
7466  SCIP_Bool breaked;
7467  SCIP_CONS* newcons;
7468  char name[SCIP_MAXSTRLEN];
7469 
7470  /* allocate temporary memory */
7471  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nlinvars + nconsanddatas) );
7472  SCIP_CALL( SCIPallocBufferArray(scip, &conscoefs, consdata->nlinvars + nconsanddatas) );
7473 
7474  /* get variables and coefficients */
7475  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, consvars, conscoefs, &nconsvars) );
7476  assert(nconsvars == consdata->nlinvars + nconsanddatas);
7477  assert(conscoefs != NULL);
7478 
7479 #ifndef NDEBUG
7480  /* all coefficients have to be 1 */
7481  for( v = 0; v < nconsvars; ++v )
7482  assert(SCIPisEQ(scip, conscoefs[v], 1.0));
7483 #endif
7484  linvar = NULL;
7485 
7486  /* calculate all not artificial linear variables */
7487  SCIP_CALL( getLinVarsAndAndRess(scip, cons, consvars, conscoefs, nconsvars, &linvar, &lincoef, &nlinvars,
7488  NULL, NULL, NULL, NULL) );
7489  assert(nlinvars == 1);
7490  assert(linvar != NULL);
7491 
7492  SCIPfreeBufferArray(scip, &conscoefs);
7493  SCIPfreeBufferArray(scip, &consvars);
7494 
7495  newandvars[0] = NULL;
7496  newandvars[1] = NULL;
7497  breaked = FALSE;
7498 
7499  /* find necessary variables, which only occur once */
7500  for( i = 1; i >= 0; --i )
7501  {
7502  for( v = nvars - 1; v >= 0; --v )
7503  {
7504  assert(i == 1 || SCIPvarGetNegatedVar(allvars[v]) != NULL);
7505  if( varcount[i][v] == 1 )
7506  {
7507  if( newandvars[0] == NULL )
7508  newandvars[0] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v];
7509  else
7510  {
7511  assert(newandvars[1] == NULL);
7512  newandvars[1] = i ? SCIPvarGetNegatedVar(allvars[v]) : allvars[v];
7513 
7514  breaked = TRUE;
7515  break;
7516  }
7517  }
7518  }
7519 
7520  if( breaked )
7521  break;
7522  }
7523  assert(newandvars[0] != NULL && newandvars[1] != NULL);
7524 
7525  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "andcons_%s_%s", SCIPconsGetName(cons), SCIPvarGetName(linvar));
7526  SCIP_CALL( SCIPcreateConsAnd(scip, &newcons, name, linvar, nvars, newandvars,
7527  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
7528  SCIP_CALL( SCIPaddCons(scip, newcons) );
7529  SCIPdebugPrintCons(scip, newcons, NULL);
7530  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
7531 
7532  /* delete old constraints */
7533  SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
7534  SCIP_CALL( SCIPdelCons(scip, cons) );
7535  (*ndelconss) += 2;
7536  } /*lint !e438*/
7537  }
7538 
7539  if( SCIPconsIsDeleted(cons) )
7540  {
7541  /* update the uses counter of consandata objects which are used in pseudoboolean constraint, which was deleted and
7542  * probably delete and-constraints
7543  */
7544  SCIP_CALL( updateConsanddataUses(scip, cons, conshdlrdata, ndelconss) );
7545  }
7546 
7547  TERMINATE:
7548  /* free temporary memory */
7549  SCIPfreeBufferArray(scip, &negated);
7550  SCIPfreeBufferArray(scip, &repvars);
7551  SCIPfreeBufferArray(scip, &(varcount[1]));
7552  SCIPfreeBufferArray(scip, &(varcount[0]));
7553  SCIPfreeBufferArray(scip, &allvars);
7554 
7555  return SCIP_OKAY;
7556 }
7557 
7558 
7559 /*
7560  * Callback methods of constraint handler
7561  */
7562 
7563 #ifdef NONLINCONSUPGD_PRIORITY
7564 /** tries to upgrade a nonlinear constraint into a pseudoboolean constraint */
7565 static
7566 SCIP_DECL_NONLINCONSUPGD(nonlinconsUpgdPseudoboolean)
7567 {
7568  SCIP_EXPRGRAPH* exprgraph;
7569  SCIP_EXPRGRAPHNODE* node;
7570  SCIP_Real lhs;
7571  SCIP_Real rhs;
7572  SCIP_VAR* var;
7573  SCIP_VAR* objvar = NULL;
7574  SCIP_VAR** linvars = NULL;
7575  int nlinvars;
7576  SCIP_VAR*** terms;
7577  int nterms;
7578  int* ntermvars;
7579  SCIP_Real* termvals;
7580  int i;
7581  int j;
7582 
7583  assert(nupgdconss != NULL);
7584  assert(upgdconss != NULL);
7585 
7586  *nupgdconss = 0;
7587 
7588  node = SCIPgetExprgraphNodeNonlinear(scip, cons);
7589 
7590  /* no interest in linear constraints */
7591  if( node == NULL )
7592  return SCIP_OKAY;
7593 
7594  switch( SCIPexprgraphGetNodeOperator(node) )
7595  {
7596  case SCIP_EXPR_VARIDX:
7597  case SCIP_EXPR_CONST:
7598  case SCIP_EXPR_PLUS:
7599  case SCIP_EXPR_MINUS:
7600  case SCIP_EXPR_SUM:
7601  case SCIP_EXPR_LINEAR:
7602  /* these should not appear as exprgraphnodes after constraint presolving */
7603  return SCIP_OKAY;
7604 
7605  case SCIP_EXPR_MUL:
7606  case SCIP_EXPR_DIV:
7607  case SCIP_EXPR_SQUARE:
7608  case SCIP_EXPR_SQRT:
7609  case SCIP_EXPR_REALPOWER:
7610  case SCIP_EXPR_INTPOWER:
7611  case SCIP_EXPR_SIGNPOWER:
7612  case SCIP_EXPR_EXP:
7613  case SCIP_EXPR_LOG:
7614  case SCIP_EXPR_SIN:
7615  case SCIP_EXPR_COS:
7616  case SCIP_EXPR_TAN:
7617  /* case SCIP_EXPR_ERF: */
7618  /* case SCIP_EXPR_ERFI: */
7619  case SCIP_EXPR_MIN:
7620  case SCIP_EXPR_MAX:
7621  case SCIP_EXPR_ABS:
7622  case SCIP_EXPR_SIGN:
7623  case SCIP_EXPR_PRODUCT:
7624  case SCIP_EXPR_USER:
7625  /* these do not look like a proper pseudoboolean expression (assuming the expression graph simplifier did run) */
7626  return SCIP_OKAY;
7627 
7628  case SCIP_EXPR_QUADRATIC: /* let cons_quadratic still handle these for now */
7629  return SCIP_OKAY;
7630 
7631  case SCIP_EXPR_POLYNOMIAL:
7632  /* these mean that we have something polynomial */
7633  break;
7634 
7635  case SCIP_EXPR_PARAM:
7636  case SCIP_EXPR_LAST:
7637  default:
7638  SCIPwarningMessage(scip, "unexpected expression operator %d in nonlinear constraint <%s>\n", SCIPexprgraphGetNodeOperator(node), SCIPconsGetName(cons));
7639  return SCIP_OKAY;
7640  }
7641 
7642  lhs = SCIPgetLhsNonlinear(scip, cons);
7643  rhs = SCIPgetRhsNonlinear(scip, cons);
7644 
7645  /* we need all linear variables to be binary, except for one that was added to reformulate an objective function */
7646  for( i = 0; i < SCIPgetNLinearVarsNonlinear(scip, cons); ++i )
7647  {
7648  var = SCIPgetLinearVarsNonlinear(scip, cons)[i];
7649  assert(var != NULL);
7650 
7651  if( SCIPvarIsBinary(var) )
7652  continue;
7653 
7654 #ifdef SCIP_DISABLED_CODE /* not working in cons_pseudoboolean yet, see cons_pseudoboolean.c:7925 */
7655  /* check whether the variable may have been added to represent the objective function */
7656  if( objvar == NULL && SCIPgetLinearCoefsNonlinear(scip, cons)[i] == -1.0 && /*TODO we could divide by the coefficient*/
7657  SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == (SCIPisInfinity(scip, rhs) ? 0 : 1) && /*TODO correct?*/
7658  SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == (SCIPisInfinity(scip, -lhs) ? 0 : 1) && /*TODO correct?*/
7660  SCIPvarGetObj(var) == 1.0 ) /*TODO we need this or just positive?*/
7661  {
7662  objvar = var;
7663  continue;
7664  }
7665 #endif
7666 
7667  SCIPdebugMsg(scip, "not pseudoboolean because linear variable <%s> is not binary or objective\n", SCIPvarGetName(var));
7668  return SCIP_OKAY;
7669  }
7670 
7671  /* if simplified, then all children of root node should be variables, we need all of them to be binary */
7672  exprgraph = SCIPgetExprgraphNonlinear(scip, SCIPconsGetHdlr(cons));
7673  for( i = 0; i < SCIPexprgraphGetNodeNChildren(node); ++i )
7674  {
7675  SCIP_EXPRGRAPHNODE* child;
7676 
7677  child = SCIPexprgraphGetNodeChildren(node)[i];
7678  assert(child != NULL);
7680  {
7681  SCIPdebugMsg(scip, "not pseudoboolean because child %d is not a variable\n", i);
7682  return SCIP_OKAY;
7683  }
7684 
7685  var = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, child);
7686  assert(var != NULL);
7687  if( !SCIPvarIsBinary(var) )
7688  {
7689  SCIPdebugMsg(scip, "not pseudoboolean because nonlinear var <%s> is not binary\n", SCIPvarGetName(var));
7690  return SCIP_OKAY;
7691  }
7692  }
7693 
7694  /* setup a pseudoboolean constraint */
7695 
7696  if( upgdconsssize < 1 )
7697  {
7698  /* request larger upgdconss array */
7699  *nupgdconss = -1;
7700  return SCIP_OKAY;
7701  }
7702 
7703  SCIPdebugMsg(scip, "upgrading nonlinear constraint <%s> to pseudo-boolean\n", SCIPconsGetName(cons));
7704 
7705  if( !SCIPisInfinity(scip, -lhs) )
7707  if( !SCIPisInfinity(scip, -rhs) )
7709 
7710  /* setup linear part, if not identical */
7711  if( objvar != NULL )
7712  {
7713  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, SCIPgetNLinearVarsNonlinear(scip, cons)-1) );
7714  nlinvars = 0;
7715  for( i = 0; i < SCIPgetNLinearVarsNonlinear(scip, cons); ++i )
7716  {
7717  var = SCIPgetLinearVarsNonlinear(scip, cons)[i];
7718  if( var != objvar )
7719  linvars[nlinvars++] = var;
7720  }
7721  }
7722  else
7723  nlinvars = SCIPgetNLinearVarsNonlinear(scip, cons);
7724 
7725  /* setup nonlinear terms */
7727  SCIP_CALL( SCIPallocBufferArray(scip, &terms, nterms) );
7728  SCIP_CALL( SCIPallocBufferArray(scip, &ntermvars, nterms) );
7729  SCIP_CALL( SCIPallocBufferArray(scip, &termvals, nterms) );
7730 
7731  for( i = 0; i < nterms; ++i )
7732  {
7733  SCIP_EXPRDATA_MONOMIAL* monomial;
7734 
7735  monomial = SCIPexprgraphGetNodePolynomialMonomials(node)[i];
7736  assert(monomial != NULL);
7737 
7738  ntermvars[i] = SCIPexprGetMonomialNFactors(monomial);
7739  SCIP_CALL( SCIPallocBufferArray(scip, &terms[i], ntermvars[i]) );
7740 
7741  for( j = 0; j < SCIPexprGetMonomialNFactors(monomial); ++j )
7742  {
7743  terms[i][j] = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, SCIPexprgraphGetNodeChildren(node)[SCIPexprGetMonomialChildIndices(monomial)[j]]);
7744  assert(SCIPexprGetMonomialExponents(monomial)[j] > 0.0);
7745  }
7746 
7747  termvals[i] = SCIPexprGetMonomialCoef(monomial);
7748  }
7749 
7750  *nupgdconss = 1;
7751  SCIP_CALL( SCIPcreateConsPseudoboolean(scip, &upgdconss[0], SCIPconsGetName(cons),
7752  objvar != NULL ? linvars : SCIPgetLinearVarsNonlinear(scip, cons), nlinvars, SCIPgetLinearCoefsNonlinear(scip, cons),
7753  terms, nterms, ntermvars, termvals, NULL, 0.0, FALSE, objvar,
7754  lhs, rhs,
7758 
7759  for( i = nterms-1; i >= 0; --i )
7760  SCIPfreeBufferArray(scip, &terms[i]);
7761 
7762  SCIPfreeBufferArray(scip, &terms);
7763  SCIPfreeBufferArray(scip, &ntermvars);
7764  SCIPfreeBufferArray(scip, &termvals);
7765  SCIPfreeBufferArrayNull(scip, &linvars);
7766 
7767  return SCIP_OKAY;
7768 }
7769 #endif
7770 
7771 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
7772 static
7773 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyPseudoboolean)
7774 { /*lint --e{715}*/
7775  assert(scip != NULL);
7776  assert(conshdlr != NULL);
7777  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7778 
7779  /* call inclusion method of constraint handler */
7781 
7782  *valid = TRUE;
7783 
7784  return SCIP_OKAY;
7785 }
7786 
7787 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
7788 static
7789 SCIP_DECL_CONSFREE(consFreePseudoboolean)
7790 { /*lint --e{715}*/
7791  SCIP_CONSHDLRDATA* conshdlrdata;
7792 
7793  assert(scip != NULL);
7794  assert(conshdlr != NULL);
7795  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7796 
7797  /* free constraint handler data */
7798  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7799  assert(conshdlrdata != NULL);
7800 
7801  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
7802 
7803  SCIPconshdlrSetData(conshdlr, NULL);
7804 
7805  return SCIP_OKAY;
7806 }
7807 
7808 
7809 /** initialization method of constraint handler (called after problem was transformed) */
7810 static
7811 SCIP_DECL_CONSINIT(consInitPseudoboolean)
7812 { /*lint --e{715}*/
7813  SCIP_CONSHDLRDATA* conshdlrdata;
7814  int c;
7815 
7816  assert(scip != NULL);
7817  assert(conshdlr != NULL);
7818  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7819 
7820  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7821  assert(conshdlrdata != NULL);
7822 
7823  /* check each constraint and get transformed constraints */
7824  for( c = conshdlrdata->nallconsanddatas - 1; c >= 0; --c )
7825  {
7826  SCIP_CONS* andcons;
7827  SCIP_VAR* resultant;
7828 #ifndef NDEBUG
7829  SCIP_VAR** vars;
7830  int nvars;
7831  int v;
7832 
7833  assert(conshdlrdata->allconsanddatas[c] != NULL);
7834  assert(conshdlrdata->allconsanddatas[c]->newvars == NULL);
7835 
7836  vars = conshdlrdata->allconsanddatas[c]->vars;
7837  nvars = conshdlrdata->allconsanddatas[c]->nvars;
7838  assert(vars != NULL || nvars == 0);
7839 
7840  /* check for correct variables data */
7841  for( v = nvars - 1; v > 0; --v )
7842  {
7843  assert(SCIPvarIsTransformed(vars[v])); /*lint !e613*/
7844  assert(SCIPvarGetIndex(vars[v]) >= SCIPvarGetIndex(vars[v-1])); /*lint !e613*/
7845  }
7846  assert(nvars == 0 || SCIPvarIsTransformed(vars[0])); /*lint !e613*/
7847 #endif
7848 
7849  andcons = conshdlrdata->allconsanddatas[c]->cons;
7850  assert(andcons != NULL);
7851 
7852  assert(SCIPconsIsTransformed(andcons));
7853 
7854  resultant = SCIPgetResultantAnd(scip, andcons);
7855  /* insert new mapping */
7856  assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)resultant));
7857  SCIP_CALL( SCIPhashmapInsert(conshdlrdata->hashmap, (void*)resultant, (void*)(conshdlrdata->allconsanddatas[c])) );
7858 
7859  SCIPdebugMsg(scip, "insert into hashmap <%s> (%p) -> <%s> (%p/%p)\n", SCIPvarGetName(resultant), (void*)resultant,
7860  SCIPconsGetName(conshdlrdata->allconsanddatas[c]->cons), (void*)(conshdlrdata->allconsanddatas[c]),
7861  (void*)(conshdlrdata->allconsanddatas[c]->cons));
7862  }
7863 
7864  return SCIP_OKAY;
7865 }
7866 
7867 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
7868 static
7869 SCIP_DECL_CONSINITPRE(consInitprePseudoboolean)
7870 { /*lint --e{715}*/
7871  SCIP_CONSHDLRDATA* conshdlrdata;
7872  int c;
7873 
7874  assert(scip != NULL);
7875  assert(conshdlr != NULL);
7876  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7877 
7878  conshdlrdata = SCIPconshdlrGetData(conshdlr);
7879  assert(conshdlrdata != NULL);
7880 
7881  /* decompose all pseudo boolean constraints into a "linear" constraint and "and" constraints */
7882  if( conshdlrdata->decomposeindicatorpbcons || conshdlrdata->decomposenormalpbcons )
7883  {
7884  for( c = 0; c < nconss; ++c )
7885  {
7886  SCIP_CONS* cons;
7887  SCIP_CONSDATA* consdata;
7888  SCIP_VAR** vars;
7889  SCIP_Real* coefs;
7890  int nvars;
7891 
7892  cons = conss[c];
7893  assert(cons != NULL);
7894 
7895  /* only added constraints can be upgraded */
7896  if( !SCIPconsIsAdded(cons) )
7897  continue;
7898 
7899  consdata = SCIPconsGetData(cons);
7900  assert(consdata != NULL);
7901 
7902  /* gets number of variables in linear constraint */
7903  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
7904 
7905  /* allocate temporary memory */
7906  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
7907  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
7908 
7909  /* get variables and coefficient of linear constraint */
7910  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
7911  assert(nvars == 0 || (coefs != NULL));
7912 
7913  if( consdata->issoftcons && conshdlrdata->decomposeindicatorpbcons )
7914  {
7915  SCIP_VAR* negindvar;
7916  char name[SCIP_MAXSTRLEN];
7917  SCIP_Real lhs;
7918  SCIP_Real rhs;
7919  SCIP_Bool initial;
7920  SCIP_Bool updateandconss;
7921  int v;
7922 #if USEINDICATOR == FALSE
7923  SCIP_CONS* lincons;
7924  SCIP_Real maxact;
7925  SCIP_Real minact;
7926  SCIP_Real lb;
7927  SCIP_Real ub;
7928 #else
7929  SCIP_CONS* indcons;
7930 #endif
7931 
7932  assert(consdata->weight != 0);
7933  assert(consdata->indvar != NULL);
7934 
7935  /* if it is a soft constraint, there should be no integer variable */
7936  assert(consdata->intvar == NULL);
7937 
7938  /* get negation of indicator variable */
7939  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->indvar, &negindvar) );
7940  assert(negindvar != NULL);
7941 
7942  /* get sides of linear constraint */
7943  SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &lhs, &rhs) );
7944  assert(!SCIPisInfinity(scip, lhs));
7945  assert(!SCIPisInfinity(scip, -rhs));
7946  assert(SCIPisLE(scip, lhs, rhs));
7947 
7948  updateandconss = FALSE;
7949 
7950 #if USEINDICATOR == FALSE
7951  maxact = 0.0;
7952  minact = 0.0;
7953 
7954  /* adding all linear coefficients up */
7955  for( v = nvars - 1; v >= 0; --v )
7956  if( coefs[v] > 0 )
7957  maxact += coefs[v];
7958  else
7959  minact += coefs[v];
7960 
7961  if( SCIPisInfinity(scip, maxact) )
7962  {
7963  SCIPwarningMessage(scip, "maxactivity = %g exceed infinity value.\n", maxact);
7964  }
7965  if( SCIPisInfinity(scip, -minact) )
7966  {
7967  SCIPwarningMessage(scip, "minactivity = %g exceed -infinity value.\n", minact);
7968  }
7969 
7970  /* @todo check whether it's better to set the initial flag to false */
7971  initial = SCIPconsIsInitial(cons); /* FALSE; */
7972 
7973  /* first soft constraints for lhs */
7974  if( !SCIPisInfinity(scip, -lhs) )
7975  {
7976  /* first we are modelling the feasibility of the soft constraint by adding a slack variable */
7977  /* we ensure that if indvar == 1 => (a^T*x + ub*indvar >= lhs) */
7978  ub = lhs - minact;
7979 
7980  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_lhs_part1", SCIPconsGetName(cons));
7981 
7982  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, lhs, SCIPinfinity(scip),
7983  initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
7986 
7987  /* update and constraint flags */
7988  SCIP_CALL( updateAndConss(scip, cons) );
7989  updateandconss = TRUE;
7990 
7991  /* add artificial indicator variable */
7992  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->indvar, ub) );
7993 
7994  SCIP_CALL( SCIPaddCons(scip, lincons) );
7995  SCIPdebugPrintCons(scip, lincons, NULL);
7996  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
7997 
7998  /* second we are modelling the implication that if the slack variable is on( negation is off), the constraint
7999  * is disabled, so only the cost arise if the slack variable is necessary */
8000  /* indvar == 1 => (a^T*x (+ ub * negindvar) <= lhs - 1) */
8001  ub = lhs - maxact - 1;
8002 
8003  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_lhs_part2", SCIPconsGetName(cons));
8004 
8005  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, -SCIPinfinity(scip), lhs - 1,
8006  initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
8009 
8010  /* add artificial indicator variable */
8011  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, negindvar, ub) );
8012 
8013  SCIP_CALL( SCIPaddCons(scip, lincons) );
8014  SCIPdebugPrintCons(scip, lincons, NULL);
8015  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
8016  }
8017 
8018  /* second soft constraints for rhs */
8019  if( !SCIPisInfinity(scip, rhs) )
8020  {
8021  /* first we are modelling the feasibility of the soft-constraint by adding a slack variable */
8022  /* indvar == 1 => (a^T*x + lb * indvar <= rhs) */
8023  lb = rhs - maxact;
8024 
8025  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_rhs_part1", SCIPconsGetName(cons));
8026 
8027  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, -SCIPinfinity(scip), rhs,
8028  initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
8031 
8032  if( !updateandconss )
8033  {
8034  /* update and constraint flags */
8035  SCIP_CALL( updateAndConss(scip, cons) );
8036  }
8037 
8038  /* add artificial indicator variable */
8039  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->indvar, lb) );
8040 
8041  SCIP_CALL( SCIPaddCons(scip, lincons) );
8042  SCIPdebugPrintCons(scip, lincons, NULL);
8043  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
8044 
8045  /* second we are modelling the implication that if the slack variable is on( negation is off), the constraint
8046  * is disabled, so only the cost arise if the slack variable is necessary */
8047  /* indvar == 1 => (a^T*x (+ lb * negindvar) >= rhs + 1) */
8048  lb = rhs - minact + 1;
8049 
8050  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_rhs_part2", SCIPconsGetName(cons));
8051 
8052  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, name, nvars, vars, coefs, rhs + 1, SCIPinfinity(scip),
8053  initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
8056 
8057  /* add artificial indicator variable */
8058  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, negindvar, lb) );
8059 
8060  SCIP_CALL( SCIPaddCons(scip, lincons) );
8061  SCIPdebugPrintCons(scip, lincons, NULL);
8062  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
8063  }
8064 #else /* with indicator */
8065  /* @todo check whether it's better to set the initial flag to false */
8066  initial = SCIPconsIsInitial(cons); /* FALSE; */
8067 
8068  if( !SCIPisInfinity(scip, rhs) )
8069  {
8070  /* first we are modelling the implication that if the negation of the indicator variable is on, the constraint
8071  * is enabled */
8072  /* indvar == 0 => a^T*x <= rhs */
8073 
8074  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_rhs_ind", SCIPconsGetName(cons));
8075 
8076  SCIP_CALL( SCIPcreateConsIndicator(scip, &indcons, name, negindvar, nvars, vars, coefs, rhs,
8077  initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
8080 
8081  /* update and constraint flags */
8082  SCIP_CALL( updateAndConss(scip, cons) );
8083  updateandconss = TRUE;
8084 
8085  SCIP_CALL( SCIPaddCons(scip, indcons) );
8086  SCIPdebugPrintCons(scip, indcons, NULL);
8087  SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
8088  }
8089 
8090  if( !SCIPisInfinity(scip, -lhs) )
8091  {
8092  /* second we are modelling the implication that if the negation of the indicator variable is on, the constraint
8093  * is enabled */
8094  /* change the a^T*x >= lhs to -a^Tx<= -lhs, for indicator constraint */
8095 
8096  for( v = nvars - 1; v >= 0; --v )
8097  coefs[v] *= -1;
8098 
8099  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_lhs_ind", SCIPconsGetName(cons));
8100 
8101  SCIP_CALL( SCIPcreateConsIndicator(scip, &indcons, name, negindvar, nvars, vars, coefs, -lhs,
8102  initial, SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
8105 
8106  if( !updateandconss )
8107  {
8108  /* update and constraint flags */
8109  SCIP_CALL( updateAndConss(scip, cons) );
8110  }
8111 
8112  SCIP_CALL( SCIPaddCons(scip, indcons) );
8113  SCIPdebugPrintCons(scip, indcons, NULL);
8114  SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
8115  }
8116 #endif
8117  /* remove pseudo boolean and corresponding linear constraint, new linear constraints were created,
8118  * and-constraints still active
8119  */
8120  SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
8121  SCIP_CALL( SCIPdelCons(scip, cons) );
8122  }
8123  /* no soft constraint */
8124  else if( !consdata->issoftcons && conshdlrdata->decomposenormalpbcons )
8125  {
8126  /* todo: maybe better create a new linear constraint and let scip do the upgrade */
8127 
8128  /* mark linear constraint not to be upgraded - otherwise we loose control over it */
8129  SCIPconsAddUpgradeLocks(consdata->lincons, 1);
8130 
8131  /* update and constraint flags */
8132  SCIP_CALL( updateAndConss(scip, cons) );
8133 
8134 #if 0 /* not implemented correctly */
8135  if( consdata->intvar != NULL )
8136  {
8137  /* add auxiliary integer variables to linear constraint */
8138  SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->intvar, -1.0) );
8139  }
8140 #endif
8141  /* remove pseudo boolean constraint, old linear constraint is still active, and-constraints too */
8142  SCIP_CALL( SCIPdelCons(scip, cons) );
8143  }
8144 
8145  /* free temporary memory */
8146  SCIPfreeBufferArray(scip, &coefs);
8147  SCIPfreeBufferArray(scip, &vars);
8148  }
8149  }
8150 
8151  return SCIP_OKAY;
8152 }
8153 
8154 /** frees specific constraint data */
8155 static
8156 SCIP_DECL_CONSDELETE(consDeletePseudoboolean)
8157 { /*lint --e{715}*/
8158  SCIP_CONSHDLRDATA* conshdlrdata;
8159  SCIP_Bool isorig;
8160 
8161  assert(scip != NULL);
8162  assert(conshdlr != NULL);
8163  assert(cons != NULL);
8164  assert(consdata != NULL);
8165  assert(*consdata != NULL);
8166  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8167 
8168  conshdlrdata = SCIPconshdlrGetData(conshdlr);
8169  assert(conshdlrdata != NULL);
8170 
8171  isorig = SCIPconsIsOriginal(cons);
8172 
8173  /* count number of used consanddata objects in original problem */
8174  if( isorig )
8175  {
8176 #ifndef NDEBUG
8177  int c;
8178  assert((*consdata)->lincons == NULL || SCIPconsIsOriginal((*consdata)->lincons));
8179 
8180  for( c = (*consdata)->nconsanddatas - 1; c >= 0; --c )
8181  {
8182  assert((*consdata)->consanddatas[c]->nuses == 0);
8183  assert((*consdata)->consanddatas[c]->cons == NULL);
8184  assert((*consdata)->consanddatas[c]->noriguses == 0 || ((*consdata)->consanddatas[c]->origcons != NULL && SCIPconsIsOriginal((*consdata)->consanddatas[c]->origcons)));
8185  }
8186 #endif
8187  conshdlrdata->noriguses -= (*consdata)->nconsanddatas;
8188  }
8189  assert(conshdlrdata->noriguses >= 0);
8190 
8191  /* free pseudo boolean constraint */
8192  SCIP_CALL( consdataFree(scip, consdata, isorig, conshdlrdata) );
8193 
8194  return SCIP_OKAY;
8195 }
8196 
8197 /** transforms constraint data into data belonging to the transformed problem */
8198 static
8199 SCIP_DECL_CONSTRANS(consTransPseudoboolean)
8200 { /*lint --e{715}*/
8201  SCIP_CONSDATA* sourcedata;
8202  SCIP_CONSDATA* targetdata;
8203  SCIP_CONS** andconss;
8204  int c;
8205 
8206  assert(scip != NULL);
8207  assert(conshdlr != NULL);
8208  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8209  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
8210  assert(sourcecons != NULL);
8211  assert(targetcons != NULL);
8212 
8213  sourcedata = SCIPconsGetData(sourcecons);
8214  assert(sourcedata != NULL);
8215 
8216  assert(sourcedata->nconsanddatas == 0 || sourcedata->consanddatas != NULL);
8217 
8218  /* allocate temporary memory */
8219  SCIP_CALL( SCIPallocBufferArray(scip, &andconss, sourcedata->nconsanddatas) );
8220 
8221  /* copy and-constraints */
8222  for( c = sourcedata->nconsanddatas - 1; c >= 0; --c )
8223  {
8224  assert(sourcedata->consanddatas[c] != NULL);
8225  andconss[c] = sourcedata->consanddatas[c]->origcons;
8226  assert(andconss[c] != NULL);
8227  assert(SCIPconsIsOriginal(andconss[c]));
8228  }
8229 
8230  /* create pseudoboolean constraint data for target constraint */
8231  SCIP_CALL( consdataCreate(scip, conshdlr, &targetdata, sourcedata->lincons, sourcedata->linconstype,
8232  andconss, sourcedata->andcoefs, sourcedata->andnegs, sourcedata->nconsanddatas, sourcedata->indvar, sourcedata->weight,
8233  sourcedata->issoftcons, sourcedata->intvar, sourcedata->lhs, sourcedata->rhs, SCIPconsIsChecked(sourcecons),
8234  TRUE) );
8235 
8236  /* free temporary memory */
8237  SCIPfreeBufferArray(scip, &andconss);
8238 
8239  /* create target constraint */
8240  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
8241  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
8242  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
8243  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
8244  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
8245 
8246  return SCIP_OKAY;
8247 }
8248 
8249 /** constraint enforcing method of constraint handler for LP solutions */
8250 static
8251 SCIP_DECL_CONSENFOLP(consEnfolpPseudoboolean)
8252 { /*lint --e{715}*/
8253  SCIP_Bool violated;
8254 
8255  assert(scip != NULL);
8256  assert(conshdlr != NULL);
8257  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8258  assert(result != NULL);
8259 
8260  violated = FALSE;
8261 
8262  /* check all and-constraints */
8263  SCIP_CALL( checkAndConss(scip, conshdlr, NULL, &violated) );
8264 
8265  if( violated )
8266  *result = SCIP_INFEASIBLE;
8267  else
8268  *result = SCIP_FEASIBLE;
8269 
8270  return SCIP_OKAY;
8271 }
8272 
8273 
8274 /** constraint enforcing method of constraint handler for relaxation solutions */
8275 static
8276 SCIP_DECL_CONSENFORELAX(consEnforelaxPseudoboolean)
8277 { /*lint --e{715}*/
8278  SCIP_Bool violated;
8279 
8280  assert(scip != NULL);
8281  assert(conshdlr != NULL);
8282  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8283  assert(result != NULL);
8284 
8285  violated = FALSE;
8286 
8287  /* check all and-constraints */
8288  SCIP_CALL( checkAndConss(scip, conshdlr, sol, &violated) );
8289 
8290  if( violated )
8291  *result = SCIP_INFEASIBLE;
8292  else
8293  *result = SCIP_FEASIBLE;
8294 
8295  return SCIP_OKAY;
8296 }
8297 
8298 
8299 /** constraint enforcing method of constraint handler for pseudo solutions */
8300 static
8301 SCIP_DECL_CONSENFOPS(consEnfopsPseudoboolean)
8302 { /*lint --e{715}*/
8303  SCIP_Bool violated;
8304 
8305  assert(scip != NULL);
8306  assert(conshdlr != NULL);
8307  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8308  assert(result != NULL);
8309 
8310  violated = FALSE;
8311 
8312  /* check all and-constraints */
8313  SCIP_CALL( checkAndConss(scip, conshdlr, NULL, &violated) );
8314 
8315  if( violated )
8316  *result = SCIP_INFEASIBLE;
8317  else
8318  *result = SCIP_FEASIBLE;
8319 
8320  return SCIP_OKAY;
8321 }
8322 
8323 
8324 /** feasibility check method of constraint handler for integral solutions */
8325 static
8326 SCIP_DECL_CONSCHECK(consCheckPseudoboolean)
8327 { /*lint --e{715}*/
8328  SCIP_Bool violated;
8329  int c;
8330 
8331  assert(scip != NULL);
8332  assert(conshdlr != NULL);
8333  assert(sol != NULL);
8334  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8335  assert(result != NULL);
8336 
8337  *result = SCIP_FEASIBLE;
8338 
8339  if( nconss > 0 )
8340  {
8341  if( SCIPconsIsOriginal(conss[0]) )
8342  {
8343  SCIP_CONSDATA* consdata;
8344 
8345  for( c = nconss - 1; c >= 0 && (*result == SCIP_FEASIBLE || completely); --c )
8346  {
8347  consdata = SCIPconsGetData(conss[c]);
8348  assert(consdata != NULL);
8349 
8350  if( consdata->issoftcons )
8351  {
8352  assert(consdata->indvar != NULL);
8353 
8354  if( SCIPisEQ(scip, SCIPgetSolVal(scip, sol, consdata->indvar), 1.0) )
8355  continue;
8356  }
8357 
8358  SCIP_CALL( checkOrigPbCons(scip, conss[c], sol, &violated, printreason) );
8359  if( violated )
8360  *result = SCIP_INFEASIBLE;
8361  }
8362  }
8363  else
8364  {
8365  /* check all and-constraints */
8366  SCIP_CALL( checkAndConss(scip, conshdlr, sol, &violated) );
8367  if( violated )
8368  *result = SCIP_INFEASIBLE;
8369  }
8370  }
8371 
8372  return SCIP_OKAY;
8373 }
8374 
8375 
8376 /** presolving method of constraint handler */
8377 static
8378 SCIP_DECL_CONSPRESOL(consPresolPseudoboolean)
8379 { /*lint --e{715}*/
8380  SCIP_CONSHDLRDATA* conshdlrdata;
8381  SCIP_Bool cutoff;
8382  int firstchange;
8383  int firstupgradetry;
8384  int oldnfixedvars;
8385  int oldnaggrvars;
8386  int oldnchgbds;
8387  int oldndelconss;
8388  int oldnupgdconss;
8389  int oldnchgcoefs;
8390  int oldnchgsides;
8391  int c;
8392 
8393  assert(scip != NULL);
8394  assert(conshdlr != NULL);
8395  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8396  assert(result != NULL);
8397 
8398  /* remember old preprocessing counters */
8399  oldnfixedvars = *nfixedvars;
8400  oldnaggrvars = *naggrvars;
8401  oldnchgbds = *nchgbds;
8402  oldndelconss = *ndelconss;
8403  oldnupgdconss = *nupgdconss;
8404  oldnchgcoefs = *nchgcoefs;
8405  oldnchgsides = *nchgsides;
8406 
8407  /* get constraint handler data */
8408  conshdlrdata = SCIPconshdlrGetData(conshdlr);
8409 
8410  /* compute all changes in consanddata objects */
8411  SCIP_CALL( computeConsAndDataChanges(scip, conshdlrdata) );
8412 
8413  firstchange = INT_MAX;
8414  firstupgradetry = INT_MAX;
8415  cutoff = FALSE;
8416 
8417  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
8418  {
8419  SCIP_CONS* cons;
8420  SCIP_CONSDATA* consdata;
8421  SCIP_VAR** vars;
8422  SCIP_Real* coefs;
8423  int nvars;
8424  SCIP_VAR** linvars;
8425  SCIP_Real* lincoefs;
8426  int nlinvars;
8427  SCIP_VAR** andress;
8428  SCIP_Real* andcoefs;
8429  SCIP_Bool* andnegs;
8430  int nandress;
8431  SCIP_Real newlhs;
8432  SCIP_Real newrhs;
8433 
8434  cons = conss[c];
8435  assert(cons != NULL);
8436  assert(SCIPconsIsActive(cons));
8437 
8438  consdata = SCIPconsGetData(cons);
8439  assert(consdata != NULL);
8440  assert(consdata->lincons != NULL);
8441 
8442  /* if linear constraint is redundant, than pseudoboolean constraint is redundant too */
8443  if( SCIPconsIsDeleted(consdata->lincons) )
8444  {
8445  /* update and constraint flags */
8446  SCIP_CALL( updateAndConss(scip, cons) );
8447 
8448  SCIP_CALL( SCIPdelCons(scip, cons) );
8449  ++(*ndelconss);
8450  continue;
8451  }
8452 
8453  /* get sides of linear constraint */
8454  SCIP_CALL( getLinearConsSides(scip, consdata->lincons, consdata->linconstype, &newlhs, &newrhs) );
8455  assert(!SCIPisInfinity(scip, newlhs));
8456  assert(!SCIPisInfinity(scip, -newrhs));
8457  assert(SCIPisLE(scip, newlhs, newrhs));
8458 
8459  /* gets number of variables in linear constraint */
8460  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
8461 
8462  /* allocate temporary memory */
8463  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
8464  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
8465  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nvars) );
8466  SCIP_CALL( SCIPallocBufferArray(scip, &lincoefs, nvars) );
8467  SCIP_CALL( SCIPallocBufferArray(scip, &andress, nvars) );
8468  SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nvars) );
8469  SCIP_CALL( SCIPallocBufferArray(scip, &andnegs, nvars) );
8470 
8471  /* get variables and coefficient of linear constraint */
8472  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
8473  assert(nvars == 0 || (coefs != NULL));
8474 
8475  /* calculate all not artificial linear variables and all artificial and-resultants which will be ordered like the
8476  * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array
8477  * afterwards
8478  */
8479  SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, &nlinvars,
8480  andress, andcoefs, andnegs, &nandress) );
8481 
8482  /* update all locks inside this constraint and all captures on all and-constraints */
8483  SCIP_CALL( correctLocksAndCaptures(scip, cons, conshdlrdata, newlhs, newrhs, andress, andcoefs, andnegs, nandress) );
8484 
8485  /* we can only presolve pseudoboolean constraints, that are not modifiable */
8486  if( SCIPconsIsModifiable(cons) )
8487  goto CONTTERMINATE;
8488 
8489  SCIPdebugMsg(scip, "presolving pseudoboolean constraint <%s>\n", SCIPconsGetName(cons));
8490  SCIPdebugPrintCons(scip, cons, NULL);
8491 
8492  /* remember the first changed constraint to begin the next aggregation round with */
8493  if( firstchange == INT_MAX && consdata->changed )
8494  firstchange = c;
8495 
8496  if( consdata->changed && !SCIPisStopped(scip) )
8497  {
8498  /* check if we can aggregated some variables */
8499  SCIP_CALL( findAggregation(scip, cons, conshdlrdata, ndelconss, naggrvars, &cutoff) );
8500  }
8501 
8502  /* if aggregation also deleted the constraint we can go to the next */
8503  if( !SCIPconsIsActive(cons) )
8504  goto CONTTERMINATE;
8505 
8506  if( consdata->changed )
8507  {
8508  /* try upgrading pseudoboolean constraint to a linear constraint and/or remove possible and-constraints */
8509  SCIP_CALL( tryUpgrading(scip, cons, conshdlrdata, ndelconss, naddconss, nfixedvars, nchgcoefs, nchgsides, &cutoff) );
8510  if( cutoff )
8511  goto CONTTERMINATE;
8512  }
8513 
8514  /* if upgrading deleted the pseudoboolean constraint we go on */
8515  if( !SCIPconsIsActive(cons) )
8516  goto CONTTERMINATE;
8517 
8518  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
8519  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
8520  firstupgradetry = c;
8521 
8522  while( !consdata->presolved && !SCIPisStopped(scip) )
8523  {
8524  /* mark constraint being presolved and propagated */
8525  consdata->presolved = TRUE;
8526 
8527  /* add cliques to the clique table */
8528  SCIP_CALL( addCliques(scip, cons, &cutoff, naggrvars, nchgbds) );
8529  if( cutoff )
8530  break;
8531 
8532  /* propagate constraint */
8533  SCIP_CALL( propagateCons(scip, cons, &cutoff, ndelconss) );
8534  if( cutoff )
8535  break;
8536  }
8537 
8538  CONTTERMINATE:
8539 
8540  /* reset changed flag */
8541  if( SCIPconsIsActive(cons) )
8542  {
8543  consdata->changed = FALSE;
8544  }
8545 
8546  /* free temporary memory */
8547  SCIPfreeBufferArray(scip, &andnegs);
8548  SCIPfreeBufferArray(scip, &andcoefs);
8549  SCIPfreeBufferArray(scip, &andress);
8550  SCIPfreeBufferArray(scip, &lincoefs);
8551  SCIPfreeBufferArray(scip, &linvars);
8552  SCIPfreeBufferArray(scip, &coefs);
8553  SCIPfreeBufferArray(scip, &vars);
8554  }
8555 
8556  /* delete unused information in constraint handler data */
8557  SCIP_CALL( correctConshdlrdata(scip, conshdlrdata, ndelconss) );
8558 
8559  /* return the correct result code */
8560  if( cutoff )
8561  *result = SCIP_CUTOFF;
8562  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
8563  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
8564  *result = SCIP_SUCCESS;
8565  else
8566  *result = SCIP_DIDNOTFIND;
8567 
8568  return SCIP_OKAY;
8569 }
8570 
8571 /** variable rounding lock method of constraint handler */
8572 static
8573 SCIP_DECL_CONSLOCK(consLockPseudoboolean)
8574 { /*lint --e{715}*/
8575  SCIP_CONSDATA* consdata;
8576  SCIP_Real lhs;
8577  SCIP_Real rhs;
8578  SCIP_Bool haslhs;
8579  SCIP_Bool hasrhs;
8580  int v;
8581  int c;
8582 
8583  assert(scip != NULL);
8584  assert(cons != NULL);
8585  assert(conshdlr != NULL);
8586  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8587  assert(locktype == SCIP_LOCKTYPE_MODEL);
8588 
8589  consdata = SCIPconsGetData(cons);
8590  assert(consdata != NULL);
8591 
8592  lhs = consdata->lhs;
8593  rhs = consdata->rhs;
8594  assert(!SCIPisInfinity(scip, lhs));
8595  assert(!SCIPisInfinity(scip, -rhs));
8596  assert(SCIPisLE(scip, lhs, rhs));
8597 
8598  haslhs = !SCIPisInfinity(scip, -lhs);
8599  hasrhs = !SCIPisInfinity(scip, rhs);
8600 
8601  SCIPdebugMsg(scip, "%socking constraint <%s> by [%d;%d].\n", (nlocksneg < 0) || (nlockspos < 0) ? "Unl" : "L", SCIPconsGetName(cons), nlocksneg, nlockspos);
8602 
8603  /* update rounding locks of every single variable corresponding to the and-constraints */
8604  for( c = consdata->nconsanddatas - 1; c >= 0; --c )
8605  {
8606  SCIP_VAR* andres;
8607  SCIP_VAR** andvars;
8608  SCIP_Real val;
8609  int nandvars;
8610  SCIP_CONS* andcons;
8611  CONSANDDATA* consanddata;
8612 
8613  consanddata = consdata->consanddatas[c];
8614  assert( consanddata != NULL );
8615 
8616  if( !consanddata->istransformed )
8617  continue;
8618 
8619  andcons = consanddata->cons;
8620 
8621  if( andcons == NULL )
8622  {
8623  /* we should have no new variables */
8624  assert(consanddata->nnewvars == 0);
8625  assert(consanddata->nvars == 0);
8626 
8627  SCIPfreeBlockMemoryArrayNull(scip, &(consanddata->vars), consanddata->svars);
8628  SCIPfreeBlockMemoryArrayNull(scip, &(consanddata->newvars), consanddata->snewvars);
8629 
8630  consanddata->nvars = 0;
8631  consanddata->svars = 0;
8632  consanddata->nnewvars = 0;
8633  consanddata->snewvars = 0;
8634  consanddata->istransformed = FALSE;
8635 
8636  continue;
8637  }
8638  assert(andcons != NULL);
8639  if( consanddata->nnewvars > 0 )
8640  {
8641  andvars = consanddata->newvars;
8642  nandvars = consanddata->nnewvars;
8643  }
8644  else
8645  {
8646  andvars = consanddata->vars;
8647  nandvars = consanddata->nvars;
8648  }
8649 
8650  /* probably we need to store the resultant too, now it's not possible to remove the resultant from the and-constraint */
8651  andres = SCIPgetResultantAnd(scip, andcons);
8652  assert(nandvars == 0 || andvars != NULL);
8653  assert(andres != NULL);
8654  val = consdata->andnegs[c] ? -consdata->andcoefs[c] : consdata->andcoefs[c];
8655 
8656  /* lock variables */
8657  if( SCIPisPositive(scip, val) )
8658  {
8659  if( haslhs )
8660  {
8661  for( v = nandvars - 1; v >= 0; --v )
8662  {
8663  SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], locktype, nlockspos, nlocksneg) );
8664  }
8665  SCIP_CALL( SCIPaddVarLocksType(scip, andres, locktype, nlocksneg + nlockspos, nlocksneg + nlockspos) );
8666 
8667  SCIP_CALL( checkLocksAndRes(scip, andres) );
8668  }
8669  if( hasrhs )
8670  {
8671  for( v = nandvars - 1; v >= 0; --v )
8672  {
8673  SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], locktype, nlocksneg, nlockspos) );
8674  }
8675  /* don't double the locks on the and-resultant */
8676  if( !haslhs )
8677  {
8678  SCIP_CALL( SCIPaddVarLocksType(scip, andres, locktype, nlocksneg + nlockspos, nlocksneg + nlockspos) );
8679 
8680  SCIP_CALL( checkLocksAndRes(scip, andres) );
8681  }
8682  }
8683  }
8684  else
8685  {
8686  if( haslhs )
8687  {
8688  for( v = nandvars - 1; v >= 0; --v )
8689  {
8690  SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], SCIP_LOCKTYPE_MODEL, nlocksneg, nlockspos) );
8691  }
8692  SCIP_CALL( SCIPaddVarLocksType(scip, andres, SCIP_LOCKTYPE_MODEL, nlocksneg + nlockspos, nlocksneg + nlockspos) );
8693 
8694  SCIP_CALL( checkLocksAndRes(scip, andres) );
8695  }
8696  if( hasrhs )
8697  {
8698  for( v = nandvars - 1; v >= 0; --v )
8699  {
8700  SCIP_CALL( SCIPaddVarLocksType(scip, andvars[v], SCIP_LOCKTYPE_MODEL, nlockspos, nlocksneg) );
8701  }
8702  /* don't double the locks on the and-resultant */
8703  if( !haslhs )
8704  {
8705  SCIP_CALL( SCIPaddVarLocksType(scip, andres, SCIP_LOCKTYPE_MODEL, nlocksneg + nlockspos, nlocksneg + nlockspos) );
8706 
8707  SCIP_CALL( checkLocksAndRes(scip, andres) );
8708  }
8709  }
8710  }
8711  }
8712 
8713  return SCIP_OKAY;
8714 }
8715 
8716 /** constraint display method of constraint handler */
8717 static
8718 SCIP_DECL_CONSPRINT(consPrintPseudoboolean)
8719 { /*lint --e{715}*/
8720  assert(scip != NULL);
8721  assert(conshdlr != NULL);
8722  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8723  assert(cons != NULL);
8724 
8725  SCIP_CALL( consdataPrint(scip, cons, file) );
8726 
8727  return SCIP_OKAY;
8728 }
8729 
8730 /** constraint copying method of constraint handler */
8731 static
8732 SCIP_DECL_CONSCOPY(consCopyPseudoboolean)
8733 { /*lint --e{715}*/
8734  const char* consname;
8735 
8736  assert(scip != NULL);
8737  assert(sourcescip != NULL);
8738  assert(sourcecons != NULL);
8739 
8740  if( name != NULL )
8741  consname = name;
8742  else
8743  consname = SCIPconsGetName(sourcecons);
8744 
8745  SCIP_CALL( copyConsPseudoboolean(scip, cons, sourcescip, sourcecons, consname, varmap, consmap,
8746  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global,
8747  valid) );
8748  assert(cons != NULL || *valid == FALSE);
8749 
8750  return SCIP_OKAY;
8751 }
8752 
8753 /** constraint method of constraint handler which returns the variables (if possible) */
8754 static
8755 SCIP_DECL_CONSGETVARS(consGetVarsPseudoboolean)
8756 { /*lint --e{715}*/
8757  SCIP_CONSHDLRDATA* conshdlrdata;
8758  SCIP_CONSDATA* consdata;
8759  CONSANDDATA* consanddata;
8760  SCIP_VAR** linconsvars;
8761  SCIP_VAR** linvars;
8762  SCIP_VAR** andress;
8763  int nlinconsvars;
8764  int nlinvars;
8765  int nandress;
8766  SCIP_Bool transformed;
8767  int nvars;
8768  int r;
8769 
8770  assert(scip != NULL);
8771  assert(conshdlr != NULL);
8772  assert(cons != NULL);
8773  assert(vars != NULL);
8774  assert(success != NULL);
8775 
8776  if( varssize < 0 )
8777  return SCIP_INVALIDDATA;
8778  assert(varssize >= 0);
8779 
8780  *success = TRUE;
8781 
8782  /* pseudoboolean constraint is already deleted */
8783  if( SCIPconsIsDeleted(cons) )
8784  {
8785  vars = NULL;
8786 
8787  return SCIP_OKAY; /*lint !e438*/
8788  }
8789 
8790  consdata = SCIPconsGetData(cons);
8791  assert(consdata != NULL);
8792  assert(consdata->lincons != NULL);
8793 
8794  /* linear constraint of pseudoboolean is already deleted */
8795  if( SCIPconsIsDeleted(consdata->lincons) )
8796  {
8797  vars = NULL;
8798 
8799  return SCIP_OKAY; /*lint !e438*/
8800  }
8801 
8802  /* gets number of variables in linear constraint */
8803  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nlinconsvars) );
8804  assert(nlinconsvars >= 0);
8805 
8806  /* no variables exist */
8807  if( nlinconsvars == 0 )
8808  {
8809  vars = NULL;
8810 
8811  return SCIP_OKAY; /*lint !e438*/
8812  }
8813  /* not enough space in the variables array */
8814  else if( varssize < nlinconsvars )
8815  {
8816  (*success) = FALSE;
8817 
8818  return SCIP_OKAY;
8819  }
8820 
8821  /* allocate temporary memory */
8822  SCIP_CALL( SCIPallocBufferArray(scip, &linconsvars, nlinconsvars) );
8823  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinconsvars) );
8824  SCIP_CALL( SCIPallocBufferArray(scip, &andress, nlinconsvars) );
8825 
8826  /* get variables and coefficient of linear constraint */
8827  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, linconsvars, NULL, &nlinconsvars) );
8828 
8829  /* calculate all non-artificial linear variables and all artificial and-resultants which will be ordered like the
8830  * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array
8831  * afterwards
8832  */
8833  SCIP_CALL( getLinVarsAndAndRess(scip, cons, linconsvars, NULL, nlinconsvars, linvars, NULL, &nlinvars,
8834  andress, NULL, NULL, &nandress) );
8835  assert(nlinconsvars == nlinvars + nandress);
8836 
8837  nvars = nlinvars;
8838 
8839  if( nlinvars > 0 )
8840  {
8841  assert(linvars != NULL);
8842  BMScopyMemoryArray(vars, linvars, nvars);
8843  }
8844 
8845  if( nandress == 0 )
8846  goto TERMINATE;
8847 
8848  assert(andress != NULL);
8849 
8850  /* get constraint handler data */
8851  conshdlrdata = SCIPconshdlrGetData(conshdlr);
8852  assert(conshdlrdata != NULL);
8853  assert(conshdlrdata->hashmap != NULL);
8854 
8855  transformed = SCIPconsIsTransformed(cons);
8856 
8857  for( r = nandress - 1; r >= 0; --r )
8858  {
8859  SCIP_CONS* andcons;
8860 
8861  assert(andress[r] != NULL);
8862 
8863  consanddata = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)andress[r]);
8864 
8865  assert(consanddata != NULL);
8866  assert(consanddata->istransformed);
8867 
8868  if( transformed )
8869  andcons = consanddata->cons;
8870  else
8871  andcons = consanddata->origcons;
8872 
8873  assert(andcons != NULL);
8874 
8875  /* not enough space for all variables */
8876  if( varssize <= nvars )
8877  {
8878  (*success) = FALSE;
8879 
8880  goto TERMINATE;
8881  }
8882 
8883  /* add the resultant */
8884  vars[nvars] = andress[r];
8885  ++nvars;
8886 
8887  /* add all and-operands and the resultant */
8888  if( !SCIPconsIsDeleted(andcons) )
8889  {
8890  int noperands = SCIPgetNVarsAnd(scip, andcons);
8891 
8892  assert(noperands >= 0);
8893 
8894  /* not enough space for all variables */
8895  if( varssize < nvars + noperands )
8896  {
8897  (*success) = FALSE;
8898 
8899  goto TERMINATE;
8900  }
8901 
8902  /* copy operands */
8903  if( noperands > 0 )
8904  {
8905  assert(SCIPgetVarsAnd(scip, andcons) != NULL);
8906  BMScopyMemoryArray(&(vars[nvars]), SCIPgetVarsAnd(scip, andcons), noperands); /*lint !e866*/
8907  nvars += noperands;
8908  }
8909  }
8910  }
8911 
8912  TERMINATE:
8913 
8914  /* free temporary memory */
8915  SCIPfreeBufferArray(scip, &andress);
8916  SCIPfreeBufferArray(scip, &linvars);
8917  SCIPfreeBufferArray(scip, &linconsvars);
8918 
8919  return SCIP_OKAY;
8920 }
8921 
8922 /** constraint method of constraint handler which returns the number of variables (if possible) */
8923 static
8924 SCIP_DECL_CONSGETNVARS(consGetNVarsPseudoboolean)
8925 { /*lint --e{715}*/
8926  SCIP_CONSHDLRDATA* conshdlrdata;
8927  SCIP_CONSDATA* consdata;
8928  CONSANDDATA* consanddata;
8929  SCIP_VAR** linconsvars;
8930  SCIP_VAR** linvars;
8931  SCIP_VAR** andress;
8932  int nlinconsvars;
8933  int nlinvars;
8934  int nandress;
8935  SCIP_Bool transformed;
8936  int r;
8937 
8938  assert(scip != NULL);
8939  assert(conshdlr != NULL);
8940  assert(cons != NULL);
8941  assert(nvars != NULL);
8942  assert(success != NULL);
8943 
8944  (*success) = TRUE;
8945 
8946  /* pseudoboolean constraint is already deleted */
8947  if( SCIPconsIsDeleted(cons) )
8948  {
8949  *nvars = 0;
8950 
8951  return SCIP_OKAY;
8952  }
8953 
8954  consdata = SCIPconsGetData(cons);
8955  assert(consdata != NULL);
8956  assert(consdata->lincons != NULL);
8957 
8958  /* linear constraint of pseudoboolean is already deleted */
8959  if( SCIPconsIsDeleted(consdata->lincons) )
8960  {
8961  *nvars = 0;
8962 
8963  return SCIP_OKAY;
8964  }
8965 
8966  /* gets number of variables in linear constraint */
8967  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nlinconsvars) );
8968  assert(nlinconsvars >= 0);
8969 
8970  /* no variables exist */
8971  if( nlinconsvars == 0 )
8972  {
8973  *nvars = 0;
8974 
8975  return SCIP_OKAY;
8976  }
8977 
8978  /* allocate temporary memory */
8979  SCIP_CALL( SCIPallocBufferArray(scip, &linconsvars, nlinconsvars) );
8980  SCIP_CALL( SCIPallocBufferArray(scip, &linvars, nlinconsvars) );
8981  SCIP_CALL( SCIPallocBufferArray(scip, &andress, nlinconsvars) );
8982 
8983  /* get variables and coefficient of linear constraint */
8984  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, linconsvars, NULL, &nlinconsvars) );
8985 
8986  /* calculate all non-artificial linear variables and all artificial and-resultants which will be ordered like the
8987  * 'consanddatas' such that the and-resultant of the and-constraint is the and-resultant in the 'andress' array
8988  * afterwards
8989  */
8990  SCIP_CALL( getLinVarsAndAndRess(scip, cons, linconsvars, NULL, nlinconsvars, linvars, NULL, &nlinvars,
8991  andress, NULL, NULL, &nandress) );
8992  assert(nlinconsvars == nlinvars + nandress);
8993 
8994  *nvars = nlinvars;
8995 
8996  if( nandress == 0 )
8997  goto TERMINATE;
8998 
8999  assert(andress != NULL);
9000 
9001  /* get constraint handler data */
9002  conshdlrdata = SCIPconshdlrGetData(conshdlr);
9003  assert(conshdlrdata != NULL);
9004  assert(conshdlrdata->hashmap != NULL);
9005 
9006  transformed = SCIPconsIsTransformed(cons);
9007 
9008  for( r = nandress - 1; r >= 0; --r )
9009  {
9010  SCIP_CONS* andcons;
9011 
9012  assert(andress[r] != NULL);
9013 
9014  consanddata = (CONSANDDATA*) SCIPhashmapGetImage(conshdlrdata->hashmap, (void*)andress[r]);
9015 
9016  assert(consanddata != NULL);
9017  assert(consanddata->istransformed);
9018 
9019  if( transformed )
9020  andcons = consanddata->cons;
9021  else
9022  andcons = consanddata->origcons;
9023 
9024  assert(andcons != NULL);
9025 
9026  if( SCIPconsIsDeleted(andcons) )
9027  {
9028  /* only add one for the resultant */
9029  ++(*nvars);
9030  }
9031  else
9032  {
9033  /* add all and-operands and one for the resultant */
9034  *nvars += SCIPgetNVarsAnd(scip, andcons) + 1;
9035  }
9036  }
9037 
9038  TERMINATE:
9039  /* free temporary memory */
9040  SCIPfreeBufferArray(scip, &andress);
9041  SCIPfreeBufferArray(scip, &linvars);
9042  SCIPfreeBufferArray(scip, &linconsvars);
9043 
9044  return SCIP_OKAY;
9045 }
9046 
9047 /*
9048  * constraint specific interface methods
9049  */
9050 
9051 /** creates the handler for pseudoboolean constraints and includes it in SCIP */
9053  SCIP* scip /**< SCIP data structure */
9054  )
9055 {
9056  SCIP_CONSHDLR* conshdlr;
9057  SCIP_CONSHDLRDATA* conshdlrdata;
9058 
9059  /* create pseudoboolean constraint handler data */
9060  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata) );
9061 
9062  /* include constraint handler */
9065  consEnfolpPseudoboolean, consEnfopsPseudoboolean, consCheckPseudoboolean, consLockPseudoboolean,
9066  conshdlrdata) );
9067  assert(conshdlr != NULL);
9068 
9069  /* set non-fundamental callbacks via specific setter functions */
9070  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyPseudoboolean, consCopyPseudoboolean) );
9071  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeletePseudoboolean) );
9072  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreePseudoboolean) );
9073  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsPseudoboolean) );
9074  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsPseudoboolean) );
9075  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitPseudoboolean) );
9076  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitprePseudoboolean) );
9077  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolPseudoboolean, CONSHDLR_MAXPREROUNDS,
9079  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintPseudoboolean) );
9080  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransPseudoboolean) );
9081  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxPseudoboolean) );
9082 
9083  /* add pseudoboolean constraint handler parameters */
9085  "constraints/" CONSHDLR_NAME "/decomposenormal",
9086  "decompose all normal pseudo boolean constraint into a \"linear\" constraint and \"and\" constraints",
9087  &conshdlrdata->decomposenormalpbcons, TRUE, DEFAULT_DECOMPOSENORMALPBCONS, NULL, NULL) );
9089  "constraints/" CONSHDLR_NAME "/decomposeindicator",
9090  "decompose all indicator pseudo boolean constraint into a \"linear\" constraint and \"and\" constraints",
9091  &conshdlrdata->decomposeindicatorpbcons, TRUE, DEFAULT_DECOMPOSEINDICATORPBCONS, NULL, NULL) );
9093  "constraints/" CONSHDLR_NAME "/nlcseparate", "should the nonlinear constraints be separated during LP processing?",
9096  "constraints/" CONSHDLR_NAME "/nlcpropagate", "should the nonlinear constraints be propagated during node processing?",
9099  "constraints/" CONSHDLR_NAME "/nlcremovable", "should the nonlinear constraints be removable?",
9101 
9102 #ifdef NONLINCONSUPGD_PRIORITY
9103  /* include the quadratic constraint upgrade in the nonlinear constraint handler */
9104  SCIP_CALL( SCIPincludeNonlinconsUpgrade(scip, nonlinconsUpgdPseudoboolean, NULL, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
9105 #endif
9106 
9107  return SCIP_OKAY;
9108 }
9109 
9110 /** creates and captures a pseudoboolean constraint, with given linear and and-constraints
9111  *
9112  * @note intvar must currently be NULL
9113  */
9115  SCIP* scip, /**< SCIP data structure */
9116  SCIP_CONS** cons, /**< pointer to hold the created constraint */
9117  const char* name, /**< name of constraint */
9118  SCIP_CONS* lincons, /**< associated linear constraint */
9119  SCIP_LINEARCONSTYPE linconstype, /**< linear constraint type of associated linear constraint */
9120  SCIP_CONS** andconss, /**< associated and-constraints */
9121  SCIP_Real* andcoefs, /**< associated coefficients of and-constraints */
9122  int nandconss, /**< number of associated and-constraints */
9123  SCIP_VAR* indvar, /**< indicator variable if it's a soft constraint, or NULL */
9124  SCIP_Real weight, /**< weight of the soft constraint, if it is one */
9125  SCIP_Bool issoftcons, /**< is this a soft constraint */
9126  SCIP_VAR* intvar, /**< an artificial variable which was added only for the objective function,
9127  * if this variable is not NULL this constraint (without this integer
9128  * variable) describes the objective function */
9129  SCIP_Real lhs, /**< left hand side of constraint */
9130  SCIP_Real rhs, /**< right hand side of constraint */
9131  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
9132  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9133  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
9134  * Usually set to TRUE. */
9135  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
9136  * TRUE for model constraints, FALSE for additional, redundant constraints. */
9137  SCIP_Bool check, /**< should the constraint be checked for feasibility?
9138  * TRUE for model constraints, FALSE for additional, redundant constraints. */
9139  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
9140  * Usually set to TRUE. */
9141  SCIP_Bool local, /**< is constraint only valid locally?
9142  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9143  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
9144  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
9145  * adds coefficients to this constraint. */
9146  SCIP_Bool dynamic, /**< is constraint subject to aging?
9147  * Usually set to FALSE. Set to TRUE for own cuts which
9148  * are seperated as constraints. */
9149  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
9150  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9151  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
9152  * if it may be moved to a more global node?
9153  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9154  )
9155 {
9156  CONSANDDATA* newdata;
9157  CONSANDDATA* tmpdata;
9158  SCIP_CONSHDLR* conshdlr;
9159  SCIP_CONSHDLRDATA* conshdlrdata;
9160  SCIP_CONSDATA* consdata;
9161  SCIP_VAR** vars;
9162  SCIP_VAR* res;
9163  SCIP_Bool memisinvalid;
9164  SCIP_Bool transformed;
9165  int nvars;
9166  int c;
9167 
9168  assert(scip != NULL);
9169  assert(cons != NULL);
9170  assert(lincons != NULL);
9171  assert(linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
9172  assert(andconss != NULL);
9173  assert(andcoefs != NULL);
9174  assert(nandconss >= 1);
9175  assert(issoftcons == (indvar != NULL));
9176 
9177  if( intvar != NULL )
9178  {
9179  /* FIXME should work or really be removed */
9180  SCIPerrorMessage("intvar currently not supported by pseudo boolean constraint handler\n");
9181  return SCIP_INVALIDDATA;
9182  }
9183 
9184  /* find the pseudoboolean constraint handler */
9185  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
9186  if( conshdlr == NULL )
9187  {
9188  SCIPerrorMessage("pseudo boolean constraint handler not found\n");
9189  return SCIP_PLUGINNOTFOUND;
9190  }
9191 
9192  /* get constraint handler data */
9193  conshdlrdata = SCIPconshdlrGetData(conshdlr);
9194  assert(conshdlrdata != NULL);
9195 
9196  /* initial hashmap and -table */
9197  SCIP_CALL( inithashmapandtable(scip, &conshdlrdata) );
9198 
9199  assert(conshdlrdata->hashmap != NULL);
9200  assert(conshdlrdata->hashtable != NULL);
9201  assert(conshdlrdata->allconsanddatas != NULL);
9202  assert(conshdlrdata->nallconsanddatas <= conshdlrdata->sallconsanddatas);
9203 
9204  memisinvalid = TRUE;
9205  newdata = NULL;
9206 
9207  transformed = SCIPconsIsTransformed(lincons);
9208 
9209  /* create hash map and hash table entries */
9210  for( c = nandconss - 1; c >= 0; --c )
9211  {
9212  assert(andconss[c] != NULL);
9213  res = SCIPgetResultantAnd(scip, andconss[c]);
9214  vars = SCIPgetVarsAnd(scip, andconss[c]);
9215  nvars = SCIPgetNVarsAnd(scip, andconss[c]);
9216  assert(vars != NULL && nvars > 0);
9217  assert(res != NULL);
9218 
9219  /* stop if the constraint has 0 variables or an error occurred (coverity issue) */
9220  if( nvars <= 0 )
9221  continue;
9222 
9223  /* if allocated memory in this for loop was already used, allocate a new block, otherwise we only need to copy the variables */
9224  if( memisinvalid )
9225  {
9226  /* allocate memory for a possible new consanddata object */
9227  SCIP_CALL( SCIPallocBlockMemory(scip, &newdata) );
9228  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(newdata->vars), vars, nvars) );
9229  newdata->svars = nvars;
9230  newdata->newvars = NULL;
9231  newdata->nnewvars = 0;
9232  newdata->snewvars = 0;
9233  newdata->istransformed = transformed;
9234  newdata->isoriginal = !transformed;
9235  newdata->noriguses = 0;
9236  newdata->nuses = 0;
9237  newdata->cons = NULL;
9238  newdata->origcons = NULL;
9239  }
9240  else
9241  {
9242  assert(newdata != NULL);
9243  /* resize variable array if necessary */
9244  if( newdata->svars < nvars )
9245  {
9246  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(newdata->vars), &(newdata->svars), nvars) );
9247  }
9248 
9249  /* copy variables in already allocated array */
9250  BMScopyMemoryArray(newdata->vars, vars, nvars);
9251  }
9252 
9253  /* sort variables */
9254  SCIPsortPtr((void**)(newdata->vars), SCIPvarComp, nvars);
9255 
9256  newdata->nvars = nvars;
9257  assert(newdata->vars != NULL && newdata->nvars > 0);
9258 
9259  if( SCIPconsIsTransformed(andconss[c]) )
9260  {
9261  int v;
9262 
9263  /* either all constraints are transformed or none */
9264  assert(transformed);
9265  newdata->cons = andconss[c];
9266 
9267  /* capture all variables */
9268  for( v = newdata->nvars - 1; v >= 0; --v )
9269  {
9270  SCIP_CALL( SCIPcaptureVar(scip, newdata->vars[v]) ); /*lint !e613*/
9271  }
9272  }
9273  else
9274  {
9275  /* either all constraints are transformed or none */
9276  assert(!transformed);
9277  newdata->origcons = andconss[c];
9278  }
9279 
9280  /* get constraint from current hash table with same variables as andconss[c] */
9281  tmpdata = (CONSANDDATA*)(SCIPhashtableRetrieve(conshdlrdata->hashtable, (void*)newdata));
9282  assert(tmpdata == NULL || tmpdata->cons != NULL || tmpdata->origcons != NULL);
9283 
9284  if( tmpdata == NULL || (tmpdata->cons != andconss[c] && tmpdata->origcons != andconss[c]))
9285  {
9286  if( tmpdata != NULL && (tmpdata->cons != NULL || tmpdata->origcons != NULL) )
9287  {
9288  SCIPwarningMessage(scip, "Another and-constraint with the same variables but different and-resultant is added to the global and-constraint hashtable of pseudoboolean constraint handler.\n");
9289  }
9290 
9291  /* resize data for all and-constraints if necessary */
9292  if( conshdlrdata->nallconsanddatas == conshdlrdata->sallconsanddatas )
9293  {
9294  SCIP_CALL( SCIPensureBlockMemoryArray(scip, &(conshdlrdata->allconsanddatas), &(conshdlrdata->sallconsanddatas), SCIPcalcMemGrowSize(scip, conshdlrdata->sallconsanddatas + 1)) );
9295  }
9296 
9297  conshdlrdata->allconsanddatas[conshdlrdata->nallconsanddatas] = newdata;
9298  ++(conshdlrdata->nallconsanddatas);
9299 
9300  /* no such and-constraint in current hash table: insert the new object into hash table */
9301  SCIP_CALL( SCIPhashtableInsert(conshdlrdata->hashtable, (void*)newdata) );
9302 
9303  /* if newdata object was new we want to allocate new memory in next loop iteration */
9304  memisinvalid = TRUE;
9305  assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)res));
9306 
9307  /* capture and-constraint */
9308  if( transformed )
9309  {
9310  SCIP_CALL( SCIPcaptureCons(scip, newdata->cons) );
9311 
9312  /* initialize usage of data object */
9313  newdata->nuses = 1;
9314  }
9315  else
9316  {
9317  SCIP_CALL( SCIPcaptureCons(scip, newdata->origcons) );
9318 
9319  /* initialize usage of data object */
9320  newdata->noriguses = 1;
9321  }
9322 
9323  /* insert new mapping */
9324  assert(!SCIPhashmapExists(conshdlrdata->hashmap, (void*)res));
9325  SCIP_CALL( SCIPhashmapInsert(conshdlrdata->hashmap, (void*)res, (void*)newdata) );
9326  }
9327  else
9328  {
9329  assert(SCIPhashmapExists(conshdlrdata->hashmap, (void*)res));
9330  memisinvalid = FALSE;
9331 
9332  if( transformed )
9333  {
9334  assert(tmpdata->nuses > 0);
9335 
9336  /* increase usage of data object */
9337  ++(tmpdata->nuses);
9338  }
9339  else
9340  {
9341  assert(tmpdata->noriguses > 0);
9342 
9343  /* increase usage of data object */
9344  ++(tmpdata->noriguses);
9345  }
9346  }
9347  }
9348 
9349  if( !memisinvalid )
9350  {
9351  assert(newdata != NULL);
9352 
9353  /* free temporary memory */
9354  SCIPfreeBlockMemoryArray(scip, &(newdata->vars), newdata->svars);
9355  SCIPfreeBlockMemory(scip, &newdata);
9356  }
9357 
9358  /* adjust right hand side */
9359  if( SCIPisInfinity(scip, rhs) )
9360  rhs = SCIPinfinity(scip);
9361  else if( SCIPisInfinity(scip, -rhs) )
9362  rhs = -SCIPinfinity(scip);
9363 
9364  /* capture linear constraint */
9365  SCIP_CALL( SCIPcaptureCons(scip, lincons) );
9366 
9367  /* todo: make the constraint upgrade flag global, now it works only for the common linear constraint */
9368  /* mark linear constraint not to be upgraded - otherwise we loose control over it */
9369  SCIPconsAddUpgradeLocks(lincons, 1);
9370 
9371  /* create constraint data */
9372  /* checking for and-constraints will be FALSE, we check all information in this constraint handler */
9373  SCIP_CALL( consdataCreate(scip, conshdlr, &consdata, lincons, linconstype, andconss, andcoefs, NULL, nandconss,
9374  indvar, weight, issoftcons, intvar, lhs, rhs, check, FALSE) );
9375  assert(consdata != NULL);
9376 
9377  /* create constraint */
9378  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
9379  local, modifiable, dynamic, removable, stickingatnode) );
9380 
9381  return SCIP_OKAY;
9382 }
9383 
9384 /** creates and captures a pseudoboolean constraint
9385  *
9386  * @note linear and nonlinear terms can be added using SCIPaddCoefPseudoboolean() and SCIPaddTermPseudoboolean(),
9387  * respectively
9388  *
9389  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9390  *
9391  * @note intvar must currently be NULL
9392  */
9394  SCIP* scip, /**< SCIP data structure */
9395  SCIP_CONS** cons, /**< pointer to hold the created constraint */
9396  const char* name, /**< name of constraint */
9397  SCIP_VAR** linvars, /**< variables of the linear part, or NULL */
9398  int nlinvars, /**< number of variables of the linear part */
9399  SCIP_Real* linvals, /**< coefficients of linear part, or NULL */
9400  SCIP_VAR*** terms, /**< nonlinear terms of variables, or NULL */
9401  int nterms, /**< number of terms of variables of nonlinear term */
9402  int* ntermvars, /**< number of variables in nonlinear terms, or NULL */
9403  SCIP_Real* termvals, /**< coefficients of nonlinear parts, or NULL */
9404  SCIP_VAR* indvar, /**< indicator variable if it's a soft constraint, or NULL */
9405  SCIP_Real weight, /**< weight of the soft constraint, if it is one */
9406  SCIP_Bool issoftcons, /**< is this a soft constraint */
9407  SCIP_VAR* intvar, /**< an artificial variable which was added only for the objective function,
9408  * if this variable is not NULL this constraint (without this integer
9409  * variable) describes the objective function */
9410  SCIP_Real lhs, /**< left hand side of constraint */
9411  SCIP_Real rhs, /**< right hand side of constraint */
9412  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
9413  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9414  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
9415  * Usually set to TRUE. */
9416  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
9417  * TRUE for model constraints, FALSE for additional, redundant constraints. */
9418  SCIP_Bool check, /**< should the constraint be checked for feasibility?
9419  * TRUE for model constraints, FALSE for additional, redundant constraints. */
9420  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
9421  * Usually set to TRUE. */
9422  SCIP_Bool local, /**< is constraint only valid locally?
9423  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9424  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
9425  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
9426  * adds coefficients to this constraint. */
9427  SCIP_Bool dynamic, /**< is constraint subject to aging?
9428  * Usually set to FALSE. Set to TRUE for own cuts which
9429  * are separated as constraints. */
9430  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
9431  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9432  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
9433  * if it may be moved to a more global node?
9434  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9435  )
9436 {
9437  SCIP_CONSHDLRDATA* conshdlrdata;
9438  SCIP_CONSHDLR* conshdlr;
9439  SCIP_CONSDATA* consdata;
9440  SCIP_VAR** andress;
9441  SCIP_CONS** andconss;
9442  SCIP_Real* andcoefs;
9443  SCIP_Bool* andnegs;
9444  int nandconss;
9445  SCIP_CONS* lincons;
9446  SCIP_LINEARCONSTYPE linconstype;
9447  int c;
9448 
9449  assert(scip != NULL);
9450  assert(cons != NULL);
9451  assert(nlinvars == 0 || (linvars != NULL && linvals != NULL));
9452  assert(nterms == 0 || (terms != NULL && termvals != NULL && ntermvars != NULL));
9453  assert(issoftcons == (indvar != NULL));
9454 
9455  if( intvar != NULL )
9456  {
9457  /* FIXME should work or really be removed */
9458  SCIPerrorMessage("intvar currently not supported by pseudo boolean constraint handler\n");
9459  return SCIP_INVALIDDATA;
9460  }
9461 
9462  /* find the pseudoboolean constraint handler */
9463  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
9464  if( conshdlr == NULL )
9465  {
9466  SCIPerrorMessage("pseudo boolean constraint handler not found\n");
9467  return SCIP_PLUGINNOTFOUND;
9468  }
9469 
9470 #if USEINDICATOR == TRUE
9471  if( issoftcons && modifiable )
9472  {
9473  SCIPerrorMessage("Indicator constraint handler can't work with modifiable constraints\n");
9474  return SCIP_INVALIDDATA;
9475  }
9476 #endif
9477 
9478  /* get constraint handler data */
9479  conshdlrdata = SCIPconshdlrGetData(conshdlr);
9480  assert(conshdlrdata != NULL);
9481 
9482  /* initial hashmap and -table */
9483  SCIP_CALL( inithashmapandtable(scip, &conshdlrdata) );
9484 
9485  /* get temporary memory */
9486  SCIP_CALL( SCIPallocBufferArray(scip, &andconss, nterms) );
9487  SCIP_CALL( SCIPallocBufferArray(scip, &andress, nterms) );
9488  SCIP_CALL( SCIPallocBufferArray(scip, &andcoefs, nterms) );
9489  SCIP_CALL( SCIPallocBufferArray(scip, &andnegs, nterms) );
9490 
9491  nandconss = 0;
9492  /* create and-constraints */
9493  SCIP_CALL( createAndAddAnds(scip, conshdlr, terms, termvals, nterms, ntermvars,
9494  initial, enforce, check, local, modifiable, dynamic, stickingatnode,
9495  andconss, andcoefs, andnegs, &nandconss) );
9496  assert(nterms >= nandconss);
9497 
9498  /* get all and-resultants for linear constraint */
9499  for( c = nandconss - 1; c >= 0; --c )
9500  {
9501  assert(andconss[c] != NULL);
9502  andress[c] = SCIPgetResultantAnd(scip, andconss[c]);
9503  }
9504 
9505  linconstype = SCIP_LINEARCONSTYPE_INVALIDCONS;
9506 
9507  /* adjust right hand side */
9508  if( SCIPisInfinity(scip, rhs) )
9509  rhs = SCIPinfinity(scip);
9510  else if( SCIPisInfinity(scip, -rhs) )
9511  rhs = -SCIPinfinity(scip);
9512 
9513  /* create and add linear constraint */
9514  /* checking for original linear constraint will be FALSE, transformed linear constraints get the check flag like this
9515  * pseudoboolean constraint, in this constraint handler we only will check all and-constraints
9516  */
9517  SCIP_CALL( createAndAddLinearCons(scip, conshdlr, linvars, nlinvars, linvals, andress, nandconss, andcoefs, andnegs,
9518  &lhs, &rhs, initial, separate, enforce, FALSE/*check*/, propagate, local, modifiable, dynamic, removable,
9519  stickingatnode, &lincons, &linconstype) );
9520  assert(lincons != NULL);
9521  assert(linconstype > SCIP_LINEARCONSTYPE_INVALIDCONS);
9522 
9523  /* create constraint data */
9524  /* checking for and-constraints will be FALSE, we check all information in this constraint handler */
9525  SCIP_CALL( consdataCreate(scip, conshdlr, &consdata, lincons, linconstype, andconss, andcoefs, andnegs, nandconss,
9526  indvar, weight, issoftcons, intvar, lhs, rhs, check, FALSE) );
9527  assert(consdata != NULL);
9528 
9529  /* free temporary memory */
9530  SCIPfreeBufferArray(scip, &andnegs);
9531  SCIPfreeBufferArray(scip, &andcoefs);
9532  SCIPfreeBufferArray(scip, &andress);
9533  SCIPfreeBufferArray(scip, &andconss);
9534 
9535  /* create constraint */
9536  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
9537  local, modifiable, dynamic, removable, stickingatnode) );
9538 
9539  return SCIP_OKAY;
9540 }
9541 
9542 /** creates and captures a pseudoboolean constraint
9543  * in its most basic variant, i. e., with all constraint flags set to their default values
9544  *
9545  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9546  *
9547  * @note intvar must currently be NULL
9548  */
9550  SCIP* scip, /**< SCIP data structure */
9551  SCIP_CONS** cons, /**< pointer to hold the created constraint */
9552  const char* name, /**< name of constraint */
9553  SCIP_VAR** linvars, /**< variables of the linear part, or NULL */
9554  int nlinvars, /**< number of variables of the linear part */
9555  SCIP_Real* linvals, /**< coefficients of linear part, or NULL */
9556  SCIP_VAR*** terms, /**< nonlinear terms of variables, or NULL */
9557  int nterms, /**< number of terms of variables of nonlinear term */
9558  int* ntermvars, /**< number of variables in nonlinear terms, or NULL */
9559  SCIP_Real* termvals, /**< coefficients of nonlinear parts, or NULL */
9560  SCIP_VAR* indvar, /**< indicator variable if it's a soft constraint, or NULL */
9561  SCIP_Real weight, /**< weight of the soft constraint, if it is one */
9562  SCIP_Bool issoftcons, /**< is this a soft constraint */
9563  SCIP_VAR* intvar, /**< a artificial variable which was added only for the objective function,
9564  * if this variable is not NULL this constraint (without this integer
9565  * variable) describes the objective function */
9566  SCIP_Real lhs, /**< left hand side of constraint */
9567  SCIP_Real rhs /**< right hand side of constraint */
9568  )
9569 {
9570  SCIP_CALL( SCIPcreateConsPseudoboolean(scip, cons, name, linvars, nlinvars, linvals,
9571  terms, nterms, ntermvars, termvals, indvar, weight, issoftcons, intvar, lhs, rhs,
9572  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
9573 
9574  return SCIP_OKAY;
9575 }
9576 
9577 /** adds a variable to the pseudo boolean constraint (if it is not zero)
9578  *
9579  * @note you can only add a coefficient if the special type of linear constraint won't changed
9580  *
9581  * @todo if adding a coefficient would change the type of the special linear constraint, we need to erase it and
9582  * create a new linear constraint
9583  */
9585  SCIP*const scip, /**< SCIP data structure */
9586  SCIP_CONS*const cons, /**< constraint data */
9587  SCIP_VAR*const var, /**< variable of constraint entry */
9588  SCIP_Real const val /**< coefficient of constraint entry */
9589  )
9590 {
9591  SCIP_CONSDATA* consdata;
9592 
9593  assert(scip != NULL);
9594  assert(cons != NULL);
9595  assert(var != NULL);
9596 
9597  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9598  {
9599  SCIPerrorMessage("constraint is not pseudo boolean\n");
9600  SCIPABORT();
9601  return SCIP_INVALIDDATA; /*lint !e527*/
9602  }
9603 
9604  if( SCIPisZero(scip, val) )
9605  return SCIP_OKAY;
9606 
9607  consdata = SCIPconsGetData(cons);
9608  assert(consdata != NULL);
9609 
9610  switch( consdata->linconstype )
9611  {
9613  SCIP_CALL( SCIPaddCoefLinear(scip, consdata->lincons, var, val) );
9614  break;
9616  if( !SCIPisEQ(scip, val, 1.0) )
9617  return SCIP_INVALIDDATA;
9618 
9619  SCIP_CALL( SCIPaddCoefLogicor(scip, consdata->lincons, var) );
9620  break;
9622  if( !SCIPisIntegral(scip, val) || !SCIPisPositive(scip, val) )
9623  return SCIP_INVALIDDATA;
9624 
9625  SCIP_CALL( SCIPaddCoefKnapsack(scip, consdata->lincons, var, (SCIP_Longint) val) );
9626  break;
9628  if( !SCIPisEQ(scip, val, 1.0) )
9629  return SCIP_INVALIDDATA;
9630 
9631  SCIP_CALL( SCIPaddCoefSetppc(scip, consdata->lincons, var) );
9632  break;
9633 #ifdef WITHEQKNAPSACK
9634  case SCIP_LINEARCONSTYPE_EQKNAPSACK:
9635  if( !SCIPisIntegral(scip, val) || !SCIPisPositive(scip, val) )
9636  return SCIP_INVALIDDATA;
9637 
9638  SCIP_CALL( SCIPaddCoefEQKnapsack(scip, consdata->lincons, var, (SCIP_Longint) val) );
9639  break;
9640 #endif
9642  default:
9643  SCIPerrorMessage("unknown linear constraint type\n");
9644  return SCIP_INVALIDDATA;
9645  }
9646 
9647  consdata->propagated = FALSE;
9648  consdata->presolved = FALSE;
9649  consdata->cliquesadded = FALSE;
9650 
9651  return SCIP_OKAY;
9652 }
9653 
9654 /** adds nonlinear term to pseudo boolean constraint (if it is not zero)
9655  *
9656  * @note you can only add a coefficient if the special type of linear constraint won't changed
9657  *
9658  * @todo if adding a coefficient would change the type of the special linear constraint, we need to erase it and
9659  * create a new linear constraint
9660  */
9662  SCIP*const scip, /**< SCIP data structure */
9663  SCIP_CONS*const cons, /**< pseudoboolean constraint */
9664  SCIP_VAR**const vars, /**< variables of the nonlinear term */
9665  int const nvars, /**< number of variables of the nonlinear term */
9666  SCIP_Real const val /**< coefficient of constraint entry */
9667  )
9668 {
9669  assert(scip != NULL);
9670  assert(cons != NULL);
9671  assert(nvars == 0 || vars != NULL);
9672 
9673  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9674  {
9675  SCIPerrorMessage("constraint is not pseudo boolean\n");
9676  SCIPABORT();
9677  return SCIP_INVALIDDATA; /*lint !e527*/
9678  }
9679 
9680  SCIP_CALL( addCoefTerm(scip, cons, vars, nvars, val) );
9681 
9682  return SCIP_OKAY;
9683 }
9684 
9685 /** gets indicator variable of pseudoboolean constraint, or NULL if there is no */
9687  SCIP*const scip, /**< SCIP data structure */
9688  SCIP_CONS*const cons /**< constraint data */
9689  )
9690 {
9691  SCIP_CONSDATA* consdata;
9692 
9693  assert(scip != NULL);
9694  assert(cons != NULL);
9695 
9696  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9697  {
9698  SCIPerrorMessage("constraint is not pseudo boolean\n");
9699  SCIPABORT();
9700  return NULL; /*lint !e527*/
9701  }
9702 
9703  consdata = SCIPconsGetData(cons);
9704  assert(consdata != NULL);
9705 
9706  return consdata->indvar;
9707 }
9708 
9709 /** gets linear constraint of pseudoboolean constraint */
9711  SCIP*const scip, /**< SCIP data structure */
9712  SCIP_CONS*const cons /**< constraint data */
9713  )
9714 {
9715  SCIP_CONSDATA* consdata;
9716 
9717  assert(scip != NULL);
9718  assert(cons != NULL);
9719 
9720  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9721  {
9722  SCIPerrorMessage("constraint is not pseudo boolean\n");
9723  SCIPABORT();
9724  return NULL; /*lint !e527*/
9725  }
9726 
9727  consdata = SCIPconsGetData(cons);
9728  assert(consdata != NULL);
9729 
9730  return consdata->lincons;
9731 }
9732 
9733 /** gets type of linear constraint of pseudoboolean constraint */
9735  SCIP*const scip, /**< SCIP data structure */
9736  SCIP_CONS*const cons /**< constraint data */
9737  )
9738 {
9739  SCIP_CONSDATA* consdata;
9740 
9741  assert(scip != NULL);
9742  assert(cons != NULL);
9743 
9744  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9745  {
9746  SCIPerrorMessage("constraint is not pseudo boolean\n");
9747  SCIPABORT();
9748  return SCIP_LINEARCONSTYPE_INVALIDCONS; /*lint !e527*/
9749  }
9750 
9751  consdata = SCIPconsGetData(cons);
9752  assert(consdata != NULL);
9753 
9754  return consdata->linconstype;
9755 }
9756 
9757 /** gets number of linear variables without artificial terms variables of pseudoboolean constraint */
9759  SCIP*const scip, /**< SCIP data structure */
9760  SCIP_CONS*const cons /**< pseudoboolean constraint */
9761  )
9762 {
9763  SCIP_CONSDATA* consdata;
9764 
9765  assert(scip != NULL);
9766  assert(cons != NULL);
9767 
9768  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9769  {
9770  SCIPerrorMessage("constraint is not pseudo boolean\n");
9771  SCIPABORT();
9772  return -1; /*lint !e527*/
9773  }
9774 
9775  checkConsConsistency(scip, cons);
9776 
9777  consdata = SCIPconsGetData(cons);
9778  assert(consdata != NULL);
9779 
9780  return consdata->nlinvars;
9781 }
9782 
9783 /** gets linear constraint of pseudoboolean constraint */
9785  SCIP*const scip, /**< SCIP data structure */
9786  SCIP_CONS*const cons, /**< pseudoboolean constraint */
9787  SCIP_VAR**const linvars, /**< array to store and-constraints */
9788  SCIP_Real*const lincoefs, /**< array to store and-coefficients */
9789  int*const nlinvars /**< pointer to store the required array size for and-constraints, have to
9790  * be initialized with size of given array */
9791  )
9792 {
9793  SCIP_CONSDATA* consdata;
9794  SCIP_VAR** vars;
9795  SCIP_Real* coefs;
9796  int nvars;
9797 
9798  assert(scip != NULL);
9799  assert(cons != NULL);
9800  assert(nlinvars != NULL);
9801  assert(*nlinvars == 0 || linvars != NULL);
9802  assert(*nlinvars == 0 || lincoefs != NULL);
9803 
9804  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9805  {
9806  SCIPerrorMessage("constraint is not pseudo boolean\n");
9807  SCIPABORT();
9808  return SCIP_INVALIDDATA; /*lint !e527*/
9809  }
9810 
9811  consdata = SCIPconsGetData(cons);
9812  assert(consdata != NULL);
9813 
9814  checkConsConsistency(scip, cons);
9815 
9816  if( *nlinvars < consdata->nlinvars )
9817  {
9818  *nlinvars = consdata->nlinvars;
9819  return SCIP_OKAY;
9820  }
9821 
9822  /* gets number of variables in linear constraint */
9823  SCIP_CALL( getLinearConsNVars(scip, consdata->lincons, consdata->linconstype, &nvars) );
9824 
9825  /* allocate temporary memory */
9826  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
9827  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
9828 
9829  /* get variables and coefficient of linear constraint */
9830  SCIP_CALL( getLinearConsVarsData(scip, consdata->lincons, consdata->linconstype, vars, coefs, &nvars) );
9831 
9832  /* calculate all not artificial linear variables */
9833  SCIP_CALL( getLinVarsAndAndRess(scip, cons, vars, coefs, nvars, linvars, lincoefs, nlinvars, NULL, NULL, NULL, NULL) );
9834 
9835  /* free temporary memory */
9836  SCIPfreeBufferArray(scip, &coefs);
9837  SCIPfreeBufferArray(scip, &vars);
9838 
9839  return SCIP_OKAY;
9840 }
9841 
9842 
9843 /** gets and-constraints of pseudoboolean constraint */
9845  SCIP*const scip, /**< SCIP data structure */
9846  SCIP_CONS*const cons, /**< pseudoboolean constraint */
9847  SCIP_CONS**const andconss, /**< array to store and-constraints */
9848  SCIP_Real*const andcoefs, /**< array to store and-coefficients */
9849  int*const nandconss /**< pointer to store the required array size for and-constraints, have to
9850  * be initialized with size of given array */
9851  )
9852 {
9853  SCIP_CONSDATA* consdata;
9854  SCIP_Bool isorig;
9855  int c;
9856 
9857  assert(scip != NULL);
9858  assert(cons != NULL);
9859  assert(nandconss != NULL);
9860  assert(*nandconss == 0 || andconss != NULL);
9861  assert(*nandconss == 0 || andcoefs != NULL);
9862 
9863  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9864  {
9865  SCIPerrorMessage("constraint is not pseudo boolean\n");
9866  SCIPABORT();
9867  return SCIP_INVALIDDATA; /*lint !e527*/
9868  }
9869 
9870  consdata = SCIPconsGetData(cons);
9871  assert(consdata != NULL);
9872 
9873  checkConsConsistency(scip, cons);
9874 
9875  if( *nandconss < consdata->nconsanddatas )
9876  {
9877  *nandconss = consdata->nconsanddatas;
9878  return SCIP_OKAY;
9879  }
9880 
9881  *nandconss = consdata->nconsanddatas;
9882  assert(*nandconss == 0 || consdata->consanddatas != NULL);
9883 
9884  isorig = SCIPconsIsOriginal(cons);
9885 
9886  for( c = *nandconss - 1; c >= 0; --c )
9887  {
9888  assert(consdata->consanddatas[c] != NULL);
9889  assert(consdata->consanddatas[c]->istransformed ? (consdata->consanddatas[c]->cons != NULL) : TRUE);
9890  assert(consdata->consanddatas[c]->isoriginal ? (consdata->consanddatas[c]->origcons != NULL) : TRUE);
9891  assert(consdata->consanddatas[c]->cons != NULL || consdata->consanddatas[c]->origcons != NULL);
9892  assert(isorig ? consdata->consanddatas[c]->origcons != NULL : consdata->consanddatas[c]->cons != NULL);
9893 
9894  andconss[c] = (isorig ? consdata->consanddatas[c]->origcons : consdata->consanddatas[c]->cons);
9895  assert(andconss[c] != NULL);
9896 
9897  andcoefs[c] = consdata->andcoefs[c];
9898  }
9899 
9900  return SCIP_OKAY;
9901 }
9902 
9903 /** gets number of and constraints of pseudoboolean constraint */
9905  SCIP*const scip, /**< SCIP data structure */
9906  SCIP_CONS*const cons /**< constraint data */
9907  )
9908 {
9909  SCIP_CONSDATA* consdata;
9910 
9911  assert(scip != NULL);
9912  assert(cons != NULL);
9913 
9914  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9915  {
9916  SCIPerrorMessage("constraint is not pseudo boolean\n");
9917  SCIPABORT();
9918  return -1; /*lint !e527*/
9919  }
9920 
9921  checkConsConsistency(scip, cons);
9922 
9923  consdata = SCIPconsGetData(cons);
9924  assert(consdata != NULL);
9925 
9926  return consdata->nconsanddatas;
9927 }
9928 
9929 /** changes left hand side of pseudoboolean constraint
9930  *
9931  * @note you can only change the left hand side if the special type of linear constraint won't changed
9932  *
9933  * @todo if changing the left hand side would change the type of the special linear constraint, we need to erase it
9934  * and create a new linear constraint
9935  */
9937  SCIP*const scip, /**< SCIP data structure */
9938  SCIP_CONS*const cons, /**< constraint data */
9939  SCIP_Real const lhs /**< new left hand side */
9940  )
9941 {
9942  SCIP_CONSDATA* consdata;
9943 
9944  assert(scip != NULL);
9945  assert(cons != NULL);
9946 
9947  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9948  {
9949  SCIPerrorMessage("constraint is not pseudo boolean\n");
9950  return SCIP_INVALIDDATA;
9951  }
9952 
9953  checkConsConsistency(scip, cons);
9954 
9955  consdata = SCIPconsGetData(cons);
9956  assert(consdata != NULL);
9957 
9958  switch( consdata->linconstype )
9959  {
9961  SCIP_CALL( chgLhs(scip, cons, lhs) );
9962  break;
9966 #ifdef WITHEQKNAPSACK
9967  case SCIP_LINEARCONSTYPE_EQKNAPSACK:
9968 #endif
9969  SCIPerrorMessage("changing left hand side only allowed on standard linear constraint \n");
9970  return SCIP_INVALIDDATA;
9972  default:
9973  SCIPerrorMessage("unknown linear constraint type\n");
9974  return SCIP_INVALIDDATA;
9975  }
9976 
9977  return SCIP_OKAY;
9978 }
9979 
9980 /** changes right hand side of pseudoboolean constraint
9981  *
9982  * @note you can only change the right hand side if the special type of linear constraint won't changed
9983  *
9984  * @todo if changing the right hand side would change the type of the special linear constraint, we need to erase it
9985  * and create a new linear constraint
9986  */
9988  SCIP*const scip, /**< SCIP data structure */
9989  SCIP_CONS*const cons, /**< constraint data */
9990  SCIP_Real const rhs /**< new right hand side */
9991  )
9992 {
9993  SCIP_CONSDATA* consdata;
9994 
9995  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9996  {
9997  SCIPerrorMessage("constraint is not pseudo boolean\n");
9998  return SCIP_INVALIDDATA;
9999  }
10000 
10001  checkConsConsistency(scip, cons);
10002 
10003  consdata = SCIPconsGetData(cons);
10004  assert(consdata != NULL);
10005 
10006  switch( consdata->linconstype )
10007  {
10009  SCIP_CALL( chgRhs(scip, cons, rhs) );
10010  break;
10014 #ifdef WITHEQKNAPSACK
10015  case SCIP_LINEARCONSTYPE_EQKNAPSACK:
10016 #endif
10017  SCIPerrorMessage("changing right hand side only allowed on standard linear constraint \n");
10018  return SCIP_INVALIDDATA;
10020  default:
10021  SCIPerrorMessage("unknown linear constraint type\n");
10022  return SCIP_INVALIDDATA;
10023  }
10024 
10025  return SCIP_OKAY;
10026 }
10027 
10028 /** get left hand side of pseudoboolean constraint */
10030  SCIP*const scip, /**< SCIP data structure */
10031  SCIP_CONS*const cons /**< pseudoboolean constraint */
10032  )
10033 {
10034  SCIP_CONSDATA* consdata;
10035 
10036  assert(scip != NULL);
10037 
10038  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
10039  {
10040  SCIPerrorMessage("constraint is not pseudo boolean\n");
10041  SCIPABORT();
10042  return SCIP_INVALID; /*lint !e527*/
10043  }
10044 
10045  checkConsConsistency(scip, cons);
10046 
10047  consdata = SCIPconsGetData(cons);
10048  assert(consdata != NULL);
10049 
10050  return consdata->lhs;
10051 }
10052 
10053 /** get right hand side of pseudoboolean constraint */
10055  SCIP*const scip, /**< SCIP data structure */
10056  SCIP_CONS*const cons /**< pseudoboolean constraint */
10057  )
10058 {
10059  SCIP_CONSDATA* consdata;
10060 
10061  assert(scip != NULL);
10062 
10063  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
10064  {
10065  SCIPerrorMessage("constraint is not pseudo boolean\n");
10066  SCIPABORT();
10067  return SCIP_INVALID; /*lint !e527*/
10068  }
10069 
10070  checkConsConsistency(scip, cons);
10071 
10072  consdata = SCIPconsGetData(cons);
10073  assert(consdata != NULL);
10074 
10075  return consdata->rhs;
10076 }
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:4209
static SCIP_DECL_CONSENFOLP(consEnfolpPseudoboolean)
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3095
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:8482
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:2486
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:5922
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:8328
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:12991
#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:8288
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:4263
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:2598
#define SCIP_MAXSTRLEN
Definition: def.h:273
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1484
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:2547
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:1601
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1218
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:9226
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:8518
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:8150
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:8258
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:9272
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:3200
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:2616
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:4354
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:559
SCIP_VAR ** newvars
int SCIPexprgraphGetNodePolynomialNMonomials(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:13214
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:2235
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:5912
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8428
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:13051
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:1531
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:13202
static SCIP_DECL_CONSLOCK(consLockPseudoboolean)
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3362
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:10898
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:1742
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:13226
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:7961
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:1443
#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:8119
#define SCIP_CALL(x)
Definition: def.h:364
#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:1648
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:257
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:9055
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:8358
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:4439
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2285
#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:3013
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:9171
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:4199
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:8398
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:8268
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8255
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:8540
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:5902
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8348
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:13083
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:5838
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:8278
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:6902
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:10590
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:9249
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3047
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8089
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1252
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8218
#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:8109
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:13001
#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:5932
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:8368
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4179
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:256
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:9295
static SCIP_RETCODE inithashmapandtable(SCIP *const scip, SCIP_CONSHDLRDATA **conshdlrdata)
constraint handler for pseudoboolean constraints
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8388
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:7840
#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:9113
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:343
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:8380
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:336
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:8308
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:3378
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:8528
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:8338
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