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