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