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