Scippy

SCIP

Solving Constraint Integer Programs

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