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