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