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