Scippy

SCIP

Solving Constraint Integer Programs

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