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