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 )
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
5066 assert(scip != NULL);
5067 assert(conshdlrdata != NULL);
5068 assert(conss != NULL || nconss == 0);
5069 assert(firstchange != NULL);
5070 assert(firstclique != NULL);
5071 assert(lastclique != NULL);
5072 assert(nfixedvars != NULL);
5073 assert(naggrvars != NULL);
5074 assert(ndelconss != NULL);
5075 assert(nchgcoefs != NULL);
5076 assert(cutoff != NULL);
5077
5078 *cutoff = FALSE;
5079
5080 if( nconss == 0 )
5081 return SCIP_OKAY;
5082
5083 nvars = SCIPgetNVars(scip);
5084
5085 if( nvars == 0 )
5086 return SCIP_OKAY;
5087
5088 susefulvars = 2 * nvars; /* two times because of negated vars, maybe due to deleted variables we need to increase this */
5089
5090 /* a hashmap from varindex to postion in varconsidxs array, because above is still too small */
5091 SCIP_CALL( SCIPhashmapCreate(&vartoindex, SCIPblkmem(scip), nvars) );
5092
5093 /* get temporary memory for the aggregation storage, to memorize aggregations which will be performed later, otherwise we would destroy our local data structures */
5094 saggregations = nvars;
5095 SCIP_CALL( SCIPallocBufferArray(scip, &undoneaggrvars, 2 * saggregations) );
5096 SCIP_CALL( SCIPallocBufferArray(scip, &undoneaggrtypes, saggregations) );
5097 BMSclearMemoryArray(undoneaggrtypes, saggregations);
5098 naggregations = 0;
5099
5100 /* get temporary memory for all clique constraints, all appearing variables and the mapping from variables to constraints */
5101 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
5102 SCIP_CALL( SCIPallocBufferArray(scip, &usefulvars, susefulvars) );
5103 BMSclearMemoryArray(usefulvars, susefulvars);
5104 SCIP_CALL( SCIPallocBufferArray(scip, &varnconss, susefulvars + 1) );
5105 BMSclearMemoryArray(varnconss, susefulvars + 1);
5106 SCIP_CALL( SCIPallocBufferArray(scip, &maxnvarconsidx, susefulvars + 1) );
5107 SCIP_CALL( SCIPallocBufferArray(scip, &varconsidxs, susefulvars + 1) );
5108 BMSclearMemoryArray(varconsidxs, susefulvars + 1);
5109 nusefulvars = 0;
5110 nusefulconss = 0;
5111 maxnvars = 0;
5112
5113 /* @todo: check for round limit for adding extra clique constraints */
5114 /* adding clique constraints which arises from global clique information */
5115 if( conshdlrdata->nclqpresolve == 0 && conshdlrdata->addvariablesascliques )
5116 {
5117 SCIP_VAR** vars = SCIPgetVars(scip);
5118 SCIP_VAR** binvars;
5119 int* cliquepartition;
5120 int ncliques;
5121 int nbinvars;
5122 int naddconss;
5123
5124 nbinvars = SCIPgetNBinVars(scip);
5125 SCIP_CALL( SCIPduplicateBufferArray(scip, &binvars, vars, nbinvars) );
5126 SCIP_CALL( SCIPallocBufferArray(scip, &cliquepartition, nbinvars) );
5127
5128 /* @todo: check for better permutations/don't permute the first round
5129 * @todo: take binary variables which are not of vartype SCIP_VARTYPE_BINARY into account
5130 */
5131 SCIPrandomPermuteArray(conshdlrdata->randnumgen, (void**)binvars, 0, nbinvars);
5132
5133 /* try to create a clique-partition over all binary variables and create these cliques as new setppc constraints
5134 * and add them to the usefulconss array and adjust all necessary data this will hopefully lead to faster
5135 * detection of redundant constraints
5136 */
5137 SCIP_CALL( SCIPcalcCliquePartition(scip, binvars, nbinvars, cliquepartition, &ncliques) );
5138
5139 /* resize usefulconss array if necessary */
5140 SCIP_CALL( SCIPreallocBufferArray(scip, &usefulconss, nconss + ncliques) );
5141
5142 naddconss = 0;
5143
5144 /* add extra clique constraints resulting from the cliquepartition calculation to SCIP and to the local data structure */
5145 SCIP_CALL( addExtraCliques(scip, binvars, nbinvars, cliquepartition, ncliques, usefulconss, &nusefulconss,
5146 nrounds, nfixedvars, &naddconss, ndelconss, nchgcoefs, cutoff) );
5147
5148 /* bad hack, we don't want to count these artificial created constraints if they got deleted, so ndelconss
5149 * can become negative which will be change to zero at the end of this method if it's still negative
5150 */
5151 *ndelconss -= naddconss;
5152
5153 SCIPfreeBufferArray(scip, &cliquepartition);
5154 SCIPfreeBufferArray(scip, &binvars);
5155
5156 if( *cutoff )
5157 goto TERMINATE;
5158 }
5159
5160 /* start to collect setpartitioning and setpacking constraints, and try to remove fixed variables and merged these
5161 * constraints
5162 */
5163 SCIP_CALL( collectCliqueConss(scip, conss, nconss, usefulconss, &nusefulconss, nfixedvars, ndelconss, nchgcoefs, cutoff) );
5164 /* @Note: Even after the call above some constraints can have fixed variables, because it might happen that caused by
5165 * mergeMultiplies some variables were fixed which occurred already in previous constraints
5166 */
5167 if( *cutoff )
5168 goto TERMINATE;
5169
5170 /* no usefulconss found */
5171 if( nusefulconss <= 1 )
5172 goto TERMINATE;
5173
5174 /* @todo: maybe sort them after biggest indices too, or another variant would be to restore the order as they were
5175 * read in
5176 */
5177 /* sort constraints first after type (partitioning before packing) and second after number of variables such that the
5178 * partitioning constraints have increasing number of variables and the packing constraints have decreasing number of
5179 * variables, because we loop from back to front we sort them downwards, so they are the other way around
5180 */
5181 SCIPsortDownPtr((void**)usefulconss, setppcConssSort, nusefulconss);
5182
5183 /* creating all necessary data in array structure, collect all clique constraint variables and occurrences */
5184 SCIP_CALL( collectCliqueData(scip, usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs, &maxnvars) );
5185 assert(maxnvars > 0);
5186
5187 /* allocate temporary memory for actual clique */
5188 SCIP_CALL( SCIPallocBufferArray(scip, &cliquevalues, maxnvars) );
5189 /* allocate temporary memory for counting an overlap of variables */
5190 SCIP_CALL( SCIPallocBufferArray(scip, &countofoverlapping, nusefulconss) );
5191
5192 /* sort usefulvars after indices of variables, negated and active counterparts will stand side by side */
5193 SCIPsortDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, nusefulvars);
5194
5195 /* extend cliques/constraints by checking whether some variables of a second constraint are in the same clique */
5196 for( c = nusefulconss - 1; c >= 0 && !SCIPisStopped(scip); --c )
5197 {
5198 SCIP_VAR** cons0vars; /* these are the clique variables */
5199 SCIP_CONS* cons0;
5200 int ncons0vars;
5201 SCIP_VAR* var0;
5202 int v1;
5203 int nadded; /* number of possible added variables to constraint */
5204 int cons0fixedzeros;
5205 int oldnchgcoefs;
5206#ifndef NDEBUG
5207 const int oldnaggrvars = *naggrvars;
5208#endif
5209 cons0 = usefulconss[c];
5210
5211 if( !SCIPconsIsActive(cons0) )
5212 continue;
5213
5214 /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
5215 * possible
5216 */
5217 SCIP_CALL( presolvePropagateCons(scip, cons0, FALSE, undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
5218
5219 if( *cutoff )
5220 break;
5221
5222 /* we can't handle aggregated variables later on so we should have saved them for later */
5223 assert(*naggrvars == oldnaggrvars);
5224
5225 if( !SCIPconsIsActive(cons0) )
5226 continue;
5227
5228 /* we need to determine the cliquedata in each iteration because we eventual will change it later */
5229 consdata = SCIPconsGetData(cons0);
5230 assert(consdata != NULL);
5231
5232 cons0vars = consdata->vars;
5233 ncons0vars = consdata->nvars;
5234
5235 /* sorting array after indices of variables, negated and active counterparts will stand side by side */
5236 SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5237 /* standard setppc-sorting now lost */
5238 consdata->sorted = FALSE;
5239
5240 /* clique array should be long enough */
5241 assert(maxnvars >= ncons0vars);
5242
5243 /* clear old entries in overlapping constraint */
5244 BMSclearMemoryArray(countofoverlapping, nusefulconss);
5245
5246 /* calculate overlapping */
5247 for( v = ncons0vars - 1; v >= 0 ; --v )
5248 {
5249 var0 = cons0vars[v];
5250
5251 /* fixed variables later to the count */
5252 if( SCIPvarGetLbLocal(var0) > 0.5 || SCIPvarGetUbLocal(var0) < 0.5 )
5253 continue;
5254
5255 assert(SCIPhashmapExists(vartoindex, (void*) var0));
5256
5257 varindex = SCIPhashmapGetImageInt(vartoindex, (void*) var0);
5258 for( v1 = varnconss[varindex] - 1; v1 >= 0 ; --v1 )
5259 ++(countofoverlapping[varconsidxs[varindex][v1]]);
5260 }
5261
5262 oldnchgcoefs = *nchgcoefs;
5263 cons0fixedzeros = consdata->nfixedzeros;
5264
5265 chgcons0 = FALSE;
5266
5267 /* check for overlapping constraint before starting lifting */
5268 SCIP_CALL( checkForOverlapping(scip, cons0, c, c, usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex,
5269 varnconss, maxnvarconsidx, varconsidxs, countofoverlapping, conshdlrdata->cliqueshrinking, &chgcons0,
5270 undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations,
5271 nfixedvars, naggrvars, nchgcoefs, ndelconss, cutoff) );
5272
5273 if( *cutoff )
5274 break;
5275
5276 /* we can't handle aggregated variables later on so we should have saved them for later */
5277 assert(*naggrvars == oldnaggrvars);
5278
5279 /* if cons0 changed, we need to reorder the variables */
5280 if( chgcons0 && *nchgcoefs > oldnchgcoefs )
5281 {
5282 consdata = SCIPconsGetData(cons0);
5283 assert(consdata != NULL);
5284
5285 cons0vars = consdata->vars;
5286 ncons0vars = consdata->nvars;
5287
5288 /* sorting array after indices of variables, negated and active counterparts will stand side by side */
5289 SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5290 /* standard setppc-sorting now lost */
5291 consdata->sorted = FALSE;
5292 }
5293
5294 /* check cons0 again for redundancy/fixings, because due to fixings in all other constraints it might happen that cons0 is redundant now */
5295 if( consdata->nfixedones > 0 || consdata->nfixedzeros > cons0fixedzeros )
5296 {
5297 /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
5298 * possible
5299 */
5300 SCIP_CALL( presolvePropagateCons(scip, cons0, FALSE, undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
5301
5302 if( *cutoff )
5303 break;
5304
5305 /* we can't handle aggregated variables later on so we should have saved them for later */
5306 assert(*naggrvars == oldnaggrvars);
5307
5308 if( !SCIPconsIsActive(cons0) )
5309 continue;
5310 }
5311
5312 nadded = 0;
5313
5314 /* iterate over the cliques variables and all possible new clique variables at the "same" time, determine starting
5315 * index
5316 *
5317 * @note: it might be better to start the first round with our computed v1, but maybe it's better to switch to
5318 * trying to add all variables the second time for set packing constraints
5319 */
5320
5321 /* we try to add all variables to the partitioning constraints, to try to fix as much as possible */
5322 if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
5323 v1 = nusefulvars - 1;
5324 else
5325 {
5326 /* if we already ran a presolving round we want to try to add new variables */
5327 if( conshdlrdata->nclqpresolve > 0 )
5328 v1 = nusefulvars - 1;
5329 else
5330 {
5331 /* find start position of variable which we will try to add to our constraint, so we will get better clique constraints */
5332 (void) SCIPsortedvecFindDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, (void*)cons0vars[ncons0vars - 1], nusefulvars, &v1);
5333 assert(v1 >= 0 && v1 < nusefulvars);
5334 /* if constraint is not merged and we found a variable which is negated the same as it's neighbour we have to
5335 * increase v1 to make sure that we don't loose this important variable */
5336 if( v1 + 1 < nusefulvars && ((SCIPvarIsNegated(usefulvars[v1 + 1]) && SCIPvarGetNegatedVar(usefulvars[v1 + 1]) == usefulvars[v1]) || (SCIPvarIsNegated(usefulvars[v1]) && SCIPvarGetNegatedVar(usefulvars[v1]) == usefulvars[v1 + 1])) )
5337 ++v1;
5338 }
5339 }
5340
5341 assert(maxnvars >= ncons0vars);
5342 /* initialize the cliquevalues array */
5343 for( v = ncons0vars - 1; v >= 0; --v )
5344 {
5345 if( SCIPvarGetLbLocal(cons0vars[v]) < 0.5 && SCIPvarGetUbLocal(cons0vars[v]) > 0.5 )
5346 {
5347 /* variable has to be either active or a negated variable of an active one */
5348 assert(SCIPvarIsActive(cons0vars[v]) || (SCIPvarGetStatus(cons0vars[v]) == SCIP_VARSTATUS_NEGATED &&
5349 SCIPvarIsActive(SCIPvarGetNegationVar(cons0vars[v]))));
5350 cliquevalues[v] = SCIPvarIsActive(cons0vars[v]) ? TRUE : FALSE;
5351 }
5352 }
5353
5354 chgcons0 = FALSE;
5355
5356 /* try to lift variables to cons0 */
5357 SCIP_CALL( liftCliqueVariables(scip, cons0, c, usefulvars, &nusefulvars, v1, &cliquevalues, vartoindex, varnconss,
5358 maxnvarconsidx, varconsidxs, &maxnvars, &nadded, &chgcons0, nfixedvars, ndelconss, cutoff) );
5359
5360 if( *cutoff )
5361 break;
5362
5363 if( !SCIPconsIsActive(cons0) )
5364 continue;
5365
5366 /* check for redundant constraints due to changing cons0 */
5367 if( chgcons0 )
5368 {
5369 int i;
5370
5371 *firstchange = MIN(*firstchange, c);
5372 *firstclique = MIN(*firstclique, c);
5373 *lastclique = MAX(*lastclique, c);
5374
5375 /* variables array has changed due to lifting variables, so get new values */
5376 assert(consdata == SCIPconsGetData(cons0));
5377 cons0vars = consdata->vars;
5378 ncons0vars = consdata->nvars;
5379
5380 /* resorting array, because we added new variables, in order of indices of variables, negated
5381 * and active counterparts would stand side by side
5382 */
5383 SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5384 /* standard setppc-sorting now lost */
5385 consdata->sorted = FALSE;
5386
5387 /* clear old entries in overlapping constraint */
5388 BMSclearMemoryArray(countofoverlapping, nusefulconss);
5389
5390 for( v = ncons0vars - 1; v >= 0 ; --v )
5391 {
5392 var0 = cons0vars[v];
5393
5394 /* fixed variables later to the count */
5395 if( SCIPvarGetLbLocal(var0) > 0.5 || SCIPvarGetUbLocal(var0) < 0.5 )
5396 continue;
5397
5398 assert(SCIPhashmapExists(vartoindex, (void*) var0));
5399
5400 varindex = SCIPhashmapGetImageInt(vartoindex, (void*) var0);
5401 for( i = varnconss[varindex] - 1; i >= 0 ; --i )
5402 ++(countofoverlapping[varconsidxs[varindex][i]]);
5403 }
5404
5405 chgcons0 = FALSE;
5406
5407 /* check for overlapping constraint after lifting, in the first round we will only check up front */
5408 SCIP_CALL( checkForOverlapping(scip, cons0, c, (conshdlrdata->nclqpresolve > 0) ? nusefulconss : c,
5409 usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs,
5410 countofoverlapping, conshdlrdata->cliqueshrinking, &chgcons0,
5411 undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations,
5412 nfixedvars, naggrvars, nchgcoefs, ndelconss, cutoff) );
5413
5414 if( *cutoff )
5415 break;
5416
5417 /* we can't handle aggregated variables later on so we should have saved them for later */
5418 assert(*naggrvars == oldnaggrvars);
5419 }
5420 }
5421
5422 TERMINATE:
5423 SCIPfreeBufferArrayNull(scip, &countofoverlapping);
5424 SCIPfreeBufferArrayNull(scip, &cliquevalues);
5425
5426 /* free temporary memory for constraints, variables and the mapping between them in reverse order as they were
5427 * allocated
5428 */
5429 for( c = nusefulvars; c > 0; --c )
5430 {
5431 if( varconsidxs[c] != NULL )
5432 {
5433 SCIPfreeBufferArrayNull(scip, &(varconsidxs[c]));
5434 }
5435 }
5436
5437 SCIPfreeBufferArray(scip, &varconsidxs);
5438 SCIPfreeBufferArray(scip, &maxnvarconsidx);
5439 SCIPfreeBufferArray(scip, &varnconss);
5440 SCIPfreeBufferArray(scip, &usefulvars);
5441 SCIPfreeBufferArray(scip, &usefulconss);
5442
5443 /* perform all collected aggregations */
5444 if( !*cutoff && naggregations > 0 && !SCIPdoNotAggr(scip) )
5445 {
5446 SCIP_CALL( performAggregations(scip, conshdlrdata, undoneaggrvars, undoneaggrtypes, naggregations, naggrvars, cutoff) );
5447 }
5448
5449 /* free temporary memory for the aggregation storage */
5450 SCIPfreeBufferArray(scip, &undoneaggrtypes);
5451 SCIPfreeBufferArray(scip, &undoneaggrvars);
5452
5453 /* free hashmap */
5454 SCIPhashmapFree(&vartoindex);
5455
5456 if( *ndelconss < 0 )
5457 *ndelconss = 0;
5458
5459 return SCIP_OKAY;
5460}
5461
5462
5463/** add cliques to SCIP */
5464static
5466 SCIP* scip, /**< SCIP data structure */
5467 SCIP_CONS** conss, /**< constraint set */
5468 int nconss, /**< number of constraints in constraint set */
5469 int firstclique, /**< first constraint to start to add cliques */
5470 int lastclique, /**< last constraint to start to add cliques */
5471 int* naddconss, /**< pointer to count number of added constraints */
5472 int* ndelconss, /**< pointer to count number of deleted constraints */
5473 int* nchgbds, /**< pointer to count number of changed bounds */
5474 SCIP_Bool* cutoff /**< pointer to store if the problem is infeasible due to a fixing */
5475 )
5476{
5477 SCIP_CONS* cons;
5478 SCIP_CONSDATA* consdata;
5479 SCIP_Bool infeasible;
5480 int nlocalbdchgs;
5481 int c;
5482
5483 assert(scip != NULL);
5484 assert(firstclique >= 0);
5485 assert(lastclique <= nconss);
5486 assert(conss != NULL || ((nconss == 0) && (lastclique == 0)));
5487
5488 /* add clique and implication information */
5489 for( c = firstclique; c < lastclique; ++c )
5490 {
5491 cons = conss[c]; /*lint !e613*/
5492 assert(cons != NULL);
5493
5494 /* ignore deleted constraints */
5495 if( !SCIPconsIsActive(cons) )
5496 continue;
5497
5498 nlocalbdchgs = 0;
5499 SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, &nlocalbdchgs, cutoff) );
5500 *nchgbds += nlocalbdchgs;
5501
5502 if( *cutoff )
5503 return SCIP_OKAY;
5504
5505 consdata = SCIPconsGetData(cons);
5506 assert(consdata != NULL);
5507
5508 if( SCIPconsIsDeleted(cons) )
5509 continue;
5510
5511 if( !consdata->cliqueadded && consdata->nvars >= 2 )
5512 {
5513 /* add a set partitioning / packing constraint as clique */
5514 if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5515 {
5516 SCIP_CALL( SCIPaddClique(scip, consdata->vars, NULL, consdata->nvars,
5517 ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING), &infeasible, &nlocalbdchgs) );
5518 *nchgbds += nlocalbdchgs;
5519
5520 if( infeasible )
5521 {
5522 *cutoff = TRUE;
5523 return SCIP_OKAY;
5524 }
5525 }
5526 else if( consdata->nvars == 2 && !SCIPconsIsModifiable(cons) )
5527 {
5528 /* a two-variable set covering constraint x + y >= 1 yields the implication x == 0 -> y == 1 */
5529 SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], FALSE, consdata->vars[1],
5530 SCIP_BOUNDTYPE_LOWER, 1.0, &infeasible, &nlocalbdchgs) );
5531 *nchgbds += nlocalbdchgs;
5532
5533 if( infeasible )
5534 {
5535 *cutoff = TRUE;
5536 return SCIP_OKAY;
5537 }
5538 }
5539 consdata->cliqueadded = TRUE;
5540 }
5541 }
5542
5543 return SCIP_OKAY;
5544}
5545
5546/** perform multi-aggregation on variables resulting from a set-partitioning/-packing constraint */
5547static
5549 SCIP* scip, /**< SCIP data structure */
5550 SCIP_Bool linearconshdlrexist,/**< does the linear constraint handler exist, necessary for multi-aggregations */
5551 SCIP_VAR** vars, /**< all variables including the variable to which will be multi-aggregated */
5552 int nvars, /**< number of all variables */
5553 int pos, /**< position of variable for multi-aggregation */
5554 SCIP_Bool* infeasible, /**< pointer to store infeasibility status of aggregation */
5555 SCIP_Bool* aggregated /**< pointer to store aggregation status */
5556 )
5557{
5558 SCIP_VAR** tmpvars;
5560 int v;
5561
5562 assert(scip != NULL);
5563 assert(vars != NULL);
5564 assert(nvars >= 1);
5565 assert(pos >= 0);
5566 assert(pos < nvars);
5567 assert(infeasible != NULL);
5568 assert(aggregated != NULL);
5569
5570 if( !linearconshdlrexist && nvars > 2 )
5571 {
5572 *infeasible = FALSE;
5573 *aggregated = FALSE;
5574
5575 return SCIP_OKAY;
5576 }
5577
5578 /* if the first variable will be multi-aggregated, we do not need to copy the variables */
5579 if( pos == 0 )
5580 tmpvars = vars + 1;
5581 /* if the last variable will be multi-aggregated, we do not need to copy the variables */
5582 else if( pos == nvars - 1 )
5583 tmpvars = vars;
5584 /* copy variables for aggregation */
5585 else
5586 {
5587 SCIP_CALL( SCIPduplicateBufferArray(scip, &tmpvars, vars, nvars - 1) );
5588 tmpvars[pos] = vars[nvars - 1];
5589 }
5590
5591 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, nvars - 1) );
5592
5593 /* initialize scalars */
5594 for( v = nvars - 2; v >= 0; --v )
5595 scalars[v] = -1.0;
5596
5597 SCIPdebugMsg(scip, "multi-aggregating binary variable <%s> (locks: [%d,%d]; to %d variables)\n",
5599 SCIPvarGetNLocksUpType(vars[pos], SCIP_LOCKTYPE_MODEL), nvars - 1);
5600
5601 /* perform multi-aggregation */
5602 SCIP_CALL( SCIPmultiaggregateVar(scip, vars[pos], nvars - 1, tmpvars, scalars, 1.0, infeasible, aggregated) );
5603 assert(!(*infeasible));
5604
5606
5607 if( pos != 0 && pos != nvars - 1 )
5608 {
5609 assert(tmpvars != vars);
5610 assert(tmpvars != vars + 1);
5611 SCIPfreeBufferArray(scip, &tmpvars);
5612 }
5613
5614 return SCIP_OKAY;
5615}
5616
5617/** determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and negated)
5618 * in any combination of set-partitioning and set-packing constraints
5619 *
5620 * we can multi-aggregate the variable and either change the set-partitioning constraint to a set-packing constraint or
5621 * even delete it
5622 *
5623 * 1. c1: x + y + z = 1, uplocks(x) = 1, downlocks(x) = 1 => x = 1 - y - z and change c1 to y + z <= 1
5624 *
5625 * 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
5626 *
5627 * 3. d1: x + y + z <= 1 and d2: ~x + u + v <= 1, uplocks(x) = 1, downlocks(x) = 1
5628 * a) obj(x) <= 0 => x = 1 - y - z and delete d1
5629 * b) obj(x) > 0 => ~x = 1 - u - v and delete d2
5630 *
5631 * 4. e1: x + y + z == 1 and e2: ~x + u + v (<= or ==) 1, uplocks(x) = (1 or 2), downlocks(x) = 2
5632 * => x = 1 - y - z and delete e1
5633 *
5634 * we can also aggregate a variable in a set-packing constraint with only two variables when the uplocks are equal to
5635 * one and then delete this constraint
5636 *
5637 * 5. f1: x + y <= 1, uplocks(x) = 1, obj(x) <= 0 => x = 1 - y and delete f1
5638 *
5639 * @todo might want to multi-aggregate variables even with more locks, when the fill in is still smaller or equal to
5640 * the old number of non-zeros, e.g.
5641 *
5642 * x + y + z = 1
5643 * ~x + u + v <=/= 1
5644 * ~x + w <= 1
5645 */
5646static
5648 SCIP* scip, /**< SCIP data structure */
5649 SCIP_CONS** conss, /**< constraint set */
5650 int nconss, /**< number of constraints in constraint set */
5651 SCIP_Bool dualpresolvingenabled,/**< is dual presolving enabled */
5652 SCIP_Bool linearconshdlrexist,/**< does the linear constraint handler exist, necessary for
5653 * multi-aggregations
5654 */
5655 int* nfixedvars, /**< pointer to count number of deleted variables */
5656 int* naggrvars, /**< pointer to count number of aggregated variables */
5657 int* ndelconss, /**< pointer to count number of deleted constraints */
5658 int* nchgcoefs, /**< pointer to count number of changed coefficients */
5659 int* nchgsides, /**< pointer to count number of changed left hand sides */
5660 SCIP_Bool* cutoff /**< pointer to store if a cut off was detected */
5661 )
5662{
5663 SCIP_CONS** usefulconss;
5664 SCIP_VAR** binvars;
5665 SCIP_HASHMAP* vartoindex;
5666 SCIP_Bool* chgtype;
5667 int* considxs;
5668 int* posincons;
5669 SCIP_Bool infeasible;
5670 SCIP_Bool aggregated;
5671 SCIP_Bool donotaggr;
5672 SCIP_Bool donotmultaggr;
5673 SCIP_Bool mustcheck;
5674 SCIP_Bool addcut;
5675 int nposvars;
5676 int ndecs;
5677 int nbinvars;
5678 int nposbinvars;
5679 int nuplocks;
5680 int ndownlocks;
5681#ifndef NDEBUG
5682 int posreplacements = 0;
5683#endif
5684 int nhashmapentries;
5685 int nlocaladdconss;
5686 int v;
5687 int c;
5688
5689 assert(scip != NULL);
5690 assert(conss != NULL);
5691 assert(nconss > 0);
5692 assert(nfixedvars != NULL);
5693 assert(naggrvars != NULL);
5694 assert(ndelconss != NULL);
5695 assert(nchgcoefs != NULL);
5696 assert(nchgsides != NULL);
5697
5698 nbinvars = SCIPgetNBinVars(scip);
5699 nposbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
5700 assert(nbinvars + SCIPgetNIntVars(scip) + SCIPgetNImplVars(scip) == nposbinvars);
5701
5702 binvars = SCIPgetVars(scip);
5703
5704 /* determine number for possible multi-aggregations */
5705 nposvars = 0;
5706 for( v = nposbinvars - 1; v >= 0; --v )
5707 {
5708 assert(SCIPvarGetType(binvars[v]) != SCIP_VARTYPE_CONTINUOUS);
5709
5710 if( v < nbinvars || SCIPvarIsBinary(binvars[v]) )
5711 {
5712 nuplocks = SCIPvarGetNLocksUpType(binvars[v], SCIP_LOCKTYPE_MODEL);
5713 ndownlocks = SCIPvarGetNLocksDownType(binvars[v], SCIP_LOCKTYPE_MODEL);
5714
5715 if( (nuplocks == 1 && ndownlocks <= 1) || (nuplocks <= 1 && ndownlocks == 1) || (nuplocks <= 2 && ndownlocks <= 2 && SCIPvarGetNegatedVar(binvars[v]) != NULL) )
5716 ++nposvars;
5717 }
5718 }
5719
5720 SCIPdebugMsg(scip, "found %d binary variables for possible multi-aggregation\n", nposvars);
5721
5722 if( nposvars == 0 )
5723 return SCIP_OKAY;
5724
5725 /* a hashmap from var to index when found in a set-partitioning constraint */
5726 SCIP_CALL( SCIPhashmapCreate(&vartoindex, SCIPblkmem(scip), nposvars) );
5727
5728 /* get temporary memory */
5729 SCIP_CALL( SCIPallocBufferArray(scip, &chgtype, nconss) );
5730 BMSclearMemoryArray(chgtype, nconss);
5731
5732 SCIP_CALL( SCIPallocBufferArray(scip, &considxs, nposbinvars) );
5733 SCIP_CALL( SCIPallocBufferArray(scip, &posincons, nposbinvars) );
5734
5735 SCIP_CALL( SCIPduplicateBufferArray(scip, &usefulconss, conss, nconss) );
5736 /* sort constraints */
5737 SCIPsortPtr((void**)usefulconss, setppcConssSort2, nconss);
5738
5739 nhashmapentries = 0;
5740 ndecs = 0;
5741 donotaggr = SCIPdoNotAggr(scip);
5742 donotmultaggr = SCIPdoNotMultaggr(scip);
5743 assert(!donotaggr || !donotmultaggr);
5744
5745 /* determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and
5746 * negated) in any combination of set-partitioning and set-packing constraints
5747 *
5748 * we can multi-aggregate the variable and either change the set-partitioning constraint to a set-packing constraint
5749 * or even delete it
5750 */
5751 for( c = 0; c < nconss; ++c )
5752 {
5753 SCIP_CONS* cons;
5754 SCIP_CONSDATA* consdata;
5755 SCIP_CONSDATA* aggrconsdata;
5756 int oldnfixedvars;
5757 int aggrconsindex;
5758 int aggrallyindex;
5759 nlocaladdconss = 0;
5760
5761 cons = usefulconss[c];
5762 assert(cons != NULL);
5763
5764 if( SCIPconsIsDeleted(cons) )
5765 continue;
5766
5767 consdata = SCIPconsGetData(cons);
5768 assert(consdata != NULL);
5769
5770 /* if we cannot find any constraint to perform a useful multi-aggregation, stop */
5771 if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING )
5772 break;
5773
5774 if( !SCIPconsIsChecked(cons) )
5775 continue;
5776
5777 if( SCIPconsIsModifiable(cons) )
5778 continue;
5779
5780 /* update the variables */
5781 SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
5782
5783 if( *cutoff )
5784 break;
5785
5786 /* due to resolving multi-aggregations a constraint can become deleted */
5787 if( SCIPconsIsDeleted(cons) )
5788 continue;
5789
5790 SCIP_CALL( processFixings(scip, cons, cutoff, nfixedvars, &addcut, &mustcheck) );
5791 assert(!addcut);
5792
5793 if( *cutoff )
5794 break;
5795
5796 if( SCIPconsIsDeleted(cons) )
5797 continue;
5798
5799 oldnfixedvars = *nfixedvars;
5800
5801 /* merging unmerged constraints */
5802 SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
5803
5804 if( *cutoff )
5805 break;
5806
5807 if( SCIPconsIsDeleted(cons) )
5808 continue;
5809
5810 if( oldnfixedvars < *nfixedvars )
5811 {
5812 /* update the variables */
5813 SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
5814 assert(!SCIPconsIsDeleted(cons));
5815 assert(nlocaladdconss == 0);
5816 assert(!*cutoff);
5817
5818 if( SCIPconsIsDeleted(cons) )
5819 continue;
5820 }
5821
5822 /* if the constraint was not merged and consists of a variable with its negation, the constraint is redundant */
5823 if( consdata->nvars < 2 )
5824 {
5825 /* deleting redundant set-packing constraint */
5826 if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5827 {
5828 SCIPdebugMsg(scip, "deleting redundant set-packing constraint <%s>\n", SCIPconsGetName(cons));
5829
5830 SCIP_CALL( SCIPdelCons(scip, cons) );
5831 ++(*ndelconss);
5832
5833 continue;
5834 }
5835 else
5836 {
5837 SCIP_Bool fixed;
5838
5839 assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
5840
5841 if( consdata->nvars == 0 )
5842 {
5843 SCIPdebugMsg(scip, "empty set partition constraint <%s> led to infeasibility\n", SCIPconsGetName(cons));
5844
5845 *cutoff = TRUE;
5846 break;
5847 }
5848
5849 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));
5850
5851 SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
5852 assert(!infeasible);
5853
5854 if( fixed )
5855 ++(*nfixedvars);
5856
5857 assert(SCIPvarGetLbGlobal(consdata->vars[0]) > 0.5);
5858
5859 SCIPdebugMsg(scip, "deleting redundant set-partition constraint <%s>\n", SCIPconsGetName(cons));
5860
5861 SCIP_CALL( SCIPdelCons(scip, cons) );
5862 ++(*ndelconss);
5863
5864 continue;
5865 }
5866 }
5867
5868 /* perform dualpresolve on set-packing constraints with exactly two variables */
5869 if( !donotaggr && consdata->nvars == 2 && dualpresolvingenabled && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5870 {
5871 SCIP_VAR* var;
5872 SCIP_Real objval;
5873 SCIP_Bool redundant;
5874
5875 var = consdata->vars[0];
5876 assert(var != NULL);
5878
5879 SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
5880
5882
5883 if( nuplocks == 1 && objval <= 0 )
5884 {
5885 /* perform aggregation on variables resulting from a set-packing constraint */
5886 SCIP_CALL( SCIPaggregateVars(scip, var, consdata->vars[1], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5887
5888 if( infeasible )
5889 {
5890 *cutoff = TRUE;
5891 break;
5892 }
5893
5894 if( aggregated )
5895 {
5896 SCIPdebugMsg(scip, "dualpresolve, aggregated %s + %s = 1, in set-packing constraint %s\n", SCIPvarGetName(var), SCIPvarGetName(consdata->vars[1]), SCIPconsGetName(cons));
5897 ++(*naggrvars);
5898
5899 SCIP_CALL( SCIPdelCons(scip, cons) );
5900 ++(*ndelconss);
5901 }
5902
5903 continue;
5904 }
5905 else
5906 {
5907 var = consdata->vars[1];
5908 assert(var != NULL);
5910
5911 SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
5912
5914
5915 if( nuplocks == 1 && objval <= 0 )
5916 {
5917 /* perform aggregation on variables resulting from a set-packing constraint */
5918 SCIP_CALL( SCIPaggregateVars(scip, var, consdata->vars[0], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5919
5920 if( infeasible )
5921 {
5922 *cutoff = TRUE;
5923 break;
5924 }
5925
5926 if( aggregated )
5927 {
5928 SCIPdebugMsg(scip, "dualpresolve, aggregated %s + %s = 1, in set-packing constraint %s\n", SCIPvarGetName(var), SCIPvarGetName(consdata->vars[0]), SCIPconsGetName(cons));
5929 ++(*naggrvars);
5930
5931 SCIP_CALL( SCIPdelCons(scip, cons) );
5932 ++(*ndelconss);
5933 }
5934
5935 continue;
5936 }
5937 }
5938 }
5939 else if( !donotaggr && consdata->nvars == 2 && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
5940 {
5941 SCIP_Bool redundant;
5942
5943 /* perform aggregation on variables resulting from a set-partitioning constraint */
5944 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5945
5946 if( infeasible )
5947 {
5948 *cutoff = TRUE;
5949 break;
5950 }
5951
5952 if( aggregated )
5953 {
5954 SCIPdebugMsg(scip, "aggregated %s + %s = 1, in set-partition constraint %s\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(consdata->vars[1]), SCIPconsGetName(cons));
5955 ++(*naggrvars);
5956
5957 SCIP_CALL( SCIPdelCons(scip, cons) );
5958 ++(*ndelconss);
5959 }
5960
5961 continue;
5962 }
5963
5964 /* we already found all possible variables for multi-aggregation */
5965 if( ndecs >= nposvars )
5966 continue;
5967
5968 /* no multi aggregation is allowed, so we can continue */
5969 if( donotmultaggr )
5970 continue;
5971
5972 /* if the following condition does not hold, we have an unmerged constraint, and we might need to merge it first */
5973 assert(nposbinvars >= consdata->nvars);
5974
5975 /* reset aggregation information */
5976 aggregated = FALSE;
5977 aggrconsindex = -1;
5978 aggrallyindex = -1;
5979
5980 /* search for possible variables for multi-aggregation */
5981 for( v = consdata->nvars - 1; v >= 0; --v )
5982 {
5983 SCIP_VAR* var = consdata->vars[v];
5984
5985 assert(var != NULL);
5987 assert(!SCIPconsIsDeleted(cons));
5988
5991 assert(nuplocks >= 1 && ndownlocks >= 0); /* we are only treating set partitioning and set packing constraints, so every variable in there should have an uplock */
5992
5993 if( dualpresolvingenabled && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING && nuplocks <= 1 && nuplocks + ndownlocks <= 2 )
5994 {
5995 assert(nuplocks == 1 && ndownlocks <= 1);
5996
5997 /* we found a redundant variable in a set-partitioning constraint */
5998 if( ndownlocks == 0 )
5999 {
6000 SCIP_Real objval;
6001 SCIP_Bool fixed;
6002
6003 SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
6004
6005 ++ndecs;
6006
6007 /* if the objective value is >= 0 the fixing is normally done by the dualfix presolver */
6008 if( !SCIPisNegative(scip, objval) )
6009 {
6010 SCIPdebugMsg(scip, "dual-fixing of variable <%s> to 0.0\n", SCIPvarGetName(var));
6011
6012 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
6013 assert(!infeasible);
6014 assert(fixed);
6015
6016 ++(*nfixedvars);
6017 }
6018 else
6019 {
6020 SCIPdebugMsg(scip, "multi-aggregating in set-packing constraint\n");
6021
6022 /* perform aggregation on variables resulting from a set-packing constraint */
6023 SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &fixed) );
6024
6025 if( infeasible )
6026 {
6027 *cutoff = TRUE;
6028 break;
6029 }
6030
6031 if( fixed )
6032 {
6033 ++(*naggrvars);
6034
6035 SCIP_CALL( delCoefPos(scip, cons, v) );
6036 ++(*nchgcoefs);
6037 }
6038 }
6039 }
6040 else if( ndownlocks == 1 && SCIPvarGetNegatedVar(var) != NULL )
6041 {
6042 SCIP_VAR* negvar = SCIPvarGetNegatedVar(var);
6043 SCIP_VAR* activevar;
6044 SCIP_Real objval;
6045 int multaggridx;
6046 int image;
6047 int consindex;
6048 int varindex;
6049
6050 assert(!SCIPhashmapExists(vartoindex, (void*) var));
6051
6052 /* if we found a new variable add it to the data */
6053 if( !SCIPhashmapExists(vartoindex, (void*) negvar) )
6054 {
6055 ++nhashmapentries;
6056 SCIP_CALL( SCIPhashmapInsertInt(vartoindex, (void*) var, nhashmapentries) );
6057
6058 considxs[nhashmapentries - 1] = c;
6059 posincons[nhashmapentries - 1] = v;
6060
6061#ifndef NDEBUG
6062 ++posreplacements;
6063#endif
6064 continue;
6065 }
6066
6067 assert(SCIPhashmapExists(vartoindex, (void*) negvar));
6068 image = SCIPhashmapGetImageInt(vartoindex, (void*) negvar);
6069 assert(image > 0 && image <= nhashmapentries);
6070
6071 consindex = considxs[image - 1];
6072 assert(0 <= consindex && consindex < nconss);
6073
6074 /* if the following assert fails, the constraint was not merged, or something really strange happened */
6075 assert(consindex < c);
6076
6077 ++ndecs;
6078#ifndef NDEBUG
6079 --posreplacements;
6080#endif
6081 assert(posreplacements >= 0);
6082
6083 varindex = posincons[image - 1];
6084 considxs[image - 1] = -1;
6085 posincons[image - 1] = -1;
6086 SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) negvar) );
6087
6088 /* this constraint can already be required for a multi-aggregation or the other constraint removed */
6089 if( aggregated || SCIPconsIsDeleted(usefulconss[consindex]) )
6090 continue;
6091
6092 aggrconsdata = SCIPconsGetData(usefulconss[consindex]);
6093 assert(aggrconsdata != NULL);
6094 assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING);
6095
6096 /* determine active variable and constraint that corresponds to */
6098 {
6099 activevar = negvar;
6100 multaggridx = consindex;
6101 }
6102 else
6103 {
6104 activevar = var;
6105 multaggridx = c;
6106 }
6107 objval = SCIPvarGetObj(activevar);
6108
6109 SCIPdebugMsg(scip, "multi-aggregating in two set-packing constraint\n");
6110
6111 /* perform aggregation on variables resulting from a set-packing constraint */
6112 if( (objval < 0.0) == (multaggridx == c) )
6113 {
6114 SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6115 aggrconsindex = c;
6116 aggrallyindex = consindex;
6117 }
6118 else
6119 {
6120 /* we need to find the variable again if other multi-aggregations invalidated the position */
6121 assert(varindex >= 0);
6122 if( varindex >= aggrconsdata->nvars || aggrconsdata->vars[varindex] != negvar )
6123 {
6124 int v2;
6125
6126 /* if the following assert is raised, then the constraint is redundant and we do not need to aggregate
6127 * anymore and can delete this constraint
6128 */
6129 assert(aggrconsdata->nvars >= 2);
6130
6131 for( v2 = aggrconsdata->nvars - 1; v2 >= 0; --v2 )
6132 {
6133 if( aggrconsdata->vars[v2] == negvar )
6134 break;
6135 }
6136 assert(v2 >= 0);
6137
6138 varindex = v2;
6139 }
6140 assert(varindex >= 0);
6141 assert(varindex < aggrconsdata->nvars);
6142 assert(aggrconsdata->vars[varindex] == negvar);
6143
6144 SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
6145 aggrconsindex = consindex;
6146 aggrallyindex = c;
6147 }
6148
6149 if( infeasible )
6150 {
6151 *cutoff = TRUE;
6152 break;
6153 }
6154 }
6155 }
6156 /* we found a redundant variable in a set-partitioning constraint */
6157 else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && nuplocks == 1 && ndownlocks == 1 )
6158 {
6159 /* this constraint can already be required for a multi-aggregation */
6160 if( aggregated )
6161 continue;
6162
6163 SCIPdebugMsg(scip, "multi-aggregating in set-partitioning constraint\n");
6164
6165 /* perform aggregation on variables resulting from a set-partitioning constraint */
6166 SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6167
6168 ++ndecs;
6169
6170 if( infeasible )
6171 {
6172 *cutoff = TRUE;
6173 break;
6174 }
6175
6176 if( aggregated )
6177 {
6178 ++(*naggrvars);
6179
6180 SCIP_CALL( delCoefPos(scip, cons, v) );
6181 ++(*nchgcoefs);
6182
6183 SCIPdebugMsg(scip, "changing constraint <%s> from set-partitioning to set-packing, due to multi-aggregation\n", SCIPconsGetName(cons));
6184
6186 ++(*nchgsides);
6187 chgtype[c] = TRUE;
6188
6189 aggregated = FALSE;
6190 break;
6191 }
6192 }
6193 /* we might have found a redundant variable */
6194 else if( ndownlocks <= 2 && nuplocks <= 2 && SCIPvarGetNegatedVar(var) != NULL )
6195 {
6196 SCIP_VAR* negvar = SCIPvarGetNegatedVar(var);
6197 int image;
6198 int consindex;
6199 int varindex;
6200
6201 /* if we have two times the same variable in a set-partitioning constraint, we cannot aggregate this */
6202 if( SCIPhashmapExists(vartoindex, (void*) var) )
6203 {
6204 image = SCIPhashmapGetImageInt(vartoindex, (void*) var);
6205 assert(image > 0 && image <= nhashmapentries);
6206
6207 assert(0 <= considxs[image - 1] && considxs[image - 1] < nconss);
6208 assert(SCIPconsIsDeleted(usefulconss[considxs[image - 1]]) || chgtype[considxs[image - 1]] || (0 <= posincons[image - 1] && posincons[image - 1] < SCIPconsGetData(usefulconss[considxs[image - 1]])->nvars));
6209
6210 considxs[image - 1] = -1;
6211 posincons[image - 1] = -1;
6212
6213 SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) var) );
6214
6215#ifndef NDEBUG
6216 --posreplacements;
6217#endif
6218 assert(posreplacements >= 0);
6219
6220 continue;
6221 }
6222 else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
6223 {
6224 /* if we found a new variable add it to the data */
6225 if( !SCIPhashmapExists(vartoindex, (void*) negvar) )
6226 {
6227 assert(!SCIPhashmapExists(vartoindex, (void*) var));
6228
6229 ++nhashmapentries;
6230 SCIP_CALL( SCIPhashmapInsertInt(vartoindex, (void*) var, nhashmapentries) );
6231
6232 considxs[nhashmapentries - 1] = c;
6233 posincons[nhashmapentries - 1] = v;
6234
6235#ifndef NDEBUG
6236 ++posreplacements;
6237#endif
6238 continue;
6239 }
6240 }
6241 else
6242 {
6243 assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING);
6244
6245 /* if the negated variable occurs in an additional packing constraint,
6246 * then we are no longer in a doubleton or singleton case;
6247 * this case of two packing and one partitioning constraint (thus,
6248 * 2 down- and 2 uplocks) cannot be handled by this routine, so the
6249 * variable cannot be aggregated, see also #3752 and !3832;
6250 * this situation is characterized by having 2 downlocks (one from the
6251 * partitioning constraint, one from the negated variable in the other
6252 * packing constraint; the current packing constraint (cons) does not
6253 * contribute a downlock)
6254 */
6255 if( ndownlocks >= 2 )
6256 continue;
6257
6258 /* if the negated variable did not occur in a set partitioning constraint
6259 * (those will be iterated over first), we cannot aggregate this variable
6260 */
6261 if( !SCIPhashmapExists(vartoindex, (void*) negvar) )
6262 continue;
6263 }
6264
6265 assert(!chgtype[c]);
6266 assert(SCIPhashmapExists(vartoindex, (void*) negvar));
6267 image = SCIPhashmapGetImageInt(vartoindex, (void*) negvar);
6268 assert(image > 0 && image <= nhashmapentries);
6269
6270 consindex = considxs[image - 1];
6271 assert(0 <= consindex && consindex < nconss);
6272
6273 /* if the following assert fails, the constraint was not merged, or something really strange happened */
6274 assert(consindex < c);
6275
6276 ++ndecs;
6277#ifndef NDEBUG
6278 --posreplacements;
6279#endif
6280 assert(posreplacements >= 0);
6281
6282 varindex = posincons[image - 1];
6283 considxs[image - 1] = -1;
6284 posincons[image - 1] = -1;
6285 SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) negvar) );
6286
6287 /* this constraint can already be required for a multi-aggregation or the other constraint removed */
6288 if( aggregated || SCIPconsIsDeleted(usefulconss[consindex]) )
6289 continue;
6290
6291 aggrconsdata = SCIPconsGetData(usefulconss[consindex]);
6292 assert(aggrconsdata != NULL);
6293
6294 /* must not multi-aggregate variables that are locked more then twice by all setppc constraints */
6295 if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING &&
6296 (SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING )
6297 {
6298 assert(!dualpresolvingenabled || nuplocks + ndownlocks > 2);
6299 continue;
6300 }
6301
6302 assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ||
6303 (SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6304
6305 /* perform aggregation on variables resulting from a set-partitioning constraint */
6306 if( chgtype[consindex] )
6307 {
6308#ifndef NDEBUG
6309 int v2;
6310
6311 assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING);
6312
6313 /* negated variables needs to be still in the upgraded set-packing constraint */
6314 for( v2 = aggrconsdata->nvars - 1; v2 >= 0; --v2 )
6315 {
6316 if( aggrconsdata->vars[v2] == negvar )
6317 break;
6318 }
6319 assert(v2 >= 0);
6320#endif
6321 assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6322
6323 SCIPdebugMsg(scip, "multi-aggregating in one set-partitioning or one set-packing constraint\n");
6324
6325 SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6326 aggrconsindex = c;
6327 aggrallyindex = consindex;
6328 }
6329 else
6330 {
6331 /* @note it might have happened that we have a variable at hand which exists actually in a set-packing
6332 * constraint and due to some other aggregation we increased the number of locks and reached this
6333 * part of the code, where we would expect only set-partitioning constraints in general, so in
6334 * such a strange case we cannot aggregate anything
6335 */
6336 if( (SCIP_SETPPCTYPE)aggrconsdata->setppctype != SCIP_SETPPCTYPE_PARTITIONING )
6337 continue;
6338
6339 SCIPdebugMsg(scip, "multi-aggregating in two set-partitioning or one set-partitioning and -packing constraint\n");
6340
6341 /* we need to find the variable again if other multi-aggregations invalidated the position */
6342 assert(varindex >= 0);
6343 if( varindex >= aggrconsdata->nvars || aggrconsdata->vars[varindex] != negvar )
6344 {
6345 int v2;
6346
6347 /* if the following assert is raised, then the constraint is redundant and we do not need to aggregate
6348 * anymore and can delete this constraint
6349 */
6350 assert(aggrconsdata->nvars >= 2);
6351
6352 for( v2 = aggrconsdata->nvars - 1; v2 >= 0; --v2 )
6353 {
6354 if( aggrconsdata->vars[v2] == negvar )
6355 break;
6356 }
6357 assert(v2 >= 0);
6358
6359 varindex = v2;
6360 }
6361 assert(varindex >= 0);
6362 assert(varindex < aggrconsdata->nvars);
6363 assert(aggrconsdata->vars[varindex] == negvar);
6364
6365 SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
6366 aggrconsindex = consindex;
6367 aggrallyindex = c;
6368 }
6369
6370 if( infeasible )
6371 {
6372 *cutoff = TRUE;
6373 break;
6374 }
6375 }
6376 }
6377
6378 if( *cutoff )
6379 break;
6380
6381 if( aggregated )
6382 {
6383 ++(*naggrvars);
6384
6385 assert(aggrconsindex >= 0);
6386 assert(aggrconsindex <= c);
6387 assert(aggrallyindex >= 0);
6388 assert(aggrallyindex <= c);
6389 cons = usefulconss[aggrallyindex];
6390
6391 /* update the variables */
6392 SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
6393
6394 if( *cutoff )
6395 break;
6396
6397 /* merging unmerged constraints */
6398 SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
6399
6400 if( *cutoff )
6401 break;
6402
6403 /* update hashmap information */
6404 if( !SCIPconsIsDeleted(cons) )
6405 {
6406 aggrconsdata = SCIPconsGetData(usefulconss[aggrconsindex]);
6407 assert(aggrconsdata != NULL);
6408
6409 for( v = aggrconsdata->nvars - 1; v >= 0; --v )
6410 {
6411 SCIP_VAR* var = aggrconsdata->vars[v];
6412
6413 if( SCIPhashmapExists(vartoindex, (void*)var) )
6414 {
6415 /* variable moved to ally constraint to unknown value position */
6416 int image = SCIPhashmapGetImageInt(vartoindex, (void*)var);
6417 considxs[image - 1] = aggrallyindex;
6418 posincons[image - 1] = 0;
6419 }
6420 }
6421 }
6422
6423 SCIPdebugMsg(scip, "deleting redundant constraint <%s>, due to multi-aggregation\n", SCIPconsGetName(usefulconss[aggrconsindex]));
6424 SCIPdebugPrintCons(scip, usefulconss[aggrconsindex], NULL);
6425
6426 assert(!SCIPconsIsDeleted(usefulconss[aggrconsindex]));
6427 SCIP_CALL( SCIPdelCons(scip, usefulconss[aggrconsindex]) );
6428 ++(*ndelconss);
6429 }
6430 }
6431
6432 /* free temporary memory */
6433 SCIPfreeBufferArray(scip, &usefulconss);
6434 SCIPfreeBufferArray(scip, &posincons);
6435 SCIPfreeBufferArray(scip, &considxs);
6436 SCIPfreeBufferArray(scip, &chgtype);
6437
6438 /* free hashmap */
6439 SCIPhashmapFree(&vartoindex);
6440
6441 return SCIP_OKAY;
6442}
6443
6444
6445/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
6446 * accordingly; in contrast to removeRedundantConstraints(), it uses a hash table
6447 */
6448static
6450 SCIP* scip, /**< SCIP data structure */
6451 BMS_BLKMEM* blkmem, /**< block memory */
6452 SCIP_CONS** conss, /**< constraint set */
6453 int nconss, /**< number of constraints in constraint set */
6454 int* firstchange, /**< pointer to store first changed constraint */
6455 int* ndelconss, /**< pointer to count number of deleted constraints */
6456 int* nchgsides /**< pointer to count number of changed left/right hand sides */
6457 )
6458{
6459 SCIP_HASHTABLE* hashtable;
6460 int hashtablesize;
6461 int c;
6462
6463 assert(scip != NULL);
6464 assert(blkmem != NULL);
6465 assert(conss != NULL || nconss == 0);
6466 assert(firstchange != NULL);
6467 assert(ndelconss != NULL);
6468 assert(nchgsides != NULL);
6469
6470 if( nconss == 0 )
6471 return SCIP_OKAY;
6472
6473 assert(conss != NULL);
6474
6475 /* create a hash table for the constraint set */
6476 hashtablesize = nconss;
6477 hashtablesize = MAX(hashtablesize, HASHSIZE_SETPPCCONS);
6478 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
6479 hashGetKeySetppccons, hashKeyEqSetppccons, hashKeyValSetppccons, (void*) scip) );
6480
6481 /* check all constraints in the given set for redundancy */
6482 for( c = 0; c < nconss; ++c )
6483 {
6484 SCIP_CONS* cons0;
6485 SCIP_CONS* cons1;
6486
6487 cons0 = conss[c];
6488
6489 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
6490 continue;
6491
6492 /* get constraint from current hash table with same variables as cons0 and with coefficients either equal or negated
6493 * to the ones of cons0 */
6494 cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
6495
6496 if( cons1 != NULL )
6497 {
6498 SCIP_CONSDATA* consdata0;
6499 SCIP_CONSDATA* consdata1;
6500
6501 assert(SCIPconsIsActive(cons1));
6502 assert(!SCIPconsIsModifiable(cons1));
6503
6504 /* constraint found: create a new constraint with same coefficients and best left and right hand side;
6505 * delete old constraints afterwards
6506 */
6507 consdata0 = SCIPconsGetData(cons0);
6508 consdata1 = SCIPconsGetData(cons1);
6509
6510 assert(consdata0 != NULL && consdata1 != NULL);
6511 assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
6512
6513 assert(consdata0->sorted && consdata1->sorted);
6514 assert(consdata0->vars[0] == consdata1->vars[0]);
6515
6516 SCIPdebugMsg(scip, "setppc constraints <%s> and <%s> have identical variable sets\n",
6517 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6518 SCIPdebugPrintCons(scip, cons0, NULL);
6519 SCIPdebugPrintCons(scip, cons1, NULL);
6520
6521 /* if necessary change type of setppc constraint */
6522 if( consdata1->setppctype != SCIP_SETPPCTYPE_PARTITIONING && consdata0->setppctype != consdata1->setppctype ) /*lint !e641*/
6523 {
6524 /* change the type of cons0 */
6526 (*nchgsides)++;
6527 }
6528
6529 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
6530 /* coverity[swapped_arguments] */
6531 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
6532
6533 /* delete cons0 */
6534 SCIP_CALL( SCIPdelCons(scip, cons0) );
6535 (*ndelconss)++;
6536
6537 /* update the first changed constraint to begin the next aggregation round with */
6538 if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
6539 *firstchange = SCIPconsGetPos(cons1);
6540
6541 assert(SCIPconsIsActive(cons1));
6542 }
6543 else
6544 {
6545 /* no such constraint in current hash table: insert cons0 into hash table */
6546 SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
6547 }
6548 }
6549
6550 /* free hash table */
6551 SCIPhashtableFree(&hashtable);
6552
6553 return SCIP_OKAY;
6554}
6555
6556/** removes the redundant second constraint and updates the flags of the first one */
6557static
6559 SCIP* scip, /**< SCIP data structure */
6560 SCIP_CONS* cons0, /**< constraint that should stay */
6561 SCIP_CONS* cons1, /**< constraint that should be deleted */
6562 int* ndelconss /**< pointer to count number of deleted constraints */
6563 )
6564{
6565 assert(ndelconss != NULL);
6566
6567 SCIPdebugMsg(scip, " -> removing setppc constraint <%s> which is redundant to <%s>\n",
6568 SCIPconsGetName(cons1), SCIPconsGetName(cons0));
6569 SCIPdebugPrintCons(scip, cons0, NULL);
6570 SCIPdebugPrintCons(scip, cons1, NULL);
6571
6572 /* update flags of cons0 */
6573 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
6574
6575 /* delete cons1 */
6576 SCIP_CALL( SCIPdelCons(scip, cons1) );
6577 (*ndelconss)++;
6578
6579 return SCIP_OKAY;
6580}
6581
6582/** for cons0 contained in cons1, fixes variables of cons1 that are not in cons0 to zero */
6583static
6585 SCIP* scip, /**< SCIP data structure */
6586 SCIP_CONS* cons0, /**< constraint that is contained in the other */
6587 SCIP_CONS* cons1, /**< constraint that is a superset of the other */
6588 SCIP_Bool* cutoff, /**< pointer to store whether a cutoff was found */
6589 int* nfixedvars /**< pointer to count number of fixed variables */
6590 )
6591{
6592 SCIP_CONSDATA* consdata0;
6593 SCIP_CONSDATA* consdata1;
6594 int v0;
6595 int v1;
6596
6597 assert(cutoff != NULL);
6598 assert(nfixedvars != NULL);
6599
6600 *cutoff = FALSE;
6601
6602 /* get constraint data */
6603 consdata0 = SCIPconsGetData(cons0);
6604 consdata1 = SCIPconsGetData(cons1);
6605 assert(consdata0 != NULL);
6606 assert(consdata1 != NULL);
6607 assert(consdata0->nvars < consdata1->nvars);
6608 assert(consdata0->sorted);
6609 assert(consdata1->sorted);
6610
6611 /* fix variables in the range of cons0 */
6612 for( v0 = 0, v1 = 0; v0 < consdata0->nvars && !(*cutoff); ++v0, ++v1 )
6613 {
6614 int index0;
6615
6616 assert(v1 < consdata1->nvars);
6617 index0 = SCIPvarGetIndex(consdata0->vars[v0]);
6618 for( ; SCIPvarGetIndex(consdata1->vars[v1]) < index0 && !(*cutoff); ++v1 ) /*lint !e445*/
6619 {
6620 SCIP_Bool fixed;
6621
6622 /* fix variable to zero */
6623 SCIP_CALL( SCIPfixVar(scip, consdata1->vars[v1], 0.0, cutoff, &fixed) );
6624 if( fixed )
6625 {
6626 SCIPdebugMsg(scip, " -> fixed <%s> == 0\n", SCIPvarGetName(consdata1->vars[v1]));
6627 (*nfixedvars)++;
6628 }
6629 assert(v1 < consdata1->nvars-1);
6630 }
6631 assert(SCIPvarGetIndex(consdata1->vars[v1]) == index0 || *cutoff);
6632 }
6633
6634 /* fix remaining variables of cons1 */
6635 for( ; v1 < consdata1->nvars && !(*cutoff); ++v1 )
6636 {
6637 SCIP_Bool fixed;
6638
6639 assert(consdata0->nvars == 0
6640 || SCIPvarGetIndex(consdata1->vars[v1]) > SCIPvarGetIndex(consdata0->vars[consdata0->nvars-1]));
6641
6642 /* fix variable to zero */
6643 SCIP_CALL( SCIPfixVar(scip, consdata1->vars[v1], 0.0, cutoff, &fixed) );
6644 if( fixed )
6645 {
6646 SCIPdebugMsg(scip, " -> fixed <%s> == 0\n", SCIPvarGetName(consdata1->vars[v1]));
6647 (*nfixedvars)++;
6648 }
6649 }
6650
6651 return SCIP_OKAY;
6652}
6653
6654/** applies reductions for cons0 being contained in cons1 */
6655static
6657 SCIP* scip, /**< SCIP data structure */
6658 SCIP_CONS* cons0, /**< constraint that is contained in the other */
6659 SCIP_CONS* cons1, /**< constraint that is a superset of the other */
6660 SCIP_Bool* cutoff, /**< pointer to store whether a cutoff was found */
6661 int* nfixedvars, /**< pointer to count number of fixed variables */
6662 int* ndelconss, /**< pointer to count number of deleted constraints */
6663 int* nchgsides /**< pointer to count number of changed left/right hand sides */
6664 )
6665{
6666 SCIP_CONSDATA* consdata0;
6667 SCIP_CONSDATA* consdata1;
6668
6669 assert(cutoff != NULL);
6670 assert(nfixedvars != NULL);
6671 assert(ndelconss != NULL);
6672 assert(nchgsides != NULL);
6673
6674 *cutoff = FALSE;
6675
6676 /* get constraint data */
6677 consdata0 = SCIPconsGetData(cons0);
6678 consdata1 = SCIPconsGetData(cons1);
6679 assert(consdata0 != NULL);
6680 assert(consdata1 != NULL);
6681 assert(consdata0->nvars < consdata1->nvars);
6682 assert(consdata0->sorted);
6683 assert(consdata1->sorted);
6684
6685 switch( consdata0->setppctype )
6686 {
6688 switch( consdata1->setppctype )
6689 {
6692 /* cons0: partitioning, cons1: partitioning or packing
6693 * -> fix additional variables in cons1 to zero, remove cons1
6694 */
6695 SCIP_CALL( fixAdditionalVars(scip, cons0, cons1, cutoff, nfixedvars) );
6696 SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6697 break;
6698
6700 /* cons0: partitioning, cons1: covering
6701 * -> remove cons1
6702 */
6703 SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6704 break;
6705
6706 default:
6707 SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6708 return SCIP_INVALIDDATA;
6709 }
6710 break;
6711
6713 switch( consdata1->setppctype )
6714 {
6717 /* cons0: packing, cons1: partitioning or packing
6718 * -> remove cons0
6719 */
6720 SCIP_CALL( removeRedundantCons(scip, cons1, cons0, ndelconss) );
6721 break;
6722
6724 /* cons0: packing, cons1: covering
6725 * -> nothing can be deduced
6726 */
6727 break;
6728
6729 default:
6730 SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6731 return SCIP_INVALIDDATA;
6732 }
6733 break;
6734
6736 switch( consdata1->setppctype )
6737 {
6740 /* cons0: covering, cons1: partitioning or packing
6741 * -> fix additional variables in cons1 to zero, remove cons1, convert cons0 into partitioning
6742 */
6743 SCIP_CALL( fixAdditionalVars(scip, cons0, cons1, cutoff, nfixedvars) );
6745 SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6746 (*nchgsides)++;
6747 break;
6748
6750 /* cons0: covering, cons1: covering
6751 * -> remove cons1
6752 */
6753 SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6754 break;
6755
6756 default:
6757 SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6758 return SCIP_INVALIDDATA;
6759 }
6760 break;
6761
6762 default:
6763 SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata0->setppctype, SCIPconsGetName(cons0));
6764 return SCIP_INVALIDDATA;
6765 }
6766
6767 return SCIP_OKAY;
6768}
6769
6770/** deletes redundant constraints */
6771static
6773 SCIP* scip, /**< SCIP data structure */
6774 SCIP_CONS** conss, /**< constraint set */
6775 int firstchange, /**< first constraint that changed since last pair preprocessing round */
6776 int chkind, /**< index of constraint to check against all prior indices up to startind */
6777 SCIP_Bool* cutoff, /**< pointer to store whether a cutoff was found */
6778 int* nfixedvars, /**< pointer to count number of fixed variables */
6779 int* ndelconss, /**< pointer to count number of deleted constraints */
6780 int* nchgsides /**< pointer to count number of changed left/right hand sides */
6781 )
6782{
6783 SCIP_CONS* cons0;
6784 SCIP_CONSDATA* consdata0;
6785 uint64_t signature0;
6786 SCIP_Bool cons0changed;
6787 int c;
6788
6789 assert(scip != NULL);
6790 assert(conss != NULL);
6791 assert(cutoff != NULL);
6792 assert(nfixedvars != NULL);
6793 assert(ndelconss != NULL);
6794 assert(nchgsides != NULL);
6795
6796 *cutoff = FALSE;
6797
6798 /* get the constraint to be checked against all prior constraints */
6799 cons0 = conss[chkind];
6800 assert(SCIPconsIsActive(cons0));
6801 assert(!SCIPconsIsModifiable(cons0));
6802
6803 consdata0 = SCIPconsGetData(cons0);
6804 assert(consdata0 != NULL);
6805 assert(consdata0->nvars >= 1);
6806
6807 /* sort the constraint cons0 */
6808 consdataSort(consdata0);
6809
6810 /* get the bit signature of the constraint */
6811 signature0 = consdataGetSignature(consdata0);
6812
6813 /* check constraint against all prior constraints */
6814 cons0changed = consdata0->changed;
6815 consdata0->changed = FALSE;
6816 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && SCIPconsIsActive(cons0); ++c )
6817 {
6818 SCIP_CONS* cons1;
6819 SCIP_CONSDATA* consdata1;
6820 uint64_t signature1;
6821 uint64_t jointsignature;
6822 SCIP_Bool cons0iscontained;
6823 SCIP_Bool cons1iscontained;
6824 int v0;
6825 int v1;
6826
6827 cons1 = conss[c];
6828
6829 /* ignore inactive and modifiable constraints */
6830 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
6831 continue;
6832
6833 consdata1 = SCIPconsGetData(cons1);
6834 assert(consdata1 != NULL);
6835
6836 /* sort the constraint cons1 */
6837 consdataSort(consdata1);
6838
6839 /* get the bit signature of cons1 */
6840 signature1 = consdataGetSignature(consdata1);
6841
6842 /* check (based on signature) if the two constraints are not included in each other */
6843 jointsignature = (signature0 | signature1);
6844 if( jointsignature != signature0 && jointsignature != signature1 )
6845 continue;
6846
6847 /* check whether one constraint is really a subset of the other */
6848 cons0iscontained = (consdata0->nvars <= consdata1->nvars);
6849 cons1iscontained = (consdata1->nvars <= consdata0->nvars);
6850 v0 = 0;
6851 v1 = 0;
6852 while( v0 < consdata0->nvars && v1 < consdata1->nvars )
6853 {
6854 int index0;
6855 int index1;
6856
6857 index0 = SCIPvarGetIndex(consdata0->vars[v0]);
6858 index1 = SCIPvarGetIndex(consdata1->vars[v1]);
6859 if( index0 < index1 )
6860 {
6861 cons0iscontained = FALSE;
6862 if( !cons1iscontained )
6863 break;
6864 for( v0++; v0 < consdata0->nvars && SCIPvarGetIndex(consdata0->vars[v0]) < index1; v0++ )
6865 {}
6866 }
6867 else if( index1 < index0 )
6868 {
6869 cons1iscontained = FALSE;
6870 if( !cons0iscontained )
6871 break;
6872 for( v1++; v1 < consdata1->nvars && SCIPvarGetIndex(consdata1->vars[v1]) < index0; v1++ )
6873 {}
6874 }
6875 else
6876 {
6877 v0++;
6878 v1++;
6879 }
6880 }
6881 cons0iscontained = cons0iscontained && (v0 == consdata0->nvars);
6882 cons1iscontained = cons1iscontained && (v1 == consdata1->nvars);
6883
6884 if( cons0iscontained && cons1iscontained )
6885 {
6886 SCIPdebugMsg(scip, "setppc constraints <%s> and <%s> have identical variable sets\n",
6887 SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6888 SCIPdebugPrintCons(scip, cons0, NULL);
6889 SCIPdebugPrintCons(scip, cons1, NULL);
6890
6891 /* both constraints consists of the same variables */
6892 if( consdata0->setppctype == consdata1->setppctype )
6893 {
6894 /* both constraints are equal: update flags in cons0 and delete cons1 */
6895 SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6896 }
6897 else if( consdata0->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
6898 {
6899 /* the set partitioning constraint is stronger: remove the other one */
6900 SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6901 }
6902 else if( consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
6903 {
6904 /* the set partitioning constraint is stronger: remove the other one */
6905 SCIP_CALL( removeRedundantCons(scip, cons1, cons0, ndelconss) );
6906 }
6907 else
6908 {
6909 /* one is a covering, the other one a packing constraint: replace them by a single partitioning constraint */
6910 assert((consdata0->setppctype == SCIP_SETPPCTYPE_COVERING && consdata1->setppctype == SCIP_SETPPCTYPE_PACKING)
6911 || (consdata1->setppctype == SCIP_SETPPCTYPE_COVERING && consdata0->setppctype == SCIP_SETPPCTYPE_PACKING)); /*lint !e641*/
6912
6913 /* change the type of cons0 */
6915 (*nchgsides)++;
6916
6917 /* delete cons1 */
6918 SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6919 }
6920 }
6921 else if( cons0iscontained )
6922 {
6923 /* cons0 is contained in cons1 */
6924 SCIPdebugMsg(scip, "setppc constraint <%s> is contained in <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6925 SCIPdebugPrintCons(scip, cons0, NULL);
6926 SCIPdebugPrintCons(scip, cons1, NULL);
6927 SCIP_CALL( processContainedCons(scip, cons0, cons1, cutoff, nfixedvars, ndelconss, nchgsides) );
6928 }
6929 else if( cons1iscontained )
6930 {
6931 /* cons1 is contained in cons1 */
6932 SCIPdebugMsg(scip, "setppc constraint <%s> is contained in <%s>\n", SCIPconsGetName(cons1), SCIPconsGetName(cons0));
6933 SCIPdebugPrintCons(scip, cons0, NULL);
6934 SCIPdebugPrintCons(scip, cons1, NULL);
6935 SCIP_CALL( processContainedCons(scip, cons1, cons0, cutoff, nfixedvars, ndelconss, nchgsides) );
6936 }
6937 }
6938
6939 return SCIP_OKAY;
6940}
6941
6942/* perform deletion of variables in all constraints of the constraint handler */
6943static
6945 SCIP* scip, /**< SCIP data structure */
6946 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
6947 SCIP_CONS** conss, /**< array of constraints */
6948 int nconss /**< number of constraints */
6949 )
6950{
6951 SCIP_CONSDATA* consdata;
6952 int i;
6953 int v;
6954
6955 assert(scip != NULL);
6956 assert(conshdlr != NULL);
6957 assert(conss != NULL);
6958 assert(nconss >= 0);
6959 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
6960
6961 /* iterate over all constraints */
6962 for( i = 0; i < nconss; i++ )
6963 {
6964 consdata = SCIPconsGetData(conss[i]);
6965
6966 /* constraint is marked, that some of its variables were deleted */
6967 if( consdata->varsdeleted )
6968 {
6969 /* iterate over all variables of the constraint and delete marked variables */
6970 for( v = consdata->nvars - 1; v >= 0; v-- )
6971 {
6972 if( SCIPvarIsDeleted(consdata->vars[v]) )
6973 {
6974 SCIP_CALL( delCoefPos(scip, conss[i], v) );
6975 }
6976 }
6977 consdata->varsdeleted = FALSE;
6978 }
6979 }
6980
6981 return SCIP_OKAY;
6982}
6983
6984/** helper function to enforce constraints */
6985static
6987 SCIP* scip, /**< SCIP data structure */
6988 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
6989 SCIP_CONS** conss, /**< constraints to process */
6990 int nconss, /**< number of constraints */
6991 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
6992 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
6993 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
6994 )
6995{
6996 SCIP_Bool cutoff;
6997 SCIP_Bool separated;
6998 SCIP_Bool reduceddom;
6999 int c;
7000
7001 assert(conshdlr != NULL);
7002 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7003 assert(nconss == 0 || conss != NULL);
7004 assert(result != NULL);
7005
7006 SCIPdebugMsg(scip, "Enforcing %d set partitioning / packing / covering constraints for %s solution\n", nconss,
7007 sol == NULL ? "LP" : "relaxation");
7008
7009 *result = SCIP_FEASIBLE;
7010
7011 cutoff = FALSE;
7012 separated = FALSE;
7013 reduceddom = FALSE;
7014
7015 /* check all useful set partitioning / packing / covering constraints for feasibility */
7016 for( c = 0; c < nusefulconss && !cutoff && !reduceddom; ++c )
7017 {
7018 SCIP_CALL( separateCons(scip, conss[c], sol, TRUE, &cutoff, &separated, &reduceddom) );
7019 }
7020
7021 /* check all obsolete set partitioning / packing / covering constraints for feasibility */
7022 for( c = nusefulconss; c < nconss && !cutoff && !separated && !reduceddom; ++c )
7023 {
7024 SCIP_CALL( separateCons(scip, conss[c], sol, TRUE, &cutoff, &separated, &reduceddom) );
7025 }
7026
7027#ifdef VARUSES
7028#ifdef BRANCHLP
7029 /* @todo also branch on relaxation solution */
7030 if( (sol == NULL) && !cutoff && !separated && !reduceddom )
7031 {
7032 /* if solution is not integral, choose a variable set to branch on */
7033 SCIP_CALL( branchLP(scip, conshdlr, result) );
7034 if( *result != SCIP_FEASIBLE )
7035 return SCIP_OKAY;
7036 }
7037#endif
7038#endif
7039
7040 /* return the correct result */
7041 if( cutoff )
7042 *result = SCIP_CUTOFF;
7043 else if( separated )
7044 *result = SCIP_SEPARATED;
7045 else if( reduceddom )
7046 *result = SCIP_REDUCEDDOM;
7047
7048 return SCIP_OKAY;
7049}
7050
7051/*
7052 * upgrading of linear constraints
7053 */
7054
7055
7056/** creates and captures a set partitioning / packing / covering constraint */
7057static
7059 SCIP* scip, /**< SCIP data structure */
7060 SCIP_CONS** cons, /**< pointer to hold the created constraint */
7061 const char* name, /**< name of constraint */
7062 int nvars, /**< number of variables in the constraint */
7063 SCIP_VAR** vars, /**< array with variables of constraint entries */
7064 SCIP_SETPPCTYPE setppctype, /**< type of constraint: set partitioning, packing, or covering constraint */
7065 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
7066 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
7067 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
7068 * Usually set to TRUE. */
7069 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
7070 * TRUE for model constraints, FALSE for additional, redundant constraints. */
7071 SCIP_Bool check, /**< should the constraint be checked for feasibility?
7072 * TRUE for model constraints, FALSE for additional, redundant constraints. */
7073 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
7074 * Usually set to TRUE. */
7075 SCIP_Bool local, /**< is constraint only valid locally?
7076 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7077 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
7078 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
7079 * adds coefficients to this constraint. */
7080 SCIP_Bool dynamic, /**< is constraint subject to aging?
7081 * Usually set to FALSE. Set to TRUE for own cuts which
7082 * are separated as constraints. */
7083 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
7084 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7085 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
7086 * if it may be moved to a more global node?
7087 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7088 )
7089{
7090 SCIP_CONSHDLR* conshdlr;
7091 SCIP_CONSDATA* consdata;
7092 SCIP_CONSHDLRDATA* conshdlrdata;
7093 int i;
7094
7095 assert(scip != NULL);
7096
7097 /* find the set partitioning constraint handler */
7098 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
7099 if( conshdlr == NULL )
7100 {
7101 SCIPerrorMessage("set partitioning / packing / covering constraint handler not found\n");
7102 return SCIP_INVALIDCALL;
7103 }
7104
7105 /* check whether all variables are binary */
7106 assert(vars != NULL || nvars == 0);
7107 for( i = 0; i < nvars; ++i )
7108 {
7109 if( !SCIPvarIsBinary(vars[i]) )
7110 {
7111 SCIPerrorMessage("operand <%s> is not binary\n", SCIPvarGetName(vars[i]));
7112 return SCIP_INVALIDDATA;
7113 }
7114 }
7115
7116 /* create the constraint specific data */
7118 {
7119 /* create constraint in original problem */
7120 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, setppctype) );
7121 }
7122 else
7123 {
7124 /* create constraint in transformed problem */
7125 SCIP_CALL( consdataCreateTransformed(scip, &consdata, nvars, vars, setppctype) );
7126 }
7127
7128 /* create constraint */
7129 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
7130 local, modifiable, dynamic, removable, stickingatnode) );
7131
7132 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7133 assert(conshdlrdata != NULL);
7134
7136 {
7137 ++(conshdlrdata->nsetpart);
7138 assert(conshdlrdata->nsetpart >= 0);
7139 }
7140
7142 {
7143 /* get event handler */
7144 assert(conshdlrdata->eventhdlr != NULL);
7145
7146 /* catch bound change events of variables */
7147 SCIP_CALL( catchAllEvents(scip, *cons, conshdlrdata->eventhdlr) );
7148 }
7149
7150 return SCIP_OKAY;
7151}
7152
7153/** creates and captures a normalized (with all coefficients +1) setppc constraint */
7154static
7156 SCIP* scip, /**< SCIP data structure */
7157 SCIP_CONS** cons, /**< pointer to hold the created constraint */
7158 const char* name, /**< name of constraint */
7159 int nvars, /**< number of variables in the constraint */
7160 SCIP_VAR** vars, /**< array with variables of constraint entries */
7161 SCIP_Real* vals, /**< array with coefficients (+1.0 or -1.0) */
7162 int mult, /**< multiplier on the coefficients(+1 or -1) */
7163 SCIP_SETPPCTYPE setppctype, /**< type of constraint: set partitioning, packing, or covering constraint */
7164 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
7165 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
7166 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
7167 * Usually set to TRUE. */
7168 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
7169 * TRUE for model constraints, FALSE for additional, redundant constraints. */
7170 SCIP_Bool check, /**< should the constraint be checked for feasibility?
7171 * TRUE for model constraints, FALSE for additional, redundant constraints. */
7172 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
7173 * Usually set to TRUE. */
7174 SCIP_Bool local, /**< is constraint only valid locally?
7175 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7176 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
7177 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
7178 * adds coefficients to this constraint. */
7179 SCIP_Bool dynamic, /**< is constraint subject to aging?
7180 * Usually set to FALSE. Set to TRUE for own cuts which
7181 * are separated as constraints. */
7182 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
7183 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7184 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
7185 * if it may be moved to a more global node?
7186 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7187 )
7188{
7189 SCIP_VAR** transvars;
7190 int v;
7191
7192 assert(nvars == 0 || vars != NULL);
7193 assert(nvars == 0 || vals != NULL);
7194 assert(mult == +1 || mult == -1);
7195
7196 /* get temporary memory */
7197 SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
7198
7199 /* negate positive or negative variables */
7200 for( v = 0; v < nvars; ++v )
7201 {
7202 if( mult * vals[v] > 0.0 )
7203 transvars[v] = vars[v];
7204 else
7205 {
7206 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
7207 }
7208 assert(transvars[v] != NULL);
7209 }
7210
7211 /* create the constraint */
7212 SCIP_CALL( createConsSetppc(scip, cons, name, nvars, transvars, setppctype,
7213 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
7214
7215 /* release temporary memory */
7216 SCIPfreeBufferArray(scip, &transvars);
7217
7218 return SCIP_OKAY;
7219}
7220
7221/** check, if linear constraint can be upgraded to set partitioning, packing, or covering constraint */
7222static
7223SCIP_DECL_LINCONSUPGD(linconsUpgdSetppc)
7224{ /*lint --e{715}*/
7225 assert(upgdcons != NULL);
7226 assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") == 0 );
7227
7228 /* check, if linear constraint can be upgraded to set partitioning, packing, or covering constraint
7229 * - all set partitioning / packing / covering constraints consist only of binary variables with a
7230 * coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
7231 * lhs <= x1 + ... + xp - y1 - ... - yn <= rhs
7232 * - negating all variables y = (1-Y) with negative coefficients gives:
7233 * lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
7234 * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
7235 * p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
7236 * - a set partitioning constraint has left hand side of +1.0, and right hand side of +1.0 : x(S) == 1.0
7237 * -> without negations: lhs == rhs == 1 - n or lhs == rhs == p - 1
7238 * - a set packing constraint has left hand side of -infinity, and right hand side of +1.0 : x(S) <= 1.0
7239 * -> without negations: (lhs == -inf and rhs == 1 - n) or (lhs == p - 1 and rhs = +inf)
7240 * - a set covering constraint has left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
7241 * -> without negations: (lhs == 1 - n and rhs == +inf) or (lhs == -inf and rhs = p - 1)
7242 */
7243 if( nposbin + nnegbin + nposimplbin + nnegimplbin == nvars && ncoeffspone + ncoeffsnone == nvars )
7244 {
7245 int mult;
7246
7247 if( SCIPisEQ(scip, lhs, rhs) && (SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) || SCIPisEQ(scip, lhs, ncoeffspone - 1.0)) )
7248 {
7249 SCIPdebugMsg(scip, "upgrading constraint <%s> to set partitioning constraint\n", SCIPconsGetName(cons));
7250
7251 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
7252 mult = SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) ? +1 : -1;
7253
7254 /* create the set partitioning constraint (an automatically upgraded constraint is always unmodifiable) */
7255 assert(!SCIPconsIsModifiable(cons));
7256 SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
7262 }
7263 else if( (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, 1.0 - ncoeffsnone))
7264 || (SCIPisEQ(scip, lhs, ncoeffspone - 1.0) && SCIPisInfinity(scip, rhs)) )
7265 {
7266 SCIPdebugMsg(scip, "upgrading constraint <%s> to set packing constraint\n", SCIPconsGetName(cons));
7267
7268 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
7269 mult = SCIPisInfinity(scip, -lhs) ? +1 : -1;
7270
7271 /* create the set packing constraint (an automatically upgraded constraint is always unmodifiable) */
7272 assert(!SCIPconsIsModifiable(cons));
7273 SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
7279 }
7280 else if( (SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, rhs))
7281 || (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, ncoeffspone - 1.0)) )
7282 {
7283 SCIPdebugMsg(scip, "upgrading constraint <%s> to set covering constraint\n", SCIPconsGetName(cons));
7284
7285 /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
7286 mult = SCIPisInfinity(scip, rhs) ? +1 : -1;
7287
7288 /* create the set covering constraint (an automatically upgraded constraint is always unmodifiable) */
7289 assert(!SCIPconsIsModifiable(cons));
7290 SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
7296 }
7297 }
7298
7299 return SCIP_OKAY;
7300}
7301
7302/** tries to upgrade a nonlinear constraint to a setpacking constraint */
7303static
7305{
7306 SCIP_Bool isquadratic;
7307 SCIP_EXPR* expr;
7308 SCIP_EXPR* expr1;
7309 SCIP_EXPR* expr2;
7310 SCIP_VAR* bilinvars[2];
7311 SCIP_VAR* vars[2];
7312 SCIP_Real bilincoef;
7313 SCIP_Real constant;
7314 SCIP_Real lincoef;
7315 SCIP_Real sqrcoef;
7316 SCIP_Real coefx;
7317 SCIP_Real coefy;
7318 SCIP_Real rhs;
7319 int nbilinexprterms;
7320 int nquadexprs;
7321 int nlinexprs;
7322
7323 assert(scip != NULL);
7324 assert(cons != NULL);
7325 assert(nupgdconss != NULL);
7326 assert(upgdconss != NULL);
7327 assert(! SCIPconsIsModifiable(cons));
7328 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "nonlinear") == 0);
7329
7330 *nupgdconss = 0;
7331
7332 SCIPdebugMsg(scip, "try to upgrade nonlinear constraint <%s> to setpacking constraint ...\n", SCIPconsGetName(cons));
7334
7335 /* need exactly two variables */
7336 if( nvarexprs != 2 )
7337 return SCIP_OKAY;
7338
7339 /* left and right hand side need to be equal
7340 * @todo we could also handle inequalities
7341 */
7342 rhs = SCIPgetRhsNonlinear(cons);
7343 if( SCIPisInfinity(scip, rhs) || !SCIPisEQ(scip, SCIPgetLhsNonlinear(cons), rhs) )
7344 return SCIP_OKAY;
7345
7346 /* check whether constraint is quadratic */
7347 SCIP_CALL( SCIPcheckQuadraticNonlinear(scip, cons, &isquadratic) );
7348 if( !isquadratic )
7349 return SCIP_OKAY;
7350
7351 expr = SCIPgetExprNonlinear(cons);
7352 SCIPexprGetQuadraticData(expr, &constant, &nlinexprs, NULL, NULL, &nquadexprs, &nbilinexprterms, NULL, NULL);
7353
7354 /* adjust rhs */
7355 rhs -= constant;
7356
7357 /* cannot currently handle linear part */
7358 if( nlinexprs > 0 )
7359 return SCIP_OKAY;
7360
7361 /* need only one bilinear term */
7362 if( nbilinexprterms != 1 )
7363 return SCIP_OKAY;
7364
7365 /* need exactly two quadratic variables */
7366 if( nquadexprs != 2 )
7367 return SCIP_OKAY;
7368
7369 /* get bilinear term */
7370 SCIPexprGetQuadraticBilinTerm(expr, 0, &expr1, &expr2, &bilincoef, NULL, NULL);
7371 bilinvars[0] = SCIPgetVarExprVar(expr1);
7372 bilinvars[1] = SCIPgetVarExprVar(expr2);
7373
7374 if( SCIPisZero(scip, bilincoef) )
7375 return SCIP_OKAY;
7376
7377 /* check variable types */
7378 if( SCIPvarGetType(bilinvars[0]) != SCIP_VARTYPE_BINARY || SCIPvarGetType(bilinvars[1]) != SCIP_VARTYPE_BINARY )
7379 return SCIP_OKAY;
7380
7381 /* get data of quadratic terms */
7382 SCIPexprGetQuadraticQuadTerm(expr, 0, &expr1, &lincoef, &sqrcoef, NULL, NULL, NULL);
7383 coefx = lincoef + sqrcoef; /* for binary variables, we can treat sqr coef as lin coef */
7384
7385 SCIPexprGetQuadraticQuadTerm(expr, 1, &expr2, &lincoef, &sqrcoef, NULL, NULL, NULL);
7386 coefy = lincoef + sqrcoef; /* for binary variables, we can treat sqr coef as lin coef */
7387
7388 /* divide constraint by coefficient of x*y */
7389 coefx /= bilincoef;
7390 coefy /= bilincoef;
7391 rhs /= bilincoef;
7392
7393 /* constraint is now of the form coefx * x + coefy * y + x * y == rhs
7394 * we can rewrite as (x + coefy) * (y + coefx) == rhs + coefx * coefy
7395 */
7396
7397 /* we can only upgrade if coefx and coefy are 0 or -1 and rhs == -coefx * coefy */
7398 if( !SCIPisZero(scip, coefx) && !SCIPisEQ(scip, coefx, -1.0) )
7399 return SCIP_OKAY;
7400 if( !SCIPisZero(scip, coefy) && !SCIPisEQ(scip, coefy, -1.0) )
7401 return SCIP_OKAY;
7402 if( !SCIPisEQ(scip, rhs, -coefx * coefy) )
7403 return SCIP_OKAY;
7404
7405 if( SCIPisZero(scip, coefy) )
7406 {
7407 vars[0] = SCIPgetVarExprVar(expr1);
7408 }
7409 else
7410 {
7411 assert(SCIPisEQ(scip, coefy, -1.0));
7412 /* x - 1 = -(1-x) = -(~x) */
7413 SCIP_CALL( SCIPgetNegatedVar(scip, SCIPgetVarExprVar(expr1), &vars[0]) );
7414 }
7415 if( SCIPisZero(scip, coefx) )
7416 {
7417 vars[1] = SCIPgetVarExprVar(expr2);
7418 }
7419 else
7420 {
7421 assert(SCIPisEQ(scip, coefx, -1.0));
7422 /* y - 1 = -(1 - y) = -(~y) */
7423 SCIP_CALL( SCIPgetNegatedVar(scip, SCIPgetVarExprVar(expr2), &vars[1]) );
7424 }
7425
7426 /* constraint is now of the form vars[0] * vars[1] == 0 */
7427
7428 SCIPdebugMsg(scip, "constraint <%s> can be upgraded ...\n", SCIPconsGetName(cons));
7429
7430 /* vars[0] + vars[1] <= 1 */
7431 SCIP_CALL( SCIPcreateConsSetpack(scip, &upgdconss[0], SCIPconsGetName(cons), 2, vars,
7435 SCIPdebugPrintCons(scip, upgdconss[0], NULL);
7436
7437 ++(*nupgdconss);
7438
7439 return SCIP_OKAY;
7440} /*lint !e715*/
7441
7442/** adds symmetry information of constraint to a symmetry detection graph */
7443static
7445 SCIP* scip, /**< SCIP pointer */
7446 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
7447 SCIP_CONS* cons, /**< constraint */
7448 SYM_GRAPH* graph, /**< symmetry detection graph */
7449 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
7450 )
7451{
7452 SCIP_CONSDATA* consdata;
7453 SCIP_VAR** vars;
7454 SCIP_Real* vals;
7455 SCIP_Real constant = 0.0;
7456 SCIP_Real lhs;
7457 SCIP_Real rhs;
7458 int nlocvars;
7459 int nvars;
7460 int i;
7461
7462 assert(scip != NULL);
7463 assert(cons != NULL);
7464 assert(graph != NULL);
7465 assert(success != NULL);
7466
7467 consdata = SCIPconsGetData(cons);
7468 assert(consdata != NULL);
7469
7470 /* get active variables of the constraint */
7471 nvars = SCIPgetNVars(scip);
7472 nlocvars = consdata->nvars;
7473
7474 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
7475 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
7476
7477 for( i = 0; i < consdata->nvars; ++i )
7478 {
7479 vars[i] = consdata->vars[i];
7480 vals[i] = 1.0;
7481 }
7482
7483 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
7484
7485 lhs = -SCIPinfinity(scip);
7486 rhs = SCIPinfinity(scip);
7487 if ( consdata->setppctype == (unsigned) SCIP_SETPPCTYPE_PACKING ) /*lint !e641*/
7488 rhs = 1.0 - constant;
7489 else if ( consdata->setppctype == (unsigned) SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
7490 lhs = 1.0 - constant;
7491 else
7492 {
7493 assert(consdata->setppctype == (unsigned) SCIP_SETPPCTYPE_PARTITIONING); /*lint !e641*/
7494
7495 rhs = 1.0 - constant;
7496 lhs = 1.0 - constant;
7497 }
7498
7499 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
7500 cons, lhs, rhs, success) );
7501
7502 SCIPfreeBufferArray(scip, &vals);
7503 SCIPfreeBufferArray(scip, &vars);
7504
7505 return SCIP_OKAY;
7506}
7507
7508/*
7509 * Callback methods of constraint handler
7510 */
7511
7512/** copy method for constraint handler plugins (called when SCIP copies plugins) */
7513static
7514SCIP_DECL_CONSHDLRCOPY(conshdlrCopySetppc)
7515{ /*lint --e{715}*/
7516 assert(scip != NULL);
7517 assert(conshdlr != NULL);
7518 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7519
7520 /* call inclusion method of constraint handler */
7522
7523 *valid = TRUE;
7524
7525 return SCIP_OKAY;
7526}
7527
7528/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
7529static
7530SCIP_DECL_CONSFREE(consFreeSetppc)
7531{ /*lint --e{715}*/
7532 SCIP_CONSHDLRDATA* conshdlrdata;
7533
7534 assert(conshdlr != NULL);
7535 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7536 assert(scip != NULL);
7537
7538 /* free constraint handler data */
7539 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7540 assert(conshdlrdata != NULL);
7541 SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
7542
7543 SCIPconshdlrSetData(conshdlr, NULL);
7544
7545 return SCIP_OKAY;
7546}
7547
7548
7549/** initialization method of constraint handler (called after problem was transformed) */
7550static
7551SCIP_DECL_CONSINIT(consInitSetppc)
7552{ /*lint --e{715}*/
7553 SCIP_CONSHDLRDATA* conshdlrdata;
7554
7555 assert(conshdlr != NULL);
7556 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7557 assert(scip != NULL);
7558
7559 /* free constraint handler data */
7560 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7561 assert(conshdlrdata != NULL);
7562
7563 conshdlrdata->noldfixedvars = 0;
7564 conshdlrdata->noldimpls = 0;
7565 conshdlrdata->noldcliques = 0;
7566 conshdlrdata->noldupgrs = 0;
7567 conshdlrdata->nclqpresolve = 0;
7568 conshdlrdata->updatedsetppctype = FALSE;
7569 conshdlrdata->enablecliquelifting = TRUE;
7570
7571 return SCIP_OKAY;
7572}
7573
7574
7575/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
7576static
7577SCIP_DECL_CONSEXITPRE(consExitpreSetppc)
7578{ /*lint --e{715}*/
7579 int c;
7580
7581 assert(scip != NULL);
7582 assert(conshdlr != NULL);
7583
7584 for( c = 0; c < nconss; ++c )
7585 {
7586 if( !SCIPconsIsDeleted(conss[c]) )
7587 {
7588 /* we are not allowed to detect infeasibility in the exitpre stage */
7589 SCIP_CALL( applyFixings(scip, conss[c], NULL, NULL, NULL, NULL) );
7590 }
7591 }
7592
7593 return SCIP_OKAY;
7594}
7595
7596/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
7597static
7598SCIP_DECL_CONSINITSOL(consInitsolSetppc)
7599{ /*lint --e{715}*/
7600 /* add nlrow representation to NLP, if NLP had been constructed */
7602 {
7603 int c;
7604 for( c = 0; c < nconss; ++c )
7605 {
7606 SCIP_CALL( addNlrow(scip, conss[c]) );
7607 }
7608 }
7609
7610 return SCIP_OKAY;
7611}
7612
7613/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
7614static
7615SCIP_DECL_CONSEXITSOL(consExitsolSetppc)
7616{ /*lint --e{715}*/
7617 SCIP_CONSDATA* consdata;
7618 int c;
7619
7620 /* release the rows and nlrows of all constraints */
7621 for( c = 0; c < nconss; ++c )
7622 {
7623 consdata = SCIPconsGetData(conss[c]);
7624 assert(consdata != NULL);
7625
7626 if( consdata->row != NULL )
7627 {
7628 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
7629 }
7630
7631 if( consdata->nlrow != NULL )
7632 {
7633 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
7634 }
7635 }
7636
7637 return SCIP_OKAY;
7638}
7639
7640
7641/** frees specific constraint data */
7642static
7643SCIP_DECL_CONSDELETE(consDeleteSetppc)
7644{ /*lint --e{715}*/
7645 SCIP_CONSHDLRDATA* conshdlrdata;
7646
7647 assert(conshdlr != NULL);
7648 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7649
7650 /* get event handler */
7651 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7652 assert(conshdlrdata != NULL);
7653 assert(conshdlrdata->eventhdlr != NULL);
7654
7655 if( SCIPisTransformed(scip) )
7656 {
7657 if( (SCIP_SETPPCTYPE)((*consdata)->setppctype) == SCIP_SETPPCTYPE_PARTITIONING )
7658 {
7659 --(conshdlrdata->nsetpart);
7660 assert(conshdlrdata->nsetpart >= 0);
7661 }
7662 }
7663
7664 /* if constraint belongs to transformed problem space, drop bound change events on variables */
7665 if( (*consdata)->nvars > 0 && SCIPvarIsTransformed((*consdata)->vars[0]) )
7666 {
7667 SCIP_CALL( dropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7668 }
7669
7670 /* free setppc constraint data */
7671 SCIP_CALL( consdataFree(scip, consdata) );
7672
7673 return SCIP_OKAY;
7674}
7675
7676
7677/** transforms constraint data into data belonging to the transformed problem */
7678static
7679SCIP_DECL_CONSTRANS(consTransSetppc)
7680{ /*lint --e{715}*/
7681 SCIP_CONSHDLRDATA* conshdlrdata;
7682 SCIP_CONSDATA* sourcedata;
7683 SCIP_CONSDATA* targetdata;
7684
7685 /*debugMsg(scip, "Trans method of setppc constraints\n");*/
7686
7687 assert(conshdlr != NULL);
7688 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7690 assert(sourcecons != NULL);
7691 assert(targetcons != NULL);
7692
7693 /* get event handler */
7694 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7695 assert(conshdlrdata != NULL);
7696 assert(conshdlrdata->eventhdlr != NULL);
7697
7698 sourcedata = SCIPconsGetData(sourcecons);
7699 assert(sourcedata != NULL);
7700 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
7701
7702 /* create constraint data for target constraint */
7703 SCIP_CALL( consdataCreateTransformed(scip, &targetdata, sourcedata->nvars, sourcedata->vars,
7704 (SCIP_SETPPCTYPE)sourcedata->setppctype) );
7705
7706 /* create target constraint */
7707 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
7708 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
7709 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
7710 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
7711 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
7712
7713 if( (SCIP_SETPPCTYPE)sourcedata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
7714 {
7715 ++(conshdlrdata->nsetpart);
7716 assert(conshdlrdata->nsetpart >= 0);
7717 }
7718
7719 /* catch bound change events of variables */
7720 SCIP_CALL( catchAllEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
7721
7722 return SCIP_OKAY;
7723}
7724
7725
7726/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
7727static
7728SCIP_DECL_CONSINITLP(consInitlpSetppc)
7729{ /*lint --e{715}*/
7730 int c;
7731
7732 *infeasible = FALSE;
7733
7734 for( c = 0; c < nconss && !(*infeasible); ++c )
7735 {
7736 assert(SCIPconsIsInitial(conss[c]));
7737 SCIP_CALL( addCut(scip, conss[c], infeasible) );
7738 }
7739
7740 return SCIP_OKAY;
7741}
7742
7743
7744/** separation method of constraint handler for LP solutions */
7745static
7746SCIP_DECL_CONSSEPALP(consSepalpSetppc)
7747{ /*lint --e{715}*/
7748 SCIP_Bool cutoff;
7749 SCIP_Bool separated;
7750 SCIP_Bool reduceddom;
7751 int c;
7752
7753 assert(conshdlr != NULL);
7754 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7755 assert(nconss == 0 || conss != NULL);
7756 assert(result != NULL);
7757
7758 SCIPdebugMsg(scip, "separating %d/%d set partitioning / packing / covering constraints\n", nusefulconss, nconss);
7759
7760 *result = SCIP_DIDNOTFIND;
7761
7762 cutoff = FALSE;
7763 separated = FALSE;
7764 reduceddom = FALSE;
7765
7766 /* check all useful set partitioning / packing / covering constraints for feasibility */
7767 for( c = 0; c < nusefulconss && !cutoff; ++c )
7768 {
7769 SCIP_CALL( separateCons(scip, conss[c], NULL, TRUE, &cutoff, &separated, &reduceddom) );
7770 }
7771
7772 /* combine set partitioning / packing / covering constraints to get more cuts */
7773 /**@todo further cuts of set partitioning / packing / covering constraints */
7774
7775 /* return the correct result */
7776 if( cutoff )
7777 *result = SCIP_CUTOFF;
7778 else if( reduceddom )
7779 *result = SCIP_REDUCEDDOM;
7780 else if( separated )
7781 *result = SCIP_SEPARATED;
7782
7783 return SCIP_OKAY;
7784}
7785
7786
7787/** separation method of constraint handler for arbitrary primal solutions */
7788static
7789SCIP_DECL_CONSSEPASOL(consSepasolSetppc)
7790{ /*lint --e{715}*/
7791 SCIP_Bool cutoff;
7792 SCIP_Bool separated;
7793 SCIP_Bool reduceddom;
7794 int c;
7795
7796 assert(conshdlr != NULL);
7797 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7798 assert(nconss == 0 || conss != NULL);
7799 assert(result != NULL);
7800
7801 SCIPdebugMsg(scip, "separating %d/%d set partitioning / packing / covering constraints\n", nusefulconss, nconss);
7802
7803 *result = SCIP_DIDNOTFIND;
7804
7805 cutoff = FALSE;
7806 separated = FALSE;
7807 reduceddom = FALSE;
7808
7809 /* check all useful set partitioning / packing / covering constraints for feasibility */
7810 for( c = 0; c < nusefulconss && !cutoff; ++c )
7811 {
7812 SCIP_CALL( separateCons(scip, conss[c], sol, FALSE, &cutoff, &separated, &reduceddom) );
7813 }
7814
7815 /* combine set partitioning / packing / covering constraints to get more cuts */
7816 /**@todo further cuts of set partitioning / packing / covering constraints */
7817
7818 /* return the correct result */
7819 if( cutoff )
7820 *result = SCIP_CUTOFF;
7821 else if( reduceddom )
7822 *result = SCIP_REDUCEDDOM;
7823 else if( separated )
7824 *result = SCIP_SEPARATED;
7825
7826 return SCIP_OKAY;
7827}
7828
7829
7830#ifdef VARUSES
7831#ifdef BRANCHLP
7832/** if fractional variables exist, chooses a set S of them and branches on (i) x(S) == 0, and (ii) x(S) >= 1 */
7833static
7834SCIP_RETCODE branchLP(
7835 SCIP* scip, /**< SCIP data structure */
7836 SCIP_CONSHDLR* conshdlr, /**< set partitioning / packing / covering constraint handler */
7837 SCIP_RESULT* result /**< pointer to store the result SCIP_BRANCHED, if branching was applied */
7838 )
7839{
7840 SCIP_CONSHDLRDATA* conshdlrdata;
7841 SCIP_INTARRAY* varuses;
7842 SCIP_VAR** lpcands;
7843 SCIP_VAR** sortcands;
7844 SCIP_VAR* var;
7845 SCIP_Real branchweight;
7846 SCIP_Real solval;
7847 int* uses;
7848 int nlpcands;
7849 int nsortcands;
7850 int nselcands;
7851 int numuses;
7852 int i;
7853 int j;
7854
7855 /**@todo use a better set partitioning / packing / covering branching on LP solution (use SOS branching) */
7856
7857 assert(conshdlr != NULL);
7858 assert(result != NULL);
7859
7860 conshdlrdata = SCIPconshdlrGetData(conshdlr);
7861 assert(conshdlrdata != NULL);
7862
7863 varuses = conshdlrdata->varuses;
7864 assert(varuses != NULL);
7865
7866 /* get fractional variables */
7867 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, NULL, &nlpcands, NULL, NULL) );
7868 if( nlpcands == 0 )
7869 return SCIP_OKAY;
7870
7871 assert(MINBRANCHWEIGHT <= MAXBRANCHWEIGHT);
7872
7873 /* get temporary memory */
7874 SCIP_CALL( SCIPallocBufferArray(scip, &sortcands, nlpcands) );
7875 SCIP_CALL( SCIPallocBufferArray(scip, &uses, nlpcands) );
7876
7877 /* sort fractional variables by number of uses in enabled set partitioning / packing / covering constraints */
7878 nsortcands = 0;
7879 for( i = 0; i < nlpcands; ++i )
7880 {
7881 var = lpcands[i];
7882 numuses = SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var));
7883 if( numuses > 0 )
7884 {
7885 for( j = nsortcands; j > 0 && numuses > uses[j-1]; --j )
7886 {
7887 sortcands[j] = sortcands[j-1];
7888 uses[j] = uses[j-1];
7889 }
7890 assert(0 <= j && j <= nsortcands);
7891 sortcands[j] = var;
7892 uses[j] = numuses;
7893 nsortcands++;
7894 }
7895 }
7896 assert(nsortcands <= nlpcands);
7897
7898 /* if none of the fractional variables is member of a set partitioning / packing / covering constraint,
7899 * we are not responsible for doing the branching
7900 */
7901 if( nsortcands > 0 )
7902 {
7903 SCIP_Real cumprio = 0.0;
7904 SCIP_Real minprio = SCIP_INVALID;
7905 SCIP_Real minestzero = SCIP_INVALID;
7906 SCIP_Real minestone = SCIP_INVALID;
7907 SCIP_Real tmp;
7908
7909 /* select the first variables from the sorted candidate list, until MAXBRANCHWEIGHT is reached;
7910 * then choose one less
7911 */
7912 branchweight = 0.0;
7913 solval = 0.0;
7914 for( nselcands = 0; nselcands < nsortcands; ++nselcands )
7915 {
7916 solval = SCIPgetVarSol(scip, sortcands[nselcands]);
7917 assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
7918 branchweight += solval;
7919
7920 /* did we exceed the maximal weight */
7921 if( branchweight > MAXBRANCHWEIGHT )
7922 break;
7923
7924 /* @todo instead of taking the minimum into account try other variants like the maximum and the average */
7925 /* calculate priorities and estimates by adding up/taking the minimum of all single priorities/estimates */
7926 cumprio += SCIPcalcNodeselPriority(scip, sortcands[nselcands], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
7927 tmp = SCIPcalcNodeselPriority(scip, sortcands[nselcands], SCIP_BRANCHDIR_UPWARDS, 1.0);
7928 minprio = MIN(minprio, tmp);
7929 tmp = SCIPcalcChildEstimate(scip, sortcands[nselcands], 0.0);;
7930 minestzero = MIN(minestzero, tmp);
7931 tmp = SCIPcalcChildEstimate(scip, sortcands[nselcands], 1.0);;
7932 minestone = MIN(minestone, tmp);
7933 }
7934 assert(minestzero != SCIP_INVALID); /*lint !e777*/
7935 assert(minestone != SCIP_INVALID); /*lint !e777*/
7936 assert(minprio != SCIP_INVALID); /*lint !e777*/
7937 assert(nselcands > 0);
7938 branchweight -= solval;
7939
7940 /* check, if we accumulated at least MIN and at most MAXBRANCHWEIGHT weight */
7941 if( MINBRANCHWEIGHT <= branchweight && branchweight <= MAXBRANCHWEIGHT )
7942 {
7943 SCIP_NODE* node;
7944
7945 /* perform the binary set branching on the selected variables */
7946 assert(1 <= nselcands && nselcands <= nlpcands);
7947
7948 /* create left child, fix x_i = 0 for all i \in S */
7949 SCIP_CALL( SCIPcreateChild(scip, &node, cumprio, minestzero) );
7950 for( i = 0; i < nselcands; ++i )
7951 {
7952 SCIP_CALL( SCIPchgVarUbNode(scip, node, sortcands[i], 0.0) );
7953 }
7954
7955 /* create right child: add constraint x(S) >= 1 */
7956 SCIP_CALL( SCIPcreateChild(scip, &node, minprio, minestone) );
7957 if( nselcands == 1 )
7958 {
7959 /* only one candidate selected: fix it to 1.0 */
7960 SCIPdebugMsg(scip, "fixing variable <%s> to 1.0 in right child node\n", SCIPvarGetName(sortcands[0]));
7961 SCIP_CALL( SCIPchgVarLbNode(scip, node, sortcands[0], 1.0) );
7962 }
7963 else
7964 {
7965 SCIP_CONS* newcons;
7966 char name[SCIP_MAXSTRLEN];
7967
7968 /* add set covering constraint x(S) >= 1 */
7970
7971 SCIP_CALL( SCIPcreateConsSetcover(scip, &newcons, name, nselcands, sortcands,
7973 SCIP_CALL( SCIPaddConsNode(scip, node, newcons, NULL) );
7974 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
7975 }
7976
7977 *result = SCIP_BRANCHED;
7978
7979#ifdef SCIP_DEBUG
7980 SCIPdebugMsg(scip, "binary set branching: nselcands=%d/%d, weight(S)=%g, A={", nselcands, nlpcands, branchweight);
7981 for( i = 0; i < nselcands; ++i )
7982 SCIPdebugMsgPrint(scip, " %s[%g]", SCIPvarGetName(sortcands[i]), SCIPgetSolVal(scip, NULL, sortcands[i]));
7983 SCIPdebugMsgPrint(scip, " }\n");
7984#endif
7985 }
7986 }
7987
7988 /* free temporary memory */
7989 SCIPfreeBufferArray(scip, &uses);
7990 SCIPfreeBufferArray(scip, &sortcands);
7991
7992 return SCIP_OKAY;
7993}
7994#endif
7995
7996/** if unfixed variables exist, chooses a set S of them and creates |S|+1 child nodes:
7997 * - for each variable i from S, create child node with x_0 = ... = x_i-1 = 0, x_i = 1
7998 * - create an additional child node x_0 = ... = x_n-1 = 0
7999 */
8000static
8001SCIP_RETCODE branchPseudo(
8002 SCIP* scip, /**< SCIP data structure */
8003 SCIP_CONSHDLR* conshdlr, /**< set partitioning / packing / covering constraint handler */
8004 SCIP_RESULT* result /**< pointer to store the result SCIP_BRANCHED, if branching was applied */
8005 )
8006{
8007 SCIP_CONSHDLRDATA* conshdlrdata;
8008 SCIP_INTARRAY* varuses;
8009 SCIP_VAR** pseudocands;
8010 SCIP_VAR** branchcands;
8011 SCIP_VAR* var;
8012 SCIP_NODE* node;
8013 int* canduses;
8014 int npseudocands;
8015 int maxnbranchcands;
8016 int nbranchcands;
8017 int uses;
8018 int i;
8019 int j;
8020
8021 /**@todo use a better set partitioning / packing / covering branching on pseudo solution (use SOS branching) */
8022
8023 assert(conshdlr != NULL);
8024 assert(result != NULL);
8025
8026 conshdlrdata = SCIPconshdlrGetData(conshdlr);
8027 assert(conshdlrdata != NULL);
8028
8029 /* check, if pseudo branching is disabled */
8030 if( conshdlrdata->npseudobranches <= 1 )
8031 return SCIP_OKAY;
8032
8033 /* get fractional variables */
8034 SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, NULL, &npseudocands) );
8035 if( npseudocands == 0 )
8036 return SCIP_OKAY;
8037
8038 varuses = conshdlrdata->varuses;
8039 assert(varuses != NULL);
8040
8041 /* choose the maximal number of branching variables */
8042 maxnbranchcands = conshdlrdata->npseudobranches-1;
8043 assert(maxnbranchcands >= 1);
8044
8045 /* get temporary memory */
8046 SCIP_CALL( SCIPallocBufferArray(scip, &branchcands, maxnbranchcands) );
8047 SCIP_CALL( SCIPallocBufferArray(scip, &canduses, maxnbranchcands) );
8048
8049 /* sort unfixed variables by number of uses in enabled set partitioning / packing / covering constraints */
8050 nbranchcands = 0;
8051 for( i = 0; i < npseudocands; ++i )
8052 {
8053 var = pseudocands[i];
8054 uses = SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var));
8055 if( uses > 0 )
8056 {
8057 if( nbranchcands < maxnbranchcands || uses > canduses[nbranchcands-1] )
8058 {
8059 for( j = MIN(nbranchcands, maxnbranchcands-1); j > 0 && uses > canduses[j-1]; --j )
8060 {
8061 branchcands[j] = branchcands[j-1];
8062 canduses[j] = canduses[j-1];
8063 }
8064 assert(0 <= j && j <= nbranchcands && j < maxnbranchcands);
8065 branchcands[j] = var;
8066 canduses[j] = uses;
8067 if( nbranchcands < maxnbranchcands )
8068 nbranchcands++;
8069 }
8070 }
8071 }
8072 assert(nbranchcands <= maxnbranchcands);
8073
8074 /* if none of the unfixed variables is member of a set partitioning / packing / covering constraint,
8075 * we are not responsible for doing the branching
8076 */
8077 if( nbranchcands > 0 )
8078 {
8079 SCIP_Real* estone;
8080 SCIP_Real minestzero = SCIP_INVALID;
8081 SCIP_Real tmp;
8082
8083 SCIP_CALL( SCIPallocBufferArray(scip, &estone, nbranchcands) );
8084
8085 /* @todo instead of taking the minimum into account try other variants like the maximum and the average */
8086 /* @todo calculate priorities instead of setting it to the number of branching candidates */
8087 /* calculate estimates by taking the minimum over all single estimates */
8088 for( i = 0; i < nbranchcands; ++i )
8089 {
8090 tmp = SCIPcalcChildEstimate(scip, branchcands[i], 0.0);;
8091 minestzero = MIN(minestzero, tmp);
8092 estone[i] = SCIPcalcChildEstimate(scip, branchcands[i], 1.0);
8093 }
8094 assert(minestzero != SCIP_INVALID); /*lint !e777*/
8095
8096 /* branch on the first part of the sorted candidates:
8097 * - for each of these variables i, create a child node x_0 = ... = x_i-1 = 0, x_i = 1
8098 * - create an additional child node x_0 = ... = x_n-1 = 0
8099 */
8100 for( i = 0; i < nbranchcands; ++i )
8101 {
8102 /* create child with x_0 = ... = x_i-1 = 0, x_i = 1 */
8103 SCIP_CALL( SCIPcreateChild(scip, &node, (SCIP_Real)nbranchcands, MIN(minestzero, estone[i])) );
8104 for( j = 0; j < i; ++j )
8105 {
8106 SCIP_CALL( SCIPchgVarUbNode(scip, node, branchcands[j], 0.0) );
8107 }
8108 SCIP_CALL( SCIPchgVarLbNode(scip, node, branchcands[i], 1.0) );
8109 }
8110 /* create child with x_0 = ... = x_n = 0 */
8111 SCIP_CALL( SCIPcreateChild(scip, &node, (SCIP_Real)nbranchcands, minestzero) );
8112 for( i = 0; i < nbranchcands; ++i )
8113 {
8114 SCIP_CALL( SCIPchgVarUbNode(scip, node, branchcands[i], 0.0) );
8115 }
8116
8117 *result = SCIP_BRANCHED;
8118
8119 SCIPfreeBufferArray(scip, &estone);
8120
8121#ifdef SCIP_DEBUG
8122 {
8123 int nchildren;
8124 SCIP_CALL( SCIPgetChildren(scip, NULL, &nchildren) );
8125 SCIPdebugMsg(scip, "branched on pseudo solution: %d children\n", nchildren);
8126 }
8127#endif
8128 }
8129
8130 /* free temporary memory */
8131 SCIPfreeBufferArray(scip, &canduses);
8132 SCIPfreeBufferArray(scip, &branchcands);
8133
8134 return SCIP_OKAY;
8135}
8136#endif
8137
8138
8139/** constraint enforcing method of constraint handler for LP solutions */
8140static
8141SCIP_DECL_CONSENFOLP(consEnfolpSetppc)
8142{ /*lint --e{715}*/
8143 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
8144
8145 return SCIP_OKAY;
8146}
8147
8148
8149/** constraint enforcing method of constraint handler for relaxation solutions */
8150static
8151SCIP_DECL_CONSENFORELAX(consEnforelaxSetppc)
8152{ /*lint --e{715}*/
8153 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
8154
8155 return SCIP_OKAY;
8156}
8157
8158
8159/** constraint enforcing method of constraint handler for pseudo solutions */
8160static
8161SCIP_DECL_CONSENFOPS(consEnfopsSetppc)
8162{ /*lint --e{715}*/
8163 SCIP_Bool cutoff;
8164 SCIP_Bool infeasible;
8165 SCIP_Bool reduceddom;
8166 SCIP_Bool solvelp;
8167 int c;
8168
8169 assert(conshdlr != NULL);
8170 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8171 assert(nconss == 0 || conss != NULL);
8172 assert(result != NULL);
8173
8174 /* if the solution is infeasible anyway due to objective value, skip the constraint processing and branch directly */
8175#ifdef VARUSES
8176 if( objinfeasible )
8177 {
8178 *result = SCIP_DIDNOTRUN;
8179 SCIP_CALL( branchPseudo(scip, conshdlr, result) );
8180 return SCIP_OKAY;
8181 }
8182#endif
8183
8184 SCIPdebugMsg(scip, "pseudo enforcing %d set partitioning / packing / covering constraints\n", nconss);
8185
8186 *result = SCIP_FEASIBLE;
8187
8188 cutoff = FALSE;
8189 infeasible = FALSE;
8190 reduceddom = FALSE;
8191 solvelp = FALSE;
8192
8193 /* check all set partitioning / packing / covering constraints for feasibility */
8194 for( c = 0; c < nconss && !cutoff && !reduceddom && !solvelp; ++c )
8195 {
8196 SCIP_CALL( enforcePseudo(scip, conss[c], &cutoff, &infeasible, &reduceddom, &solvelp) );
8197 }
8198
8199 if( cutoff )
8200 *result = SCIP_CUTOFF;
8201 else if( reduceddom )
8202 *result = SCIP_REDUCEDDOM;
8203 else if( solvelp )
8204 *result = SCIP_SOLVELP;
8205 else if( infeasible )
8206 {
8207 *result = SCIP_INFEASIBLE;
8208
8209#ifdef VARUSES
8210 /* at least one constraint is violated by pseudo solution and we didn't find a better way to resolve this:
8211 * -> branch on pseudo solution
8212 */
8213 SCIP_CALL( branchPseudo(scip, conshdlr, result) );
8214#endif
8215 }
8216
8217 return SCIP_OKAY;
8218}
8219
8220
8221/** feasibility check method of constraint handler for integral solutions */
8222static
8223SCIP_DECL_CONSCHECK(consCheckSetppc)
8224{ /*lint --e{715}*/
8225 SCIP_CONS* cons;
8226 SCIP_CONSDATA* consdata;
8227 int c;
8228
8229 assert(conshdlr != NULL);
8230 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8231 assert(nconss == 0 || conss != NULL);
8232 assert(result != NULL);
8233
8234 *result = SCIP_FEASIBLE;
8235
8236 /* check all set partitioning / packing / covering constraints for feasibility */
8237 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
8238 {
8239 cons = conss[c];
8240 consdata = SCIPconsGetData(cons);
8241 assert(consdata != NULL);
8242 if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
8243 {
8244 if( !checkCons(scip, consdata, sol) )
8245 {
8246 /* constraint is violated */
8247 *result = SCIP_INFEASIBLE;
8248
8249 if( printreason )
8250 {
8251 SCIP_Real sum = 0.0;
8252 int v;
8253
8254 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
8255
8256 for( v = 0; v < consdata->nvars; ++v )
8257 {
8258 assert(SCIPvarIsBinary(consdata->vars[v]));
8259
8260 sum += SCIPgetSolVal(scip, sol, consdata->vars[v]);
8261 }
8262 SCIPinfoMessage(scip, NULL, ";\n");
8263 SCIPinfoMessage(scip, NULL, "violation: the right hand side is violated by by %.15g\n", ABS(sum - 1));
8264 }
8265 }
8266 }
8267 }
8268
8269 return SCIP_OKAY;
8270}
8271
8272/** domain propagation method of constraint handler */
8273static
8274SCIP_DECL_CONSPROP(consPropSetppc)
8275{ /*lint --e{715}*/
8276 SCIP_Bool cutoff;
8277 SCIP_Bool addcut;
8278 SCIP_Bool mustcheck;
8279 SCIP_Bool inpresolve;
8280 int nfixedvars = 0;
8281 int c;
8282
8283 assert(conshdlr != NULL);
8284 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8285 assert(nconss == 0 || conss != NULL);
8286 assert(result != NULL);
8287
8288 *result = SCIP_DIDNOTFIND;
8289
8290 SCIPdebugMsg(scip, "propagating %d/%d set partitioning / packing / covering constraints\n", nmarkedconss, nconss);
8291
8292 cutoff = FALSE;
8293 inpresolve = (SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE);
8294
8295 /* propagate all marked set partitioning / packing / covering constraints */
8296 for( c = nmarkedconss - 1; c >= 0 && !cutoff; --c )
8297 {
8298 assert(SCIPconsGetData(conss[c]) != NULL);
8299
8300 /* during presolving, we do not want to propagate constraints with multiaggregated variables. After presolving,
8301 * we want to resolve the multiaggregation to have a clean data structure; All initial constraints should not
8302 * have multiaggregated variables, but this is not true for constraints that were introduced during solving
8303 */
8304 if( SCIPconsGetData(conss[c])->existmultaggr )
8305 {
8306 int naddconss, ndelconss;
8307
8308 if( inpresolve )
8309 continue;
8310
8311 naddconss = ndelconss = 0;
8312 SCIP_CALL( applyFixings(scip, conss[c], &naddconss, &ndelconss, &nfixedvars, &cutoff) );
8313
8314 if( cutoff )
8315 break;
8316 }
8317
8318 /* all multiaggregations should be resolved at here */
8319 assert(inpresolve || ! SCIPconsGetData(conss[c])->existmultaggr);
8320
8321 SCIP_CALL( processFixings(scip, conss[c], &cutoff, &nfixedvars, &addcut, &mustcheck) );
8322
8324 }
8325
8326 /* return the correct result */
8327 if( cutoff )
8328 *result = SCIP_CUTOFF;
8329 else if( nfixedvars > 0 )
8330 *result = SCIP_REDUCEDDOM;
8331
8332 return SCIP_OKAY; /*lint !e438*/
8333}
8334
8335
8336/** presolving method of constraint handler */
8337static
8338SCIP_DECL_CONSPRESOL(consPresolSetppc)
8339{ /*lint --e{715}*/
8340 SCIP_CONSHDLRDATA* conshdlrdata;
8341 int oldnfixedvars;
8342 int oldnaggrvars;
8343 int oldndelconss;
8344 int oldnchgcoefs;
8345 int firstchange;
8346 int firstclique;
8347 int lastclique;
8348 int startdelconss;
8349 int c;
8350 SCIP_Bool cutoff;
8351
8352 assert(conshdlr != NULL);
8353 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8354 assert(scip != NULL);
8355 assert(result != NULL);
8356
8357 *result = SCIP_DIDNOTFIND;
8358 oldnfixedvars = *nfixedvars;
8359 oldndelconss = *ndelconss;
8360 oldnaggrvars = *naggrvars;
8361 oldnchgcoefs = *nchgcoefs;
8362 cutoff = FALSE;
8363
8364 conshdlrdata = SCIPconshdlrGetData(conshdlr);
8365 assert(conshdlrdata != NULL);
8366
8367 /* determine whether we want to run the clique lifting procedure */
8368 conshdlrdata->enablecliquelifting = conshdlrdata->enablecliquelifting || conshdlrdata->updatedsetppctype
8369 || conshdlrdata->noldfixedvars != SCIPgetNFixedVars(scip) || conshdlrdata->noldimpls != SCIPgetNImplications(scip)
8370 || conshdlrdata->noldcliques != SCIPgetNCliques(scip) || conshdlrdata->noldupgrs != nconss;
8371
8372 /* remember old values */
8373 startdelconss = *ndelconss;
8374 conshdlrdata->noldimpls = SCIPgetNImplications(scip);
8375 conshdlrdata->noldcliques = SCIPgetNCliques(scip);
8376 conshdlrdata->updatedsetppctype = FALSE;
8377
8378 /* process constraints */
8379 firstchange = INT_MAX;
8380 firstclique = INT_MAX;
8381 lastclique = -1;
8382 for( c = 0; c < nconss && !SCIPisStopped(scip); ++c )
8383 {
8384 SCIP_CONS* cons;
8385 SCIP_CONSDATA* consdata;
8386
8387 assert(*result != SCIP_CUTOFF);
8388
8389 cons = conss[c];
8390 assert(cons != NULL);
8391 consdata = SCIPconsGetData(cons);
8392 assert(consdata != NULL);
8393
8394 /*SCIPdebugMsg(scip, "presolving set partitioning / packing / covering constraint <%s>\n", SCIPconsGetName(cons));*/
8395
8396 /* remove all variables that are fixed to zero and replace all aggregated variables */
8397 if( consdata->nfixedzeros > 0 || nnewaggrvars > 0 || nnewaddconss > 0 || nnewupgdconss > 0
8398 || *naggrvars > oldnaggrvars || (nrounds == 0 && SCIPgetNRuns(scip) > 1) )
8399 {
8400 SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
8401
8402 if( cutoff )
8403 {
8404 *result = SCIP_CUTOFF;
8405 return SCIP_OKAY;
8406 }
8407
8408 if( SCIPconsIsDeleted(cons) )
8409 continue;
8410 }
8411
8412 /* find pairs of negated variables in constraint:
8413 * partitioning/packing: all other variables must be zero, constraint is redundant
8414 * covering: constraint is redundant
8415 *
8416 * find sets of equal variables in constraint:
8417 * partitioning/packing: variable must be zero
8418 * covering: multiple entries of variable can be replaced by single entry
8419 */
8420 SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
8421
8422 if( cutoff )
8423 {
8424 *result = SCIP_CUTOFF;
8425 return SCIP_OKAY;
8426 }
8427
8428 /* if constraint was deleted while merging, go to the next constraint */
8429 if( !SCIPconsIsActive(cons) )
8430 continue;
8431
8432 /* remove fixings found by merging */
8433 if( consdata->nfixedzeros > 0 )
8434 {
8435 SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
8436
8437 if( cutoff )
8438 {
8439 *result = SCIP_CUTOFF;
8440 return SCIP_OKAY;
8441 }
8442
8443 if( SCIPconsIsDeleted(cons) )
8444 continue;
8445 }
8446
8447 /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
8448 * possible
8449 */
8450 SCIP_CALL( presolvePropagateCons(scip, cons, TRUE, NULL, NULL, NULL, NULL, nfixedvars, naggrvars, ndelconss, &cutoff) );
8451
8452 if( cutoff )
8453 {
8454 *result = SCIP_CUTOFF;
8455 return SCIP_OKAY;
8456 }
8457
8458 /* if constraint was deleted while propagation, go to the next constraint */
8459 if( !SCIPconsIsActive(cons) )
8460 continue;
8461
8462 /* remove fixings found by presolvePropagateCons() */
8463 if( consdata->nfixedzeros > 0 )
8464 {
8465 SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
8466
8467 if( cutoff )
8468 {
8469 *result = SCIP_CUTOFF;
8470 return SCIP_OKAY;
8471 }
8472
8473 if( SCIPconsIsDeleted(cons) )
8474 continue;
8475 }
8476
8477 /* perform dual reductions */
8478 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
8479 {
8480 SCIP_CALL( dualPresolving(scip, cons, nfixedvars, ndelconss, naggrvars, result) );
8481
8482 /* if dual reduction deleted the constraint we take the next */
8483 if( !SCIPconsIsActive(cons) )
8484 continue;
8485 }
8486
8487 /* remember the first changed constraint to begin the next redundancy round with */
8488 if( firstchange == INT_MAX && consdata->changed )
8489 firstchange = c;
8490
8491 /* remember the first and last constraints for which we have to add the clique information */
8492 if( !consdata->cliqueadded && consdata->nvars >= 2 )
8493 {
8494 if( firstclique == INT_MAX )
8495 firstclique = c;
8496 lastclique = c;
8497 }
8498 }
8499
8500 /* update result pointer */
8501 if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss || oldnchgcoefs < *nchgcoefs )
8502 *result = SCIP_SUCCESS;
8503
8504 if( firstchange < nconss && conshdlrdata->presolusehashing )
8505 {
8506 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
8507 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, ndelconss, nchgsides) );
8508 if( oldndelconss < *ndelconss )
8509 *result = SCIP_SUCCESS;
8510 }
8511
8512 /* determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and
8513 * negated) in any combination of set-partitioning and set-packing constraints
8514 */
8515 if( nconss > 1 && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0
8516 && ((conshdlrdata->nsetpart > 0 && !SCIPdoNotMultaggr(scip) && conshdlrdata->conshdlrlinear != NULL)
8517 || (conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip)
8518 && conshdlrdata->nsetpart < nconss && !SCIPdoNotAggr(scip))) )
8519 {
8520 SCIP_CALL( removeDoubleAndSingletonsAndPerformDualpresolve(scip, conss, nconss, conshdlrdata->dualpresolving
8521 && SCIPallowStrongDualReds(scip), conshdlrdata->conshdlrlinear != NULL, nfixedvars,
8522 naggrvars, ndelconss, nchgcoefs, nchgsides, &cutoff) );
8523
8524 if( cutoff )
8525 {
8526 *result = SCIP_CUTOFF;
8527 return SCIP_OKAY;
8528 }
8529 else if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss )
8530 *result = SCIP_SUCCESS;
8531 }
8532
8533 /* clique lifting */
8534 if( conshdlrdata->cliquelifting && conshdlrdata->enablecliquelifting && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
8535 {
8536 /* add cliques first before lifting variables */
8537 SCIP_CALL( addCliques(scip, conss, nconss, firstclique, lastclique, naddconss, ndelconss, nchgbds, &cutoff) );
8538
8539 if( cutoff )
8540 {
8541 *result = SCIP_CUTOFF;
8542 return SCIP_OKAY;
8543 }
8544
8545 firstclique = nconss;
8546 lastclique = -1;
8547
8548 /* lift variables and check for fixings due to clique information */
8549 SCIP_CALL( preprocessCliques(scip, conshdlrdata, conss, nconss, nrounds, &firstchange, &firstclique,
8550 &lastclique, nfixedvars, naggrvars, ndelconss, nchgcoefs, &cutoff) );
8551 ++(conshdlrdata->nclqpresolve);
8552
8553 if( cutoff )
8554 {
8555 *result = SCIP_CUTOFF;
8556 return SCIP_OKAY;
8557 }
8558 else if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss || oldnchgcoefs < *nchgcoefs )
8559 *result = SCIP_SUCCESS;
8560
8561 /* remember the number of fixings */
8562 conshdlrdata->noldfixedvars = *nfixedvars + *naggrvars;
8563 conshdlrdata->enablecliquelifting = FALSE;
8564 }
8565
8566 if( oldndelconss == *ndelconss && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
8567 {
8568 /* check constraints for redundancy */
8569 if( conshdlrdata->presolpairwise )
8570 {
8571 SCIP_Longint npaircomparisons = 0;
8572
8573 oldndelconss = *ndelconss;
8574 oldnfixedvars = *nfixedvars;
8575
8576 for( c = firstchange; c < nconss && !SCIPisStopped(scip); ++c )
8577 {
8578 assert(*result != SCIP_CUTOFF);
8579
8580 if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
8581 {
8582 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange);
8583
8584 SCIP_CALL( removeRedundantConstraints(scip, conss, firstchange, c, &cutoff, nfixedvars, ndelconss, nchgsides) );
8585 if( cutoff )
8586 {
8587 *result = SCIP_CUTOFF;
8588 return SCIP_OKAY;
8589 }
8590
8591 if( npaircomparisons > NMINCOMPARISONS )
8592 {
8593 if( (*ndelconss - oldndelconss + *nfixedvars - oldnfixedvars) / ((SCIP_Real)npaircomparisons) < MINGAINPERNMINCOMPARISONS )
8594 break;
8595 oldndelconss = *ndelconss;
8596 oldnfixedvars = *nfixedvars;
8597 npaircomparisons = 0;
8598 *result = SCIP_SUCCESS;
8599 }
8600 }
8601 }
8602 }
8603 }
8604
8605 /* add cliques after lifting variables */
8606 SCIP_CALL( addCliques(scip, conss, nconss, MIN(firstclique, nconss), MIN(lastclique, nconss), naddconss, ndelconss,
8607 nchgbds, &cutoff) );
8608
8609 if( cutoff )
8610 *result = SCIP_CUTOFF;
8611
8612 conshdlrdata->noldupgrs = nconss - (*ndelconss - startdelconss);
8613
8614 return SCIP_OKAY;
8615}
8616
8617
8618/** propagation conflict resolving method of constraint handler */
8619static
8620SCIP_DECL_CONSRESPROP(consRespropSetppc)
8621{ /*lint --e{715}*/
8622 SCIP_CONSDATA* consdata;
8623 int v;
8624
8625 assert(conshdlr != NULL);
8626 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8627 assert(cons != NULL);
8628 assert(infervar != NULL);
8629 assert(result != NULL);
8630
8631 consdata = SCIPconsGetData(cons);
8632 assert(consdata != NULL);
8633
8634 SCIPdebugMsg(scip, "conflict resolving method of set partitioning / packing / covering constraint handler\n");
8635
8636 if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING
8637 || ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
8638 && SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5) )
8639 {
8640#ifndef NDEBUG
8641 SCIP_Bool confvarfound;
8642#endif
8643
8644 /* the inference constraint is a set partitioning or covering constraint with the inference variable inferred to 1.0:
8645 * the reason for the deduction is the assignment of 0.0 to all other variables
8646 */
8647#ifndef NDEBUG
8648 confvarfound = FALSE;
8649#endif
8650 for( v = 0; v < consdata->nvars; ++v )
8651 {
8652 if( consdata->vars[v] != infervar )
8653 {
8654 /* the reason variable must be assigned to zero */
8655 assert(SCIPgetVarUbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) < 0.5);
8656 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
8657 }
8658#ifndef NDEBUG
8659 else
8660 {
8661 assert(!confvarfound);
8662 confvarfound = TRUE;
8663 }
8664#endif
8665 }
8666 assert(confvarfound);
8667 }
8668 else
8669 {
8670 /* the inference constraint is a set partitioning or packing constraint with the inference variable inferred to 0.0:
8671 * the reason for the deduction is the assignment of 1.0 to a single variable
8672 */
8673 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
8674
8675 if( inferinfo >= 0 )
8676 {
8677 assert(SCIPgetVarLbAtIndex(scip, consdata->vars[inferinfo], bdchgidx, FALSE) > 0.5);
8678 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[inferinfo]) );
8679 }
8680 else
8681 {
8682 for( v = 0; v < consdata->nvars; ++v )
8683 {
8684 if( SCIPgetVarLbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) > 0.5 )
8685 {
8686 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
8687 break;
8688 }
8689 }
8690 assert(v < consdata->nvars);
8691 }
8692 }
8693
8694 *result = SCIP_SUCCESS;
8695
8696 return SCIP_OKAY;
8697}
8698
8699
8700/** variable rounding lock method of constraint handler */
8701static
8702SCIP_DECL_CONSLOCK(consLockSetppc)
8703{ /*lint --e{715}*/
8704 SCIP_CONSDATA* consdata;
8705 int nlocksdown;
8706 int nlocksup;
8707 int i;
8708
8709 consdata = SCIPconsGetData(cons);
8710 assert(consdata != NULL);
8711
8712 switch( consdata->setppctype )
8713 {
8715 nlocksdown = nlockspos + nlocksneg;
8716 nlocksup = nlockspos + nlocksneg;
8717 break;
8719 nlocksdown = nlocksneg;
8720 nlocksup = nlockspos;
8721 break;
8723 nlocksdown = nlockspos;
8724 nlocksup = nlocksneg;
8725 break;
8726 default:
8727 SCIPerrorMessage("unknown setppc type\n");
8728 return SCIP_INVALIDDATA;
8729 }
8730
8731 for( i = 0; i < consdata->nvars; ++i )
8732 {
8733 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksdown, nlocksup) );
8734 }
8735
8736 return SCIP_OKAY;
8737}
8738
8739
8740/** constraint activation notification method of constraint handler */
8741static
8742SCIP_DECL_CONSACTIVE(consActiveSetppc)
8743{ /*lint --e{715}*/
8744 assert(cons != NULL);
8745 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8746 assert(SCIPconsIsTransformed(cons));
8747
8748 SCIPdebugMsg(scip, "activation information for set partitioning / packing / covering constraint <%s>\n",
8749 SCIPconsGetName(cons));
8750
8751 /* we only might add the constraint to the propagation list, when we are not activating it in probing mode */
8753 {
8754 SCIP_CONSDATA* consdata = SCIPconsGetData(cons);
8755 assert(consdata != NULL);
8756
8757 if( consdata->nfixedones >= 1 || consdata->nfixedzeros >= consdata->nvars - 1 )
8758 {
8760 }
8761 }
8762
8763#ifdef VARUSES
8764 /* increase the number of uses for each variable in the constraint */
8765 SCIP_CALL( consdataIncVaruses(scip, SCIPconshdlrGetData(conshdlr), SCIPconsGetData(cons)) );
8766#endif
8767
8769 {
8770 SCIP_CALL( addNlrow(scip, cons) );
8771 }
8772
8773 return SCIP_OKAY;
8774}
8775
8776
8777/** constraint deactivation notification method of constraint handler */
8778static
8779SCIP_DECL_CONSDEACTIVE(consDeactiveSetppc)
8780{ /*lint --e{715}*/
8781 SCIP_CONSDATA* consdata;
8782
8783 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8784 assert(SCIPconsIsTransformed(cons));
8785
8786 SCIPdebugMsg(scip, "deactivation information for set partitioning / packing / covering constraint <%s>\n",
8787 SCIPconsGetName(cons));
8788
8789 /* get constraint data */
8790 consdata = SCIPconsGetData(cons);
8791 assert(consdata != NULL);
8792
8793#ifdef VARUSES
8794 /* decrease the number of uses for each variable in the constraint */
8795 SCIP_CALL( consdataDecVaruses(scip, SCIPconshdlrGetData(conshdlr), condata) );
8796#endif
8797
8798 if( SCIPconsIsDeleted(cons) )
8799 {
8800 SCIP_CONSHDLRDATA* conshdlrdata;
8801
8802 /* get event handler */
8803 conshdlrdata = SCIPconshdlrGetData(conshdlr);
8804 assert(conshdlrdata != NULL);
8805 assert(conshdlrdata->eventhdlr != NULL);
8806
8807 /* if constraint belongs to transformed problem space, drop bound change events on variables */
8808 if( consdata->nvars > 0 && SCIPvarIsTransformed(consdata->vars[0]) )
8809 {
8810 SCIP_CALL( dropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
8811 }
8812 }
8813
8814 /* remove row from NLP, if still in solving
8815 * if we are in exitsolve, the whole NLP will be freed anyway
8816 */
8817 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
8818 {
8819 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
8820 }
8821
8822 return SCIP_OKAY;
8823}
8824
8825/** variable deletion method of constraint handler */
8826static
8827SCIP_DECL_CONSDELVARS(consDelvarsSetppc)
8828{
8829 assert( scip != NULL );
8830 assert( conshdlr != NULL );
8831 assert( conss != NULL || nconss == 0 );
8832
8833 if( nconss > 0 )
8834 {
8835 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
8836 }
8837
8838 return SCIP_OKAY;
8839}
8840
8841
8842
8843/** constraint display method of constraint handler */
8844static
8845SCIP_DECL_CONSPRINT(consPrintSetppc)
8846{ /*lint --e{715}*/
8847 assert( scip != NULL );
8848 assert( conshdlr != NULL );
8849 assert( cons != NULL );
8850
8852
8853 return SCIP_OKAY;
8854}
8855
8856/** constraint copying method of constraint handler */
8857static
8858SCIP_DECL_CONSCOPY(consCopySetppc)
8859{ /*lint --e{715}*/
8860 SCIP_VAR** sourcevars;
8861 const char* consname;
8862 SCIP_Real lhs;
8863 SCIP_Real rhs;
8864 int nvars;
8865 SCIP_SETPPCTYPE type;
8866
8867 /* get variables and coefficients of the source constraint */
8868 sourcevars = SCIPgetVarsSetppc(sourcescip, sourcecons);
8869 nvars = SCIPgetNVarsSetppc(sourcescip, sourcecons);
8870
8871 /* get setppc type */
8872 type = SCIPgetTypeSetppc(sourcescip, sourcecons);
8873 lhs = -SCIPinfinity(scip);
8874 rhs = SCIPinfinity(scip);
8875
8876 switch( type )
8877 {
8879 lhs = 1.0;
8880 rhs = 1.0;
8881 break;
8883 rhs = 1.0;
8884 break;
8886 lhs = 1.0;
8887 break;
8888 default:
8889 SCIPerrorMessage("unknown setppc type\n");
8890 return SCIP_INVALIDDATA;
8891 }
8892
8893 if( name != NULL )
8894 consname = name;
8895 else
8896 consname = SCIPconsGetName(sourcecons);
8897
8898 /* copy the logic using the linear constraint copy method */
8899 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, NULL,
8900 lhs, rhs, varmap, consmap,
8901 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
8902 assert(cons != NULL);
8903
8904 return SCIP_OKAY;
8905}
8906
8907/** constraint parsing method of constraint handler */
8908static
8909SCIP_DECL_CONSPARSE(consParseSetppc)
8910{ /*lint --e{715}*/
8911 SCIP_VAR** vars;
8912 int nvars;
8913
8914 assert(scip != NULL);
8915 assert(success != NULL);
8916 assert(str != NULL);
8917 assert(name != NULL);
8918 assert(cons != NULL);
8919
8920 *success = TRUE;
8921
8922 nvars = 0;
8923 vars = NULL;
8924
8925 /* check if lhs is just 0 */
8926 if( str[0] == '0' )
8927 {
8928 assert(str[1] == ' ');
8929 str += 2;
8930 }
8931 else
8932 {
8933 SCIP_Real* coefs;
8934 char* endptr;
8935 int coefssize;
8936 int requsize;
8937
8938 /* initialize buffers for storing the coefficients */
8939 coefssize = 100;
8940 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
8941 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
8942
8943 /* parse linear sum to get variables and coefficients */
8944 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
8945
8946 if( *success && requsize > coefssize )
8947 {
8948 /* realloc buffers and try again */
8949 coefssize = requsize;
8950 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
8951 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
8952
8953 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
8954 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
8955 }
8956
8957 if( !*success )
8958 {
8959 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", str);
8960 }
8961 else
8962 str = endptr;
8963
8964 /* free coefficient array */
8965 SCIPfreeBufferArray(scip, &coefs);
8966 }
8967
8968 /* remove white spaces */
8969 SCIP_CALL( SCIPskipSpace((char**)&str) );
8970
8971 if( *success )
8972 {
8973 switch( *str )
8974 {
8975 case '=' :
8976 SCIP_CALL( SCIPcreateConsSetpart(scip, cons, name, nvars, vars,
8977 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8978 break;
8979 case '<' :
8980 SCIP_CALL( SCIPcreateConsSetpack(scip, cons, name, nvars, vars,
8981 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8982 break;
8983 case '>' :
8984 SCIP_CALL( SCIPcreateConsSetcover(scip, cons, name, nvars, vars,
8985 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8986 break;
8987 default:
8988 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "error parsing setppc type\n");
8989 *success = FALSE;
8990 break;
8991 }
8992 }
8993
8994 /* free variable array */
8996
8997 return SCIP_OKAY;
8998}
8999
9000/** constraint method of constraint handler which returns the variables (if possible) */
9001static
9002SCIP_DECL_CONSGETVARS(consGetVarsSetppc)
9003{ /*lint --e{715}*/
9004 SCIP_CONSDATA* consdata;
9005
9006 consdata = SCIPconsGetData(cons);
9007 assert(consdata != NULL);
9008
9009 if( varssize < consdata->nvars )
9010 (*success) = FALSE;
9011 else
9012 {
9013 assert(vars != NULL);
9014
9015 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
9016 (*success) = TRUE;
9017 }
9018
9019 return SCIP_OKAY;
9020}
9021
9022/** constraint method of constraint handler which returns the number of variables (if possible) */
9023static
9024SCIP_DECL_CONSGETNVARS(consGetNVarsSetppc)
9025{ /*lint --e{715}*/
9026 SCIP_CONSDATA* consdata;
9027
9028 consdata = SCIPconsGetData(cons);
9029 assert(consdata != NULL);
9030
9031 (*nvars) = consdata->nvars;
9032 (*success) = TRUE;
9033
9034 return SCIP_OKAY;
9035}
9036
9037/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
9038static
9039SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSetppc)
9040{ /*lint --e{715}*/
9041 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
9042
9043 return SCIP_OKAY;
9044}
9045
9046/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
9047static
9048SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSetppc)
9049{ /*lint --e{715}*/
9050 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
9051
9052 return SCIP_OKAY;
9053}
9054
9055/*
9056 * Callback methods of event handler
9057 */
9058
9059static
9060SCIP_DECL_EVENTEXEC(eventExecSetppc)
9061{ /*lint --e{715}*/
9062 SCIP_CONS* cons;
9063 SCIP_CONSDATA* consdata;
9064 SCIP_EVENTTYPE eventtype;
9065
9066 assert(eventhdlr != NULL);
9067 assert(eventdata != NULL);
9068 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
9069 assert(event != NULL);
9070
9071 /*debugMsg(scip, "Exec method of bound change event handler for set partitioning / packing / covering constraints\n");*/
9072
9073 cons = (SCIP_CONS*)eventdata;
9074 assert(cons != NULL);
9075
9076 consdata = SCIPconsGetData(cons);
9077 assert(consdata != NULL);
9078
9079 eventtype = SCIPeventGetType(event);
9080
9081 switch( eventtype )
9082 {
9084 consdata->nfixedones++;
9085 break;
9087 consdata->nfixedones--;
9088 break;
9090 consdata->nfixedzeros++;
9091 break;
9093 consdata->nfixedzeros--;
9094 break;
9096 consdata->varsdeleted = TRUE;
9097 break;
9099 if( consdata->merged )
9100 {
9101 SCIP_VAR* var = SCIPeventGetVar(event);
9102
9103 /* this event should only arise during the presolving stage */
9105 assert(var != NULL);
9106
9107 /* one variable was changed to a negated or aggregated variable, so maybe we can merge again */
9108 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED && SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
9109 consdata->merged = FALSE;
9110 }
9111
9112 if( !consdata->existmultaggr )
9113 {
9114 SCIP_VAR* var = SCIPeventGetVar(event);
9115 assert(var != NULL);
9116
9118 consdata->existmultaggr = TRUE;
9119 }
9120 break;
9121 default:
9122 SCIPerrorMessage("invalid event type\n");
9123 return SCIP_INVALIDDATA;
9124 }
9125 assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nvars);
9126 assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nvars);
9127
9128 if( eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED )
9129 {
9130 if( consdata->nfixedones >= 1 || consdata->nfixedzeros >= consdata->nvars - 1 )
9131 {
9132 consdata->presolpropagated = FALSE;
9134 }
9135 else if( (SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE) && (consdata->nfixedzeros >= consdata->nvars - 2) )
9136 {
9137 consdata->presolpropagated = FALSE;
9138 }
9139 }
9140
9141 /*debugMsg(scip, " -> constraint has %d zero-fixed and %d one-fixed of %d variables\n",
9142 consdata->nfixedzeros, consdata->nfixedones, consdata->nvars);*/
9143
9144 return SCIP_OKAY;
9145}
9146
9147
9148
9149
9150/*
9151 * Callback methods of conflict handler
9152 */
9153
9154/** conflict processing method of conflict handler (called when conflict was found) */
9155static
9156SCIP_DECL_CONFLICTEXEC(conflictExecSetppc)
9157{ /*lint --e{715}*/
9158 SCIP_VAR** vars;
9159 int i;
9160
9161 assert(conflicthdlr != NULL);
9162 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
9163 assert(bdchginfos != NULL || nbdchginfos == 0);
9164 assert(result != NULL);
9165
9166 /* don't process already resolved conflicts */
9167 if( resolved )
9168 {
9169 *result = SCIP_DIDNOTRUN;
9170 return SCIP_OKAY;
9171 }
9172
9173 *result = SCIP_DIDNOTFIND;
9174
9175 /* for two (binary) variables we will create a set packing constraint and add the clique information of the conflict is global */
9176 if( nbdchginfos == 2 )
9177 {
9178 SCIP_CONS* cons;
9179 char consname[SCIP_MAXSTRLEN];
9180 SCIP_VAR* twovars[2];
9181
9182 assert(bdchginfos != NULL);
9183
9184 twovars[0] = SCIPbdchginfoGetVar(bdchginfos[0]);
9185
9186 /* we can only treat binary variables */
9187 if( !SCIPvarIsBinary(twovars[0]) )
9188 return SCIP_OKAY;
9189
9190 /* if the variable is fixed to zero in the conflict set, we have to use its negation */
9191 if( SCIPbdchginfoGetNewbound(bdchginfos[0]) < 0.5 )
9192 {
9193 SCIP_CALL( SCIPgetNegatedVar(scip, twovars[0], &twovars[0]) );
9194 }
9195
9196 twovars[1] = SCIPbdchginfoGetVar(bdchginfos[1]);
9197
9198 /* we can only treat binary variables */
9199 if( !SCIPvarIsBinary(twovars[1]) )
9200 return SCIP_OKAY;
9201
9202 /* if the variable is fixed to zero in the conflict set, we have to use its negation */
9203 if( SCIPbdchginfoGetNewbound(bdchginfos[1]) < 0.5 )
9204 {
9205 SCIP_CALL( SCIPgetNegatedVar(scip, twovars[1], &twovars[1]) );
9206 }
9207
9208 /* create a constraint out of the conflict set */
9210 SCIP_CALL( SCIPcreateConsSetpack(scip, &cons, consname, 2, twovars,
9211 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
9212
9213 /* if the constraint gets globally added, we also add the clique information */
9214 if( !SCIPconsIsLocal(cons) )
9215 {
9216 SCIP_Bool infeasible;
9217 int ncliquebdchgs;
9218
9219 SCIP_CALL( SCIPaddClique(scip, twovars, NULL, 2, FALSE, &infeasible, &ncliquebdchgs) );
9220
9221 SCIPdebugMsg(scip, "new clique of conflict constraint %s led to %d fixings\n", consname, ncliquebdchgs);
9222
9223 if( infeasible )
9224 {
9225 SCIPdebugMsg(scip, "new clique of conflict constraint %s led to infeasibility\n", consname);
9226 }
9227 }
9228
9229 /* add conflict to SCIP */
9230 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
9231
9232 *result = SCIP_CONSADDED;
9233
9234 return SCIP_OKAY;
9235 }
9236
9237 /* create array of variables in conflict constraint */
9238 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
9239 for( i = 0; i < nbdchginfos; ++i )
9240 {
9241 assert(bdchginfos != NULL);
9242
9243 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
9244
9245 /* we can only treat binary variables */
9246 if( !SCIPvarIsBinary(vars[i]) )
9247 break;
9248
9249 /* if the variable is fixed to one in the conflict set, we have to use its negation */
9250 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
9251 {
9252 SCIP_CALL( SCIPgetNegatedVar(scip, vars[i], &vars[i]) );
9253 }
9254 }
9255
9256 if( i == nbdchginfos )
9257 {
9258 SCIP_CONS* cons;
9259 char consname[SCIP_MAXSTRLEN];
9260
9261 /* create a constraint out of the conflict set */
9263 SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, consname, nbdchginfos, vars,
9264 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
9265 SCIP_CALL( SCIPaddConsNode(scip, node, cons, validnode) );
9266 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
9267
9268 *result = SCIP_CONSADDED;
9269 }
9270
9271 /* free temporary memory */
9272 SCIPfreeBufferArray(scip, &vars);
9273
9274 return SCIP_OKAY;
9275}
9276
9277
9278
9279
9280/*
9281 * constraint specific interface methods
9282 */
9283
9284/** creates the handler for set partitioning / packing / covering constraints and includes it in SCIP */
9286 SCIP* scip /**< SCIP data structure */
9287 )
9288{
9289 SCIP_CONSHDLRDATA* conshdlrdata;
9290 SCIP_CONSHDLR* conshdlr;
9291 SCIP_EVENTHDLR* eventhdlr;
9292
9293 /* create event handler for bound change events */
9295 eventExecSetppc, NULL) );
9296
9297 /* create conflict handler for setppc constraints */
9299 conflictExecSetppc, NULL) );
9300
9301 /* create constraint handler data */
9302 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
9303
9304 /* include constraint handler */
9307 consEnfolpSetppc, consEnfopsSetppc, consCheckSetppc, consLockSetppc,
9308 conshdlrdata) );
9309 assert(conshdlr != NULL);
9310
9311 /* set non-fundamental callbacks via specific setter functions */
9312 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveSetppc) );
9313 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveSetppc) );
9314 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySetppc, consCopySetppc) );
9315 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSetppc) );
9316 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsSetppc) );
9317 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreSetppc) );
9318 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolSetppc) );
9319 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolSetppc) );
9320 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSetppc) );
9321 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSetppc) );
9322 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSetppc) );
9323 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitSetppc) );
9324 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSetppc) );
9325 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSetppc) );
9327 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSetppc) );
9330 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSetppc) );
9331 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSetppc, consSepasolSetppc, CONSHDLR_SEPAFREQ,
9333 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSetppc) );
9334 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSetppc) );
9335 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphSetppc) );
9336 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphSetppc) );
9337
9338 conshdlrdata->conshdlrlinear = SCIPfindConshdlr(scip,"linear");
9339
9340 if( conshdlrdata->conshdlrlinear != NULL )
9341 {
9342 /* include the linear constraint to setppc constraint upgrade in the linear constraint handler */
9344 }
9345 if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
9346 {
9347 /* notify function that upgrades quadratic constraint to setpacking */
9349 }
9350
9351 /* set partitioning constraint handler parameters */
9353 "constraints/" CONSHDLR_NAME "/npseudobranches",
9354 "number of children created in pseudo branching (0: disable pseudo branching)",
9355 &conshdlrdata->npseudobranches, TRUE, DEFAULT_NPSEUDOBRANCHES, 0, INT_MAX, NULL, NULL) );
9357 "constraints/" CONSHDLR_NAME "/presolpairwise",
9358 "should pairwise constraint comparison be performed in presolving?",
9359 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
9361 "constraints/" CONSHDLR_NAME "/presolusehashing",
9362 "should hash table be used for detecting redundant constraints in advance",
9363 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
9365 "constraints/" CONSHDLR_NAME "/dualpresolving",
9366 "should dual presolving steps be performed?",
9367 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
9369 "constraints/" CONSHDLR_NAME "/cliquelifting",
9370 " should we try to lift variables into other clique constraints, fix variables, aggregate them, and also shrink the amount of variables in clique constraints",
9371 &conshdlrdata->cliquelifting, TRUE, DEFAULT_CLIQUELIFTING, NULL, NULL) );
9373 "constraints/" CONSHDLR_NAME "/addvariablesascliques",
9374 "should we try to generate extra cliques out of all binary variables to maybe fasten redundant constraint detection",
9375 &conshdlrdata->addvariablesascliques, TRUE, DEFAULT_ADDVARIABLESASCLIQUES, NULL, NULL) );
9377 "constraints/" CONSHDLR_NAME "/cliqueshrinking",
9378 "should we try to shrink the number of variables in a clique constraints, by replacing more than one variable by only one",
9379 &conshdlrdata->cliqueshrinking, TRUE, DEFAULT_CLIQUESHRINKING, NULL, NULL) );
9380
9381 return SCIP_OKAY;
9382}
9383
9384/** creates and captures a set partitioning constraint
9385 *
9386 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9387 */
9389 SCIP* scip, /**< SCIP data structure */
9390 SCIP_CONS** cons, /**< pointer to hold the created constraint */
9391 const char* name, /**< name of constraint */
9392 int nvars, /**< number of variables in the constraint */
9393 SCIP_VAR** vars, /**< array with variables of constraint entries */
9394 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
9395 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9396 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
9397 * Usually set to TRUE. */
9398 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
9399 * TRUE for model constraints, FALSE for additional, redundant constraints. */
9400 SCIP_Bool check, /**< should the constraint be checked for feasibility?
9401 * TRUE for model constraints, FALSE for additional, redundant constraints. */
9402 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
9403 * Usually set to TRUE. */
9404 SCIP_Bool local, /**< is constraint only valid locally?
9405 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9406 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
9407 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
9408 * adds coefficients to this constraint. */
9409 SCIP_Bool dynamic, /**< is constraint subject to aging?
9410 * Usually set to FALSE. Set to TRUE for own cuts which
9411 * are separated as constraints. */
9412 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
9413 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9414 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
9415 * if it may be moved to a more global node?
9416 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9417 )
9418{
9419 return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_PARTITIONING,
9420 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
9421}
9422
9423/** creates and captures a set partitioning constraint with all constraint flags set
9424 * to their default values
9425 *
9426 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9427 */
9429 SCIP* scip, /**< SCIP data structure */
9430 SCIP_CONS** cons, /**< pointer to hold the created constraint */
9431 const char* name, /**< name of constraint */
9432 int nvars, /**< number of variables in the constraint */
9433 SCIP_VAR** vars /**< array with variables of constraint entries */
9434 )
9435{
9436 SCIP_CALL( SCIPcreateConsSetpart(scip, cons, name, nvars, vars,
9438
9439 return SCIP_OKAY;
9440}
9441
9442/** creates and captures a set packing constraint
9443 *
9444 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9445 */
9447 SCIP* scip, /**< SCIP data structure */
9448 SCIP_CONS** cons, /**< pointer to hold the created constraint */
9449 const char* name, /**< name of constraint */
9450 int nvars, /**< number of variables in the constraint */
9451 SCIP_VAR** vars, /**< array with variables of constraint entries */
9452 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
9453 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9454 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
9455 * Usually set to TRUE. */
9456 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
9457 * TRUE for model constraints, FALSE for additional, redundant constraints. */
9458 SCIP_Bool check, /**< should the constraint be checked for feasibility?
9459 * TRUE for model constraints, FALSE for additional, redundant constraints. */
9460 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
9461 * Usually set to TRUE. */
9462 SCIP_Bool local, /**< is constraint only valid locally?
9463 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9464 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
9465 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
9466 * adds coefficients to this constraint. */
9467 SCIP_Bool dynamic, /**< is constraint subject to aging?
9468 * Usually set to FALSE. Set to TRUE for own cuts which
9469 * are separated as constraints. */
9470 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
9471 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9472 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
9473 * if it may be moved to a more global node?
9474 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9475 )
9476{
9477 return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_PACKING,
9478 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
9479}
9480
9481/** creates and captures a set packing constraint with all constraint flags set
9482 * to their default values
9483 *
9484 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9485 */
9487 SCIP* scip, /**< SCIP data structure */
9488 SCIP_CONS** cons, /**< pointer to hold the created constraint */
9489 const char* name, /**< name of constraint */
9490 int nvars, /**< number of variables in the constraint */
9491 SCIP_VAR** vars /**< array with variables of constraint entries */
9492 )
9493{
9494 SCIP_CALL( SCIPcreateConsSetpack(scip, cons, name, nvars, vars,
9496
9497 return SCIP_OKAY;
9498}
9499
9500/** creates and captures a set covering constraint
9501 *
9502 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9503 */
9505 SCIP* scip, /**< SCIP data structure */
9506 SCIP_CONS** cons, /**< pointer to hold the created constraint */
9507 const char* name, /**< name of constraint */
9508 int nvars, /**< number of variables in the constraint */
9509 SCIP_VAR** vars, /**< array with variables of constraint entries */
9510 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
9511 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9512 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
9513 * Usually set to TRUE. */
9514 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
9515 * TRUE for model constraints, FALSE for additional, redundant constraints. */
9516 SCIP_Bool check, /**< should the constraint be checked for feasibility?
9517 * TRUE for model constraints, FALSE for additional, redundant constraints. */
9518 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
9519 * Usually set to TRUE. */
9520 SCIP_Bool local, /**< is constraint only valid locally?
9521 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9522 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
9523 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
9524 * adds coefficients to this constraint. */
9525 SCIP_Bool dynamic, /**< is constraint subject to aging?
9526 * Usually set to FALSE. Set to TRUE for own cuts which
9527 * are separated as constraints. */
9528 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
9529 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9530 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
9531 * if it may be moved to a more global node?
9532 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9533 )
9534{
9535 return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_COVERING,
9536 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
9537}
9538
9539/** creates and captures a set covering constraint with all constraint flags set
9540 * to their default values
9541 *
9542 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9543 */
9545 SCIP* scip, /**< SCIP data structure */
9546 SCIP_CONS** cons, /**< pointer to hold the created constraint */
9547 const char* name, /**< name of constraint */
9548 int nvars, /**< number of variables in the constraint */
9549 SCIP_VAR** vars /**< array with variables of constraint entries */
9550 )
9551{
9552 SCIP_CALL( SCIPcreateConsSetcover(scip, cons, name, nvars, vars,
9554
9555 return SCIP_OKAY;
9556}
9557
9558/** adds coefficient in set partitioning / packing / covering constraint */
9560 SCIP* scip, /**< SCIP data structure */
9561 SCIP_CONS* cons, /**< constraint data */
9562 SCIP_VAR* var /**< variable to add to the constraint */
9563 )
9564{
9565 assert(var != NULL);
9566
9567 /*debugMsg(scip, "adding variable <%s> to setppc constraint <%s>\n",
9568 SCIPvarGetName(var), SCIPconsGetName(cons));*/
9569
9570 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9571 {
9572 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9573 return SCIP_INVALIDDATA;
9574 }
9575
9576 SCIP_CALL( addCoef(scip, cons, var) );
9577
9578 return SCIP_OKAY;
9579}
9580
9581/** gets number of variables in set partitioning / packing / covering constraint */
9583 SCIP* scip, /**< SCIP data structure */
9584 SCIP_CONS* cons /**< constraint data */
9585 )
9586{
9587 SCIP_CONSDATA* consdata;
9588
9589 assert(scip != NULL);
9590
9591 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9592 {
9593 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9594 SCIPABORT();
9595 return -1; /*lint !e527*/
9596 }
9597
9598 consdata = SCIPconsGetData(cons);
9599 assert(consdata != NULL);
9600
9601 return consdata->nvars;
9602}
9603
9604/** gets array of variables in set partitioning / packing / covering constraint */
9606 SCIP* scip, /**< SCIP data structure */
9607 SCIP_CONS* cons /**< constraint data */
9608 )
9609{
9610 SCIP_CONSDATA* consdata;
9611
9612 assert(scip != NULL);
9613
9614 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9615 {
9616 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9617 SCIPABORT();
9618 return NULL; /*lint !e527*/
9619 }
9620
9621 consdata = SCIPconsGetData(cons);
9622 assert(consdata != NULL);
9623
9624 return consdata->vars;
9625}
9626
9627/** gets type of set partitioning / packing / covering constraint */
9629 SCIP* scip, /**< SCIP data structure */
9630 SCIP_CONS* cons /**< constraint data */
9631 )
9632{
9633 SCIP_CONSDATA* consdata;
9634
9635 assert(scip != NULL);
9636
9637 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9638 {
9639 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9640 SCIPABORT();
9641 }
9642
9643 consdata = SCIPconsGetData(cons);
9644 assert(consdata != NULL);
9645
9646 return (SCIP_SETPPCTYPE)(consdata->setppctype);
9647}
9648
9649/** gets the dual solution of the set partitioning / packing / covering constraint in the current LP */
9651 SCIP* scip, /**< SCIP data structure */
9652 SCIP_CONS* cons /**< constraint data */
9653 )
9654{
9655 SCIP_CONSDATA* consdata;
9656
9657 assert(scip != NULL);
9658
9659 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9660 {
9661 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9662 SCIPABORT();
9663 return SCIP_INVALID; /*lint !e527*/
9664 }
9665
9666 consdata = SCIPconsGetData(cons);
9667 assert(consdata != NULL);
9668
9669 if( consdata->row != NULL )
9670 return SCIProwGetDualsol(consdata->row);
9671 else
9672 return 0.0;
9673}
9674
9675/** gets the dual Farkas value of the set partitioning / packing / covering constraint in the current infeasible LP */
9677 SCIP* scip, /**< SCIP data structure */
9678 SCIP_CONS* cons /**< constraint data */
9679 )
9680{
9681 SCIP_CONSDATA* consdata;
9682
9683 assert(scip != NULL);
9684
9685 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9686 {
9687 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9688 SCIPABORT();
9689 return SCIP_INVALID; /*lint !e527*/
9690 }
9691
9692 consdata = SCIPconsGetData(cons);
9693 assert(consdata != NULL);
9694
9695 if( consdata->row != NULL )
9696 return SCIProwGetDualfarkas(consdata->row);
9697 else
9698 return 0.0;
9699}
9700
9701/** returns the linear relaxation of the given set partitioning / packing / covering constraint; may return NULL if no
9702 * LP row was yet created; the user must not modify the row!
9703 */
9705 SCIP* scip, /**< SCIP data structure */
9706 SCIP_CONS* cons /**< constraint data */
9707 )
9708{
9709 SCIP_CONSDATA* consdata;
9710
9711 assert(scip != NULL);
9712
9713 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9714 {
9715 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9716 SCIPABORT();
9717 return NULL; /*lint !e527*/
9718 }
9719
9720 consdata = SCIPconsGetData(cons);
9721 assert(consdata != NULL);
9722
9723 return consdata->row;
9724}
9725
9726/** returns current number of variables fixed to one in the constraint */
9728 SCIP* scip, /**< SCIP data structure */
9729 SCIP_CONS* cons /**< constraint data */
9730 )
9731{
9732 SCIP_CONSDATA* consdata;
9733
9734 assert(scip != NULL);
9735
9736 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9737 {
9738 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9739 SCIPABORT();
9740 return -1; /*lint !e527*/
9741 }
9742
9743 consdata = SCIPconsGetData(cons);
9744 assert(consdata != NULL);
9745
9746 return consdata->nfixedones;
9747}
9748
9749
9750/** returns current number of variables fixed to zero in the constraint */
9752 SCIP* scip, /**< SCIP data structure */
9753 SCIP_CONS* cons /**< constraint data */
9754 )
9755{
9756 SCIP_CONSDATA* consdata;
9757
9758 assert(scip != NULL);
9759
9760 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9761 {
9762 SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9763 SCIPABORT();
9764 return -1; /*lint !e527*/
9765 }
9766
9767 consdata = SCIPconsGetData(cons);
9768 assert(consdata != NULL);
9769
9770 return consdata->nfixedzeros;
9771}
9772
9773/** cleans up (multi-)aggregations and fixings from setppc constraints */
9775 SCIP* scip, /**< SCIP data structure */
9776 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
9777 SCIP_Bool* infeasible, /**< pointer to return whether problem was detected to be infeasible */
9778 int* naddconss, /**< pointer to count number of added (linear) constraints */
9779 int* ndelconss, /**< pointer to count number of deleted (setppc) constraints */
9780 int* nchgcoefs, /**< pointer to count number of changed coefficients */
9781 int* nfixedvars /**< pointer to count number of fixed variables */
9782 )
9783{
9784 SCIP_CONSHDLR* conshdlr;
9785 SCIP_CONS** conss;
9786 int nconss;
9787 int i;
9788
9789 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
9790 if( conshdlr == NULL )
9791 return SCIP_OKAY;
9792
9793 assert(naddconss != NULL);
9794 assert(ndelconss != NULL);
9795 assert(nfixedvars != NULL);
9796 assert(infeasible != NULL);
9797 *infeasible = FALSE;
9798
9799 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
9800 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
9801
9802 /* loop backwards since then deleted constraints do not interfere with the loop */
9803 for( i = nconss - 1; i >= 0; --i )
9804 {
9805 SCIP_CONS* cons = conss[i];
9806
9807 SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, infeasible) );
9808
9809 if( *infeasible )
9810 break;
9811
9812 if( SCIPconsIsDeleted(cons) )
9813 continue;
9814
9815 /* merging unmerged constraints */
9816 SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, infeasible) );
9817
9818 if( *infeasible )
9819 break;
9820 }
9821
9822 return SCIP_OKAY;
9823}
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:8845
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:7530
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:9002
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:9024
#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:7058
#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:8151
#define CONSHDLR_PROP_TIMING
Definition: cons_setppc.c:83
static SCIP_DECL_CONSACTIVE(consActiveSetppc)
Definition: cons_setppc.c:8742
#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:7155
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:7746
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:7789
static SCIP_DECL_CONFLICTEXEC(conflictExecSetppc)
Definition: cons_setppc.c:9156
#define CONSHDLR_MAXPREROUNDS
Definition: cons_setppc.c:77
static SCIP_DECL_CONSCOPY(consCopySetppc)
Definition: cons_setppc.c:8858
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:8620
#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:6944
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:7598
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:8338
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
Definition: cons_setppc.c:7444
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:8161
#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:7679
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:5647
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_setppc.c:98
static SCIP_DECL_CONSENFOLP(consEnfolpSetppc)
Definition: cons_setppc.c:8141
static SCIP_DECL_CONSDELETE(consDeleteSetppc)
Definition: cons_setppc.c:7643
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:8909
static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSetppc)
Definition: cons_setppc.c:9039
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:9060
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:5548
static SCIP_DECL_SORTPTRCOMP(setppcConssSort)
Definition: cons_setppc.c:239
static SCIP_DECL_CONSEXITPRE(consExitpreSetppc)
Definition: cons_setppc.c:7577
#define CONSHDLR_PROPFREQ
Definition: cons_setppc.c:74
static SCIP_DECL_CONSEXITSOL(consExitsolSetppc)
Definition: cons_setppc.c:7615
static SCIP_DECL_LINCONSUPGD(linconsUpgdSetppc)
Definition: cons_setppc.c:7223
static SCIP_DECL_CONSDEACTIVE(consDeactiveSetppc)
Definition: cons_setppc.c:8779
#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:6986
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_setppc.c:708
static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSetppc)
Definition: cons_setppc.c:9048
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:8827
#define CONSHDLR_EAGERFREQ
Definition: cons_setppc.c:75
static SCIP_DECL_CONSINIT(consInitSetppc)
Definition: cons_setppc.c:7551
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:7728
#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:7304
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:6656
static SCIP_DECL_CONSCHECK(consCheckSetppc)
Definition: cons_setppc.c:8223
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:7514
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:8274
#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:6449
#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:5465
#define EVENTHDLR_NAME
Definition: cons_setppc.c:88
static SCIP_DECL_CONSLOCK(consLockSetppc)
Definition: cons_setppc.c:8702
static SCIP_RETCODE removeRedundantCons(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1, int *ndelconss)
Definition: cons_setppc.c:6558
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:6584
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:6772
Constraint handler for the set partitioning / packing / covering constraints .
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#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:242
#define SCIP_Real
Definition: def.h:172
#define ABS(x)
Definition: def.h:234
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:373
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:9774
SCIP_RETCODE SCIPcreateConsBasicSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
Definition: cons_setppc.c:9428
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:9751
SCIP_ROW * SCIPgetRowSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9704
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9582
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:9446
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9605
SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
int SCIPgetNFixedonesSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9727
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:9544
SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_setppc.c:9559
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:9628
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:9388
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:9504
SCIP_Real SCIPgetLhsNonlinear(SCIP_CONS *cons)
SCIP_Real SCIPgetDualsolSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9650
SCIP_RETCODE SCIPcreateConsBasicSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
Definition: cons_setppc.c:9486
SCIP_Real SCIPgetDualfarkasSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9676
@ 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:9285
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:3111
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3077
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3426
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3195
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3442
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:11215
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:10182
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:4664
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:4235
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4621
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:4205
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:4225
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:4678
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:4601
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:8252
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:8232
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8481
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8242
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8391
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8421
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8351
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8531
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8615
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8411
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8283
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:8441
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8461
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8222
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:8471
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:8651
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:8501
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8401
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8491
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:4204
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:4119
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:4164
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
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:1956
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:1773
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:1422
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2167
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17358
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17556
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17345
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:11912
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:17648
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:17902
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17756
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17607
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:17546
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:17956
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18152
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17569
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:17934
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:12226
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17592
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18096
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17766
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:17427
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:18688
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:18142
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17582
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17912
int SCIPgetNCliques(SCIP *scip)
Definition: scip_var.c:7680
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18086
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:11950
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:12318
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:11483
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18678
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:10880
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10869
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:5741
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:54
@ 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