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