Scippy

SCIP

Solving Constraint Integer Programs

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