SCIP Doxygen Documentation
Loading...
Searching...
No Matches
cons_linking.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file cons_linking.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief constraint handler for linking constraints
28 * @author Stefan Heinz
29 * @author Jens Schulz
30 *
31 * The constraints handler stores linking constraints between a linking variable (integer or continuous) and an array of binary variables. Such
32 * a linking constraint has the form:
33 *
34 * linkvar = sum_{i=1}^n {vals[i] * binvars[i]}
35 *
36 * with the additional side condition that exactly one binary variable has to be one (set partitioning condition).
37 *
38 * This constraint can be created only with the linking variable if it is an integer variable. In this case the binary variables are only created on
39 * demand. That is, whenever someone asks for the binary variables. Therefore, such constraints can be used to get a
40 * "binary representation" of the domain of the linking variable which will be dynamically created.
41 *
42 *
43 * @todo add pairwise comparison of constraints in presolving (fast hash table version and complete pairwise comparison)
44 * @todo in case the integer variable is set to lower or upper bound it follows that only the corresponding binary
45 * variable has a positive value which is one, this can be used to fasten the checking routine
46 */
47
48/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
49
51#include "scip/cons_linear.h"
52#include "scip/cons_linking.h"
53#include "scip/cons_setppc.h"
54#include "scip/pub_cons.h"
55#include "scip/pub_event.h"
56#include "scip/pub_lp.h"
57#include "scip/pub_message.h"
58#include "scip/pub_misc.h"
59#include "scip/pub_misc_sort.h"
60#include "scip/pub_var.h"
61#include "scip/scip_conflict.h"
62#include "scip/scip_cons.h"
63#include "scip/scip_copy.h"
64#include "scip/scip_cut.h"
65#include "scip/scip_event.h"
66#include "scip/scip_general.h"
67#include "scip/scip_lp.h"
68#include "scip/scip_mem.h"
69#include "scip/scip_message.h"
70#include "scip/scip_nlp.h"
71#include "scip/scip_numerics.h"
72#include "scip/scip_param.h"
73#include "scip/scip_prob.h"
74#include "scip/scip_probing.h"
75#include "scip/scip_sol.h"
76#include "scip/scip_tree.h"
77#include "scip/scip_var.h"
78#include "scip/symmetry_graph.h"
80#include <ctype.h>
81
82
83/* constraint handler properties */
84#define CONSHDLR_NAME "linking"
85#define CONSHDLR_DESC "linking constraint x = sum_{i=1}^{n} c_i*y_i, y1+...+yn = 1, x real, y's binary"
86
87#define EVENTHDLR_NAME "linking"
88#define EVENTHDLR_DESC "event handler for linking constraints"
89
90#define CONSHDLR_SEPAPRIORITY 750000 /**< priority of the constraint handler for separation */
91#define CONSHDLR_ENFOPRIORITY -2050000 /**< priority of the constraint handler for constraint enforcing */
92#define CONSHDLR_CHECKPRIORITY -750000 /**< priority of the constraint handler for checking feasibility */
93#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
94#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
95#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation, propagation and enforcement, -1 for no eager evaluations, 0 for first only */
96#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
97#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
98#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
99#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
100
101#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
102#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
103
104
105#define HASHSIZE_BINVARSCONS 500 /**< minimal size of hash table in linking constraint handler */
106#define DEFAULT_LINEARIZE FALSE /**< should the linking constraint be linearize after the binary variable are created */
107
108/*
109 * Data structures
110 */
111
112/** constraint data for linking constraints */
113struct SCIP_ConsData
114{
115 SCIP_VAR* linkvar; /**< continuous variable which is linked */
116 SCIP_VAR** binvars; /**< binary variables */
117 SCIP_Real* vals; /**< coefficients */
118 SCIP_ROW* row1; /**< LP row for the linking itself */
119 SCIP_ROW* row2; /**< LP row ensuring the set partitioning condition of the binary variables */
120 SCIP_NLROW* nlrow1; /**< NLP row for the linking itself */
121 SCIP_NLROW* nlrow2; /**< NLP row ensuring the set partitioning condition of the binary variables */
122 int nbinvars; /**< number of binary variables */
123 int sizebinvars; /**< size of the binary variable array */
124 int nfixedzeros; /**< current number of variables fixed to zero in the constraint */
125 int nfixedones; /**< current number of variables fixed to one in the constraint */
126 int firstnonfixed; /**< index of first locally non-fixed binary variable in binvars array */
127 int lastnonfixed; /**< index of last locally non-fixed binary variable in binvars array */
128 unsigned int cliqueadded:1; /**< was the set partitioning condition already added as clique? */
129 unsigned int sorted:1; /**< are the coefficients of the binary variables are sorted in non-decreasing order */
130};
131
132/** constraint handler data */
133struct SCIP_ConshdlrData
134{
135 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events on binary variables */
136 SCIP_HASHMAP* varmap; /**< hash map mapping a linking variable to its linking constraint */
137 SCIP_Bool linearize; /**< should the linking constraint be linearize after the binary variable are created */
138};
139
140/*
141 * Local methods
142 */
143
144/** returns for a given linking variable the corresponding hash map key */
145static
147 SCIP_VAR* var /**< variable to get the hash map key for */
148 )
149{
150 /* return the unique variable index + 1 */
151 return (void*)(size_t)(SCIPvarGetIndex(var) + 1); /*lint !e571 !e776*/
152}
153
154/* sort binary variable in non-decreasing order w.r.t. coefficients */
155static
157 SCIP_CONSDATA* consdata /**< linking constraint data */
158 )
159{
160 if( consdata->sorted )
161 return;
162
163 /* sort binary variable in non-decreasing order w.r.t. coefficients */
164 SCIPsortRealPtr(consdata->vals, (void**)consdata->binvars, consdata->nbinvars);
165
166 consdata->sorted = TRUE;
167}
168
169
170/** installs rounding locks for the binary variables in the given linking constraint */
171static
173 SCIP* scip, /**< SCIP data structure */
174 SCIP_CONS* cons, /**< linking constraint */
175 SCIP_VAR** binvars, /**< binary variables */
176 int nbinvars /**< number of binary variables */
177 )
178{
179 int b;
180
181 for( b = 0; b < nbinvars; ++b )
182 {
183 SCIP_CALL( SCIPlockVarCons(scip, binvars[b], cons, TRUE, TRUE) );
184 }
185
186 return SCIP_OKAY;
187}
188
189/** creates constraint handler data for the linking constraint handler */
190static
192 SCIP* scip, /**< SCIP data structure */
193 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
194 SCIP_EVENTHDLR* eventhdlr /**< event handler */
195 )
196{
197 assert(scip != NULL);
198 assert(conshdlrdata != NULL);
199 assert(eventhdlr != NULL);
200
201 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
202
203 /* create hash map */
204 (*conshdlrdata)->varmap = NULL;
205
206 /* set event handler for bound change events on binary variables */
207 (*conshdlrdata)->eventhdlr = eventhdlr;
208
209 return SCIP_OKAY;
210}
211
212/** frees constraint handler data for linking constraint handler */
213static
215 SCIP* scip, /**< SCIP data structure */
216 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
217 )
218{
219 assert(conshdlrdata != NULL);
220 assert(*conshdlrdata != NULL);
221
222 /* free hash map */
223 if( (*conshdlrdata)->varmap != NULL )
224 SCIPhashmapFree(&(*conshdlrdata)->varmap);
225
226 /* free memory of constraint handler data */
227 SCIPfreeBlockMemory(scip, conshdlrdata);
228}
229
230/** prints linking constraint to file stream */
231static
233 SCIP* scip, /**< SCIP data structure */
234 SCIP_CONSDATA* consdata, /**< linking constraint data */
235 FILE* file /**< output file (or NULL for standard output) */
236 )
237{
238 SCIP_VAR** binvars;
239 SCIP_VAR* linkvar;
240 int nbinvars;
241
242 assert(scip != NULL);
243 assert(consdata != NULL);
244
245 linkvar = consdata->linkvar;
246 binvars = consdata->binvars;
247 nbinvars = consdata->nbinvars;
248
249 assert(linkvar != NULL);
250 assert(binvars != NULL || nbinvars == 0);
251
252 /* print linking variable */
253 SCIP_CALL( SCIPwriteVarName(scip, file, linkvar, FALSE) );
254
255 SCIPinfoMessage(scip, file, " = ");
256
257 if( nbinvars == 0 )
258 {
259 SCIPinfoMessage(scip, file, " no binary variables yet");
260 }
261 else
262 {
263 assert(binvars != NULL);
264
265 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, binvars, consdata->vals, nbinvars, FALSE) );
266 }
267
268 return SCIP_OKAY;
269}
270
271/** catches events for variable at given position */
272static
274 SCIP* scip, /**< SCIP data structure */
275 SCIP_CONSDATA* consdata, /**< linking constraint data */
276 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
277 int pos /**< array position of variable to catch bound change events for */
278 )
279{
280 SCIP_VAR* var;
281
282 assert(consdata != NULL);
283 assert(eventhdlr != NULL);
284 assert(0 <= pos && pos < consdata->nbinvars);
285 assert(consdata->binvars != NULL);
286
287 var = consdata->binvars[pos];
288 assert(var != NULL);
289
290 /* catch bound change events on variable */
291 /**@todo do we have to add the event SCIP_EVENTTYPE_VARFIXED? */
293
294 /* update the fixed variables counters for this variable */
295 if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
296 consdata->nfixedzeros++;
297 else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
298 consdata->nfixedones++;
299
300 return SCIP_OKAY;
301}
302
303/** drops events for variable at given position */
304static
306 SCIP* scip, /**< SCIP data structure */
307 SCIP_CONSDATA* consdata, /**< linking constraint data */
308 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
309 int pos /**< array position of variable to catch bound change events for */
310 )
311{
312 SCIP_VAR* var;
313
314 assert(consdata != NULL);
315 assert(eventhdlr != NULL);
316 assert(0 <= pos && pos < consdata->nbinvars);
317 assert(consdata->binvars != NULL);
318
319 var = consdata->binvars[pos];
320 assert(var != NULL);
321
322 /* drop events on variable */
324
325 /* update the fixed variables counters for this variable */
326 if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
327 consdata->nfixedzeros--;
328 else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
329 consdata->nfixedones--;
330
331 return SCIP_OKAY;
332}
333
334/** catches bound change events for all variables in transformed linking constraint */
335static
337 SCIP* scip, /**< SCIP data structure */
338 SCIP_CONSDATA* consdata, /**< linking constraint data */
339 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
340 )
341{
342 int i;
343
344 assert(consdata != NULL);
345
346 /* author bzfhende
347 *
348 * TODO should we catch events even in the trivial case of only 1 binary variable
349 */
350
351 /* catch event for every single variable */
352 for( i = 0; i < consdata->nbinvars; ++i )
353 {
354 SCIP_CALL( catchEvent(scip, consdata, eventhdlr, i) );
355 }
356
357 return SCIP_OKAY;
358}
359
360/** drops bound change events for all variables in transformed linking constraint */
361static
363 SCIP* scip, /**< SCIP data structure */
364 SCIP_CONSDATA* consdata, /**< linking constraint data */
365 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
366 )
367{
368 int i;
369
370 assert(consdata != NULL);
371
372 /* author bzfhende
373 *
374 * TODO drop the events even in the trivial case nbinvars == 1?
375 */
376
377 /* drop event of every single variable */
378 for( i = 0; i < consdata->nbinvars; ++i )
379 {
380 SCIP_CALL( dropEvent(scip, consdata, eventhdlr, i) );
381 }
382
383 return SCIP_OKAY;
384}
385
386/** linearize the given linking constraint into a set partitioning constraint for the binary variables and a linear
387 * constraint for the linking between the linking variable and the binary variables */
388static
390 SCIP* scip, /**< SCIP data structure */
391 SCIP_CONS* cons, /**< linking constraint */
392 SCIP_CONSDATA* consdata /**< linking constraint data */
393 )
394{
395 SCIP_CONS* lincons;
396 int b;
397
398 SCIPdebugMsg(scip, "linearized linking constraint <%s>\n", SCIPconsGetName(cons));
399
400 /* create set partitioning constraint for the binary variables */
401 SCIP_CALL( SCIPcreateConsSetpart(scip, &lincons, SCIPconsGetName(cons), consdata->nbinvars, consdata->binvars,
405 SCIP_CALL( SCIPaddCons(scip, lincons) );
406 SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
407
408 /* create linear constraint for the linking between the binary variables and the linking variable */
409 SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons), 0, NULL, NULL, 0.0, 0.0,
413
414 for( b = 0; b < consdata->nbinvars; ++b )
415 {
416 SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->binvars[b], consdata->vals[b]) );
417 }
418 SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->linkvar, -1.0) );
419
420 SCIP_CALL( SCIPaddCons(scip, lincons) );
421 SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
422
423 return SCIP_OKAY;
424}
425
426/** creates the binary variables */
427static
429 SCIP* scip, /**< SCIP data structure */
430 SCIP_CONS* cons, /**< linking constraint */
431 SCIP_CONSDATA* consdata, /**< linking constraint data */
432 SCIP_EVENTHDLR* eventhdlr, /**< event handler for bound change events on binary variables */
433 SCIP_Bool linearize /**< should the linking constraint be linearized */
434 )
435{
436 SCIP_VAR* linkvar;
437 SCIP_VAR* binvar;
438 int lb;
439 int ub;
440 char name[SCIP_MAXSTRLEN];
441 int nbinvars;
442 int b;
443
444 assert(scip != NULL);
445 assert(consdata != NULL);
446 assert(consdata->nbinvars == 0);
447 assert(consdata->binvars == NULL);
448 assert(SCIPvarIsIntegral(consdata->linkvar));
449 assert(!SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->linkvar)));
450 assert(!SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->linkvar)));
451
452 SCIPdebugMsg(scip, "create binary variables for linking variable <%s>\n", SCIPvarGetName(consdata->linkvar));
453
454 linkvar = consdata->linkvar;
457
458 nbinvars = ub - lb + 1;
459 assert(nbinvars > 0);
460
461 /* allocate block memory for the binary variables */
462 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->binvars, nbinvars) );
463 /* allocate block memory for the binary variables */
464 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vals, nbinvars) );
465 consdata->sizebinvars = nbinvars;
466
467 /* check if the linking variable is fixed */
468 if( nbinvars == 1 )
469 {
470 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s[%d]", SCIPvarGetName(linkvar), lb);
471
472 /* creates and captures a fixed binary variables */
473 SCIP_CALL( SCIPcreateVar(scip, &binvar, name, 1.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
474 FALSE, TRUE, NULL, NULL, NULL, NULL, NULL) );
475 SCIP_CALL( SCIPaddVar(scip, binvar) );
476
477 consdata->binvars[0] = binvar;
478 consdata->vals[0] = lb;
479 }
480 else
481 {
482 for( b = 0; b < nbinvars; ++b)
483 {
484 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s[%d]", SCIPvarGetName(linkvar), lb + b);
485
486 /* creates and captures variables */
487 SCIP_CALL( SCIPcreateVar(scip, &binvar, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
488 TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
489
490 /* add variable to the problem */
491 SCIP_CALL( SCIPaddVar(scip, binvar) );
492 consdata->binvars[b] = binvar;
493 consdata->vals[b] = lb + b;
494 }
495 }
496
497 consdata->nbinvars = nbinvars;
498 consdata->lastnonfixed = nbinvars - 1;
499
500 assert(consdata->nfixedzeros == 0);
501 assert(consdata->nfixedones == 0);
502
504 {
505 /* (rounding) lock binary variable */
506 SCIP_CALL( lockRounding(scip, cons, consdata->binvars, consdata->nbinvars) );
507
508 /* catch bound change events of variables */
509 SCIP_CALL( catchAllEvents(scip, consdata, eventhdlr) );
510
511 if( nbinvars > 1 )
512 {
513 if( linearize )
514 {
515 SCIP_CALL( consdataLinearize(scip, cons, consdata) );
516 }
517 else
518 {
519 /* enable constraint */
520 SCIP_CALL( SCIPenableCons(scip, cons) );
521 }
522 }
523 }
524
525 return SCIP_OKAY;
526}
527
528/** creates consdata */
529static
531 SCIP* scip, /**< SCIP data structure */
532 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
533 SCIP_CONSDATA** consdata, /**< pointer to constraint data */
534 SCIP_VAR* linkvar, /**< linking variable which is linked */
535 SCIP_VAR** binvars, /**< binary variables */
536 SCIP_Real* vals, /**< coefficients of the binary variables */
537 int nbinvars /**< number of binary starting variables */
538 )
539{
540 int v;
541
542 assert(scip!= NULL);
543 assert(consdata != NULL);
544 assert(linkvar != NULL);
545 assert(binvars != NULL || nbinvars == 0);
546 assert(SCIPvarIsIntegral(linkvar) || nbinvars > 0);
547
548 /* allocate memory for consdata */
549 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
550
551 (*consdata)->linkvar = linkvar;
552 (*consdata)->nbinvars = nbinvars;
553 (*consdata)->sizebinvars = nbinvars;
554 (*consdata)->row1 = NULL;
555 (*consdata)->row2 = NULL;
556 (*consdata)->nlrow1 = NULL;
557 (*consdata)->nlrow2 = NULL;
558 (*consdata)->cliqueadded = FALSE;
559
560 /* initialize constraint state */
561 (*consdata)->sorted = FALSE;
562 (*consdata)->firstnonfixed = 0;
563 (*consdata)->lastnonfixed = nbinvars - 1;
564 (*consdata)->nfixedzeros = 0;
565 (*consdata)->nfixedones = 0;
566
567 if( nbinvars == 0 )
568 {
569 (*consdata)->binvars = NULL;
570 (*consdata)->vals = NULL;
571 }
572 else
573 {
574 /* copy binary variable array */
575 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->binvars, binvars, nbinvars) );
576
577 /* copy coefficients */
578 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, vals, nbinvars) );
579 }
580
581 /* get transformed variable, if we are in the transformed problem */
583 {
584 if( nbinvars > 0 )
585 {
586 SCIP_CALL( SCIPgetTransformedVars(scip, nbinvars, (*consdata)->binvars, (*consdata)->binvars) );
587
588 /* catch bound change events of variables */
589 SCIP_CALL( catchAllEvents(scip, *consdata, eventhdlr) );
590 }
591
592 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->linkvar, &(*consdata)->linkvar) );
593 }
594
595 /* author bzfhende
596 *
597 * TODO do we need to forbid multi-aggregations? This was only needed if we substitute and resubstitute linking
598 * variables into linear constraints.
599 */
600
601 /* capture variables */
602 for( v = 0; v < nbinvars; ++v )
603 {
604 assert((*consdata)->binvars[v] != NULL);
605 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->binvars[v]) );
606 }
607 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->linkvar) );
608
609 return SCIP_OKAY;
610}
611
612
613/** free consdata */
614static
616 SCIP* scip, /**< SCIP data structure */
617 SCIP_CONSDATA** consdata /**< pointer to consdata */
618 )
619{
620 int v;
621
622 assert(consdata != NULL);
623 assert(*consdata != NULL);
624 assert((*consdata)->nbinvars == 0 || (*consdata)->binvars != NULL);
625
626 /* release the rows */
627 if( (*consdata)->row1 != NULL )
628 {
629 assert((*consdata)->row2 != NULL);
630
631 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row1) );
632 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row2) );
633 }
634
635 /* release the nlrows */
636 if( (*consdata)->nlrow1 != NULL )
637 {
638 assert((*consdata)->nlrow2 != NULL);
639
640 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow1) );
641 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow2) );
642 }
643
644 /* capture variables */
645 for( v = 0; v < (*consdata)->nbinvars; ++v )
646 {
647 assert((*consdata)->binvars[v] != NULL);
648 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->binvars[v]) );
649 }
650 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->linkvar) );
651
652 /* free binary variable array */
653 if( (*consdata)->sizebinvars > 0 )
654 {
655 /* if constraint belongs to transformed problem space, drop bound change events on variables */
656 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vals, (*consdata)->sizebinvars);
657 SCIPfreeBlockMemoryArray(scip, &(*consdata)->binvars, (*consdata)->sizebinvars);
658 }
659
660 /* check if the fixed counters are reset */
661 assert((*consdata)->nfixedzeros == 0);
662 assert((*consdata)->nfixedones == 0);
663
664 /* free constraint data */
665 SCIPfreeBlockMemory(scip, consdata);
666
667 return SCIP_OKAY;
668}
669
670
671/** analyzes conflicting assignment on given constraint where reason comes from the linking variable lower or upper
672 * bound
673 */
674static
676 SCIP* scip, /**< SCIP data structure */
677 SCIP_CONS* cons, /**< linking constraint to be processed */
678 SCIP_VAR* linkvar, /**< linking variable */
679 SCIP_VAR* binvar, /**< binary variable is the reason */
680 SCIP_Bool lblinkvar, /**< lower bound of linking variable is the reason */
681 SCIP_Bool ublinkvar /**< upper bound of linking variable is the reason */
682 )
683{
684 assert(scip != NULL);
685
686 /* conflict analysis can only be applied in solving stage and if it is turned on */
688 return SCIP_OKAY;
689
690 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
692
693 if( lblinkvar )
694 {
695 assert(linkvar != NULL);
696 SCIP_CALL( SCIPaddConflictLb(scip, linkvar, NULL) );
697 }
698
699 if( ublinkvar )
700 {
701 assert(linkvar != NULL);
702 SCIP_CALL( SCIPaddConflictUb(scip, linkvar, NULL) );
703 }
704
705 if( binvar != NULL )
706 {
708 }
709
710 /* analyze the conflict */
712
713 return SCIP_OKAY;
714}
715
716/* author bzfhende
717 *
718 * TODO check if the method below produces valid results even if the variable is continuous
719 */
720
721/** fix linking variable to the value of the binary variable at pos */
722static
724 SCIP* scip, /**< SCIP data structure */
725 SCIP_CONS* cons, /**< linking constraint to be processed */
726 int pos, /**< position of binary variable */
727 SCIP_Bool* cutoff /**< pointer to store TRUE, if the node can be cut off */
728 )
729{
730 SCIP_CONSDATA* consdata;
731 SCIP_VAR* linkvar;
732 SCIP_Bool infeasible;
733 SCIP_Bool tightened;
734 SCIP_Real coef;
735
736 consdata = SCIPconsGetData(cons);
737 assert(consdata != NULL);
738
739 linkvar = consdata->linkvar;
740 coef = consdata->vals[pos];
741
742 /* change lower bound of the linking variable */
743 SCIP_CALL( SCIPinferVarLbCons(scip, linkvar, coef, cons, pos, TRUE, &infeasible, &tightened) );
744
745 if( infeasible )
746 {
747 assert(coef > SCIPvarGetUbLocal(linkvar));
748 assert(coef >= SCIPvarGetLbLocal(linkvar));
749
750 SCIP_CALL( analyzeConflict(scip, cons, linkvar, consdata->binvars[pos], FALSE, TRUE) );
751
752 *cutoff = TRUE;
753 return SCIP_OKAY;
754 }
755 assert(SCIPisFeasLE(scip, coef, SCIPvarGetUbLocal(linkvar)));
756
757 /* change upper bound of the integer variable */
758 SCIP_CALL( SCIPinferVarUbCons(scip, linkvar, coef, cons, pos, TRUE, &infeasible, &tightened) );
759
760 if( infeasible )
761 {
762 assert(coef < SCIPvarGetLbLocal(linkvar));
763 assert(coef <= SCIPvarGetUbLocal(linkvar));
764
765 SCIP_CALL( analyzeConflict(scip, cons, linkvar, consdata->binvars[pos], TRUE, FALSE) );
766
767 *cutoff = TRUE;
768 return SCIP_OKAY;
769 }
770
772
773 return SCIP_OKAY;
774}
775
776/** checks constraint for violation from the local bound of the linking variable, applies fixings to the binary
777 * variables if possible
778 */
779static
781 SCIP* scip, /**< SCIP data structure */
782 SCIP_CONS* cons, /**< linking constraint to be processed */
783 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
784 int* nchgbds, /**< pointer to store the number of changes (foxed) variable bounds */
785 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
786 )
787{
788 SCIP_CONSDATA* consdata;
789 SCIP_VAR** binvars;
790 SCIP_VAR* linkvar;
791 SCIP_Real* vals;
792 SCIP_Real lb;
793 SCIP_Real ub;
794 int nbinvars;
795 int b;
796 SCIP_Bool infeasible;
797 SCIP_Bool tightened;
798
799 assert(cons != NULL);
800 assert(SCIPconsGetHdlr(cons) != NULL);
801 assert(cutoff != NULL);
802 assert(nchgbds != NULL);
803 assert(mustcheck != NULL);
804
806
807 consdata = SCIPconsGetData(cons);
808 assert(consdata != NULL);
809
810 /* ensure that the binary variables are sorted in non-decreasing order w.r.t. their coefficients */
811 consdataSort(consdata);
812
813 nbinvars = consdata->nbinvars;
814
815 /* in case there is only at most one binary variables, the constraints should already be disabled */
816 assert(nbinvars > 1);
817
818 /* if more than one binary variable is fixed to one or at least nbinvars minus one variable are fixed to zero */
819 if( consdata->nfixedones > 0 || consdata->nfixedzeros >= nbinvars-1 )
820 return SCIP_OKAY;
821
822 linkvar = consdata->linkvar;
823 assert(linkvar != NULL);
824
825 binvars = consdata->binvars;
826 vals = consdata->vals;
827
828 lb = SCIPvarGetLbLocal(linkvar);
829 ub = SCIPvarGetUbLocal(linkvar);
830
831 assert(lb <= ub);
832
833#ifndef NDEBUG
834 /* check that the first variable are locally fixed to zero */
835 for( b = 0; b < consdata->firstnonfixed; ++b )
836 assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
837
838 /* check that the last variable are locally fixed to zero */
839 for( b = consdata->lastnonfixed + 1; b < nbinvars; ++b )
840 assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
841#endif
842
843 for( b = consdata->firstnonfixed; b < nbinvars; ++b )
844 {
845 if( SCIPisLT(scip, vals[b], lb) )
846 {
847 SCIP_VAR* var;
848
849 var = binvars[b];
850 assert(var != NULL);
851
852 SCIPdebugMsg(scip, "fix variable <%s> to zero due to the lower bound of the linking variable <%s> [%g,%g]\n",
853 SCIPvarGetName(var), SCIPvarGetName(linkvar), lb, ub);
854
855 SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, -2, &infeasible, &tightened) );
856
857 if( infeasible )
858 {
859 SCIP_CALL( analyzeConflict(scip, cons, linkvar, var, TRUE, FALSE) );
860 *cutoff = TRUE;
861 return SCIP_OKAY;
862 }
863
864 if( tightened )
865 (*nchgbds)++;
866
867 /* adjust constraint state */
868 consdata->firstnonfixed++;
869 }
870 else
871 break;
872 }
873
874 /* fix binary variables to zero if not yet fixed, from local upper bound + 1*/
875 for( b = consdata->lastnonfixed; b >= 0; --b )
876 {
877 if( SCIPisGT(scip, vals[b], ub) )
878 {
879 SCIP_VAR* var;
880
881 var = binvars[b];
882 assert(var != NULL);
883
884 SCIPdebugMsg(scip, "fix variable <%s> to zero due to the upper bound of the linking variable <%s> [%g,%g]\n",
885 SCIPvarGetName(var), SCIPvarGetName(linkvar), lb, ub);
886
887 SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, -3, &infeasible, &tightened) );
888
889 if( infeasible )
890 {
891 SCIP_CALL( analyzeConflict(scip, cons, linkvar, var, FALSE, TRUE) );
892 *cutoff = TRUE;
893 return SCIP_OKAY;
894 }
895
896 if( tightened )
897 (*nchgbds)++;
898
899 /* adjust constraint state */
900 consdata->lastnonfixed--;
901 }
902 else
903 break;
904 }
905
906 if( consdata->firstnonfixed > consdata->lastnonfixed )
907 {
908 *cutoff = TRUE;
909 return SCIP_OKAY;
910 }
911
912 *mustcheck = (*nchgbds) == 0;
913
914 /* if linking variable is fixed, create for the binary variables which have a coefficient equal to the fixed value a
915 * set partitioning constraint
916 */
917 if( SCIPisEQ(scip, lb, ub) )
918 {
919 if( consdata->firstnonfixed == consdata->lastnonfixed )
920 {
921 SCIP_VAR* var;
922
923 var = binvars[consdata->firstnonfixed];
924
925 SCIPdebugMsg(scip, "fix variable <%s> to one due to the fixed linking variable <%s> [%g,%g]\n",
926 SCIPvarGetName(var), SCIPvarGetName(linkvar), lb, ub);
927
928 /* TODO can the forbidden cases be covered more elegantly? */
930 return SCIP_OKAY;
931
935 return SCIP_OKAY;
936
937 SCIP_CALL( SCIPinferBinvarCons(scip, var, TRUE, cons, -6, &infeasible, &tightened) );
938
939 if( infeasible )
940 {
941 SCIP_CALL( analyzeConflict(scip, cons, linkvar, var, TRUE, TRUE) );
942 *cutoff = TRUE;
943 return SCIP_OKAY;
944 }
945
946 if( tightened )
947 (*nchgbds)++;
948
949 SCIPdebugMsg(scip, " -> disabling linking constraint <%s>\n", SCIPconsGetName(cons));
951
952 *mustcheck = FALSE;
953 }
954 else if( SCIPgetDepth(scip) <= 0 )
955 {
956 SCIP_CONS* setppc;
957 SCIP_VAR** vars;
958 int nvars;
959
960 /* get sub array of variables which have the same coefficient */
961 vars = &consdata->binvars[consdata->firstnonfixed];
962 nvars = consdata->lastnonfixed - consdata->firstnonfixed + 1;
963
968
969 SCIP_CALL( SCIPaddCons(scip, setppc) );
970 SCIP_CALL( SCIPreleaseCons(scip, &setppc) );
971
973 }
974 }
975
976 return SCIP_OKAY;
977}
978
979/** deletes coefficient at given position from the binary variable array */
980static
982 SCIP* scip, /**< SCIP data structure */
983 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
984 SCIP_CONS* cons, /**< linking constraint */
985 int pos /**< position of coefficient to delete */
986 )
987{
988 SCIP_CONSDATA* consdata;
989 SCIP_VAR* var;
990
991 assert(scip != NULL);
992 assert(eventhdlr != NULL);
993
994 consdata = SCIPconsGetData(cons);
995 assert(consdata != NULL);
996 assert(0 <= pos && pos < consdata->nbinvars);
997
998 var = consdata->binvars[pos];
999 assert(var != NULL);
1001
1002 /* remove the rounding locks for the deleted variable */
1004
1005 /* if we are in transformed problem, delete the event data of the variable */
1006 if( SCIPconsIsTransformed(cons) )
1007 {
1008 SCIP_CONSHDLR* conshdlr;
1009 SCIP_CONSHDLRDATA* conshdlrdata;
1010
1011 /* get event handler */
1012 conshdlr = SCIPconsGetHdlr(cons);
1013 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1014 assert(conshdlrdata != NULL);
1015 assert(conshdlrdata->eventhdlr != NULL);
1016
1017 /* drop bound change events of variable */
1018 SCIP_CALL( dropEvent(scip, consdata, conshdlrdata->eventhdlr, pos) );
1019 }
1020
1021 /* move the last variable to the free slot */
1022 if( pos != consdata->nbinvars - 1 )
1023 {
1024 consdata->binvars[pos] = consdata->binvars[consdata->nbinvars-1];
1025 consdata->vals[pos] = consdata->vals[consdata->nbinvars-1];
1026 consdata->sorted = FALSE;
1027 }
1028
1029 consdata->nbinvars--;
1030
1031 /* release variable */
1033
1034 return SCIP_OKAY;
1035}
1036
1037/** remove the trailing and leading binary variables that are fixed to zero */
1038static
1040 SCIP* scip, /**< SCIP data structure */
1041 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1042 SCIP_CONS* cons /**< linking constraint */
1043 )
1044{
1045 SCIP_CONSDATA* consdata;
1046 int nbinvars;
1047 int b;
1048
1049 consdata = SCIPconsGetData(cons);
1050 assert(consdata != NULL);
1051 assert(consdata->sorted);
1052
1056
1057 nbinvars = consdata->nbinvars;
1058
1059 for( b = nbinvars - 1; b > consdata->lastnonfixed; --b )
1060 {
1061 SCIP_CALL( delCoefPos(scip, eventhdlr, cons, b) );
1062 }
1063
1064 for( b = consdata->firstnonfixed - 1; b >= 0; --b )
1065 {
1066 SCIP_CALL( delCoefPos(scip, eventhdlr, cons, b) );
1067 }
1068
1069 for( b = consdata->nbinvars - 1; b >= 0; --b )
1070 {
1071 if( SCIPvarGetUbLocal(consdata->binvars[b]) < 0.5 )
1072 {
1073 SCIP_CALL( delCoefPos(scip, eventhdlr, cons, b) );
1074 }
1075 }
1076
1077 /* set the constraint state */
1078 consdata->firstnonfixed = 0;
1079 consdata->lastnonfixed = consdata->nbinvars - 1;
1080
1081 return SCIP_OKAY;
1082}
1083
1084/** tightened the linking variable due to binary variables which are fixed to zero */
1085static
1087 SCIP* scip, /**< SCIP data structure */
1088 SCIP_CONS* cons, /**< linking constraint to be processed */
1089 SCIP_CONSDATA* consdata, /**< linking constraint to be processed */
1090 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1091 int* nchgbds /**< pointer to store the number of changed variable bounds */
1092 )
1093{
1094 SCIP_VAR** binvars;
1095 SCIP_VAR* linkvar;
1096 SCIP_Real* vals;
1097
1098 SCIP_Bool infeasible;
1099 SCIP_Bool tightened;
1100 int nbinvars;
1101 int b;
1102
1103 /* if more than one binary variable is fixed to one or at least nbinvars minus one variable are fixed to zero return */
1104 if( consdata->nfixedones > 1 || consdata->nfixedzeros >= consdata->nbinvars-1 )
1105 return SCIP_OKAY;
1106
1107 if( *cutoff )
1108 return SCIP_OKAY;
1109
1110 assert(consdata->sorted);
1111
1112 linkvar = consdata->linkvar;
1113 binvars = consdata->binvars;
1114 vals = consdata->vals;
1115 nbinvars = consdata->nbinvars;
1116
1117#ifndef NDEBUG
1118 /* check that the first variable are locally fixed to zero */
1119 for( b = 0; b < consdata->firstnonfixed; ++b )
1120 assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
1121#endif
1122
1123 assert(consdata->firstnonfixed < nbinvars);
1124 assert(consdata->lastnonfixed < nbinvars);
1125
1126 /* find first non fixed binary variable */
1127 for( b = consdata->firstnonfixed; b < nbinvars; ++b )
1128 {
1129 if( SCIPvarGetUbLocal(binvars[b]) > 0.5 )
1130 break;
1131
1132 consdata->firstnonfixed++;
1133 }
1134
1135 SCIP_CALL( SCIPinferVarLbCons(scip, linkvar, vals[b], cons, -4, TRUE, &infeasible, &tightened) );
1136
1137 /* start conflict analysis if infeasible */
1138 if( infeasible )
1139 {
1140 /* analyze the cutoff if if SOLVING stage and conflict analysis is turned on */
1142 {
1143 SCIPdebugMsg(scip, "conflict at <%s> due to bounds and fixed binvars: [lb,ub] = [%g,%g]; b= %d; coef = %g \n",
1144 SCIPvarGetName(linkvar), SCIPvarGetLbLocal(linkvar), SCIPvarGetUbLocal(linkvar), b, vals[b]);
1145
1147
1148 /* ??????????? use resolve method and only add binvars which are needed to exceed the upper bound */
1149
1150 /* add conflicting variables */
1151 SCIP_CALL( SCIPaddConflictUb(scip, linkvar, NULL) );
1152
1153 for( b = 0; b < consdata->firstnonfixed; ++b )
1154 {
1155 SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
1156 }
1157
1158 /* analyze the conflict */
1160 }
1161
1162 *cutoff = TRUE;
1163 return SCIP_OKAY;
1164 }
1165
1166 if( tightened )
1167 (*nchgbds)++;
1168
1169#ifndef NDEBUG
1170 /* check that the last variable are locally fixed to zero */
1171 for( b = consdata->lastnonfixed + 1; b < nbinvars; ++b )
1172 assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
1173#endif
1174
1175 /* find last non fixed variable */
1176 for( b = consdata->lastnonfixed; b >= 0; --b )
1177 {
1178 if( SCIPvarGetUbLocal(binvars[b]) > 0.5 )
1179 break;
1180
1181 consdata->lastnonfixed--;
1182 }
1183
1185 SCIP_CALL( SCIPinferVarUbCons(scip, linkvar, (SCIP_Real)vals[b], cons, -5, TRUE, &infeasible, &tightened) );
1186
1187 if( infeasible )
1188 {
1189 /* conflict analysis can only be applied in solving stage and if conflict analysis is turned on */
1191 {
1192 SCIPdebugMsg(scip, "conflict at <%s> due to bounds and fixed binvars: [lb,ub] = [%g,%g]; b = %d; coef = %g,\n",
1193 SCIPvarGetName(linkvar), SCIPvarGetLbLocal(linkvar), SCIPvarGetUbLocal(linkvar), b, vals[b]);
1194
1196
1197 /* ??????????? use resolve method and only add binvars which are needed to fall below the lower bound */
1198
1199 /* add conflicting variables */
1200 SCIP_CALL( SCIPaddConflictLb(scip, linkvar, NULL) );
1201
1202 for( b = consdata->lastnonfixed + 1; b < nbinvars; ++b )
1203 {
1204 SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
1205 }
1206
1207 /* analyze the conflict */
1209 }
1210
1211 *cutoff = TRUE;
1212 return SCIP_OKAY;
1213 }
1214
1215 if( tightened )
1216 (*nchgbds)++;
1217
1218 return SCIP_OKAY;
1219}
1220
1221/** checks constraint for violation only looking at the fixed binary variables, applies further fixings if possible */
1222static
1224 SCIP* scip, /**< SCIP data structure */
1225 SCIP_CONS* cons, /**< linking constraint to be processed */
1226 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1227 int* nchgbds, /**< pointer to store the number of changed variable bounds */
1228 SCIP_Bool* addcut, /**< pointer to store whether this constraint must be added as a cut */
1229 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1230 )
1231{
1232 SCIP_CONSDATA* consdata;
1233 SCIP_Bool infeasible;
1234 SCIP_Bool tightened;
1235
1236 assert(cons != NULL);
1237 assert(SCIPconsGetHdlr(cons) != NULL);
1238 assert(cutoff != NULL);
1239 assert(nchgbds != NULL);
1240 assert(addcut != NULL);
1241 assert(mustcheck != NULL);
1242
1244
1245 consdata = SCIPconsGetData(cons);
1246 assert(consdata != NULL);
1247 assert(consdata->nbinvars == 0 || consdata->binvars != NULL);
1248 assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nbinvars);
1249 assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nbinvars);
1250
1251 /* ensure that the binary variables are sorted in non-decreasing order w.r.t. their coefficients */
1252 consdataSort(consdata);
1253
1254 /* in case there is only at most one binary variables, the constraints should already be disabled */
1255 assert(consdata->nbinvars > 1);
1256
1257 if( *cutoff )
1258 return SCIP_OKAY;
1259
1260 if( consdata->nfixedones == 1 )
1261 {
1262 /* exactly one variable is fixed to 1:
1263 * - all other binary variables in a set partitioning must be zero
1264 * - linking variable is fixed to that binary variable
1265 */
1266 if( consdata->nfixedzeros < consdata->nbinvars - 1 ||
1267 SCIPisLT(scip, SCIPvarGetLbLocal(consdata->linkvar), SCIPvarGetUbLocal(consdata->linkvar)) )
1268 {
1269 SCIP_VAR** vars;
1270 SCIP_VAR* var;
1271#ifndef NDEBUG
1272 SCIP_Bool fixedonefound;
1273#endif
1274 int nvars;
1275 int v;
1276
1277 SCIPdebugMsg(scip, " -> fixing all other variables to zero due to the set partitioning condition <%s>\n",
1278 SCIPconsGetName(cons));
1279
1280 /* unfixed variables exist: fix them to zero;
1281 * this could result in additional variables fixed to one due to aggregations; in this case, the
1282 * constraint is infeasible in local bounds
1283 */
1284 vars = consdata->binvars;
1285 nvars = consdata->nbinvars;
1286#ifndef NDEBUG
1287 fixedonefound = FALSE;
1288#endif
1289
1290 for( v = 0; v < nvars && consdata->nfixedones == 1 && !(*cutoff); ++v ) /* cppcheck-suppress knownConditionTrueFalse */
1291 {
1292 var = vars[v];
1294 /* TODO can this be handled more elegantly? */
1296 continue;
1297
1301 continue;
1302
1303 if( SCIPvarGetLbLocal(var) < 0.5 )
1304 {
1305 SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, -1, &infeasible, &tightened) );
1306 assert(!infeasible);
1307 SCIPdebugMsg(scip, " -> fixed <%s> to zero (tightened=%u)\n", SCIPvarGetName(var), tightened);
1308 }
1309 else
1310 {
1311#ifndef NDEBUG
1312 fixedonefound = TRUE;
1313#endif
1314 /* fix linking variable */
1315 /* TODO check if variable status allows fixing (probably in consFixLinkvar) */
1316 SCIP_CALL( consFixLinkvar(scip, cons, v, cutoff) );
1317 }
1318 }
1319 if( !(*cutoff) )
1320 {
1321 /* the fixed to one variable must have been found, and at least one variable must have been fixed */
1322 assert(consdata->nfixedones >= 1 || fixedonefound);
1323
1325 (*nchgbds)++;
1326 }
1327 }
1328
1329 /* now all other variables are fixed to zero:
1330 * the constraint is feasible, and if it's not modifiable, it is redundant
1331 */
1332 if( !SCIPconsIsModifiable(cons) && consdata->nfixedones == 1 ) /* cppcheck-suppress knownConditionTrueFalse */
1333 {
1334 SCIPdebugMsg(scip, " -> disabling set linking constraint <%s>\n", SCIPconsGetName(cons));
1336 }
1337 }
1338 else if( consdata->nfixedones >= 2 )
1339 {
1340 /* at least two variables are fixed to 1:
1341 * - the set partitioning condition is violated
1342 */
1343 SCIPdebugMsg(scip, " -> conflict on " CONSHDLR_NAME " constraint <%s> due to the set partitioning condition\n", SCIPconsGetName(cons));
1344
1346
1347 /* conflict analysis can only be applied in solving stage and if it is applicable */
1349 {
1350 SCIP_VAR** vars;
1351 int nvars;
1352 int n;
1353 int v;
1354
1355 vars = consdata->binvars;
1356 nvars = consdata->nbinvars;
1357
1358 /* initialize conflict analysis, and add the two variables assigned to one to conflict candidate queue */
1360
1361 n = 0;
1362
1363 for( v = 0; v < nvars && n < 2; ++v )
1364 {
1365 if( SCIPvarGetLbLocal(vars[v]) > 0.5 )
1366 {
1368 n++;
1369 }
1370 }
1371 assert(n == 2);
1372
1373 /* analyze the conflict */
1375 }
1376
1377 *cutoff = TRUE;
1378 }
1379 else if( consdata->nfixedzeros == consdata->nbinvars )
1380 {
1381 /* all variables are fixed to zero:
1382 * - the set partitioning condition is violated, and if it's unmodifiable, the node
1383 * can be cut off -- otherwise, the constraint must be added as a cut and further pricing must
1384 * be performed
1385 */
1386 assert(consdata->nfixedones == 0);
1387
1388 SCIPdebugMsg(scip, " -> " CONSHDLR_NAME " constraint <%s> is infeasible due to the set partitioning condition\n",
1389 SCIPconsGetName(cons));
1390
1392 if( SCIPconsIsModifiable(cons) )
1393 *addcut = TRUE;
1394 else
1395 {
1396 /* conflict analysis can only be applied in solving stage and if it is applicable */
1398 {
1399 SCIP_VAR** vars;
1400 int nvars;
1401 int v;
1402
1403 vars = consdata->binvars;
1404 nvars = consdata->nbinvars;
1405
1406 /* initialize conflict analysis, add all variables of infeasible constraint to conflict candidate queue */
1408
1409 for( v = 0; v < nvars; ++v )
1410 {
1411 assert(SCIPvarGetUbLocal(vars[v]) < 0.5);
1413 }
1414
1415 /* analyze the conflict */
1417 }
1418 *cutoff = TRUE;
1419 }
1420 }
1421 else if( consdata->nfixedzeros == consdata->nbinvars - 1 )
1422 {
1423 /* all variables except one are fixed to zero:
1424 * - an unmodifiable set partitioning constraint is feasible and can be disabled after the
1425 * remaining variable is fixed to one
1426 * - a modifiable set partitioning constraint must be checked manually
1427 */
1428 assert(consdata->nfixedones == 0);
1429
1430 if( !SCIPconsIsModifiable(cons) )
1431 {
1432 SCIP_VAR** vars;
1433 SCIP_VAR* var;
1434 int nvars;
1435 int v;
1436
1437 /* search the single variable that can be fixed */
1438 vars = consdata->binvars;
1439 nvars = consdata->nbinvars;
1440 for( v = 0; v < nvars && !(*cutoff); ++v )
1441 {
1442 var = vars[v];
1445
1446 if( SCIPvarGetUbLocal(var) > 0.5 )
1447 {
1449 SCIPdebugMsg(scip, " -> fixing remaining binary variable <%s> to one in " CONSHDLR_NAME " constraint <%s>\n",
1451
1453 {
1454 SCIP_CALL( SCIPinferBinvarCons(scip, var, TRUE, cons, -1, &infeasible, &tightened) );
1455 assert(!infeasible);
1456 assert(tightened);
1457 }
1458
1459 /* fix linking variable */
1460 /* TODO check if variable status allows fixing (probably in consFixLinkvar)*/
1461 SCIP_CALL( consFixLinkvar(scip, cons, v, cutoff) );
1462 break;
1463 }
1464 }
1465 assert(v < nvars);
1466 assert(consdata->nfixedzeros == consdata->nbinvars - 1);
1467 assert(consdata->nfixedones == 1);
1468
1470 (*nchgbds)++;
1471 }
1472 }
1473 else
1474 {
1475 SCIP_CALL( tightenedLinkvar(scip, cons, consdata, cutoff, nchgbds) );
1476 }
1477
1478 *mustcheck = (*nchgbds) == 0;
1479
1480 assert(consdata->nfixedzeros + consdata->nfixedones <= consdata->nbinvars);
1481
1482 return SCIP_OKAY;
1483}
1484
1485/** returns whether the given solution is feasible for the given linking constraint */
1486static
1488 SCIP* scip, /**< SCIP data structure */
1489 SCIP_CONS* cons, /**< linking constraint to be checked */
1490 SCIP_SOL* sol /**< primal solution, or NULL for current LP/pseudo solution */
1491 )
1492{
1493 SCIP_CONSDATA* consdata;
1494 SCIP_VAR** binvars;
1495 SCIP_Real* vals;
1496 SCIP_Real solval;
1497 SCIP_Real linksum;
1498 SCIP_Real linkvarval;
1499 SCIP_Real setpartsum;
1500 SCIP_Real setpartsumbound;
1501 SCIP_Real absviol;
1502 SCIP_Real relviol;
1503 int nbinvars;
1504 int b;
1505
1506 assert(scip != NULL);
1507 assert(cons != NULL);
1508
1509 SCIPdebugMsg(scip, "checking linking constraint <%s> for feasibility of solution %p\n", SCIPconsGetName(cons), (void*)sol);
1510
1511 consdata = SCIPconsGetData(cons);
1512 assert(consdata != NULL);
1513 assert(consdata->binvars != NULL || consdata->nbinvars == 0);
1514
1515 /* in case there is only at most one binary variables, the constraints should already be disabled */
1516 assert(consdata->nbinvars > 1);
1517
1518 /* calculate the constraint's activity for the linking part and the set partitioning part */
1519 binvars = consdata->binvars;
1520 vals = consdata->vals;
1521 nbinvars = consdata->nbinvars;
1522
1523 linksum = 0.0;
1524 setpartsum = 0.0;
1525 setpartsumbound = 1.0 + 2*SCIPfeastol(scip);
1526
1527 for( b = 0; b < nbinvars && setpartsum < setpartsumbound; ++b ) /* if sum >= sumbound, the feasibility is clearly decided */
1528 {
1529 assert(SCIPvarIsBinary(binvars[b]));
1530
1531 solval = SCIPgetSolVal(scip, sol, binvars[b]);
1532 assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
1533
1534 linksum += vals[b] * solval;
1535 setpartsum += solval;
1536 }
1537
1538 /* calculate and update absolute and relative violation of the equality constraint */
1539 linkvarval = SCIPgetSolVal(scip, sol, consdata->linkvar);
1540 absviol = REALABS(linksum - linkvarval);
1541 relviol = REALABS(SCIPrelDiff(linksum, linkvarval));
1542 if( sol != NULL )
1543 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
1544
1545 /* calculate and update absolute and relative violation of the set partitioning constraint */
1546 absviol = REALABS(setpartsum - 1.0);
1547 relviol = REALABS(SCIPrelDiff(setpartsum, 1.0));
1548 if( sol != NULL )
1549 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
1550
1551 /* check if the fixed binary variable match with the linking variable */
1552 return SCIPisFeasEQ(scip, linksum, linkvarval) && SCIPisFeasEQ(scip, setpartsum, 1.0);
1553}
1554
1555#ifdef SCIP_DISABLED_CODE
1556/* The following should work, but does not seem to be tested well. */
1557
1558/** transfer aggregated integer variables to the corresponding binary variables */
1559static
1561 SCIP* scip, /**< SCIP data structure */
1562 SCIP_HASHMAP* varmap, /**< hash map mapping a integer variables to its linking constraint */
1563 SCIP_CONS** conss, /**< array of linking constraint */
1564 int nconss, /**< number of linking constraints */
1565 int* naggrvars, /**< pointer to store the number of aggregate variables */
1566 SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
1567 )
1568{
1569 SCIP_CONS* aggrcons;
1570 SCIP_CONSDATA* aggrconsdata;
1571 SCIP_CONSDATA* consdata;
1572 SCIP_VAR** binvars;
1573 SCIP_VAR** aggrbinvars;
1574 SCIP_VAR* linkvar;
1575 SCIP_VAR* aggrvar;
1576 SCIP_Real aggrconst;
1577 SCIP_Real aggrscalar;
1578 SCIP_Bool infeasible;
1579 SCIP_Bool redundant;
1580 SCIP_Bool aggregated;
1581 int offset;
1582 int aggroffset;
1583 int nbinvars;
1584 int shift;
1585 int b;
1586 int c;
1587
1588 assert(varmap != NULL);
1589
1590 for( c = 0; c < nconss; ++c )
1591 {
1592 consdata = SCIPconsGetData(conss[c]);
1593 assert(consdata != NULL);
1594
1595 linkvar = consdata->linkvar;
1596 assert(linkvar != NULL);
1597
1599 {
1600 aggrvar = SCIPvarGetAggrVar(linkvar);
1601 aggrcons = (SCIP_CONS*) SCIPhashmapGetImage(varmap, getHashmapKey(aggrvar));
1602
1603 /* check if the aggregate variable belongs to a linking constraint */
1604 if( aggrcons != NULL )
1605 {
1606 aggrconsdata = SCIPconsGetData(aggrcons);
1607 assert(aggrconsdata != NULL);
1608
1609 aggrconst = SCIPvarGetAggrConstant(linkvar);
1610 aggrscalar = SCIPvarGetAggrScalar(linkvar);
1611
1612 /**@todo extend the aggregation for those cases were the aggrscalar is not equal to 1.0 */
1613 if( SCIPisEQ(scip, aggrscalar, 1.0 ) )
1614 {
1615 /* since both variables are integer variable and the aggrscalar is 1.0 the aggrconst should
1616 * integral
1617 */
1618 assert(SCIPisIntegral(scip, aggrconst));
1619 shift = SCIPconvertRealToInt(scip, aggrconst);
1620
1621 offset = consdata->offset;
1622 binvars = consdata->binvars;
1623 aggroffset = aggrconsdata->offset;
1624 aggrbinvars = aggrconsdata->binvars;
1625
1626 nbinvars = MIN(consdata->nbinvars + offset, aggrconsdata->nbinvars + shift + aggroffset);
1627
1628 for( b = MAX(offset, aggroffset-shift); b < nbinvars; ++b )
1629 {
1630 assert(b - offset >= 0);
1631 assert(b + shift - aggroffset >= 0);
1632 assert(b < consdata->nbinvars);
1633 assert(b < aggrconsdata->nbinvars - shift);
1634
1635 /* add aggregation x - y = 0.0 */
1636 SCIP_CALL( SCIPaggregateVars(scip, binvars[b-offset], aggrbinvars[b+shift-aggroffset], 1.0, -1.0, 0.0,
1637 &infeasible, &redundant, &aggregated) );
1638
1639 if( infeasible )
1640 {
1641 (*cutoff) = TRUE;
1642 return SCIP_OKAY;
1643 }
1644
1645 if( aggregated )
1646 (*naggrvars)++;
1647 }
1648 }
1649 }
1650 }
1651 }
1652 return SCIP_OKAY;
1653}
1654#endif
1655
1656/** create two rows for the linking constraint
1657 *
1658 * - row1: {sum_{b=1}^n-1 vals[b] * binvars[b]} - linkvar = 0
1659 * - row2: {sum_{b=0}^n-1 binvars[b]} = 1.0
1660 */
1661static
1663 SCIP* scip, /**< SCIP data structure */
1664 SCIP_CONS* cons /**< linking constraint */
1665 )
1666{
1667 SCIP_CONSDATA* consdata;
1668 char rowname[SCIP_MAXSTRLEN];
1669 int b;
1670
1671 assert( cons != NULL);
1672
1673 /* get constraint data */
1674 consdata = SCIPconsGetData(cons);
1675 assert(consdata != NULL);
1676 assert(consdata->row1 == NULL);
1677 assert(consdata->row2 == NULL);
1678 assert(consdata->nbinvars > 1);
1679
1680 /* create the LP row which captures the linking between the real and binary variables */
1681 (void)SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s[link]", SCIPconsGetName(cons));
1682
1683 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row1, cons, rowname, 0.0, 0.0,
1685
1686 /* add linking variable to the row */
1687 assert(consdata->linkvar != NULL);
1688 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row1, consdata->linkvar, -1.0) );
1689
1690 /* adding binary variables to the row */
1691 assert(consdata->binvars != NULL);
1692 for( b = 0; b < consdata->nbinvars; ++b )
1693 {
1694 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row1, consdata->binvars[b], consdata->vals[b]) );
1695 }
1696
1697 /* create the LP row which captures the set partitioning condition of the binary variables */
1698 (void)SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s[setppc]", SCIPconsGetName(cons));
1699 assert( consdata->nbinvars > 0 );
1700
1701 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row2, cons, rowname, 1.0, 1.0,
1703
1704 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row2, consdata->nbinvars, consdata->binvars, 1.0) );
1705
1706 return SCIP_OKAY;
1707}
1708
1709
1710/** adds linking constraint as cut to the LP */
1711static
1713 SCIP* scip, /**< SCIP data structure */
1714 SCIP_CONS* cons, /**< linking constraint */
1715 SCIP_Bool* cutoff /**< whether a cutoff has been detected */
1716 )
1717{
1718 SCIP_CONSDATA* consdata;
1719
1720 assert( cutoff != NULL );
1721 *cutoff = FALSE;
1722
1723 consdata = SCIPconsGetData(cons);
1724 assert(consdata != NULL);
1725
1726 /* in case there is only at most one binary variables, the constraints should already be disabled */
1727 assert(consdata->nbinvars > 1);
1728
1729 if( consdata->row1 == NULL )
1730 {
1731 assert(consdata->row2 == NULL);
1732
1733 /* convert linking data into LP rows */
1734 SCIP_CALL( createRows(scip, cons) );
1735 }
1736 assert(consdata->row1 != NULL);
1737 assert(consdata->row2 != NULL);
1738
1739 /* insert LP linking row as cut */
1740 if( !SCIProwIsInLP(consdata->row1) )
1741 {
1742 SCIPdebugMsg(scip, "adding linking row of constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1743 SCIP_CALL( SCIPaddRow(scip, consdata->row1, TRUE/*FALSE*/, cutoff) );
1744 }
1745
1746 /* insert LP set partitioning row as cut */
1747 if( !SCIProwIsInLP(consdata->row2) )
1748 {
1749 SCIPdebugMsg(scip, "adding set partitioning row of constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1750 SCIP_CALL( SCIPaddRow(scip, consdata->row2, TRUE/*FALSE*/, cutoff) );
1751 }
1752
1753 return SCIP_OKAY;
1754}
1755
1756/** adds linking constraint as rows to the NLP, if not added yet */
1757static
1759 SCIP* scip, /**< SCIP data structure */
1760 SCIP_CONS* cons /**< linking constraint */
1761 )
1762{
1763 SCIP_CONSDATA* consdata;
1764
1766
1767 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
1768 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
1769 return SCIP_OKAY;
1770
1771 consdata = SCIPconsGetData(cons);
1772 assert(consdata != NULL);
1773
1774 if( consdata->nlrow1 == NULL )
1775 {
1776 char rowname[SCIP_MAXSTRLEN];
1777 SCIP_Real* coefs;
1778 int i;
1779
1780 assert(consdata->nlrow2 == NULL);
1781
1782 /* create the NLP row which captures the linking between the real and binary variables */
1783 (void)SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s[link]", SCIPconsGetName(cons));
1784
1785 /* create nlrow1 with binary variables */
1786 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow1, rowname,
1787 0.0, consdata->nbinvars, consdata->binvars, consdata->vals, NULL, 0.0, 0.0, SCIP_EXPRCURV_LINEAR) );
1788 /* add linking variable to the row */
1789 SCIP_CALL( SCIPaddLinearCoefToNlRow(scip, consdata->nlrow1, consdata->linkvar, -1.0) );
1790
1791 /* create the NLP row which captures the set partitioning condition of the binary variables */
1792 (void)SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s[setppc]", SCIPconsGetName(cons));
1793
1794 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, consdata->nbinvars) );
1795 for( i = 0; i < consdata->nbinvars; ++i )
1796 coefs[i] = 1.0;
1797
1798 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow2, rowname,
1799 0.0, consdata->nbinvars, consdata->binvars, coefs, NULL, 1.0, 1.0, SCIP_EXPRCURV_LINEAR) );
1800
1801 SCIPfreeBufferArray(scip, &coefs);
1802 }
1803
1804 assert(SCIPnlrowIsInNLP(consdata->nlrow1) == SCIPnlrowIsInNLP(consdata->nlrow2));
1805 if( !SCIPnlrowIsInNLP(consdata->nlrow1) )
1806 {
1807 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow1) );
1808 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow2) );
1809 }
1810
1811 return SCIP_OKAY;
1812}
1813
1814/** checks constraint for violation, and adds it as a cuts if possible */
1815static
1817 SCIP* scip, /**< SCIP data structure */
1818 SCIP_CONS* cons, /**< linking constraint to be separated */
1819 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1820 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1821 SCIP_Bool* separated, /**< pointer to store TRUE, if a cut was found */
1822 int* nchgbds /**< pointer to store the number of changed variables bounds */
1823 )
1824{
1825 SCIP_CONSDATA* consdata;
1826 SCIP_Bool addcut;
1827 SCIP_Bool mustcheck;
1828
1829 assert(cons != NULL);
1830 assert(SCIPconsGetHdlr(cons) != NULL);
1831 assert(cutoff != NULL);
1832 assert(separated != NULL);
1833 assert(nchgbds != NULL);
1834
1836
1837 consdata = SCIPconsGetData(cons);
1838 assert(consdata != NULL);
1839
1840 /* in case there is only at most one binary variables, the constraints should already be disabled */
1841 assert(consdata->nbinvars > 1);
1842
1843 SCIPdebugMsg(scip, "separating constraint <%s>\n", SCIPconsGetName(cons));
1844
1845 *cutoff = FALSE;
1846 addcut = FALSE;
1847 mustcheck = TRUE;
1848
1849 /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
1850 if( sol == NULL )
1851 {
1852 SCIP_CALL( processRealBoundChg(scip, cons, cutoff, nchgbds, &mustcheck) );
1853 }
1854
1855 if( mustcheck && !(*cutoff) )
1856 {
1857 /* variable's fixings didn't give us any information -> we have to check the constraint */
1858 if( sol == NULL && consdata->row1 != NULL )
1859 {
1860 SCIP_Real feasibility;
1861 SCIP_Real tmp;
1862
1863 assert(consdata->row2 != NULL);
1864
1865 /* skip constraints already in the LP */
1866 if( SCIProwIsInLP(consdata->row1) && SCIProwIsInLP(consdata->row2))
1867 return SCIP_OKAY;
1868
1869 feasibility = 1.0;
1870
1871 /* check first row (linking) for feasibility */
1872 if( !SCIProwIsInLP(consdata->row1) )
1873 {
1874 tmp = SCIPgetRowLPFeasibility(scip, consdata->row1);
1875 feasibility = MIN(feasibility, tmp);
1876 }
1877
1878 /* check second row (setppc) for feasibility */
1879 if( !SCIProwIsInLP(consdata->row2) )
1880 {
1881 tmp = SCIPgetRowLPFeasibility(scip, consdata->row2);
1882 feasibility = MIN(feasibility, tmp);
1883 }
1884 addcut = SCIPisFeasNegative(scip, feasibility);
1885 }
1886 else
1887 addcut = !checkCons(scip, cons, sol);
1888
1889 if( !addcut )
1890 {
1891 /* constraint was feasible -> increase age */
1892 SCIP_CALL( SCIPincConsAge(scip, cons) );
1893 }
1894 }
1895
1896 if( addcut )
1897 {
1898 /* insert LP row as cut */
1899 assert(!(*cutoff));
1900 SCIP_CALL( addCuts(scip, cons, cutoff) );
1902 *separated = TRUE;
1903 }
1904
1905 return SCIP_OKAY;
1906}
1907
1908/** enforces the pseudo solution on the given constraint */
1909static
1911 SCIP* scip, /**< SCIP data structure */
1912 SCIP_CONS* cons, /**< linking constraint to be separated */
1913 SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1914 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
1915 int* nchgbds, /**< pointer to store the number of changed variable bounds */
1916 SCIP_Bool* solvelp /**< pointer to store TRUE, if the LP has to be solved */
1917 )
1918{
1919 SCIP_Bool addcut;
1920 SCIP_Bool mustcheck;
1921
1923 assert(cons != NULL);
1924 assert(SCIPconsGetHdlr(cons) != NULL);
1925 assert(cutoff != NULL);
1926 assert(infeasible != NULL);
1927 assert(nchgbds != NULL);
1928 assert(solvelp != NULL);
1929
1931
1932 addcut = FALSE;
1933 mustcheck = TRUE;
1934
1935 /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
1936 SCIP_CALL( processRealBoundChg(scip, cons, cutoff, nchgbds, &mustcheck) );
1937 SCIP_CALL( processBinvarFixings(scip, cons, cutoff, nchgbds, &addcut, &mustcheck) );
1938
1939 if( mustcheck )
1940 {
1941 assert(!addcut);
1942
1943 if( checkCons(scip, cons, NULL) )
1944 {
1945 /* constraint was feasible -> increase age */
1946 SCIP_CALL( SCIPincConsAge(scip, cons) );
1947 }
1948 else
1949 {
1950 /* constraint was infeasible -> reset age */
1952 *infeasible = TRUE;
1953 }
1954 }
1955
1956 if( addcut )
1957 {
1958 assert(!(*cutoff));
1959 /* a cut must be added to the LP -> we have to solve the LP immediately */
1961 *solvelp = TRUE;
1962 }
1963
1964 return SCIP_OKAY;
1965}
1966
1967/** helper function to enforce constraints */
1968static
1970 SCIP* scip, /**< SCIP data structure */
1971 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1972 SCIP_CONS** conss, /**< constraints to process */
1973 int nconss, /**< number of constraints */
1974 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
1975 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
1976 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
1977 )
1978{
1980 SCIP_Bool separated;
1981 int nchgbds;
1982 int c;
1983
1984 assert(conshdlr != NULL);
1985 assert(nconss == 0 || conss != NULL);
1986 assert(result != NULL);
1987
1989
1990 SCIPdebugMsg(scip, "Enforcing %d linking constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
1991
1992 cutoff = FALSE;
1993 separated = FALSE;
1994 nchgbds = 0;
1995
1996 /* check all useful linking constraints for feasibility */
1997 for( c = 0; c < nusefulconss && !cutoff && nchgbds == 0; ++c )
1998 {
1999 SCIP_CALL( separateCons(scip, conss[c], sol, &cutoff, &separated, &nchgbds) );
2000 }
2001
2002 /* check all obsolete linking constraints for feasibility */
2003 for( c = nusefulconss; c < nconss && !cutoff && !separated && nchgbds == 0; ++c )
2004 {
2005 SCIP_CALL( separateCons(scip, conss[c], sol, &cutoff, &separated, &nchgbds) );
2006 }
2007
2008 /* return the correct result */
2009 if( cutoff )
2011 else if( nchgbds > 0 )
2013 else if( separated )
2015 else
2017
2018 return SCIP_OKAY;
2019}
2020
2021/** adds symmetry information of constraint to a symmetry detection graph */
2022static
2024 SCIP* scip, /**< SCIP pointer */
2025 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
2026 SCIP_CONS* cons, /**< constraint */
2027 SYM_GRAPH* graph, /**< symmetry detection graph */
2028 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
2029 )
2030{
2031 SCIP_CONSDATA* consdata;
2032 SCIP_VAR** vars;
2033 SCIP_Real* vals;
2034 SCIP_Real constant = 0.0;
2035 int nlocvars;
2036 int nvars;
2037 int i;
2038
2039 assert(scip != NULL);
2040 assert(cons != NULL);
2041 assert(graph != NULL);
2042 assert(success != NULL);
2043
2044 consdata = SCIPconsGetData(cons);
2045 assert(consdata != NULL);
2046
2047 /* get active variables of the constraint */
2049 nlocvars = consdata->nbinvars + 1;
2050
2053
2054 /* get binary variables */
2055 for( i = 0; i < consdata->nbinvars; ++i )
2056 {
2057 vars[i] = consdata->binvars[i];
2058 vals[i] = consdata->vals[i];
2059 }
2060
2061 /* get linking variable */
2062 vars[consdata->nbinvars] = consdata->linkvar;
2063 vals[consdata->nbinvars] = -1.0;
2064
2065 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
2066
2068 cons, -constant, -constant, success) );
2069
2070 SCIPfreeBufferArray(scip, &vals);
2072
2073 return SCIP_OKAY;
2074}
2075
2076/*
2077 * Callback methods of constraint handler
2078 */
2079
2080/** copy method for constraint handler plugins (called when SCIP copies plugins) */
2081static
2082SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinking)
2083{ /*lint --e{715}*/
2084 assert(scip != NULL);
2085 assert(conshdlr != NULL);
2086
2088
2089 /* call inclusion method of constraint handler */
2091
2092 *valid = TRUE;
2093
2094 return SCIP_OKAY;
2095}
2096
2097/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
2098static
2099SCIP_DECL_CONSFREE(consFreeLinking)
2100{
2101 SCIP_CONSHDLRDATA* conshdlrdata;
2102
2103 assert(conshdlr != NULL);
2104 assert(scip != NULL);
2105
2107
2108 /* free constraint handler data */
2109 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2110 assert(conshdlrdata != NULL);
2111
2112 conshdlrdataFree(scip, &conshdlrdata);
2113
2114 return SCIP_OKAY;
2115}
2116
2117
2118/** presolving initialization method of constraint handler (called when presolving is about to begin) */
2119static
2120SCIP_DECL_CONSINITPRE(consInitpreLinking)
2121{ /*lint --e{715}*/
2122 SCIP_CONSHDLRDATA* conshdlrdata;
2123 SCIP_CONSDATA* consdata;
2124 int c;
2125
2126 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2127 assert(conshdlrdata != NULL);
2128
2129 /* disable all linking constraints which contain at most one binary variable */
2130 for( c = 0; c < nconss; ++c )
2131 {
2132 consdata = SCIPconsGetData(conss[c]);
2133 assert(consdata != NULL);
2134
2135 /* skip constraints which are not added */
2136 if( !SCIPconsIsAdded(conss[c]) )
2137 continue;
2138
2139 if( consdata->nbinvars <= 1 )
2140 {
2141 SCIP_CALL( SCIPdisableCons(scip, conss[c]) );
2142 assert(consdata->nbinvars == 0 || SCIPvarGetLbGlobal(consdata->binvars[0]) > 0.5);
2143 }
2144 else if( conshdlrdata->linearize )
2145 {
2146 SCIP_CALL( consdataLinearize(scip, conss[c], consdata) );
2147 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
2148 }
2149 }
2150
2151 return SCIP_OKAY;
2152}
2153
2154/** solving process initialization method of constraint handler */
2155static
2156SCIP_DECL_CONSINITSOL(consInitsolLinking)
2157{ /*lint --e{715}*/
2158 /* add nlrow representations to NLP, if NLP had been constructed */
2160 {
2161 int c;
2162 for( c = 0; c < nconss; ++c )
2163 {
2164 SCIP_CALL( addNlrow(scip, conss[c]) );
2165 }
2166 }
2167
2168 return SCIP_OKAY;
2169}
2170
2171/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
2172static
2173SCIP_DECL_CONSEXITSOL(consExitsolLinking)
2174{ /*lint --e{715}*/
2175 SCIP_CONSDATA* consdata;
2176 int c;
2177
2178 for( c = 0; c < nconss; ++c )
2179 {
2180 consdata = SCIPconsGetData(conss[c]);
2181 assert(consdata != NULL);
2182
2183 /* release the rows and nlrows of all constraints */
2184 if( consdata->row1 != NULL )
2185 {
2186 assert(consdata->row2 != NULL);
2187
2188 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row1) );
2189 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row2) );
2190 }
2191
2192 if( consdata->nlrow1 != NULL )
2193 {
2194 assert(consdata->nlrow2 != NULL);
2195
2196 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow1) );
2197 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow2) );
2198 }
2199 }
2200
2201 return SCIP_OKAY;
2202}
2203
2204
2205/** frees specific constraint data */
2206static
2207SCIP_DECL_CONSDELETE(consDeleteLinking)
2208{ /*lint --e{715}*/
2209 SCIP_CONSHDLRDATA* conshdlrdata;
2210
2211 assert(conshdlr != NULL);
2212 assert(consdata != NULL);
2213 assert(*consdata != NULL);
2214
2216
2217 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2218 assert(conshdlrdata != NULL);
2219 assert(conshdlrdata->eventhdlr != NULL);
2220
2221 /* remove linking constraint form variable hash map */
2222 assert(conshdlrdata->varmap != NULL);
2223 assert(SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey((*consdata)->linkvar)));
2224 SCIP_CALL( SCIPhashmapRemove(conshdlrdata->varmap, getHashmapKey((*consdata)->linkvar)) );
2225
2226 if( (*consdata)->nbinvars > 0 && SCIPisTransformed(scip) )
2227 {
2228 SCIP_CALL( dropAllEvents(scip, *consdata, conshdlrdata->eventhdlr) );
2229 }
2230
2231 /* free consdata */
2232 SCIP_CALL( consdataFree(scip, consdata) );
2233
2234 return SCIP_OKAY;
2235}
2236
2237
2238/** transforms constraint data into data belonging to the transformed problem */
2239static
2240SCIP_DECL_CONSTRANS(consTransLinking)
2241{ /*lint --e{715}*/
2242 SCIP_CONSDATA* sourcedata;
2243 SCIP_CONSDATA* targetdata;
2244 SCIP_CONSHDLRDATA* conshdlrdata;
2245
2246 assert(conshdlr != NULL);
2248 assert(sourcecons != NULL);
2249 assert(targetcons != NULL);
2250
2252
2253 /* free constraint handler data */
2254 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2255 assert(conshdlrdata != NULL);
2256 assert(conshdlrdata->eventhdlr != NULL);
2257
2258 sourcedata = SCIPconsGetData(sourcecons);
2259 assert(sourcedata != NULL);
2260 assert(sourcedata->row1 == NULL); /* in original problem, there cannot be LP rows */
2261 assert(sourcedata->row2 == NULL); /* in original problem, there cannot be LP rows */
2262
2263 SCIPdebugMsg(scip, "transform linking constraint for variable <%s>\n", SCIPvarGetName(sourcedata->linkvar));
2264
2265 /* create constraint data for target constraint */
2266 SCIP_CALL( consdataCreate(scip, conshdlrdata->eventhdlr, &targetdata,
2267 sourcedata->linkvar, sourcedata->binvars, sourcedata->vals, sourcedata->nbinvars) );
2268
2269 /* create target constraint */
2270 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
2271 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
2272 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
2273 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
2274 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
2275
2276 /* insert (transformed) linking constraint into the hash map */
2277 assert(conshdlrdata->varmap != NULL);
2278 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varmap, getHashmapKey(targetdata->linkvar), *targetcons) );
2279
2280 return SCIP_OKAY;
2281}
2282
2283/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
2284static
2285SCIP_DECL_CONSINITLP(consInitlpLinking)
2286{ /*lint --e{715}*/
2287 SCIP_CONSDATA* consdata;
2288 int c;
2289
2290 *infeasible = FALSE;
2291
2292 for( c = 0; c < nconss && !(*infeasible); ++c )
2293 {
2294 assert(SCIPconsIsInitial(conss[c]));
2295
2296 consdata = SCIPconsGetData(conss[c]);
2297 assert(consdata != NULL);
2298
2299 if( consdata->nbinvars <= 1 )
2300 continue;
2301
2302 SCIP_CALL( addCuts(scip, conss[c], infeasible) );
2303 }
2304
2305 return SCIP_OKAY;
2306}
2307
2308
2309/** separation method of constraint handler for LP solutions */
2310static
2311SCIP_DECL_CONSSEPALP(consSepalpLinking)
2312{ /*lint --e{715}*/
2314 SCIP_Bool separated;
2315 int nchgbds;
2316 int c;
2317
2318 assert(conshdlr != NULL);
2319 assert(nconss == 0 || conss != NULL);
2320 assert(result != NULL);
2321
2323
2324 SCIPdebugMsg(scip, "separating %d/%d linking constraints\n", nusefulconss, nconss);
2325
2326 cutoff = FALSE;
2327 separated = FALSE;
2328 nchgbds = 0;
2329
2330 /* check all useful linking constraints for feasibility */
2331 for( c = 0; c < nusefulconss && !cutoff; ++c )
2332 {
2333 SCIP_CALL( separateCons(scip, conss[c], NULL, &cutoff, &separated, &nchgbds) );
2334 }
2335
2336 /* return the correct result */
2337 if( cutoff )
2339 else if( nchgbds > 0 )
2341 else if( separated )
2343 else
2345
2346 return SCIP_OKAY;
2347}
2348
2349
2350/** separation method of constraint handler for arbitrary primal solutions */
2351static
2352SCIP_DECL_CONSSEPASOL(consSepasolLinking)
2353{ /*lint --e{715}*/
2355 SCIP_Bool separated;
2356 int nchgbds;
2357 int c;
2358
2359 assert(conshdlr != NULL);
2360 assert(nconss == 0 || conss != NULL);
2361 assert(result != NULL);
2362
2364
2365 SCIPdebugMsg(scip, "separating %d/%d " CONSHDLR_NAME " constraints\n", nusefulconss, nconss);
2366
2367 cutoff = FALSE;
2368 separated = FALSE;
2369 nchgbds = 0;
2370
2371 /* check all useful set partitioning / packing / covering constraints for feasibility */
2372 for( c = 0; c < nusefulconss && !cutoff; ++c )
2373 {
2374 SCIP_CALL( separateCons(scip, conss[c], sol, &cutoff, &separated, &nchgbds) );
2375 }
2376
2377 /* return the correct result */
2378 if( cutoff )
2380 else if( nchgbds > 0 )
2382 else if( separated )
2384 else
2386
2387 return SCIP_OKAY;
2388}
2389
2390
2391/** constraint enforcing method of constraint handler for LP solutions */
2392static
2393SCIP_DECL_CONSENFOLP(consEnfolpLinking)
2394{ /*lint --e{715}*/
2395 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
2396
2397 return SCIP_OKAY;
2398}
2399
2400
2401/** constraint enforcing method of constraint handler for relaxation solutions */
2402static
2403SCIP_DECL_CONSENFORELAX(consEnforelaxLinking)
2404{ /*lint --e{715}*/
2405 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
2406
2407 return SCIP_OKAY;
2408}
2409
2410
2411/** constraint enforcing method of constraint handler for pseudo solutions */
2412static
2413SCIP_DECL_CONSENFOPS(consEnfopsLinking)
2414{ /*lint --e{715}*/
2416 SCIP_Bool infeasible;
2417 int nchgbds;
2418 SCIP_Bool solvelp;
2419 int c;
2420
2421 assert(conshdlr != NULL);
2422 assert(nconss == 0 || conss != NULL);
2423 assert(result != NULL);
2424
2426
2427 SCIPdebugMsg(scip, "pseudo enforcing %d " CONSHDLR_NAME " constraints\n", nconss);
2428
2429 if( objinfeasible )
2430 {
2432 return SCIP_OKAY;
2433 }
2434
2435 cutoff = FALSE;
2436 infeasible = FALSE;
2437 nchgbds = 0;
2438 solvelp = FALSE;
2439
2440 /* check all linking constraint for domain reductions and feasibility */
2441 for( c = 0; c < nconss && !cutoff && !solvelp; ++c )
2442 {
2443 SCIP_CALL( enforcePseudo(scip, conss[c], &cutoff, &infeasible, &nchgbds, &solvelp) );
2444 }
2445
2446 if( cutoff )
2448 else if( nchgbds > 0 )
2450 else if( solvelp )
2452 else if( infeasible )
2454 else
2456
2457 return SCIP_OKAY;
2458}
2459
2460
2461/** feasibility check method of constraint handler for integral solutions */
2462static
2463SCIP_DECL_CONSCHECK(consCheckLinking)
2464{ /*lint --e{715}*/
2465 SCIP_CONS* cons;
2466 SCIP_CONSDATA* consdata;
2467 int c;
2468
2469 assert(conshdlr != NULL);
2470 assert(nconss == 0 || conss != NULL);
2471 assert(result != NULL);
2472
2474
2476
2477 /* check all linking constraints for feasibility */
2478 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
2479 {
2480 cons = conss[c];
2481 consdata = SCIPconsGetData(cons);
2482 assert(consdata != NULL);
2483
2484 if( consdata->nbinvars > 1 && (checklprows || consdata->row1 == NULL || !SCIProwIsInLP(consdata->row1)) )
2485 {
2486 if( !checkCons(scip, cons, sol) )
2487 {
2488 /* constraint is violated */
2490
2491 if( printreason )
2492 {
2493 int pos;
2494 int b;
2495
2496 pos = -1;
2497
2498#ifndef NDEBUG
2499 for( b = 0; b < consdata->nbinvars; ++b )
2500 {
2501 assert(consdata->binvars[b] != NULL);
2502 assert(SCIPvarIsBinary(consdata->binvars[b]));
2503 }
2504#endif
2505
2506 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
2507 SCIPinfoMessage(scip, NULL, ";\n");
2508
2509 /* check that at most one binary variable is fixed */
2510 for( b = 0; b < consdata->nbinvars; ++b )
2511 {
2512 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, consdata->binvars[b])) );
2513
2514 /* check if binary variable is fixed */
2515 if( SCIPgetSolVal(scip, sol, consdata->binvars[b]) > 0.5 )
2516 {
2517 if( pos != -1 )
2518 {
2519 SCIPinfoMessage(scip, NULL, "violation: more than one binary variable is set to one");
2520 break;
2521 }
2522 pos = b ;
2523 }
2524 }
2525
2526 /* check that at least one binary variable is fixed */
2527 if( pos == -1 )
2528 {
2529 SCIPinfoMessage(scip, NULL, "violation: none of the binary variables is set to one\n");
2530 }
2531 else if( !SCIPisFeasEQ(scip, consdata->vals[pos], SCIPgetSolVal(scip, sol, consdata->linkvar)) )
2532 {
2533 /* check if the fixed binary variable match with the linking variable */
2534 SCIPinfoMessage(scip, NULL, "violation: <%s> = <%g> and <%s> is one\n",
2535 SCIPvarGetName(consdata->linkvar), SCIPgetSolVal(scip, sol, consdata->linkvar),
2536 SCIPvarGetName(consdata->binvars[pos]) );
2537 }
2538 }
2539 }
2540 }
2541 }
2542
2543 return SCIP_OKAY;
2544}
2545
2546/** domain propagation method of constraint handler */
2547static
2548SCIP_DECL_CONSPROP(consPropLinking)
2549{ /*lint --e{715}*/
2551 int nchgbds = 0;
2552 int c;
2553
2554 assert(conshdlr != NULL);
2555 assert(nconss == 0 || conss != NULL);
2556 assert(result != NULL);
2557
2559
2560 SCIPdebugMsg(scip, "propagating %d/%d " CONSHDLR_NAME " constraints\n", nusefulconss, nconss);
2561
2562 /* propagate all useful set partitioning / packing / covering constraints */
2563 for( c = 0; c < nusefulconss && !cutoff; ++c )
2564 {
2565 SCIP_Bool addcut;
2566 SCIP_Bool mustcheck;
2567
2568 SCIP_CALL( processRealBoundChg(scip, conss[c], &cutoff, &nchgbds, &mustcheck) );
2569 SCIP_CALL( processBinvarFixings(scip, conss[c], &cutoff, &nchgbds, &addcut, &mustcheck) );
2570 } /*lint !e438*/
2571
2572 /* return the correct result */
2573 if( cutoff )
2575 else if( nchgbds > 0 )
2577 else
2579
2580 return SCIP_OKAY;
2581}
2582
2583
2584/** presolving method of constraint handler */
2585static
2586SCIP_DECL_CONSPRESOL(consPresolLinking)
2587{ /*lint --e{715}*/
2588 SCIP_CONSHDLRDATA* conshdlrdata;
2589 int oldnfixedvars;
2590 int oldnchgbds;
2591 int oldnaggrvars;
2592 int oldndelconss;
2593 int firstchange;
2594 int firstclique;
2595 int lastclique;
2596 int c;
2597 SCIP_Bool fixed;
2599 SCIP_Bool infeasible;
2600 SCIP_Bool mustcheck;
2601
2602 assert(conshdlr != NULL);
2603 assert(scip != NULL);
2604 assert(result != NULL);
2605
2607
2608 SCIPdebugMsg(scip, "presolve %d linking constraints\n", nconss);
2609
2610 (*result) = SCIP_DIDNOTFIND;
2611
2612 oldnchgbds = *nchgbds;
2613 oldnaggrvars = *naggrvars;
2614 oldnfixedvars = *nfixedvars;
2615 oldndelconss = *ndelconss;
2616 cutoff = FALSE;
2617
2618 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2619 assert(conshdlrdata != NULL);
2620
2621 /* process constraints */
2622 firstchange = INT_MAX;
2623 firstclique = INT_MAX;
2624 lastclique = -1;
2625
2626 /* check for each linking constraint the set partitioning condition */
2627 for( c = 0; c < nconss && !SCIPisStopped(scip); ++c )
2628 {
2629 SCIP_CONS* cons;
2630 SCIP_CONSDATA* consdata;
2631
2633
2634 cons = conss[c];
2635 assert(cons != NULL);
2637
2638 SCIPdebugMsg(scip, "presolve linking constraints <%s>\n", SCIPconsGetName(cons));
2639
2640 consdata = SCIPconsGetData(cons);
2641 assert(consdata != NULL);
2642
2643 if( !SCIPconsIsEnabled(cons) /* || consdata->nbinvars <= 1 */ )
2644 continue;
2645
2646 /* in case there is only at most one binary variables, the constraints should already be disabled */
2647 assert(consdata->nbinvars > 1);
2648
2649 /*SCIPdebugMsg(scip, "presolving set partitioning / packing / covering constraint <%s>\n", SCIPconsGetName(cons));*/
2650 if( consdata->nfixedones >= 2 )
2651 {
2652 /* at least two variables are fixed to 1:
2653 * - a linking constraint is infeasible due to the set partitioning condition
2654 */
2655 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> is infeasible\n", SCIPconsGetName(cons));
2657 return SCIP_OKAY;
2658 }
2659
2660 if( consdata->nfixedones == 1 )
2661 {
2662 /* exactly one variable is fixed to 1:
2663 * - all other binary variables must be zero due to the set partitioning condition
2664 * - linking variable has to be fixed to corresponding binary variable which is fixed to one
2665 * - if constraint is not modifiable it can be removed
2666 */
2667 SCIP_VAR* var;
2668 int v;
2669
2670 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> has a binary variable fixed to 1.0\n", SCIPconsGetName(cons));
2671
2672 for( v = 0; v < consdata->nbinvars; ++v )
2673 {
2674 var = consdata->binvars[v];
2675 assert(var != NULL);
2676
2677 if( SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
2678 {
2679 SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
2680
2681 if( infeasible )
2682 {
2683 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == 0\n",
2685
2687 return SCIP_OKAY;
2688 }
2689 assert(fixed);
2690 (*nfixedvars)++;
2691 }
2692 else if( SCIPvarGetLbGlobal(var) > 0.5 )
2693 {
2694 /* fix linking variable */
2695 assert(SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_LOOSE
2696 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_AGGREGATED
2697 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_COLUMN
2698 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_FIXED
2699 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_NEGATED);
2700 SCIP_CALL( SCIPfixVar(scip, consdata->linkvar, consdata->vals[v], &infeasible, &fixed) );
2701
2702 if( infeasible )
2703 {
2704 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == %g\n",
2705 SCIPconsGetName(cons), SCIPvarGetName(consdata->linkvar), consdata->vals[v]);
2706
2708 return SCIP_OKAY;
2709 }
2710
2711 if( fixed )
2712 (*nfixedvars)++;
2713 }
2714 }
2715
2716 /* now all other variables are fixed to zero:
2717 * the constraint is feasible, and if it's not modifiable, it is redundant
2718 */
2719 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> is redundant\n", SCIPconsGetName(cons));
2720 SCIP_CALL( SCIPdelCons(scip, cons) );
2721 (*ndelconss)++;
2722 continue;
2723 }
2724
2725 if( consdata->nfixedzeros == consdata->nbinvars )
2726 {
2727 /* all variables are fixed to zero:
2728 * - a linking constraint is infeasible due the set partitioning condition
2729 */
2730 assert(consdata->nfixedones == 0);
2731
2732 SCIPdebugMsg(scip, "linking constraint <%s> is infeasible due to set partitioning condition\n", SCIPconsGetName(cons));
2734 return SCIP_OKAY;
2735 }
2736
2737 if( consdata->nfixedzeros == consdata->nbinvars - 1 )
2738 {
2739 /* all variables except one are fixed to zero:
2740 * - a linking constraint is feasible due the set partitioning condition
2741 * - the remaining binary variable can be fixed to one
2742 * - linking variable has to be fixed to corresponding binary variable which is fixed to one
2743 * - constraint can be deleted since it is not modifiable
2744 */
2745 SCIP_VAR* var;
2746 int v;
2747
2748 assert(consdata->nfixedones == 0);
2749
2750 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s> has only one binary variable not fixed to zero\n",
2751 SCIPconsGetName(cons));
2752
2753 /* search unfixed variable */
2754 /* intentional empty for loop to increment counter to proper position */
2755 /* TODO speed up loop by considering only variables between firstnonfixed and lastnonfixed */
2756 for( v = 0; v < consdata->nbinvars && SCIPvarGetUbGlobal(consdata->binvars[v]) < 0.5; ++v ); /*lint !e722*/
2757 assert(v < consdata->nbinvars);
2758 var = consdata->binvars[v];
2759
2760 /* fix remaining binary variable */
2761 SCIP_CALL( SCIPfixVar(scip, var, 1.0, &infeasible, &fixed) );
2762 if( infeasible )
2763 {
2764 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == 1\n",
2767 return SCIP_OKAY;
2768 }
2769 assert(fixed);
2770 (*nfixedvars)++;
2771
2772 /* fix linking variable */
2773 assert(SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_LOOSE
2774 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_AGGREGATED
2775 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_COLUMN
2776 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_FIXED
2777 || SCIPvarGetStatus(consdata->linkvar) == SCIP_VARSTATUS_NEGATED);
2778 SCIP_CALL( SCIPfixVar(scip, consdata->linkvar, consdata->vals[v], &infeasible, &fixed) );
2779
2780 if( infeasible )
2781 {
2782 SCIPdebugMsg(scip, CONSHDLR_NAME " constraint <%s>: infeasible fixing <%s> == %g\n",
2783 SCIPconsGetName(cons), SCIPvarGetName(consdata->linkvar), consdata->vals[v]);
2784
2786 return SCIP_OKAY;
2787 }
2788 assert(!SCIPvarIsActive(consdata->linkvar) || fixed);
2789 if( fixed )
2790 (*nfixedvars)++;
2791
2792 /* delete constraint from problem */
2793 SCIP_CALL( SCIPdelCons(scip, cons) );
2794 (*ndelconss)++;
2795 continue;
2796 }
2797
2798 if( consdata->nfixedzeros == consdata->nbinvars - 2 ) /*lint !e641*/
2799 {
2800 SCIP_VAR* var;
2801 SCIP_VAR* var1;
2802 SCIP_VAR* var2;
2803 SCIP_Bool redundant;
2804 SCIP_Bool aggregated;
2805 int v;
2806
2807 /* aggregate variable, if set partitioning condition consists only of two
2808 * non-fixed variables
2809 */
2810
2811 /* search unfixed variable */
2812 var1 = NULL;
2813 var2 = NULL;
2814 for( v = 0; v < consdata->nbinvars && var2 == NULL; ++v )
2815 {
2816 var = consdata->binvars[v];
2817 if( SCIPvarGetUbGlobal(var) > 0.5 )
2818 {
2819 if( var1 == NULL )
2820 var1 = var;
2821 else
2822 var2 = var;
2823 }
2824 }
2825 assert(var1 != NULL && var2 != NULL);
2826
2827 /* aggregate binary equality var1 + var2 == 1 */
2828 SCIPdebugMsg(scip, "" CONSHDLR_NAME " constraint <%s>: aggregate <%s> + <%s> == 1\n",
2829 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
2830 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
2831
2832 /* evaluate aggregation result */
2833 if( infeasible )
2834 {
2835 SCIPdebugMsg(scip, "linking constraint <%s>: infeasible aggregation <%s> + <%s> == 1\n",
2836 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
2838 return SCIP_OKAY;
2839 }
2840 if( aggregated )
2841 (*naggrvars)++;
2842 }
2843
2844 /* apply real bound to binary variables */
2845 SCIP_CALL( processRealBoundChg(scip, cons, &cutoff, nchgbds, &mustcheck) );
2846
2847 /* tightened linking variable */
2848 SCIP_CALL( tightenedLinkvar(scip, cons, consdata, &cutoff, nchgbds) );
2849
2850 /* remove the trailing and leeading binary variable which are fixed to zero */
2851 SCIP_CALL( removeFixedBinvars(scip, conshdlrdata->eventhdlr, cons) );
2852
2853 /* fix the linking variable to the only remaining value and the corresponding binary variable to 1.0 */
2854 if( ! cutoff && consdata->nbinvars == 1 )
2855 {
2856 SCIP_VAR* linkvar;
2857 SCIP_VAR* binvar;
2858 SCIP_Real val;
2859
2860 linkvar = consdata->linkvar;
2861 binvar = consdata->binvars[0];
2862 val = consdata->vals[0];
2863
2864 SCIPdebugMsg(scip, "linking constraint <%s>: fix <%s> to %16.9g as only one binary variable remains",
2865 SCIPconsGetName(cons), SCIPvarGetName(linkvar), val);
2866
2867 SCIP_CALL( SCIPfixVar(scip, binvar, 1.0, &infeasible, &fixed) );
2868 assert(fixed);
2869 ++(*nfixedvars);
2870
2871 if( ! infeasible )
2872 {
2873 SCIP_CALL( SCIPfixVar(scip, linkvar, val, &infeasible, &fixed) );
2874 assert(fixed);
2875 ++(*nfixedvars);
2876 }
2877 cutoff = infeasible;
2878
2879 SCIP_CALL( SCIPdelCons(scip, cons) );
2880 ++(*ndelconss);
2881 }
2882
2883 if( cutoff )
2884 {
2886 return SCIP_OKAY;
2887 }
2888
2889 /* remember the first changed constraint to begin the next redundancy round with */
2890 if( firstchange == INT_MAX )
2891 firstchange = c;
2892
2893 /* remember the first and last constraints for which we have to add the clique information */
2894 if( !consdata->cliqueadded && consdata->nbinvars >= 2 )
2895 {
2896 if( firstclique == INT_MAX )
2897 firstclique = c;
2898 lastclique = c;
2899 }
2900 }
2901
2902 /* add clique and implication information */
2903 for( c = firstclique; c < lastclique && !SCIPisStopped(scip); ++c )
2904 {
2905 SCIP_CONS* cons;
2906 SCIP_CONSDATA* consdata;
2907
2909
2910 cons = conss[c];
2911 assert(cons != NULL);
2912
2913 /* ignore deleted constraints */
2914 if( !SCIPconsIsActive(cons) )
2915 continue;
2916
2917 consdata = SCIPconsGetData(cons);
2918 assert(consdata != NULL);
2919
2920 if( !consdata->cliqueadded && consdata->nbinvars >= 3 )
2921 {
2922 /* add set partitioning condition as clique */
2923 int ncliquebdchgs;
2924
2925 SCIP_CALL( SCIPaddClique(scip, consdata->binvars, NULL, consdata->nbinvars, TRUE, &infeasible, &ncliquebdchgs) );
2926 *nchgbds += ncliquebdchgs;
2927
2928 if( infeasible )
2929 {
2931 return SCIP_OKAY;
2932 }
2933
2934 consdata->cliqueadded = TRUE;
2935 }
2936 }
2937
2938#ifdef SCIP_DISABLED_CODE
2939 /* The following should work, but does not seem to be tested well. */
2940
2941 /* transfer aggregated linking variables to the corresponding binary variables */
2942 SCIP_CALL( aggregateVariables(scip, conshdlrdata->varmap, conss, nconss, naggrvars, &cutoff) );
2943#endif
2944
2945 if( cutoff )
2947 else if( oldndelconss < *ndelconss || oldnfixedvars < *nfixedvars || oldnchgbds < *nchgbds || oldnaggrvars < *naggrvars)
2949
2950 return SCIP_OKAY; /*lint !e438*/
2951}
2952
2953
2954/** propagation conflict resolving method of constraint handler */
2955static
2956SCIP_DECL_CONSRESPROP(consRespropLinking)
2957{ /*lint --e{715}*/
2958 SCIP_CONSDATA* consdata;
2959 SCIP_VAR* linkvar;
2960 int v;
2961
2962 SCIPdebugMsg(scip, "conflict resolving method of " CONSHDLR_NAME " constraint handler\n");
2963
2964 consdata = SCIPconsGetData(cons);
2965 assert(consdata != NULL);
2966
2967 linkvar = consdata->linkvar;
2968 assert(linkvar != NULL);
2969
2971
2972 if( inferinfo == -1 )
2973 {
2974 /* we have to resolve a fixing of a binary variable which was done due to fixed binary variables */
2975 assert(SCIPvarIsBinary(infervar));
2976 assert(SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, FALSE)));
2977 assert(SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, FALSE)));
2978
2979 if( boundtype == SCIP_BOUNDTYPE_UPPER )
2980 {
2981 /* we fixed the binary variable to zero since one of the other binary variable was fixed to one (set
2982 * partitioning condition)
2983 */
2984 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
2985
2986 for( v = 0; v < consdata->nbinvars; ++v )
2987 {
2988 if( SCIPgetVarLbAtIndex(scip, consdata->binvars[v], bdchgidx, FALSE) > 0.5 )
2989 {
2990 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvars[v]) );
2991 break;
2992 }
2993 }
2994 assert(v < consdata->nbinvars);
2995 }
2996 else
2997 {
2998 /* we fixed the binary variable to one since all other binary variable were fixed to zero */
2999 assert(boundtype == SCIP_BOUNDTYPE_LOWER);
3000 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
3001
3002 for( v = 0; v < consdata->nbinvars; ++v )
3003 {
3004 if( consdata->binvars[v] != infervar )
3005 {
3006 /* the reason variable must be assigned to zero */
3007 assert(SCIPgetVarUbAtIndex(scip, consdata->binvars[v], bdchgidx, FALSE) < 0.5);
3008 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvars[v]) );
3009 }
3010 }
3011 }
3012 }
3013 else if( inferinfo == -2 )
3014 {
3015 /* we have to resolve a fixing of a binary variable which was done due to the linking variable lower bound */
3016 assert(SCIPvarIsBinary(infervar));
3017 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
3018 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5); /*@repair: neu*/
3019 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5); /*@repair: neu*/
3020 assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3021 assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3022
3023 SCIP_CALL( SCIPaddConflictLb(scip, linkvar, bdchgidx) );
3024 }
3025 else if( inferinfo == -3 )
3026 {
3027 /* we have to resolve a fixing of a binary variable which was done due to the linking variable upper bound */
3028 assert(SCIPvarIsBinary(infervar));
3029 assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
3030 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
3031 assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5);
3032 assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3033 assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3034
3035 SCIP_CALL( SCIPaddConflictUb(scip, linkvar, bdchgidx) );
3036 }
3037 else if( inferinfo == -4 )
3038 {
3039 SCIP_VAR** binvars;
3040 SCIP_Real* vals;
3041 SCIP_Real lb;
3042 int nbinvars;
3043 int b;
3044
3045 /* we tightened the lower bound of the linking variable due the fixing of the corresponding binary variable to zero */
3046 assert(infervar == linkvar);
3047 assert(boundtype == SCIP_BOUNDTYPE_LOWER);
3048
3049 binvars = consdata->binvars;
3050 nbinvars = consdata->nbinvars;
3051 vals = consdata->vals;
3052
3053 /* get propagated lower bound */
3054 lb = SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, TRUE);
3055
3056 for( b = 0; b < nbinvars; ++b )
3057 {
3058 if( vals[b] >= lb )
3059 break;
3060
3061 assert(SCIPvarGetUbLocal(binvars[b]) < 0.5);
3062 SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
3063 }
3064 }
3065 else if( inferinfo == -5 )
3066 {
3067 SCIP_VAR** binvars;
3068 SCIP_Real* vals;
3069 SCIP_Real ub;
3070 int nbinvars;
3071 int b;
3072
3073 /* we tightened the upper bound of the linking variable due the fixing of the corresponding binary variable two zero */
3074
3075 assert(infervar == linkvar);
3076 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
3077
3078 binvars = consdata->binvars;
3079 nbinvars = consdata->nbinvars;
3080 vals = consdata->vals;
3081
3082 /* get old and new upper bound */
3083 ub = SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, TRUE);
3084
3085 /* resolve tightening of upper bound of the linking variable by binary variables */
3086 for( b = nbinvars - 1; b >= 0; --b )
3087 {
3088 if( vals[b] <= ub )
3089 break;
3090
3091 SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[b]) );
3092 }
3093 }
3094 else if( inferinfo == -6 )
3095 {
3096 /* we fixed a binary variable to one since the linking variable was fixed */
3097 assert(SCIPvarIsBinary(infervar));
3098 assert(boundtype == SCIP_BOUNDTYPE_LOWER);
3099 assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3100 assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3101 assert( SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3102 assert( SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, linkvar, bdchgidx, FALSE)) );
3103
3104 assert( !SCIPisFeasEQ(scip, SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE), SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, FALSE)) );
3105
3106 SCIP_CALL( SCIPaddConflictLb(scip, linkvar, bdchgidx) );
3107 SCIP_CALL( SCIPaddConflictUb(scip, linkvar, bdchgidx) );
3108 }
3109 else
3110 {
3111 /* we fixed the linking variable to (vals[inferinfo]) since the corresponding binary variable was fixed to one */
3112 assert(infervar == linkvar);
3113 assert(inferinfo >= 0);
3114 assert(inferinfo < consdata->nbinvars);
3115 assert(SCIPisEQ(scip, consdata->vals[inferinfo], SCIPgetVarUbAtIndex(scip, consdata->linkvar, bdchgidx, TRUE))
3116 || SCIPisEQ(scip, consdata->vals[inferinfo], SCIPgetVarLbAtIndex(scip, consdata->linkvar, bdchgidx, TRUE)));
3117
3118 assert(SCIPgetVarLbAtIndex(scip, consdata->binvars[inferinfo], bdchgidx, FALSE) > 0.5);
3119 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvars[inferinfo]) );
3120 }
3121
3123
3124 return SCIP_OKAY;
3125}
3126
3127/** variable rounding lock method of constraint handler */
3128static
3129SCIP_DECL_CONSLOCK(consLockLinking)
3130{ /*lint --e{715}*/
3131 SCIP_CONSDATA* consdata;
3132 int b;
3133
3134 assert(locktype == SCIP_LOCKTYPE_MODEL);
3135
3136 consdata = SCIPconsGetData(cons);
3137 assert(consdata != NULL);
3138
3139 /* lock linking variable in both directions */
3140 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->linkvar, locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
3141
3142 /* look binary variables in both directions */
3143 for( b = 0; b < consdata->nbinvars; ++b )
3144 {
3145 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->binvars[b], locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
3146 }
3147
3148 return SCIP_OKAY;
3149}
3150
3151/** constraint activation notification method of constraint handler */
3152static
3153SCIP_DECL_CONSACTIVE(consActiveLinking)
3154{ /*lint --e{715}*/
3155 assert(cons != NULL);
3157
3159
3161 {
3162 SCIP_CALL( addNlrow(scip, cons) );
3163 }
3164
3165 return SCIP_OKAY;
3166}
3167
3168
3169/** constraint deactivation notification method of constraint handler */
3170static
3171SCIP_DECL_CONSDEACTIVE(consDeactiveLinking)
3172{ /*lint --e{715}*/
3173 SCIP_CONSDATA* consdata;
3174
3176
3178
3179 /* get constraint data */
3180 consdata = SCIPconsGetData(cons);
3181 assert(consdata != NULL);
3182
3183 /* remove row from NLP, if still in solving
3184 * if we are in exitsolve, the whole NLP will be freed anyway
3185 */
3186 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow1 != NULL )
3187 {
3188 assert(consdata->nlrow2 != NULL);
3189 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow1) );
3190 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow2) );
3191 }
3192
3193 return SCIP_OKAY;
3194}
3195
3196/** constraint enabling notification method of constraint handler */
3197static
3198SCIP_DECL_CONSENABLE(consEnableLinking)
3199{ /*lint --e{715}*/
3200#ifdef SCIP_DISABLED_CODE
3201 SCIP_CONSHDLRDATA* conshdlrdata;
3202#endif
3203 SCIP_CONSDATA* consdata;
3204
3205#ifdef SCIP_DISABLED_CODE
3206 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3207 assert(conshdlrdata != NULL);
3208#endif
3209
3210 consdata = SCIPconsGetData(cons);
3211 assert(consdata != NULL);
3212
3213 if( consdata->nbinvars <= 1 && SCIPgetStage(scip) >= SCIP_STAGE_TRANSFORMED )
3214 {
3215 SCIP_CALL( SCIPdisableCons(scip, cons) );
3216 assert(consdata->nbinvars == 0 || SCIPvarGetLbGlobal(consdata->binvars[0]) > 0.5);
3217 }
3218#ifdef SCIP_DISABLED_CODE
3219 /** @todo The following might help, but it would need to be tested whether it speeds up the solution process. */
3220 else if( conshdlrdata->linearize )
3221 {
3222 SCIP_CALL( consdataLinearize(scip, cons, consdata) );
3223 SCIP_CALL( SCIPdelCons(scip, cons) );
3224 }
3225#endif
3226 return SCIP_OKAY;
3227}
3228
3229/** constraint display method of constraint handler */
3230static
3231SCIP_DECL_CONSPRINT(consPrintLinking)
3232{ /*lint --e{715}*/
3233 assert(scip != NULL);
3234 assert(conshdlr != NULL);
3235 assert(cons != NULL);
3236
3238
3239 return SCIP_OKAY;
3240}
3241
3242
3243/** constraint copying method of constraint handler */
3244static
3245SCIP_DECL_CONSCOPY(consCopyLinking)
3246{ /*lint --e{715}*/
3247 SCIP_CONSDATA* sourceconsdata;
3248 SCIP_VAR** binvars;
3249 SCIP_VAR* linkvar;
3250 SCIP_Real* vals;
3251 const char* consname;
3252 int nbinvars;
3253 int v;
3254
3256
3257 (*valid) = TRUE;
3258
3259 sourceconsdata = SCIPconsGetData(sourcecons);
3260 assert(sourceconsdata != NULL);
3261
3262 /* get number of binary variables, linking variables */
3263 nbinvars = sourceconsdata->nbinvars;
3264 linkvar = sourceconsdata->linkvar;
3265
3266 /* duplicate variable array */
3267 if( nbinvars > 0 )
3268 {
3269 SCIP_CALL( SCIPduplicateBufferArray(scip, &binvars, sourceconsdata->binvars, nbinvars) );
3270 SCIP_CALL( SCIPduplicateBufferArray(scip, &vals, sourceconsdata->vals, nbinvars) );
3271 }
3272 else
3273 {
3274 binvars = NULL;
3275 vals = NULL;
3276 }
3277
3278 /* get copy for the binary variables */
3279 for( v = 0; v < nbinvars && *valid; ++v )
3280 {
3281 assert(binvars != NULL); /* for flexelint */
3282 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, binvars[v], &binvars[v], varmap, consmap, global, valid) );
3283 assert(!(*valid) || binvars[v] != NULL);
3284 }
3285
3286 /* copy the linking variable */
3287 if( *valid )
3288 {
3289 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, linkvar, &linkvar, varmap, consmap, global, valid) );
3290 assert(!(*valid) || linkvar != NULL);
3291 }
3292
3293 /* only create the target constraint, if all variables could be copied */
3294 if( *valid )
3295 {
3296 if( name != NULL )
3297 consname = name;
3298 else
3299 consname = SCIPconsGetName(sourcecons);
3300
3301 SCIP_CALL( SCIPcreateConsLinking(scip, cons, consname, linkvar, binvars, vals, nbinvars,
3302 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3303 }
3304
3305 /* free buffer array */
3306 if( nbinvars > 0 )
3307 {
3309 SCIPfreeBufferArrayNull(scip, &binvars);
3310 }
3311
3312 return SCIP_OKAY;
3313}
3314
3315/** constraint parsing method of constraint handler */
3316static
3317SCIP_DECL_CONSPARSE(consParseLinking)
3318{ /*lint --e{715}*/
3319 SCIP_VAR** binvars;
3320 SCIP_VAR* linkvar;
3321 SCIP_Real* vals;
3322 char* endptr;
3323 int varssize;
3324 int nbinvars;
3325
3326 assert(scip != NULL);
3327 assert(success != NULL);
3328 assert(str != NULL);
3329 assert(name != NULL);
3330 assert(cons != NULL);
3331
3332 *success = TRUE;
3333
3334 /* parse linking variable */
3335 SCIP_CALL( SCIPparseVarName(scip, str, &linkvar, &endptr) );
3336
3337 if( linkvar == NULL )
3338 {
3339 SCIPerrorMessage("unknown variable name at '%s'\n", str);
3340 *success = FALSE;
3341 return SCIP_OKAY;
3342 }
3343
3344 /* find "==" */
3345 endptr = strchr(endptr, '=');
3346
3347 /* if the string end has been reached without finding the "==" */
3348 if( endptr == NULL )
3349 {
3350 SCIPerrorMessage("Could not find initializing '='.\n");
3351 *success = FALSE;
3352 return SCIP_OKAY;
3353 }
3354
3355 str = endptr;
3356
3357 /* skip "==" */
3358 str += *(str+1) == '=' ? 2 : 1;
3359
3360 /* skip whitespace */
3361 SCIP_CALL( SCIPskipSpace((char**)&str) );
3362
3363 nbinvars = 0;
3364 varssize = 16;
3365 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, varssize) );
3366 SCIP_CALL( SCIPallocBufferArray(scip, &vals, varssize) );
3367
3368 /* check for the string "no binary variables yet" */
3369 if( strncmp(str, "no binary variables yet", 24) != 0 )
3370 {
3371 int requsize;
3372 int v;
3373
3374 /* parse linear sum to get variables and coefficients */
3375 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, binvars, vals, &nbinvars, varssize, &requsize, &endptr, success) );
3376
3377 if( *success && requsize > varssize )
3378 {
3379 /* realloc buffers and try again */
3380 varssize = requsize;
3381 SCIP_CALL( SCIPreallocBufferArray(scip, &binvars, varssize) );
3382 SCIP_CALL( SCIPreallocBufferArray(scip, &vals, varssize) );
3383
3384 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, binvars, vals, &nbinvars, varssize, &requsize, &endptr, success) );
3385 assert(!*success || requsize <= varssize); /* if successful, then should have had enough space now */
3386 }
3387
3388 /* check coefficients */
3389 if( *success )
3390 {
3391 /* convert SCIP_Real to integer */
3392 for( v = 0; v < nbinvars; ++v )
3393 {
3394 if( SCIPisIntegral(scip, vals[v]) )
3395 vals[v] = SCIPconvertRealToInt(scip, vals[v]);
3396 }
3397 }
3398 }
3399
3400 if( *success )
3401 {
3402 SCIP_CALL( SCIPcreateConsLinking(scip, cons, name, linkvar, binvars, vals, nbinvars,
3403 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3404 }
3405
3406 SCIPfreeBufferArray(scip, &vals);
3407 SCIPfreeBufferArray(scip, &binvars);
3408
3409 return SCIP_OKAY;
3410}
3411
3412/** constraint method of constraint handler which returns the variables (if possible) */
3413static
3414SCIP_DECL_CONSGETVARS(consGetVarsLinking)
3415{ /*lint --e{715}*/
3416 SCIP_CONSDATA* consdata;
3417
3418 consdata = SCIPconsGetData(cons);
3419 assert(consdata != NULL);
3420
3421 if( varssize < consdata->nbinvars + 1)
3422 (*success) = FALSE;
3423 else
3424 {
3425 assert(vars != NULL);
3426
3427 BMScopyMemoryArray(vars, consdata->binvars, consdata->nbinvars);
3428 vars[consdata->nbinvars] = consdata->linkvar;
3429 (*success) = TRUE;
3430 }
3431
3432 return SCIP_OKAY;
3433}
3434
3435/** constraint method of constraint handler which returns the number of variables (if possible) */
3436static
3437SCIP_DECL_CONSGETNVARS(consGetNVarsLinking)
3438{ /*lint --e{715}*/
3439 SCIP_CONSDATA* consdata;
3440
3441 consdata = SCIPconsGetData(cons);
3442 assert(consdata != NULL);
3443
3444 (*nvars) = consdata->nbinvars + 1;
3445 (*success) = TRUE;
3446
3447 return SCIP_OKAY;
3448}
3449
3450/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
3451static
3452SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinking)
3453{ /*lint --e{715}*/
3454 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
3455
3456 return SCIP_OKAY;
3457}
3458
3459/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
3460static
3461SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinking)
3462{ /*lint --e{715}*/
3463 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
3464
3465 return SCIP_OKAY;
3466}
3467
3468/*
3469 * Callback methods of event handler
3470 */
3471
3472/** execution method of event handler */
3473static
3474SCIP_DECL_EVENTEXEC(eventExecBinvar)
3475{ /*lint --e{715}*/
3476 SCIP_CONSDATA* consdata;
3477 SCIP_EVENTTYPE eventtype;
3478
3479 assert(eventhdlr != NULL);
3480 assert(eventdata != NULL);
3481 assert(event != NULL);
3482
3484
3485 consdata = (SCIP_CONSDATA*)eventdata;
3486 assert(consdata != NULL);
3487
3488 eventtype = SCIPeventGetType(event);
3489 switch( eventtype )
3490 {
3492 consdata->nfixedones++;
3493 break;
3495 consdata->nfixedones--;
3496 consdata->firstnonfixed = 0;
3497 consdata->lastnonfixed = consdata->nbinvars - 1;
3498 break;
3500 consdata->nfixedzeros++;
3501 break;
3503 consdata->firstnonfixed = 0;
3504 consdata->lastnonfixed = consdata->nbinvars - 1;
3505 consdata->nfixedzeros--;
3506 break;
3507 default:
3508 SCIPerrorMessage("invalid event type\n");
3509 return SCIP_INVALIDDATA;
3510 }
3511 assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nbinvars);
3512 assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nbinvars);
3513
3514 /*debugMsg(scip, " -> constraint has %d zero-fixed and %d one-fixed of %d variables\n",
3515 consdata->nfixedzeros, consdata->nfixedones, consdata->nvars);*/
3516
3517 return SCIP_OKAY;
3518}
3519
3520/*
3521 * constraint specific interface methods
3522 */
3523
3524/** creates the handler for linking constraints and includes it in SCIP */
3526 SCIP* scip /**< SCIP data structure */
3527 )
3528{
3529 SCIP_CONSHDLRDATA* conshdlrdata;
3530 SCIP_CONSHDLR* conshdlr;
3531 SCIP_EVENTHDLR* eventhdlr;
3532
3533 /* create event handler for bound change events */
3535 eventExecBinvar, NULL) );
3536
3537 /* create linking constraint handler data */
3538 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
3539
3540 /* include constraint handler */
3543 consEnfolpLinking, consEnfopsLinking, consCheckLinking, consLockLinking,
3544 conshdlrdata) );
3545
3546 assert(conshdlr != NULL);
3547
3548 /* set non-fundamental callbacks via specific setter functions */
3549 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinking, consCopyLinking) );
3550 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinking) );
3551 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinking) );
3552 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinking) );
3553 SCIP_CALL( SCIPsetConshdlrEnable(scip, conshdlr, consEnableLinking) );
3554 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinking) );
3555 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinking) );
3556 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinking) );
3557 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinking) );
3558 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinking) );
3559 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLinking) );
3560 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinking) );
3561 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinking) );
3563 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinking) );
3566 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinking) );
3567 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinking, consSepasolLinking, CONSHDLR_SEPAFREQ,
3569 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinking) );
3570 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinking) );
3571 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinking) );
3572 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinking) );
3573
3574 /* include the linear constraint to linking constraint upgrade in the linear constraint handler */
3575 /* SCIP_CALL( SCIPincludeLinconsUpgrade(scip, linconsUpgdLinking, LINCONSUPGD_PRIORITY, CONSHDLR_NAME) ); */
3576
3577 /* add linking constraint handler parameters */
3579 "constraints/" CONSHDLR_NAME "/linearize", "this constraint will not propagate or separate, linear and setppc are used?",
3580 &conshdlrdata->linearize, FALSE, DEFAULT_LINEARIZE, NULL, NULL) );
3581
3582 return SCIP_OKAY;
3583}
3584
3585/** creates and captures a linking constraint
3586 *
3587 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3588 */
3590 SCIP* scip, /**< SCIP data structure */
3591 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3592 const char* name, /**< name of constraint */
3593 SCIP_VAR* linkvar, /**< linking variable (continuous or integer) which should be linked */
3594 SCIP_VAR** binvars, /**< binary variables */
3595 SCIP_Real* vals, /**< coefficients of the binary variables */
3596 int nbinvars, /**< number of binary starting variables */
3597 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3598 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3599 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3600 * Usually set to TRUE. */
3601 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3602 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3603 SCIP_Bool check, /**< should the constraint be checked for feasibility?
3604 * TRUE for model constraints, FALSE for additional, redundant constraints. */
3605 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3606 * Usually set to TRUE. */
3607 SCIP_Bool local, /**< is constraint only valid locally?
3608 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3609 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3610 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3611 * adds coefficients to this constraint. */
3612 SCIP_Bool dynamic, /**< is constraint subject to aging?
3613 * Usually set to FALSE. Set to TRUE for own cuts which
3614 * are separated as constraints. */
3615 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3616 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3617 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3618 * if it may be moved to a more global node?
3619 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3620 )
3621{
3622 SCIP_CONSHDLR* conshdlr;
3623 SCIP_CONSDATA* consdata;
3624 SCIP_CONSHDLRDATA* conshdlrdata;
3625 int k;
3626
3627 assert(scip != NULL);
3628 assert(linkvar != NULL);
3629 assert(binvars != NULL || nbinvars == 0);
3630 assert(vals != NULL || nbinvars == 0);
3631
3632 /* find the linking constraint handler */
3633 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3634 if( conshdlr == NULL )
3635 {
3636 SCIPerrorMessage("linking constraint handler not found\n");
3637 return SCIP_PLUGINNOTFOUND;
3638 }
3639
3640 SCIPdebugMsg(scip, "create linking constraint for variable <%s> with %d binary variables (SCIP stage %d)\n",
3641 SCIPvarGetName(linkvar), nbinvars, SCIPgetStage(scip));
3642
3643 if( binvars == NULL && ( !SCIPvarIsIntegral(linkvar)
3645 || SCIPisInfinity(scip, SCIPvarGetUbGlobal(linkvar)) ) )
3646 {
3647 SCIPerrorMessage("linking variable <%s> is %s\n",
3648 SCIPvarGetName(linkvar), SCIPvarIsIntegral(linkvar) ? "unbounded" : "continuous");
3649 return SCIP_INVALIDDATA;
3650 }
3651
3652 for( k = 0; k < nbinvars; ++k )
3653 {
3654 SCIPdebugMsg(scip, "Var %d : <%s>\n", k, SCIPvarGetName(binvars[k]));
3655 if( !SCIPisFinite(vals[k]) || SCIPisInfinity(scip, REALABS(vals[k])) )
3656 {
3657 SCIPerrorMessage("linking value %lf of <%s> is %s\n",
3658 vals[k], SCIPvarGetName(binvars[k]), SCIPisFinite(vals[k]) ? "infinite" : "nan");
3659 return SCIP_INVALIDDATA;
3660 }
3661 }
3662
3663 /* get constraint handler data */
3664 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3665 assert(conshdlrdata != NULL);
3666
3667 if( conshdlrdata->varmap == NULL )
3668 {
3669 SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varmap, SCIPblkmem(scip), HASHSIZE_BINVARSCONS) );
3670 }
3671 assert(conshdlrdata->varmap != NULL);
3672
3673 /* check if the linking for the requests linking variable already exists */
3674 assert(!SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey(linkvar)));
3675
3676 /* create the constraint specific data */
3677 SCIP_CALL( consdataCreate(scip, conshdlrdata->eventhdlr, &consdata, linkvar, binvars, vals, nbinvars) );
3678
3679 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata,
3680 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3681
3682 /* create binary variables for the real domain */
3683 if( consdata->binvars == NULL )
3684 {
3685 SCIP_CALL( consdataCreateBinvars(scip, *cons, consdata, conshdlrdata->eventhdlr, conshdlrdata->linearize) );
3686 }
3687
3688 /* insert linking constraint into the hash map */
3689 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varmap, getHashmapKey(linkvar), *cons) );
3690 assert(SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey(linkvar)));
3691
3692 return SCIP_OKAY;
3693}
3694
3695/** creates and captures a linking constraint
3696 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3697 * method SCIPcreateConsLinking(); all flags can be set via SCIPsetCons<Flagname>-methods in scip.h
3698 *
3699 * @see SCIPcreateConsLinking() for information about the basic constraint flag configuration
3700 *
3701 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3702 */
3704 SCIP* scip, /**< SCIP data structure */
3705 SCIP_CONS** cons, /**< pointer to hold the created constraint */
3706 const char* name, /**< name of constraint */
3707 SCIP_VAR* linkvar, /**< linking variable (continuous or integer) which should be linked */
3708 SCIP_VAR** binvars, /**< binary variables, or NULL */
3709 SCIP_Real* vals, /**< coefficients of the binary variables */
3710 int nbinvars /**< number of binary variables */
3711 )
3712{
3713 assert(scip != NULL);
3714
3715 SCIP_CALL( SCIPcreateConsLinking(scip, cons, name, linkvar, binvars, vals, nbinvars,
3717
3718 return SCIP_OKAY;
3719}
3720
3721/** checks if for the given linking variable (continuous or integer) a linking constraint exists */
3723 SCIP* scip, /**< SCIP data structure */
3724 SCIP_VAR* linkvar /**< linking variable (continuous or integer) which should be linked */
3725 )
3726{
3727 SCIP_CONSHDLR* conshdlr;
3728 SCIP_CONSHDLRDATA* conshdlrdata;
3729
3730 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3731 assert(conshdlr != NULL);
3732
3733 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3734 assert(conshdlrdata != NULL);
3735
3736 return (conshdlrdata->varmap != NULL) && SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey(linkvar));
3737}
3738
3739/** returns the linking constraint belonging the given linking variable (continuous or integer) or NULL if it does not exist yet */
3741 SCIP* scip, /**< SCIP data structure */
3742 SCIP_VAR* linkvar /**< linking variable (continuous or integer) which should be linked */
3743 )
3744{
3745 SCIP_CONSHDLR* conshdlr;
3746 SCIP_CONSHDLRDATA* conshdlrdata;
3747
3748 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3749 assert(conshdlr != NULL);
3750
3751 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3752 assert(conshdlrdata != NULL);
3753
3754 if( conshdlrdata->varmap != NULL )
3755 return (SCIP_CONS*) SCIPhashmapGetImage(conshdlrdata->varmap, getHashmapKey(linkvar));
3756 else
3757 return NULL;
3758}
3759
3760/** returns the linking variable (continuous or integer) of the linking constraint */
3762 SCIP* scip, /**< SCIP data structure */
3763 SCIP_CONS* cons /**< linking constraint */
3764 )
3765{
3766 SCIP_CONSDATA* consdata;
3767
3768 assert(scip != NULL);
3769
3771
3772 consdata = SCIPconsGetData(cons);
3773 assert(consdata != NULL);
3774
3775 return consdata->linkvar;
3776}
3777
3778/** returns the binary variables of the linking constraint */
3780 SCIP* scip, /**< SCIP data structure */
3781 SCIP_CONS* cons, /**< linking constraint */
3782 SCIP_VAR*** binvars, /**< pointer to store the binary variables array pointer */
3783 int* nbinvars /**< pointer to store the number of returned binary variables */
3784 )
3785{
3786 SCIP_CONSDATA* consdata;
3787
3788 assert(scip != NULL);
3789
3791
3792 consdata = SCIPconsGetData(cons);
3793 assert(consdata != NULL);
3794 assert(consdata->binvars != NULL);
3795
3796 if( binvars != NULL )
3797 (*binvars) = consdata->binvars;
3798 if( nbinvars != NULL )
3799 (*nbinvars) = consdata->nbinvars;
3800
3801 return SCIP_OKAY;
3802}
3803
3804/** returns the number of binary variables of the linking constraint */
3806 SCIP* scip, /**< SCIP data structure */
3807 SCIP_CONS* cons /**< linking constraint */
3808 )
3809{
3810 SCIP_CONSDATA* consdata;
3811
3812 assert(scip != NULL);
3813
3815
3816 consdata = SCIPconsGetData(cons);
3817 assert(consdata != NULL);
3818
3819 return consdata->nbinvars;
3820}
3821
3822/** returns the coefficients of the binary variables */
3824 SCIP* scip, /**< SCIP data structure */
3825 SCIP_CONS* cons /**< linking constraint */
3826 )
3827{
3828 SCIP_CONSDATA* consdata;
3829
3830 assert(scip != NULL);
3831
3833
3834 consdata = SCIPconsGetData(cons);
3835 assert(consdata != NULL);
3836 consdataSort(consdata);
3837
3838 return consdata->vals;
3839}
3840
3841/** return all binary variable information of the linking constraint */
3843 SCIP_CONS* cons, /**< linking constraint */
3844 SCIP_VAR*** binvars, /**< pointer to store binary variables, or NULL */
3845 SCIP_Real** vals, /**< pointer to store the binary coefficients, or NULL */
3846 int* nbinvars /**< pointer to store the number of binary variables, or NULL */
3847 )
3848{
3849 SCIP_CONSDATA* consdata;
3850
3852
3853 consdata = SCIPconsGetData(cons);
3854 assert(consdata != NULL);
3855
3856 consdataSort(consdata);
3857
3858 if( binvars != NULL )
3859 *binvars = consdata->binvars;
3860 if( vals != NULL )
3861 *vals = consdata->vals;
3862 if( nbinvars != NULL )
3863 *nbinvars = consdata->nbinvars;
3864
3865 return SCIP_OKAY;
3866}
#define EVENTHDLR_NAME
SCIP_VAR ** b
#define EVENTHDLR_DESC
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:96
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:89
#define CONSHDLR_CHECKPRIORITY
Definition cons_and.c:88
#define CONSHDLR_DESC
Definition cons_and.c:85
#define CONSHDLR_PROP_TIMING
Definition cons_and.c:99
#define CONSHDLR_MAXPREROUNDS
Definition cons_and.c:93
#define CONSHDLR_SEPAPRIORITY
Definition cons_and.c:86
#define DEFAULT_LINEARIZE
Definition cons_and.c:105
#define CONSHDLR_PROPFREQ
Definition cons_and.c:90
#define CONSHDLR_PRESOLTIMING
Definition cons_and.c:98
#define CONSHDLR_EAGERFREQ
Definition cons_and.c:91
#define CONSHDLR_ENFOPRIORITY
Definition cons_and.c:87
#define CONSHDLR_DELAYSEPA
Definition cons_and.c:94
#define CONSHDLR_NAME
Definition cons_and.c:84
#define CONSHDLR_DELAYPROP
Definition cons_and.c:95
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars)
Constraint handler for linear constraints in their most general form, .
static SCIP_RETCODE consdataLinearize(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata)
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *linkvar, SCIP_VAR *binvar, SCIP_Bool lblinkvar, SCIP_Bool ublinkvar)
static SCIP_RETCODE enforcePseudo(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, SCIP_Bool *infeasible, int *nchgbds, SCIP_Bool *solvelp)
static SCIP_RETCODE addCuts(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
static SCIP_RETCODE catchAllEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE consFixLinkvar(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff)
static SCIP_RETCODE dropEvent(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE dropAllEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE removeFixedBinvars(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons)
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
static SCIP_RETCODE processBinvarFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool *addcut, SCIP_Bool *mustcheck)
static void * getHashmapKey(SCIP_VAR *var)
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **binvars, int nbinvars)
static SCIP_Bool checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
static SCIP_RETCODE catchEvent(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE processRealBoundChg(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool *mustcheck)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONSDATA **consdata, SCIP_VAR *linkvar, SCIP_VAR **binvars, SCIP_Real *vals, int nbinvars)
static SCIP_RETCODE consdataCreateBinvars(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool linearize)
static SCIP_RETCODE tightenedLinkvar(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *cutoff, int *nchgbds)
static SCIP_RETCODE createRows(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_CONS *cons, int pos)
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static void consdataSort(SCIP_CONSDATA *consdata)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff, SCIP_Bool *separated, int *nchgbds)
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
#define HASHSIZE_BINVARSCONS
constraint handler for linking binary variables to a linking (continuous or integer) variable
Constraint handler for the set partitioning / packing / covering constraints .
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
int SCIPgetNBinvarsLinking(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetBinvarsLinking(SCIP *scip, SCIP_CONS *cons, SCIP_VAR ***binvars, int *nbinvars)
SCIP_Bool SCIPexistsConsLinking(SCIP *scip, SCIP_VAR *linkvar)
SCIP_VAR * SCIPgetLinkvarLinking(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_CONS * SCIPgetConsLinking(SCIP *scip, SCIP_VAR *linkvar)
SCIP_RETCODE SCIPcreateConsLinking(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *linkvar, SCIP_VAR **binvars, SCIP_Real *vals, int nbinvars, 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 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 SCIPcreateConsBasicLinking(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *linkvar, SCIP_VAR **binvars, SCIP_Real *vals, int nbinvars)
SCIP_Real * SCIPgetValsLinking(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetBinvarsDataLinking(SCIP_CONS *cons, SCIP_VAR ***binvars, SCIP_Real **vals, int *nbinvars)
SCIP_RETCODE SCIPincludeConshdlrLinking(SCIP *scip)
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition scip_copy.c:713
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition scip_prob.c:1907
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3284
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition misc.c:3143
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition misc.c:3061
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3466
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition misc.c:3482
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:4067
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition misc.c:11162
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
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
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 SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:670
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrEnable(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:716
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:492
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition scip_cons.c:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition scip_cons.c:281
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:323
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition scip_cons.c:181
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:808
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:785
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:924
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),)
Definition scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:444
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:693
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4340
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:468
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:854
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition cons.c:8423
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1837
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2536
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8702
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition scip_cons.c:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
SCIP_Bool SCIPconsIsEnabled(SCIP_CONS *cons)
Definition cons.c:8490
SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1871
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1812
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition cons.c:8822
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8672
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:413
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition scip_lp.c:87
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
#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 SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition scip_mem.h:137
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:105
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition scip_nlp.c:110
SCIP_RETCODE SCIPaddLinearCoefToNlRow(SCIP *scip, SCIP_NLROW *nlrow, SCIP_VAR *var, SCIP_Real val)
Definition scip_nlp.c:1161
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition scip_nlp.c:1058
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition nlp.c:1953
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition scip_nlp.c:954
SCIP_Bool SCIPinProbing(SCIP *scip)
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition scip_lp.c:1718
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1398
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1974
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17917
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition scip_sol.c:467
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
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_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPconvertRealToInt(SCIP *scip, SCIP_Real real)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition scip_tree.c:146
int SCIPgetDepth(SCIP *scip)
Definition scip_tree.c:672
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5210
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition scip_var.c:8882
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition scip_var.c:2119
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition var.c:23803
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition var.c:23462
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition scip_var.c:10550
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:7069
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition var.c:23780
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17595
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition scip_var.c:728
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition scip_var.c:5118
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5296
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2872
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition scip_var.c:899
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition scip_var.c:120
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition scip_var.c:10318
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6964
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2736
SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:7412
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition scip_var.c:361
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition scip_var.c:474
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition scip_var.c:2078
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1853
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition var.c:23768
void SCIPsortRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
return SCIP_OKAY
int c
SCIP_Bool cutoff
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_Bool propagate
static SCIP_VAR ** vars
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition memory.h:134
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
public data structures and miscellaneous methods
#define SCIPisFinite(x)
Definition pub_misc.h:82
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 problem copies
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 solutions
public methods for the branch-and-bound tree
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
#define SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(x)
Definition type_cons.h:956
#define SCIP_DECL_CONSGETPERMSYMGRAPH(x)
Definition type_cons.h:938
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:363
#define SCIP_DECL_CONSINITPRE(x)
Definition type_cons.h:156
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:867
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:201
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:769
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
struct SYM_Graph SYM_GRAPH
Definition type_cons.h:68
#define SCIP_DECL_CONSENFORELAX(x)
Definition type_cons.h:388
#define SCIP_DECL_CONSPROP(x)
Definition type_cons.h:506
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:885
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:612
#define SCIP_DECL_CONSACTIVE(x)
Definition type_cons.h:691
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:845
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:706
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:561
#define SCIP_DECL_CONSENABLE(x)
Definition type_cons.h:721
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:259
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:676
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:810
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:474
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:108
#define SCIP_DECL_CONSEXITSOL(x)
Definition type_cons.h:216
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:116
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:320
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition type_event.h:127
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition type_event.h:79
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:259
#define SCIP_EVENTTYPE_LBRELAXED
Definition type_event.h:78
uint64_t SCIP_EVENTTYPE
Definition type_event.h:156
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition type_event.h:77
#define SCIP_EVENTTYPE_UBRELAXED
Definition type_event.h:80
@ SCIP_EXPRCURV_LINEAR
Definition type_expr.h:65
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_FEASIBLE
Definition type_result.h:45
@ SCIP_REDUCEDDOM
Definition type_result.h:51
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_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_PLUGINNOTFOUND
@ SCIP_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_PRESOLVING
Definition type_set.h:49
@ SCIP_STAGE_TRANSFORMED
Definition type_set.h:47
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
enum SYM_Symtype SYM_SYMTYPE
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition type_var.h:53
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition type_var.h:55
@ SCIP_VARSTATUS_LOOSE
Definition type_var.h:52
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141