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