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