Scippy

SCIP

Solving Constraint Integer Programs

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