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