Scippy

SCIP

Solving Constraint Integer Programs

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