Scippy

SCIP

Solving Constraint Integer Programs

cons_superindicator.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file cons_superindicator.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief constraint handler for indicator constraints over arbitrary constraint types
28 * @author Ambros Gleixner
29 * @author Frederic Pythoud
30 */
31
32/**@todo allow more types for slack constraint */
33/**@todo implement more upgrades, e.g., for nonlinear, quadratic, logicor slack constraints; upgrades could also help to
34 * handle difficult slack constraints such as pseudoboolean or indicator
35 */
36/**@todo unify enfolp and enfops, sepalp and sepaps callbacks */
37/**@todo enforce by branching on binary variable if slack constraint only returns SCIP_INFEASIBLE */
38/**@todo consider enforcing by adding slack constraint (or copy of it) locally if binary variable is fixed to 1
39 * (some constraint handler cannot enforce constraints that are not active)
40 */
41
42/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
43
45#include "scip/cons_indicator.h"
46#include "scip/cons_linear.h"
48#include "scip/dialog_default.h"
49#include "scip/pub_cons.h"
50#include "scip/pub_dialog.h"
51#include "scip/pub_heur.h"
52#include "scip/pub_message.h"
53#include "scip/pub_misc.h"
54#include "scip/pub_sol.h"
55#include "scip/pub_var.h"
56#include "scip/scip_conflict.h"
57#include "scip/scip_cons.h"
58#include "scip/scip_copy.h"
59#include "scip/scip_dialog.h"
60#include "scip/scip_general.h"
61#include "scip/scip_mem.h"
62#include "scip/scip_message.h"
63#include "scip/scip_numerics.h"
64#include "scip/scip_param.h"
65#include "scip/scip_prob.h"
66#include "scip/scip_sol.h"
67#include "scip/scip_var.h"
68#include "scip/symmetry_graph.h"
69#include <string.h>
70
71/* constraint handler properties */
72#define CONSHDLR_NAME "superindicator"
73#define CONSHDLR_DESC "constraint handler for indicator constraints over arbitrary constraint types"
74#define CONSHDLR_SEPAPRIORITY 0 /**< priority of the constraint handler for separation */
75#define CONSHDLR_ENFOPRIORITY -5000000 /**< priority of the constraint handler for constraint enforcing */
76#define CONSHDLR_CHECKPRIORITY -5000000 /**< priority of the constraint handler for checking feasibility */
77#define CONSHDLR_SEPAFREQ -1 /**< frequency for separating cuts; zero means to separate only in the root node */
78#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
79#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
80 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
81#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler
82 * participates in (-1: no limit) */
83#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
84#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
85#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
86
87#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
88#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
89
90#define DEFAULT_CHECKSLACKTYPE TRUE /**< should type of slack constraint be checked when creating superindicator constraint? */
91#define DEFAULT_UPGDPRIOINDICATOR 1 /**< priority for upgrading to an indicator constraint (-1: never) */
92#define DEFAULT_UPGDPRIOLINEAR 2 /**< priority for upgrading to a linear constraint (-1: never) */
93#define DEFAULT_MAXUPGDCOEFLINEAR 1e4 /**< maximum big-M coefficient of binary variable in upgrade to a linear constraint
94 * (relative to smallest coefficient) */
95
96
97/*
98 * Data structures
99 */
100
101/** constraint data for superindicator constraints */
102struct SCIP_ConsData
103{
104 SCIP_CONS* slackcons; /**< constraint corresponding to the handled constraint */
105 SCIP_VAR* binvar; /**< binary variable for indicator constraint */
106};
107
108/** constraint handler data */
109struct SCIP_ConshdlrData
110{
111 SCIP_Bool checkslacktype; /**< should type of slack constraint be checked when creating superindicator constraint? */
112 SCIP_Real maxupgdcoeflinear; /**< maximum big-M coefficient of binary variable in upgrade to a linear constraint
113 * (relative to smallest coefficient) */
114 int upgdprioindicator; /**< priority for upgrading to an indicator constraint (-1: never) */
115 int upgdpriolinear; /**< priority for upgrading to a linear constraint (-1: never) */
116 int nrejects; /**< number of rejected calls to create method */
117};
118
119/*
120 * Local methods
121 */
122
123/** creates superindicator constraint data */
124static
126 SCIP* scip, /**< SCIP data structure */
127 SCIP_CONSDATA** consdata, /**< pointer to constraint data */
128 SCIP_VAR* binvar, /**< binary variable */
129 SCIP_CONS* slackcons /**< slack constraint */
130 )
131{
132 assert(scip != NULL);
133
134 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
135
136 (*consdata)->binvar = binvar;
137 (*consdata)->slackcons = slackcons;
138
140 {
141 SCIPdebugMsg(scip, "creating the transformed data\n");
142
143 /* do not capture the slack constraint when scip is in transformed mode; this automatically happens in
144 * SCIPtransformCons() if necessary
145 */
146 SCIP_CALL( SCIPtransformCons(scip, (*consdata)->slackcons, &(*consdata)->slackcons) );
147
148 /* get transformed binary variable */
149 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->binvar, &(*consdata)->binvar) );
150 }
151 else
152 {
153 /* we need to capture the constraint to avoid that SCIP deletes them since they are not (yet) added to the problem */
154 SCIP_CALL( SCIPcaptureCons(scip, slackcons) );
155 }
156
157 assert((*consdata)->slackcons != NULL);
158
159 return SCIP_OKAY;
160}
161
162/** checks the feasibility of a superindicator constraint */
163static
165 SCIP* scip, /**< SCIP data structure */
166 SCIP_CONSDATA* consdata, /**< pointer to superindicator constraint data */
167 SCIP_SOL* sol, /**< pointer to the solution to be checked */
168 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */
169 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
170 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
171 SCIP_RESULT* result /**< pointer to store the result of the test */
172 )
173{
174 SCIP_Real binval;
175
176 /* not to be called if infeasibility is already detected */
177 assert(*result == SCIP_FEASIBLE || *result == SCIP_DIDNOTRUN);
178
179 binval = SCIPgetSolVal(scip, sol, consdata->binvar);
180
181 /* check integrality of binary variable */
182 if( checkintegrality && !SCIPisIntegral(scip, binval) )
183 {
184 if( printreason )
185 {
186 SCIPinfoMessage(scip, NULL, "violation: binvar takes fractional value %.15g\n", binval);
187 }
188
189 *result = SCIP_INFEASIBLE;
190 }
191 /* if binvar is one, call SCIPcheckCons() for the slack constraint */
192 else if( binval > 0.5 )
193 {
194 assert(SCIPisFeasEQ(scip, binval, 1.0));
195
196 SCIP_CALL( SCIPcheckCons(scip, consdata->slackcons, sol, checkintegrality, checklprows, printreason, result) );
197
198 if( printreason && *result != SCIP_FEASIBLE )
199 {
200 SCIPinfoMessage(scip, NULL, "violation: SCIPcheckCons() for slack constraint <%s> returns infeasible while binvar <%s> == 1\n",
201 SCIPconsGetName(consdata->slackcons), SCIPvarGetName(consdata->binvar));
202 }
203
204#ifdef SCIP_DEBUG
205 {
206 /* checking in debug mode that different flags don't give us different results */
207 SCIP_RESULT testresultnotintegrality;
208 SCIP_RESULT testresultnotlprows;
209
210 SCIP_CALL( SCIPcheckCons(scip, consdata->slackcons, sol, checkintegrality, TRUE, TRUE, &testresultnotintegrality) );
211 SCIP_CALL( SCIPcheckCons(scip, consdata->slackcons, sol, TRUE, checklprows, TRUE, &testresultnotlprows) );
212
213 assert(*result == testresultnotintegrality);
214 assert(*result == testresultnotlprows);
215 }
216#endif
217
218 SCIPdebugMsg(scip, "binvar <%s> == 1, sol=%p --> SCIPcheckCons() on constraint <%s> --> %s\n",
219 SCIPvarGetName(consdata->binvar), (void*)sol, SCIPconsGetName(consdata->slackcons),
220 *result == SCIP_FEASIBLE ? "satisfied" : "violated");
221 }
222 /* if binval is zero, the superindicator constraint is feasible */
223 else
224 {
225 *result = SCIP_FEASIBLE;
226 }
227
228 return SCIP_OKAY;
229}
230
231/** computes the minactivity, maxactivity, and minimal absolute value of nonzero coefficients of a linear constraint
232 * with respect to its global bounds
233 */
234static
236 SCIP* scip, /**< SCIP data structure */
237 SCIP_CONS* cons, /**< pointer to linear constraint */
238 SCIP_Real* minactivity, /**< pointer to return the minimal activity */
239 SCIP_Real* maxactivity, /**< pointer to return the maximal activity */
240 SCIP_Real* minabscoef /**< pointer to return the minimal absolute value of the coefficients */
241 )
242{
243 SCIP_VAR** vars;
244 SCIP_Real* vals;
245 SCIP_Bool ismininfinity;
246 SCIP_Bool ismaxinfinity;
247 int nvars;
248 int i;
249
250 assert(scip != NULL);
251 assert(cons != NULL);
252 assert(minactivity != NULL);
253 assert(maxactivity != NULL);
254 assert(minabscoef != NULL);
255 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") == 0);
256
257 /* get nonzero elements */
258 vars = SCIPgetVarsLinear(scip, cons);
259 vals = SCIPgetValsLinear(scip, cons);
260 nvars = SCIPgetNVarsLinear(scip, cons);
261
262 /* initialize values */
263 *minactivity = 0.0;
264 *maxactivity = 0.0;
265 *minabscoef = SCIPinfinity(scip);
266 ismininfinity = FALSE;
267 ismaxinfinity = FALSE;
268
269 /* we loop over all the coefficients of the constraint and we cannot end if the minactivity is infinite as we
270 * still need to compute the minimum absolute coefficient value
271 */
272 for( i = nvars-1; i >= 0; i-- )
273 {
274 SCIP_Real val;
275 SCIP_Real lb;
276 SCIP_Real ub;
277
278 val = vals[i];
279 lb = SCIPvarGetLbGlobal(vars[i]);
280 ub = SCIPvarGetUbGlobal(vars[i]);
281
282 /* update flags for infinite bounds */
283 ismininfinity = ismininfinity || (val > 0.0 && (SCIPisInfinity(scip, lb) || SCIPisInfinity(scip, -lb)))
284 || (val < 0.0 && (SCIPisInfinity(scip, ub) || SCIPisInfinity(scip, -ub)));
285
286 ismaxinfinity = ismaxinfinity || (val > 0.0 && (SCIPisInfinity(scip, ub) || SCIPisInfinity(scip, -ub)))
287 || (val < 0.0 && (SCIPisInfinity(scip, lb) || SCIPisInfinity(scip, -lb)));
288
289 /* update activities if not infinite */
290 if( !ismininfinity )
291 *minactivity += (val > 0.0) ? val * lb : val * ub;
292
293 if( !ismaxinfinity )
294 *maxactivity += (val > 0.0) ? val * ub : val * lb;
295
296 /* update minimal absolute coefficient value */
297 if( val > 0.0 && val < *minabscoef )
298 *minabscoef = val;
299 else if( val < 0.0 && -val < *minabscoef )
300 *minabscoef = -vals[i];
301 }
302
303 if( ismininfinity )
304 *minactivity = -SCIPinfinity(scip);
305
306 if( ismaxinfinity )
307 *maxactivity = SCIPinfinity(scip);
308}
309
310/** tries to upgrade superindicator constraint to an indicator constraint */
311static
313 SCIP* scip, /**< SCIP data structure */
314 SCIP_CONS* cons, /**< superindicator constraint to be upgraded */
315 SCIP_Bool* success, /**< pointer to store if the upgrading was successful */
316 SCIP_Bool* deleted /**< pointer to store if the constraint was deleted */
317 )
318{
319 SCIP_CONSHDLR* conshdlr;
320 SCIP_CONSDATA* consdata;
321 SCIP_CONS* indcons;
322
323 SCIP_Real lhs;
324 SCIP_Real rhs;
325 char name[SCIP_MAXSTRLEN];
326 int i;
327
328#ifdef SCIP_DEBUG
329 int nnewconss;
330#endif
331
332 assert(scip != NULL);
333 assert(cons != NULL);
334 assert(success != NULL);
335 assert(deleted != NULL);
336
337 *success = FALSE;
338 *deleted = FALSE;
339
340 SCIPdebug( nnewconss = 0 );
341
342 /* get data of superindicator constraint */
343 consdata = SCIPconsGetData(cons);
344 assert(consdata != NULL);
345
346 /* upgrade only for linear slack constraint */
347 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(consdata->slackcons)), "linear") != 0 )
348 return SCIP_OKAY;
349
350 /* upgrade only if indicator constraint handler found */
351 conshdlr = SCIPfindConshdlr(scip, "indicator");
352 if( conshdlr == NULL )
353 return SCIP_OKAY;
354
355 /* if linear slack constraint is free we can delete the superindicator constraint */
356 lhs = SCIPgetLhsLinear(scip, consdata->slackcons);
357 rhs = SCIPgetRhsLinear(scip, consdata->slackcons);
358 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
359 {
360 SCIP_CALL( SCIPdelCons(scip, cons) );
361 *deleted = TRUE;
362
363 SCIPdebugMsg(scip, "constraint <%s> deleted because of free slack constraint\n", SCIPconsGetName(cons));
364
365 return SCIP_OKAY;
366 }
367
368 /* upgrade rhs inequality */
369 if( !SCIPisInfinity(scip, rhs) )
370 {
371 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_upgd_indrhs", SCIPconsGetName(cons));
372
373 SCIP_CALL( SCIPcreateConsIndicator(scip, &indcons, name, consdata->binvar, SCIPgetNVarsLinear(scip, consdata->slackcons),
374 SCIPgetVarsLinear(scip, consdata->slackcons), SCIPgetValsLinear(scip, consdata->slackcons), rhs,
378
379 SCIP_CALL( SCIPaddCons(scip, indcons) );
380 SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
381
382 SCIPdebug( nnewconss++ );
383 }
384
385 /* upgrade lhs inequality */
386 if( !SCIPisInfinity(scip, -lhs) )
387 {
388 SCIP_Real* negvals;
389 SCIP_Real* vals;
390 int nvars;
391
392 vals = SCIPgetValsLinear(scip, consdata->slackcons);
393 nvars = SCIPgetNVarsLinear(scip, consdata->slackcons);
394
395 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_upgd_indlhs", SCIPconsGetName(cons));
396
397 /* create array of negated coefficient values */
398 SCIP_CALL( SCIPallocBufferArray(scip, &negvals, nvars) );
399 for( i = nvars-1; i >= 0; i-- )
400 negvals[i] = -vals[i];
401
402 SCIP_CALL( SCIPcreateConsIndicator(scip, &indcons, name, consdata->binvar, nvars,
403 SCIPgetVarsLinear(scip, consdata->slackcons), negvals, -lhs,
407
408 SCIP_CALL( SCIPaddCons(scip, indcons) );
409 SCIP_CALL( SCIPreleaseCons(scip, &indcons) );
410
411 SCIPfreeBufferArray(scip, &negvals);
412
413 SCIPdebug( nnewconss++ );
414 }
415
416 SCIPdebug( SCIPdebugMsg(scip, "constraint <%s> upgraded to %d indicator constraint%s\n",
417 SCIPconsGetName(cons), nnewconss, nnewconss == 1 ? "" : "s") );
418
419 /* delete the superindicator constraint */
420 SCIP_CALL( SCIPdelCons(scip, cons) );
421 *success = TRUE;
422
423 return SCIP_OKAY;
424}
425
426/** upgrades a superindicator constraint to a linear constraint if possible */
427static
429 SCIP* scip, /**< SCIP data structure */
430 SCIP_CONS* cons, /**< superindicator constraint to be upgraded */
431 SCIP_Bool* success, /**< pointer to store if the upgrading was successful */
432 SCIP_Bool* deleted /**< pointer to store if the constraint was deleted */
433 )
434{
435 SCIP_CONSHDLR* conshdlr;
436 SCIP_CONSDATA* consdata;
437 SCIP_CONS* slackcons;
438 SCIP_VAR** slackvars;
439 SCIP_VAR** newvars;
440 SCIP_Real* slackvals;
441 SCIP_Real* newvals;
442
443 SCIP_Real maxcoef;
444 SCIP_Real minabscoef;
445 SCIP_Real minact;
446 SCIP_Real maxact;
447 SCIP_Real lhs;
448 SCIP_Real rhs;
449
450 int nvars;
451 int i;
452
453#ifdef SCIP_DEBUG
454 int nnewconss;
455#endif
456
457 assert(scip != NULL);
458 assert(cons != NULL);
459 assert(success != NULL);
460 assert(deleted != NULL);
461
462 *success = FALSE;
463 *deleted = FALSE;
464
465 SCIPdebug( nnewconss = 0 );
466
467 /* get data of superindicator constraint */
468 consdata = SCIPconsGetData(cons);
469 assert(consdata != NULL);
470
471 slackcons = consdata->slackcons;
472 assert(slackcons != NULL);
473
474 /* upgrade only for linear slack constraint */
475 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "linear") != 0 )
476 return SCIP_OKAY;
477
478 /**@todo store in conshdlrdata */
479
480 /* upgrade only if linear constraint handler found */
481 conshdlr = SCIPfindConshdlr(scip, "linear");
482 if( conshdlr == NULL )
483 return SCIP_OKAY;
484
485 /* if linear slack constraint is free we can delete the superindicator constraint */
486 rhs = SCIPgetRhsLinear(scip, slackcons);
487 lhs = SCIPgetLhsLinear(scip, slackcons);
488
489 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
490 {
491 SCIP_CALL( SCIPdelCons(scip, cons) );
492 *deleted = TRUE;
493
494 SCIPdebugMsg(scip, "constraint <%s> deleted because of free slack constraint\n", SCIPconsGetName(cons));
495
496 return SCIP_OKAY;
497 }
498
499 /* if linear slack constraint is redundant due to bounded activities we can delete the superindicator constraint */
500 extractLinearValues(scip, slackcons, &minact, &maxact, &minabscoef);
501 assert(!SCIPisInfinity(scip, minact));
502 assert(!SCIPisInfinity(scip, -maxact));
503
504 if( (SCIPisInfinity(scip, -lhs) || SCIPisLE(scip, lhs, minact)) && (SCIPisInfinity(scip, rhs) || SCIPisGE(scip, rhs, maxact)) )
505 {
506 SCIP_CALL( SCIPdelCons(scip, cons) );
507 *deleted = TRUE;
508
509 SCIPdebugMsg(scip, "constraint <%s> deleted because of redundant slack constraint\n", SCIPconsGetName(cons));
510
511 return SCIP_OKAY;
512 }
513
514 /* if the big-M coefficient is too large compared to the coefficients of the slack constraint, we do not upgrade to
515 * avoid numerical problems
516 */
517 maxcoef = minabscoef * SCIPconshdlrGetData(SCIPconsGetHdlr(cons))->maxupgdcoeflinear;
518
519 if( (!SCIPisInfinity(scip, rhs) && (SCIPisInfinity(scip, maxact) || SCIPisInfinity(scip, maxact - rhs) ||
520 maxact - rhs > maxcoef)) ||
521 (!SCIPisInfinity(scip, -lhs) && (SCIPisInfinity(scip, -minact) || SCIPisInfinity(scip, lhs - minact) ||
522 lhs - minact > maxcoef)) )
523 {
524 SCIPdebugMsg(scip, "constraint <%s> not upgraded to a linear constraint due to large big-M coefficient\n",
525 SCIPconsGetName(cons));
526 return SCIP_OKAY;
527 }
528
529 /* allocating memory for new constraint */
530 nvars = SCIPgetNVarsLinear(scip, slackcons);
531 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars+1) );
532 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, nvars+1) );
533
534 /* copy the vars and the vals array */
535 slackvars = SCIPgetVarsLinear(scip, slackcons);
536 slackvals = SCIPgetValsLinear(scip, slackcons);
537
538 assert(slackvars != NULL);
539 assert(slackvals != NULL);
540
541 for( i = nvars-1; i >= 0; i-- )
542 {
543 newvars[i] = slackvars[i];
544 newvals[i] = slackvals[i];
545 }
546
547 /* add binary variable */
548 newvars[nvars] = consdata->binvar;
549 assert(newvars[nvars] != NULL);
550
551 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
552
553 /* create the upgraded constraint for rhs inequality */
554 if( !SCIPisInfinity(scip, rhs) )
555 {
556 SCIP_CONS* newcons;
557 char name[SCIP_MAXSTRLEN];
558
559 assert(!SCIPisInfinity(scip, -maxact) );
560 assert(!SCIPisInfinity(scip, maxact));
561
562 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_upgd_linrhs", SCIPconsGetName(cons));
563
564 /* compute big-M */
565 newvals[nvars] = maxact - rhs;
566 assert(!SCIPisInfinity(scip, newvals[nvars]));
567 assert(!SCIPisInfinity(scip, -newvals[nvars]));
568
569 /* rhs inequality is redundant if maxact is less equal rhs */
570 if( SCIPisPositive(scip, newvals[nvars]) )
571 {
572 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, nvars+1, newvars, newvals, -SCIPinfinity(scip), maxact,
576
577 SCIP_CALL( SCIPaddCons(scip, newcons) );
578 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
579
580 SCIPdebug( nnewconss++ );
581 }
582 }
583
584 /* create the upgraded constraint for rhs inequality */
585 if( !SCIPisInfinity(scip, -lhs) )
586 {
587 SCIP_CONS* newcons;
588 char name[SCIP_MAXSTRLEN];
589
590 assert(!SCIPisInfinity(scip, minact));
591 assert(!SCIPisInfinity(scip, -minact));
592
593 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_upgd_linlhs", SCIPconsGetName(cons));
594
595 /* compute big-M */
596 newvals[nvars] = minact - lhs;
597 assert(!SCIPisInfinity(scip, newvals[nvars]));
598 assert(!SCIPisInfinity(scip, -newvals[nvars]));
599
600 /* lhs inequality is redundant if minact is greater equal lhs */
601 if( SCIPisNegative(scip, newvals[nvars]) )
602 {
603 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, nvars+1, newvars, newvals, minact, SCIPinfinity(scip),
607
608 SCIP_CALL( SCIPaddCons(scip, newcons) );
609 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
610
611 SCIPdebug( nnewconss++ );
612 }
613 }
614
615 /* free memory */
616 SCIPfreeBufferArray(scip, &newvals);
617 SCIPfreeBufferArray(scip, &newvars);
618
619 SCIPdebug( SCIPdebugMsg(scip, "constraint <%s> upgraded to %d indicator constraint%s\n",
620 SCIPconsGetName(cons), nnewconss, nnewconss == 1 ? "" : "s") );
621
622 /* delete the superindicator constraint */
623 SCIP_CALL( SCIPdelCons(scip, cons) );
624 *success = TRUE;
625
626 return SCIP_OKAY;
627}
628
629/** tries to upgrade a superindicator constraint in order of the upgrade priority parameters */
630static
632 SCIP* scip, /**< SCIP data structure */
633 SCIP_CONS* cons, /**< superindicator constraint to be updated */
634 SCIP_Bool* success, /**< pointer to store if the constraint was upgraded */
635 SCIP_Bool* deleted /**< pointer to store if the constraint was deleted */
636 )
637{
638 SCIP_CONSHDLRDATA* conshdlrdata;
639
640 assert(scip != NULL);
641 assert(cons != NULL);
642 assert(success != NULL);
643 assert(deleted != NULL);
644
645 *success = FALSE;
646 *deleted = FALSE;
647
648 conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
649
650 /* indicator upgrade before linear upgrade */
651 if( conshdlrdata->upgdprioindicator > conshdlrdata->upgdpriolinear )
652 {
653 assert(conshdlrdata->upgdprioindicator >= 0);
654
655 SCIP_CALL( upgradeIndicatorSuperindicator(scip, cons, success, deleted) );
656
657 if( !*deleted && !*success && conshdlrdata->upgdpriolinear >= 0 )
658 {
659 SCIP_CALL( upgradeLinearSuperindicator(scip, cons, success, deleted) );
660 }
661 }
662 /* linear upgrade before indicator upgrade */
663 else if( conshdlrdata->upgdpriolinear >= 0 )
664 {
665 SCIP_CALL( upgradeLinearSuperindicator(scip, cons, success, deleted) );
666
667 if( !*deleted && !*success && conshdlrdata->upgdprioindicator >= 0 )
668 {
669 SCIP_CALL( upgradeIndicatorSuperindicator(scip, cons, success, deleted) );
670 }
671 }
672
673 return SCIP_OKAY;
674}
675
676/** helper function to enforce constraints */ /*lint -e{715}*/
677static
679 SCIP* scip, /**< SCIP data structure */
680 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
681 SCIP_CONS** conss, /**< constraints to process */
682 int nconss, /**< number of constraints */
683 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
684 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
685 SCIP_Bool solinfeasible, /**< was the solution already declared infeasible by a constraint handler? */
686 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
687 )
688{ /*lint --e{715}*/
689 SCIP_Bool cont;
690 int i;
691
692 assert(scip != NULL);
693 assert(conshdlr != NULL);
694 assert(result != NULL);
695
696 /* if the solution is infeasible anyway, skip the enforcement */
697 if( solinfeasible )
698 {
699 *result = SCIP_FEASIBLE;
700 return SCIP_OKAY;
701 }
702
703 SCIPdebugMsg(scip, "executing enforcement callback for %s solution\n", sol == NULL ? "LP" : "relaxation");
704
705 cont = TRUE;
706 *result = SCIP_FEASIBLE;
707
708#ifdef SCIP_OUTPUT
710#endif
711
712 /* check all constraints */
713 for( i = nconss-1; i >= 0 && cont; i-- )
714 {
715 SCIP_CONSDATA* consdata;
716 SCIP_RESULT locresult;
717
718 consdata = SCIPconsGetData(conss[i]);
719 assert(consdata != NULL);
720
721 locresult = SCIP_FEASIBLE;
722
723 /* enforce only if binvar is fixed to one */
724 if( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
725 {
726 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->binvar), 1.0));
727
728 if( sol == NULL )
729 {
730 SCIPdebugMsg(scip, "binvar <%s> == 1 locally --> SCIPenfolpCons() on constraint <%s>\n",
731 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
732
733 SCIP_CALL( SCIPenfolpCons(scip, consdata->slackcons, solinfeasible, &locresult) );
734 }
735 else
736 {
737 SCIPdebugMsg(scip, "binvar <%s> == 1 locally --> SCIPenforelaxCons() on constraint <%s>\n",
738 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
739
740 SCIP_CALL( SCIPenforelaxCons(scip, consdata->slackcons, sol, solinfeasible, &locresult) );
741 }
742
743 SCIPdebugPrintf(" --> %slocresult=%d\n", locresult == SCIP_FEASIBLE ? "satisfied, " : "", locresult);
744 }
745 /* otherwise check if we have not yet detected infeasibility */
746 else if( *result == SCIP_FEASIBLE )
747 {
748 SCIP_CALL( consdataCheckSuperindicator(scip, consdata, sol, TRUE, FALSE, FALSE, &locresult) );
749 }
750
751 /* evaluate result */
752 switch( locresult )
753 {
754 case SCIP_CUTOFF:
755 case SCIP_BRANCHED:
756 assert(*result != SCIP_CUTOFF);
757 assert(*result != SCIP_BRANCHED);
758 *result = locresult;
759 cont = FALSE;
760 break;
761 case SCIP_CONSADDED:
762 assert(*result != SCIP_CUTOFF);
763 assert(*result != SCIP_BRANCHED);
764 if( *result != SCIP_CUTOFF )
765 *result = locresult;
766 break;
767 case SCIP_REDUCEDDOM:
768 assert(*result != SCIP_CUTOFF);
769 assert(*result != SCIP_BRANCHED);
770 if( *result != SCIP_CUTOFF
771 && *result != SCIP_CONSADDED )
772 *result = locresult;
773 break;
774 case SCIP_SEPARATED:
775 assert(*result != SCIP_CUTOFF);
776 assert(*result != SCIP_BRANCHED);
777 if( *result != SCIP_CUTOFF
778 && *result != SCIP_CONSADDED
779 && *result != SCIP_REDUCEDDOM )
780 *result = locresult;
781 break;
782 case SCIP_INFEASIBLE:
783 assert(*result != SCIP_CUTOFF);
784 assert(*result != SCIP_BRANCHED);
785 if( *result != SCIP_CUTOFF
786 && *result != SCIP_CONSADDED
787 && *result != SCIP_REDUCEDDOM
788 && *result != SCIP_SEPARATED
789 && *result != SCIP_BRANCHED )
790 *result = locresult;
791 break;
792 case SCIP_FEASIBLE:
793 break;
794 default:
795 SCIPerrorMessage("invalid SCIP result %d\n", locresult);
796 return SCIP_INVALIDRESULT;
797 } /*lint !e788*/
798 }
799
800 SCIPdebugMsg(scip, "enforcement result=%d\n", *result);
801
802 return SCIP_OKAY;
803}
804
805
806/** adds symmetry information of constraint to a symmetry detection graph */
807static
809 SCIP* scip, /**< SCIP pointer */
810 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
811 SCIP_CONS* cons, /**< constraint */
812 SYM_GRAPH* graph, /**< symmetry detection graph */
813 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
814 )
815{
816 SYM_GRAPH* symgraph;
817 SCIP_CONSHDLR* conshdlr;
818 SCIP_CONSDATA* consdata;
819 SCIP_VAR** vars;
820 SCIP_Real* vals;
821 SCIP_Real constant;
822 int nlocvars;
823 int rootnode;
824 int subroot = -1;
825
826 assert(scip != NULL);
827 assert(cons != NULL);
828 assert(graph != NULL);
829 assert(success != NULL);
830
831 *success = TRUE;
832
833 consdata = SCIPconsGetData(cons);
834 assert(consdata != NULL);
835 assert(consdata->binvar != NULL);
836 assert(consdata->slackcons != NULL);
837
838 /* terminate if slackcons cannot provide a symmetry detection graph */
839 conshdlr = SCIPconsGetHdlr(consdata->slackcons);
840 assert(conshdlr != NULL);
841
842 if( (symtype == SYM_SYMTYPE_PERM && !SCIPconshdlrSupportsPermsymDetection(conshdlr))
844 {
845 *success = FALSE;
846 return SCIP_OKAY;
847 }
848
849 /* start building the symmetry detection graph for the superindicator constraint */
850 SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &rootnode) );
851
852 /* copy symmetry detection graph of slackcons, use modest estimation for graph size */
854 15, 15, 1, SCIPgetNVars(scip)) );
855
856 if( symtype == SYM_SYMTYPE_PERM )
857 {
858 SCIP_CALL( SCIPgetConsPermsymGraph(scip, consdata->slackcons, symgraph, success) );
859 }
860 else
861 {
862 assert(symtype == SYM_SYMTYPE_SIGNPERM);
863
864 SCIP_CALL( SCIPgetConsSignedPermsymGraph(scip, consdata->slackcons, symgraph, success) );
865 }
866
867 if( *success )
868 {
869 /* copy the symmetry detection graph and find its root node with index in target graph */
870 SCIP_CALL( SCIPcopySymgraphAsSubgraph(scip, symgraph, graph, consdata->slackcons, &subroot) );
871
872 if( subroot < 0 )
873 *success = FALSE;
874
875 /* connect root of superindicator constraint with root of copied graph */
876 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnode, subroot, FALSE, 0.0) );
877 }
878 SCIP_CALL( SCIPfreeSymgraph(scip, &symgraph) );
879
880 if( !(*success) )
881 return SCIP_OKAY;
882
883 /* connect root node with binary variable (possibly resolve aggregation) */
886
887 vars[0] = consdata->binvar;
888 vals[0] = 1.0;
889 constant = 0.0;
890 nlocvars = 1;
891
892 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
893
894 if( nlocvars > 1 || !SCIPisEQ(scip, vals[0], 1.0) || !SCIPisZero(scip, constant) )
895 {
896 int opnodeidx;
897
898 /* encode aggregation by a sum-expression and connect it to indicator node */
899 SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &opnodeidx) ); /*lint !e641*/
900 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnode, opnodeidx, FALSE, 0.0) );
901
902 /* add nodes and edges for variables in aggregation */
903 SCIP_CALL( SCIPaddSymgraphVarAggregation(scip, graph, opnodeidx, vars, vals, nlocvars, constant) );
904 }
905 else if( nlocvars == 1 )
906 {
907 int nodeidx;
908
909 if( symtype == SYM_SYMTYPE_SIGNPERM )
910 {
911 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, vars[0]);
912 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnode, nodeidx, TRUE, 1.0) );
913
914 nodeidx = SCIPgetSymgraphNegatedVarnodeidx(scip, graph, vars[0]);
915 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnode, nodeidx, TRUE, -1.0) );
916 }
917 else
918 {
919 nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, vars[0]);
920 SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, rootnode, nodeidx, TRUE, 1.0) );
921 }
922 }
925
926 return SCIP_OKAY;
927}
928
929
930/*
931 * Callback methods of constraint handler
932 */
933
934/** copy method for constraint handler plugins (called when SCIP copies plugins) */
935static
936SCIP_DECL_CONSHDLRCOPY(conshdlrCopySuperindicator)
937{ /*lint --e{715}*/
938 assert(scip != NULL);
939 assert(conshdlr != NULL);
940 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
941
942 /* call inclusion method of constraint handler */
944
945 *valid = TRUE;
946
947 return SCIP_OKAY;
948}
949
950/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
951static
952SCIP_DECL_CONSFREE(consFreeSuperindicator)
953{ /*lint --e{715}*/
954 SCIP_CONSHDLRDATA* conshdlrdata;
955
956 assert(conshdlr != NULL);
957 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
958 assert(scip != NULL);
959
960 SCIPdebugMsg(scip, "freeing superindicator constraint handler data\n");
961
962 /* free constraint handler data */
963 conshdlrdata = SCIPconshdlrGetData(conshdlr);
964 assert(conshdlrdata != NULL);
965
966 SCIPfreeBlockMemory(scip, &conshdlrdata);
967
968 SCIPconshdlrSetData(conshdlr, NULL);
969
970 return SCIP_OKAY;
971}
972
973/** presolving initialization method of constraint handler (called when presolving is about to begin) */
974static
975SCIP_DECL_CONSINITPRE(consInitpreSuperindicator)
976{ /*lint --e{715}*/
977 SCIP_CONSDATA* consdata;
978 int i;
979
980 SCIPdebugMsg(scip, "initializing presolving\n");
981
982 for( i = nconss-1; i >= 0; i-- )
983 {
984 consdata = SCIPconsGetData(conss[i]);
985 assert(consdata != NULL);
986
987 /* make the constraint local to avoid wrong propagation */
988 SCIP_CALL( SCIPsetConsLocal(scip, consdata->slackcons, TRUE) );
989 }
990
991 return SCIP_OKAY;
992}
993
994/** frees specific constraint data */
995static
996SCIP_DECL_CONSDELETE(consDeleteSuperindicator)
997{ /*lint --e{715}*/
998 assert(conshdlr != NULL);
999 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1000 assert(consdata != NULL);
1001 assert(*consdata != NULL);
1002 assert((*consdata)->slackcons != NULL);
1003
1004 SCIPdebugMsg(scip, "deleting constraint <%s>\n", SCIPconsGetName(cons));
1005
1006 /* we have to release the slack constraint also in case we transformed it manually since it is captured automatically
1007 * in SCIPtransformCons()
1008 */
1009 SCIP_CALL( SCIPreleaseCons(scip, &((*consdata)->slackcons)) );
1010
1011 /* free memory */
1012 SCIPfreeBlockMemory(scip, consdata);
1013
1014 return SCIP_OKAY;
1015}
1016
1017/** transforms constraint data into data belonging to the transformed problem */
1018static
1019SCIP_DECL_CONSTRANS(consTransSuperindicator)
1020{ /*lint --e{715}*/
1021 SCIP_CONSDATA* sourcedata;
1022 SCIP_CONSDATA* targetdata;
1023 char newname[SCIP_MAXSTRLEN];
1024
1025 SCIPdebugMsg(scip, "transforming superindicator constraint <%s>\n", SCIPconsGetName(sourcecons));
1026
1027 /* get constraint data of source constraint */
1028 sourcedata = SCIPconsGetData(sourcecons);
1029 assert(sourcedata != NULL);
1030
1031 (void) SCIPsnprintf(newname, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons) );
1032 SCIP_CALL( consdataCreateSuperindicator(scip, &targetdata, sourcedata->binvar, sourcedata->slackcons) );
1033
1034 /* create target constraint and capture it at the same time */
1035 SCIP_CALL( SCIPcreateCons(scip, targetcons, newname, conshdlr, targetdata,
1036 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1037 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
1038 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons),
1039 SCIPconsIsStickingAtNode(sourcecons)) );
1040
1041 return SCIP_OKAY;
1042}
1043
1044/** LP initialization method of constraint handler */
1045static
1046SCIP_DECL_CONSINITLP(consInitlpSuperindicator)
1047{
1048 int c;
1049
1050 assert(scip != NULL);
1051 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1052 assert(infeasible != NULL);
1053
1054 *infeasible = FALSE;
1055
1056 SCIPdebugMsg(scip, "executing initlp callback\n");
1057
1058 for( c = nconss-1; c >= 0 && !(*infeasible); c-- )
1059 {
1060 SCIP_CONSDATA* consdata;
1061
1062 consdata = SCIPconsGetData(conss[c]);
1063
1064 assert(consdata != NULL);
1065 assert(SCIPconsIsInitial(conss[c]));
1066
1067 if( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
1068 {
1069 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->binvar), 1.0));
1070
1071 SCIPdebugMsg(scip, "binvar <%s> == 1 --> SCIPinitlpCons() on constraint <%s>\n",
1072 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
1073
1074 SCIP_CALL( SCIPinitlpCons(scip, consdata->slackcons, infeasible) );
1075 }
1076 }
1077
1078 return SCIP_OKAY;
1079}
1080
1081/** separation method of constraint handler for LP solutions */
1082static
1083SCIP_DECL_CONSSEPALP(consSepalpSuperindicator)
1084{ /*lint --e{715}*/
1085 int c;
1086
1087 assert(conshdlr != NULL);
1088 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1089 assert(conss != NULL);
1090 assert(result != NULL);
1091
1092 *result = SCIP_DELAYED;
1093
1094 SCIPdebugMsg(scip, "executing sepalp callback\n");
1095
1096#ifdef SCIP_OUTPUT
1098#endif
1099
1100 /* check all useful constraints */
1101 for( c = nusefulconss-1; c >= 0 && *result != SCIP_CUTOFF; c-- )
1102 {
1103 SCIP_CONSDATA* consdata;
1104 SCIP_RESULT locresult;
1105
1106 consdata = SCIPconsGetData(conss[c]);
1107 assert(consdata != NULL);
1108
1109 locresult = SCIP_DELAYED;
1110
1111 /* separate only if binvar is fixed to one */
1112 if( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
1113 {
1114 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->binvar), 1.0));
1115
1116 SCIPdebugMsg(scip, "binvar <%s> == 1 --> SCIPsepalpCons() on constraint <%s>\n",
1117 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
1118
1119 SCIP_CALL( SCIPsepalpCons(scip, consdata->slackcons, &locresult) );
1120
1121 SCIPdebugMsgPrint(scip, " --> locresult=%d\n", locresult);
1122 }
1123
1124 /* evaluate result value */
1125 switch( locresult )
1126 {
1127 case SCIP_CUTOFF:
1128 case SCIP_CONSADDED:
1129 assert(*result != SCIP_CUTOFF);
1130 *result = locresult;
1131 break;
1132 case SCIP_REDUCEDDOM:
1133 assert(*result != SCIP_CUTOFF);
1134 if( *result != SCIP_CONSADDED )
1135 *result = locresult;
1136 break;
1137 case SCIP_SEPARATED:
1138 assert(*result != SCIP_CUTOFF);
1139 if( *result != SCIP_CONSADDED
1140 && *result != SCIP_REDUCEDDOM )
1141 *result = locresult;
1142 break;
1143 case SCIP_NEWROUND:
1144 assert(*result != SCIP_CUTOFF);
1145 if( *result != SCIP_CONSADDED
1146 && *result != SCIP_REDUCEDDOM
1147 && *result != SCIP_SEPARATED )
1148 *result = locresult;
1149 break;
1150 case SCIP_DIDNOTFIND:
1151 assert(*result != SCIP_CUTOFF);
1152 if( *result != SCIP_CONSADDED
1153 && *result != SCIP_REDUCEDDOM
1154 && *result != SCIP_NEWROUND
1155 && *result != SCIP_SEPARATED )
1156 *result = locresult;
1157 break;
1158 case SCIP_DIDNOTRUN:
1159 assert(*result != SCIP_CUTOFF);
1160 if( *result != SCIP_CONSADDED
1161 && *result != SCIP_REDUCEDDOM
1162 && *result != SCIP_NEWROUND
1163 && *result != SCIP_SEPARATED
1164 && *result != SCIP_DIDNOTFIND )
1165 *result = locresult;
1166 break;
1167 case SCIP_INFEASIBLE:
1168 assert(*result != SCIP_CUTOFF);
1169 if( *result != SCIP_CONSADDED
1170 && *result != SCIP_REDUCEDDOM
1171 && *result != SCIP_SEPARATED
1172 && *result != SCIP_DIDNOTFIND
1173 && *result != SCIP_DIDNOTRUN
1174 && *result != SCIP_NEWROUND )
1175 *result = locresult;
1176 break;
1177 case SCIP_DELAYED:
1178 break;
1179 default:
1180 SCIPerrorMessage("invalid SCIP result %d\n", locresult);
1181 return SCIP_INVALIDRESULT;
1182 } /*lint !e788*/
1183 }
1184
1185 SCIPdebugMsg(scip, "sepalp result=%d\n", *result);
1186
1187 return SCIP_OKAY;
1188}
1189
1190/** separation method of constraint handler for arbitrary primal solutions */
1191static
1192SCIP_DECL_CONSSEPASOL(consSepasolSuperindicator)
1193{ /*lint --e{715}*/
1194 int c;
1195
1196 assert(conshdlr != NULL);
1197 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1198 assert(conss != NULL);
1199 assert(result != NULL);
1200
1201 *result = SCIP_DELAYED;
1202
1203 SCIPdebugMsg(scip, "executing sepasol callback\n");
1204
1205#ifdef SCIP_OUTPUT
1207#endif
1208
1209 /* check all the useful constraint */
1210 for( c = 0; c < nusefulconss && *result != SCIP_CUTOFF; ++c )
1211 {
1212 SCIP_CONSDATA* consdata;
1213 SCIP_RESULT locresult;
1214
1215 consdata = SCIPconsGetData(conss[c]);
1216 assert(consdata != NULL);
1217
1218 locresult = SCIP_DELAYED;
1219
1220 /* separate only if binvar is fixed to one */
1221 if( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
1222 {
1223 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->binvar), 1.0));
1224
1225 SCIPdebugMsg(scip, "binvar <%s> == 0 --> SCIPsepasolCons() on constraint <%s>\n",
1226 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
1227
1228 SCIP_CALL( SCIPsepasolCons(scip, consdata->slackcons, sol, &locresult) );
1229
1230 SCIPdebugMsgPrint(scip, " --> result=%d\n", locresult);
1231 }
1232
1233 /* evaluate result value */
1234 switch( locresult )
1235 {
1236 case SCIP_CUTOFF:
1237 case SCIP_CONSADDED:
1238 assert(*result != SCIP_CUTOFF);
1239 *result = locresult;
1240 break;
1241 case SCIP_REDUCEDDOM:
1242 assert(*result != SCIP_CUTOFF);
1243 if( *result != SCIP_CONSADDED )
1244 *result = locresult;
1245 break;
1246 case SCIP_SEPARATED:
1247 assert(*result != SCIP_CUTOFF);
1248 if( *result != SCIP_CONSADDED
1249 && *result != SCIP_REDUCEDDOM )
1250 *result = locresult;
1251 break;
1252 case SCIP_NEWROUND:
1253 assert(*result != SCIP_CUTOFF);
1254 if( *result != SCIP_CONSADDED
1255 && *result != SCIP_REDUCEDDOM
1256 && *result != SCIP_SEPARATED )
1257 *result = locresult;
1258 break;
1259 case SCIP_DIDNOTFIND:
1260 assert(*result != SCIP_CUTOFF);
1261 if( *result != SCIP_CONSADDED
1262 && *result != SCIP_REDUCEDDOM
1263 && *result != SCIP_NEWROUND
1264 && *result != SCIP_SEPARATED )
1265 *result = locresult;
1266 break;
1267 case SCIP_DIDNOTRUN:
1268 assert(*result != SCIP_CUTOFF);
1269 if( *result != SCIP_CONSADDED
1270 && *result != SCIP_REDUCEDDOM
1271 && *result != SCIP_NEWROUND
1272 && *result != SCIP_SEPARATED
1273 && *result != SCIP_DIDNOTFIND )
1274 *result = locresult;
1275 break;
1276 case SCIP_INFEASIBLE:
1277 assert(*result != SCIP_CUTOFF);
1278 if( *result != SCIP_CONSADDED
1279 && *result != SCIP_REDUCEDDOM
1280 && *result != SCIP_SEPARATED
1281 && *result != SCIP_DIDNOTFIND
1282 && *result != SCIP_DIDNOTRUN
1283 && *result != SCIP_NEWROUND )
1284 *result = locresult;
1285 break;
1286 case SCIP_DELAYED:
1287 break;
1288 default:
1289 SCIPerrorMessage("invalid SCIP result %d\n", locresult);
1290 return SCIP_INVALIDRESULT;
1291 } /*lint !e788*/
1292 }
1293
1294 SCIPdebugMsg(scip, "sepa sol result=%d\n", *result);
1295
1296 return SCIP_OKAY;
1297}
1298
1299/** constraint enforcing method of constraint handler for LP solutions */
1300static
1301SCIP_DECL_CONSENFOLP(consEnfolpSuperindicator)
1302{ /*lint --e{715}*/
1303 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, solinfeasible, result) );
1304
1305 return SCIP_OKAY;
1306}
1307
1308/** constraint enforcing method of constraint handler for relaxation solutions */
1309static
1310SCIP_DECL_CONSENFORELAX(consEnforelaxSuperindicator)
1311{ /*lint --e{715}*/
1312 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, solinfeasible, result) );
1313
1314 return SCIP_OKAY;
1315}
1316
1317/** constraint enforcing method of constraint handler for pseudo solutions */
1318static
1319SCIP_DECL_CONSENFOPS(consEnfopsSuperindicator)
1320{ /*lint --e{715}*/
1321 SCIP_Bool cont;
1322 int i;
1323
1324 assert(scip != NULL);
1325 assert(conshdlr != NULL);
1326 assert(result != NULL);
1327
1328 /* if the solution is infeasible anyway, skip the enforcement */
1329 if( solinfeasible )
1330 {
1331 *result = SCIP_FEASIBLE;
1332 return SCIP_OKAY;
1333 }
1334 else if( objinfeasible )
1335 {
1336 *result = SCIP_DIDNOTRUN;
1337 return SCIP_OKAY;
1338 }
1339
1340 SCIPdebugMsg(scip, "executing enfops callback\n");
1341
1342 *result = SCIP_FEASIBLE;
1343 cont = TRUE;
1344
1345 /* check all contraints */
1346 for( i = nconss-1; i >= 0 && cont; i-- )
1347 {
1348 SCIP_CONSDATA* consdata;
1349 SCIP_RESULT locresult;
1350
1351 consdata = SCIPconsGetData(conss[i]);
1352 assert(consdata != NULL);
1353
1354 locresult = SCIP_DIDNOTRUN;
1355
1356 /* enforce only if binvar is fixed to one */
1357 if( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
1358 {
1359 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->binvar), 1.0));
1360
1361 SCIPdebugMsg(scip, "binvar <%s> == 1 locally --> SCIPenfopsCons() on constraint <%s>\n",
1362 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
1363
1364 SCIP_CALL( SCIPenfopsCons(scip, consdata->slackcons, solinfeasible, objinfeasible, &locresult) );
1365
1366 SCIPdebugMsgPrint(scip, " --> %slocresult=%d\n", locresult == SCIP_FEASIBLE ? "satisfied, " : "", locresult);
1367 }
1368 /* otherwise check if we have not yet detected infeasibility */
1369 else if( *result == SCIP_FEASIBLE || *result == SCIP_DIDNOTRUN )
1370 {
1371 SCIP_CALL( consdataCheckSuperindicator(scip, consdata, NULL, TRUE, FALSE, FALSE, &locresult) );
1372 }
1373
1374 /* evaluate result value */
1375 switch( locresult )
1376 {
1377 case SCIP_CUTOFF:
1378 case SCIP_BRANCHED:
1379 assert(*result != SCIP_CUTOFF);
1380 assert(*result != SCIP_BRANCHED);
1381 *result = locresult;
1382 cont = FALSE;
1383 break;
1384 case SCIP_CONSADDED:
1385 assert(*result != SCIP_CUTOFF);
1386 assert(*result != SCIP_BRANCHED);
1387 if( *result != SCIP_CUTOFF )
1388 *result = locresult;
1389 break;
1390 case SCIP_REDUCEDDOM:
1391 assert(*result != SCIP_CUTOFF);
1392 assert(*result != SCIP_BRANCHED);
1393 if( *result != SCIP_CUTOFF
1394 && *result != SCIP_CONSADDED )
1395 *result = locresult;
1396 break;
1397 case SCIP_SOLVELP:
1398 assert(*result != SCIP_CUTOFF);
1399 assert(*result != SCIP_BRANCHED);
1400 if( *result != SCIP_CUTOFF
1401 && *result != SCIP_CONSADDED
1402 && *result != SCIP_REDUCEDDOM
1403 && *result != SCIP_BRANCHED )
1404 *result = locresult;
1405 break;
1406 case SCIP_INFEASIBLE:
1407 assert(*result != SCIP_CUTOFF);
1408 assert(*result != SCIP_BRANCHED);
1409 if( *result != SCIP_CUTOFF
1410 && *result != SCIP_CONSADDED
1411 && *result != SCIP_REDUCEDDOM
1412 && *result != SCIP_BRANCHED
1413 && *result != SCIP_SOLVELP )
1414 *result = locresult;
1415 break;
1416 case SCIP_DIDNOTRUN:
1417 assert(*result != SCIP_CUTOFF);
1418 assert(*result != SCIP_BRANCHED);
1419 if( *result != SCIP_CUTOFF
1420 && *result != SCIP_CONSADDED
1421 && *result != SCIP_REDUCEDDOM
1422 && *result != SCIP_BRANCHED
1423 && *result != SCIP_SOLVELP
1424 && *result != SCIP_INFEASIBLE )
1425 *result = locresult;
1426 break;
1427 case SCIP_FEASIBLE:
1428 assert(*result != SCIP_CUTOFF);
1429 assert(*result != SCIP_BRANCHED);
1430 if( *result != SCIP_CUTOFF
1431 && *result != SCIP_CONSADDED
1432 && *result != SCIP_REDUCEDDOM
1433 && *result != SCIP_BRANCHED
1434 && *result != SCIP_SOLVELP
1435 && *result != SCIP_INFEASIBLE
1436 && *result != SCIP_DIDNOTRUN )
1437 *result = locresult;
1438 break;
1439 default:
1440 SCIPerrorMessage("invalid SCIP result %d\n", locresult);
1441 return SCIP_INVALIDRESULT;
1442 } /*lint !e788*/
1443 }
1444
1445 SCIPdebugMsg(scip, "enfops result=%d\n", *result);
1446
1447 return SCIP_OKAY;
1448}
1449
1450/** feasibility check method of constraint handler for integral solutions */
1451static
1452SCIP_DECL_CONSCHECK(consCheckSuperindicator)
1453{ /*lint --e{715}*/
1454 int i;
1455
1456 assert(scip != NULL);
1457 assert(conshdlr != NULL);
1458 assert(result != NULL);
1459 assert(sol != NULL);
1460
1461 *result = SCIP_FEASIBLE;
1462
1463 for( i = nconss-1; i >= 0 && (*result == SCIP_FEASIBLE || completely); i-- )
1464 {
1465 SCIP_CONSDATA* consdata;
1466
1467 consdata = SCIPconsGetData(conss[i]);
1468 SCIP_CALL( consdataCheckSuperindicator(scip, consdata, sol, checkintegrality, checklprows, printreason, result) );
1469 }
1470
1471 SCIPdebugMsg(scip, "checked solution from <%s> (checkintegrality=%u, checklprows=%u) --> result=%d (%sfeasible)\n",
1472 SCIPsolGetHeur(sol) == NULL ? "NULL" : SCIPheurGetName(SCIPsolGetHeur(sol)), checkintegrality, checklprows,
1473 *result, *result == SCIP_INFEASIBLE ? "in" : "");
1474
1475 return SCIP_OKAY;
1476}
1477
1478/** domain propagation method of constraint handler */
1479static
1480SCIP_DECL_CONSPROP(consPropSuperindicator)
1481{ /*lint --e{715}*/
1482 int i;
1483
1484 assert(scip != NULL);
1485 assert(conshdlr != NULL);
1486 assert(result != NULL);
1487
1488 *result = SCIP_DIDNOTRUN;
1489
1490 SCIPdebugMsg(scip, "executing prop callback\n");
1491
1492 /* loop over all useful contraints */
1493 for( i = nusefulconss-1; i >= 0 && *result != SCIP_CUTOFF; i-- )
1494 {
1495 SCIP_CONSDATA* consdata;
1496 SCIP_RESULT locresult;
1497
1498 consdata = SCIPconsGetData(conss[i]);
1499 assert(consdata != NULL);
1500
1501 locresult = SCIP_DIDNOTRUN;
1502
1503 /* propagate only if binvar is fixed to one */
1504 if( SCIPvarGetLbGlobal(consdata->binvar) > 0.5 )
1505 {
1506 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->binvar), 1.0));
1507
1508 SCIPdebugMsg(scip, "binvar <%s> == 1 globally --> deleting superindicator and adding slack constraint <%s>\n",
1509 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
1510
1511 SCIP_CALL( SCIPsetConsLocal(scip, consdata->slackcons, FALSE) );
1512 SCIP_CALL( SCIPaddCons(scip, consdata->slackcons) );
1513 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
1514
1515 locresult = SCIP_DIDNOTFIND;
1516 }
1517 else if( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
1518 {
1519 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->binvar), 1.0));
1520
1521 SCIPdebugMsg(scip, "binvar <%s> == 1 locally --> propagating slack constraint <%s>\n",
1522 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
1523
1524 SCIP_CALL( SCIPpropCons(scip, consdata->slackcons, proptiming, &locresult) );
1525
1526 SCIPdebugMsgPrint(scip, " --> locresult=%d\n", locresult);
1527 }
1528 /**@todo else propagate the domain of the binvar as well: start probing mode, fix binvar to one, propagate
1529 * constraint, and see whether we become infeasible; if this is implemented, the resprop callback must be
1530 * updated
1531 */
1532
1533 /* evaluate result value */
1534 switch( locresult )
1535 {
1536 case SCIP_CUTOFF:
1537 case SCIP_DELAYED:
1538 /* if propagation of one constraint is delayed, we want to propagate again unless the node is cut off */
1539 assert(*result != SCIP_CUTOFF);
1540 *result = locresult;
1541 break;
1542 case SCIP_REDUCEDDOM:
1543 assert(*result != SCIP_CUTOFF);
1544 if( *result != SCIP_DELAYED )
1545 *result = locresult;
1546 break;
1547 case SCIP_DIDNOTFIND:
1548 assert(*result != SCIP_CUTOFF);
1549 if( *result != SCIP_REDUCEDDOM
1550 && *result != SCIP_DELAYED )
1551 *result = locresult;
1552 break;
1553 case SCIP_DIDNOTRUN:
1554 assert(*result != SCIP_CUTOFF);
1555 if( *result != SCIP_REDUCEDDOM
1556 && *result != SCIP_DIDNOTFIND
1557 && *result != SCIP_DELAYED )
1558 *result = locresult;
1559 break;
1560 default:
1561 SCIPerrorMessage("invalid SCIP result %d\n", locresult);
1562 return SCIP_INVALIDRESULT;
1563 } /*lint !e788*/
1564 }
1565
1566 SCIPdebugMsg(scip, "prop result=%d\n", *result);
1567
1568 return SCIP_OKAY;
1569}
1570
1571/** presolving method of constraint handler */
1572static
1573SCIP_DECL_CONSPRESOL(consPresolSuperindicator)
1574{ /*lint --e{715}*/
1575 int i;
1576
1577 assert(scip != NULL);
1578 assert(conss != NULL);
1579 assert(conshdlr != NULL);
1580
1581 *result = SCIP_DIDNOTRUN;
1582
1583 SCIPdebugMsg(scip, "executing presol callback\n");
1584
1585 for( i = nconss-1; i >= 0 && *result != SCIP_CUTOFF; i-- )
1586 {
1587 SCIP_CONSDATA* consdata;
1588 SCIP_RESULT locresult;
1589
1590 consdata = SCIPconsGetData(conss[i]);
1591 assert(consdata != NULL);
1592
1593 locresult = SCIP_DIDNOTFIND;
1594
1595 /**@todo check whether the slack constraint is added to SCIP; in this case the superindicator can be deleted */
1596
1597 /**@todo check whether the slack constraint is a superindicator constraint and presolve */
1598
1599 /* if binvar is globally fixed to 1, we add the slack constraint and remove the superindicator */
1600 if( SCIPvarGetLbGlobal(consdata->binvar) > 0.5 )
1601 {
1602 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->binvar), 1.0));
1603
1604 SCIPdebugMsg(scip, "binvar <%s> == 1 globally --> deleting superindicator and adding slack constraint <%s>\n",
1605 SCIPvarGetName(consdata->binvar), SCIPconsGetName(consdata->slackcons));
1606
1607 SCIP_CALL( SCIPsetConsLocal(scip, consdata->slackcons, FALSE) );
1608 SCIP_CALL( SCIPaddCons(scip, consdata->slackcons) );
1609 SCIP_CALL( SCIPdelCons(scip, conss[i]) );
1610
1611 locresult = SCIP_SUCCESS;
1612 }
1613 /* otherwise try upgrading */
1614 else
1615 {
1616 SCIP_Bool success;
1617 SCIP_Bool deleted;
1618
1619 SCIP_CALL( upgradeSuperindicator(scip, conss[i], &success, &deleted) );
1620
1621 /* update statistics */
1622 if( deleted )
1623 (*ndelconss)++;
1624 else if( success )
1625 (*nupgdconss)++;
1626
1627 /**@todo mark if upgrading failed to avoid trying too often; however, since upgrading might fail only due to
1628 * large domains, we may want to try again later, e.g., if SCIPisPresolveFinished() is TRUE
1629 */
1630
1631 if( deleted || success )
1632 locresult = SCIP_SUCCESS;
1633 }
1634 /**@todo else propagate the domain of the binvar as well: start probing mode, fix binvar to one, propagate
1635 * constraint, and see whether we become infeasible
1636 */
1637
1638 /* evaluate result value */
1639 switch( locresult )
1640 {
1641 case SCIP_SUCCESS:
1642 assert(*result != SCIP_CUTOFF);
1643 if( *result != SCIP_DELAYED )
1644 *result = locresult;
1645 break;
1646 default:
1647 assert(locresult == SCIP_DIDNOTFIND);
1648 assert(*result != SCIP_CUTOFF);
1649 if( *result != SCIP_UNBOUNDED && *result != SCIP_DELAYED && *result != SCIP_SUCCESS )
1650 *result = locresult;
1651 break;
1652 } /*lint !e788*/
1653 }
1654
1655 SCIPdebugMsg(scip, "presol result=%d\n", *result);
1656
1657 return SCIP_OKAY;
1658}
1659
1660/** propagation conflict resolving method of constraint handler */
1661static
1662SCIP_DECL_CONSRESPROP(consRespropSuperindicator)
1663{ /*lint --e{715}*/
1664 SCIP_CONSDATA* consdata;
1665
1666 assert(scip != NULL);
1667 assert(cons != NULL);
1668 assert(infervar != NULL);
1669 assert(bdchgidx != NULL);
1670 assert(result != NULL);
1671
1672 SCIPdebugMsg(scip, "executing resprop callback for constraint <%s>\n", SCIPconsGetName(cons));
1673
1674 consdata = SCIPconsGetData(cons);
1675 assert(consdata != NULL);
1676
1677 *result = SCIP_DIDNOTFIND;
1678
1679 /* check that we only propagated if the binvar is fixed to one */
1680 assert(SCIPisFeasEQ(scip, SCIPgetVarUbAtIndex(scip, consdata->binvar, bdchgidx, TRUE), 1.0));
1681
1682 /* add tightened lower bound on binvar to conflict set */
1683 SCIP_CALL( SCIPaddConflictLb(scip, consdata->binvar, bdchgidx) );
1684
1685 /* call propagation conflict resolving method for the slack constraint */
1686 SCIP_CALL( SCIPrespropCons(scip, consdata->slackcons, infervar, inferinfo, boundtype, bdchgidx, relaxedbd, result) );
1687
1688 SCIPdebugMsgPrint(scip, " --> result=%d\n", *result);
1689
1690 return SCIP_OKAY;
1691}
1692
1693/** variable rounding lock method of constraint handler */
1694static
1695SCIP_DECL_CONSLOCK(consLockSuperindicator)
1696{ /*lint --e{715}*/
1697 SCIP_CONSDATA* consdata;
1698
1699 assert(scip != NULL);
1700 assert(locktype == SCIP_LOCKTYPE_MODEL);
1701
1702 SCIPdebugMsg(scip, "locking variables for constraint <%s>\n", SCIPconsGetName(cons));
1703
1704 consdata = SCIPconsGetData(cons);
1705 assert(consdata != NULL);
1706
1707 /* lock binvar up */
1708 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->binvar, locktype, nlocksneg, nlockspos) );
1709
1710 /* call lock method for the slack constraint */
1711 SCIP_CALL( SCIPaddConsLocksType(scip, consdata->slackcons, locktype, nlockspos, nlocksneg) );
1712
1713 return SCIP_OKAY;
1714}
1715
1716
1717/** constraint display method of constraint handler */
1718static
1719SCIP_DECL_CONSPRINT(consPrintSuperindicator)
1720{ /*lint --e{715}*/
1721 SCIP_CONSDATA* consdata;
1722 SCIP_VAR* binvar;
1723 int zeroone;
1724
1725 assert(scip != NULL);
1726 assert(conshdlr != NULL);
1727 assert(cons != NULL);
1728 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1729
1730 consdata = SCIPconsGetData(cons);
1731 assert(consdata != NULL);
1732
1733 /* get binary variable */
1734 binvar = consdata->binvar;
1735 assert(binvar != NULL);
1736
1737 /* resolve negation if necessary */
1738 zeroone = 1;
1740 {
1741 zeroone = 0;
1742 binvar = SCIPvarGetNegatedVar(binvar);
1743 assert(binvar != NULL);
1744 }
1745
1746 /* print name of the binary variable */
1747 SCIP_CALL( SCIPwriteVarName(scip, file, binvar, TRUE) );
1748
1749 /* print implication */
1750 SCIPinfoMessage(scip, file, " = %d ->", zeroone);
1751
1752 /* print slack constraint */
1753 assert(consdata->slackcons != NULL);
1754 SCIP_CALL( SCIPprintCons(scip, consdata->slackcons, file) );
1755
1756 return SCIP_OKAY;
1757}
1758
1759/** constraint copying method of constraint handler */
1760static
1761SCIP_DECL_CONSCOPY(consCopySuperindicator)
1762{ /*lint --e{715}*/
1763 SCIP_CONSHDLR* conshdlrslack;
1764 SCIP_CONSDATA* sourceconsdata;
1765 SCIP_CONS* sourceslackcons;
1766 SCIP_CONS* targetslackcons;
1767 SCIP_VAR* targetbinvar;
1768 const char* consname;
1769
1770 assert(scip != NULL);
1771 assert(sourcescip != NULL);
1772 assert(sourcecons != NULL);
1773 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(sourcecons)), CONSHDLR_NAME) == 0);
1774
1775 *valid = TRUE;
1776
1777 if( name != NULL )
1778 consname = name;
1779 else
1780 consname = SCIPconsGetName(sourcecons);
1781
1782 SCIPdebugMsg(scip, "copying superindicator constraint <%s> to <%s>\n", SCIPconsGetName(sourcecons), consname);
1783
1784 if( modifiable )
1785 {
1786 SCIPwarningMessage(scip, "cannot create modifiable superindicator constraint when trying to copy constraint <%s>\n",
1787 SCIPconsGetName(sourcecons));
1788 *valid = FALSE;
1789 return SCIP_OKAY;
1790 }
1791
1792 sourceconsdata = SCIPconsGetData(sourcecons);
1793 assert(sourceconsdata != NULL);
1794
1795 /* get slack constraint */
1796 sourceslackcons = sourceconsdata->slackcons;
1797 assert(sourceslackcons != NULL);
1798
1799 /* if the slack constraint has been deleted, create an empty linear constraint */
1800 if( SCIPconsIsDeleted(sourceslackcons) )
1801 {
1802 SCIPdebugMsg(scip, "slack constraint <%s> deleted; creating empty linear constraint\n",
1803 SCIPconsGetName(sourceslackcons));
1804
1805 SCIP_CALL( SCIPcreateConsLinear(scip, &targetslackcons, "dummy", 0, NULL, NULL, 0.0, SCIPinfinity(scip),
1807
1808 SCIP_CALL( SCIPaddCons(scip, targetslackcons) );
1809 }
1810 else
1811 {
1812 /* get copied version of slack constraint */
1813 conshdlrslack = SCIPconsGetHdlr(sourceslackcons);
1814 assert(conshdlrslack != NULL);
1815
1816 /* if copying scip after transforming the original instance before presolving, we need to correct the slack
1817 * constraint pointer
1818 */
1819 assert(!SCIPisTransformed(sourcescip) || SCIPconsIsTransformed(sourceslackcons));
1820 if( SCIPisTransformed(sourcescip) && !SCIPconsIsTransformed(sourceslackcons) )
1821 {
1822 SCIP_CONS* transslackcons;
1823
1824 SCIP_CALL( SCIPgetTransformedCons(sourcescip, sourceslackcons, &transslackcons) );
1825 assert(transslackcons != NULL);
1826 SCIP_CALL( SCIPreleaseCons(sourcescip, &sourceconsdata->slackcons) );
1827 SCIP_CALL( SCIPcaptureCons(sourcescip, transslackcons) );
1828
1829 sourceconsdata->slackcons = transslackcons;
1830 sourceslackcons = transslackcons;
1831 }
1832
1833 SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceslackcons, &targetslackcons, conshdlrslack, varmap, consmap,
1834 SCIPconsGetName(sourceslackcons), SCIPconsIsInitial(sourceslackcons), SCIPconsIsSeparated(sourceslackcons),
1835 SCIPconsIsEnforced(sourceslackcons), SCIPconsIsChecked(sourceslackcons), SCIPconsIsPropagated(sourceslackcons),
1836 SCIPconsIsLocal(sourceslackcons), SCIPconsIsModifiable(sourceslackcons), SCIPconsIsDynamic(sourceslackcons),
1837 SCIPconsIsRemovable(sourceslackcons), SCIPconsIsStickingAtNode(sourceslackcons), global, valid) );
1838 }
1839
1840 /* find copied variable corresponding to binvar */
1841 if( *valid )
1842 {
1843 SCIP_VAR* sourcebinvar;
1844
1845 sourcebinvar = sourceconsdata->binvar;
1846 assert(sourcebinvar != NULL);
1847
1848 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcebinvar, &targetbinvar, varmap, consmap, global, valid) );
1849 }
1850 else
1851 targetbinvar = NULL;
1852
1853 /* create superindicator constraint */
1854 if( *valid )
1855 {
1856 assert(targetslackcons != NULL);
1857 assert(targetbinvar != NULL);
1858 assert(!modifiable);
1859
1860 SCIP_CALL( SCIPcreateConsSuperindicator(scip, cons, consname, targetbinvar, targetslackcons,
1861 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
1862 }
1863
1864 /* relase slack constraint */
1865 if( targetslackcons != NULL )
1866 {
1867 SCIP_CALL( SCIPreleaseCons(scip, &targetslackcons) );
1868 }
1869
1870 if( !(*valid) )
1871 {
1872 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "could not copy superindicator constraint <%s>\n", SCIPconsGetName(sourcecons));
1873 }
1874
1875 return SCIP_OKAY;
1876}
1877
1878/** constraint parsing method of constraint handler */
1879static
1880SCIP_DECL_CONSPARSE(consParseSuperindicator)
1881{ /*lint --e{715}*/
1882 SCIP_VAR* binvar;
1883 SCIP_CONS* slackcons;
1884 char binvarname[1024];
1885 const char* slackstr;
1886 int zeroone;
1887 int nargs;
1888
1889 assert(cons != NULL);
1890 assert(scip != NULL);
1891 assert(success != NULL);
1892 assert(str != NULL);
1893 assert(name != NULL);
1894
1895 *success = FALSE;
1896
1897 /* extract binary variable name and value which triggers slack constraint */
1898 /* coverity[secure_coding] */
1899 nargs = sscanf(str, " <%1023[^>]>[B] = %d", binvarname, &zeroone);
1900
1901 if( nargs != 2 || (zeroone != 0 && zeroone != 1) )
1902 {
1903 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: expected the following form: <var> = [0|1] -> <cons>\n");
1904 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "got: %s\n", str);
1905 return SCIP_OKAY;
1906 }
1907
1908 /* extract string describing slack constraint */
1909 slackstr = strstr(str, "->");
1910
1911 if( slackstr == NULL )
1912 {
1913 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: expected the following form: <var> = [0|1] -> <cons>\n");
1914 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "got: %s\n", str);
1915 return SCIP_OKAY;
1916 }
1917
1918 slackstr = strstr(slackstr, "[");
1919
1920 if( slackstr == NULL )
1921 {
1922 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: expected the following form: <var> = [0|1] -> <cons>\n");
1923 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "got: %s\n", str);
1924 return SCIP_OKAY;
1925 }
1926
1927 SCIPdebugMsg(scip, "binvarname=%s, zeroone=%d, slackstr=%s\n", binvarname, zeroone, slackstr);
1928
1929 /* get binary variable */
1930 binvar = SCIPfindVar(scip, binvarname);
1931 if( binvar == NULL )
1932 {
1933 SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable <%s>\n", binvarname);
1934 return SCIP_OKAY;
1935 }
1936
1937 /* resolve negation if necessary */
1938 if( zeroone == 0 )
1939 {
1940 SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &binvar) );
1941 }
1942
1943 /**@todo get slack constraint name and check whether constraint already exists; however, using only SCIPfindCons() is
1944 * not sufficient since slack constraints are not added to the problem; do we need something like
1945 * SCIPfindConsInConshdlr()?; currently, if there are two superindicator constraints with same slack constraint
1946 * (binvars may be different), then after writing and reading, the slack constraint will be created twice with
1947 * identical constraint name; this is not incorrect, but might consume more memory or time
1948 */
1949
1950 /* parse slack constraint string */
1951 SCIP_CALL( SCIPparseCons(scip, &slackcons, slackstr, initial, separate, enforce, check, propagate, local, modifiable,
1952 dynamic, removable, stickingatnode, success) );
1953
1954 if( *success )
1955 {
1956 assert(binvar != NULL);
1957 assert(slackcons != NULL);
1958
1959 /* create the superindicator constraint */
1960 SCIP_CALL( SCIPcreateConsSuperindicator(scip, cons, name, binvar, slackcons,
1961 initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
1962
1963 /* the new superindicator constraint captured the slack constraint, so we can release it now */
1964 SCIP_CALL( SCIPreleaseCons(scip, &slackcons) );
1965 }
1966
1967 return SCIP_OKAY;
1968}
1969
1970/** constraint method of constraint handler which returns the variables (if possible) */
1971static
1972SCIP_DECL_CONSGETVARS(consGetVarsSuperindicator)
1973{ /*lint --e{715}*/
1974 SCIP_CONSDATA* consdata;
1975
1976 consdata = SCIPconsGetData(cons);
1977 assert(consdata != NULL);
1978
1979 /* must be ready to hold at least the binary variable */
1980 if( varssize <= 0 )
1981 *success = FALSE;
1982 else
1983 {
1984 /* add binary variable */
1985 vars[0] = consdata->binvar;
1986
1987 /* add variables of slack constraint */
1988 SCIP_CALL( SCIPgetConsVars(scip, consdata->slackcons, &(vars[1]), varssize-1, success) );
1989 }
1990
1991 return SCIP_OKAY;
1992}
1993
1994/** constraint method of constraint handler which returns the number of variables (if possible) */
1995static
1996SCIP_DECL_CONSGETNVARS(consGetNVarsSuperindicator)
1997{ /*lint --e{715}*/
1998 SCIP_CONSDATA* consdata;
1999
2000 consdata = SCIPconsGetData(cons);
2001 assert(consdata != NULL);
2002
2003 /* get number of variables in slack constraint */
2004 SCIP_CALL( SCIPgetConsNVars(scip, consdata->slackcons, nvars, success) );
2005
2006 /* add binary variable */
2007 if( *success )
2008 (*nvars)++;
2009
2010 return SCIP_OKAY;
2011}
2012
2013
2014/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
2015static
2016SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSuperindicator)
2017{ /*lint --e{715}*/
2018 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
2019
2020 return SCIP_OKAY;
2021}
2022
2023
2024/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
2025static
2026SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSuperindicator)
2027{ /*lint --e{715}*/
2028 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
2029
2030 return SCIP_OKAY;
2031}
2032
2033
2034/*
2035 * constraint specific interface methods
2036 */
2037
2038/** creates the handler for superindicator constraints and includes it in SCIP */
2040 SCIP* scip /**< SCIP data structure */
2041 )
2042{
2043 SCIP_CONSHDLRDATA* conshdlrdata;
2044 SCIP_CONSHDLR* conshdlr;
2045 SCIP_DIALOG* root;
2046 SCIP_DIALOG* changemenu;
2047 SCIP_DIALOG* dialog;
2048
2049 /* create superindicator constraint handler data */
2050 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
2051
2052 conshdlrdata->nrejects = 0;
2053
2054 /* include constraint handler */
2057 consEnfolpSuperindicator, consEnfopsSuperindicator, consCheckSuperindicator, consLockSuperindicator,
2058 conshdlrdata) );
2059
2060 assert(conshdlr != NULL);
2061
2062 /* set non-fundamental callbacks via specific setter functions */
2063 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySuperindicator, consCopySuperindicator) );
2064 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSuperindicator) );
2065 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSuperindicator) );
2066 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSuperindicator) );
2067 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSuperindicator) );
2068 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSuperindicator) );
2069 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreSuperindicator) );
2070 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSuperindicator) );
2071 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolSuperindicator, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
2072 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSuperindicator) );
2074 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSuperindicator) );
2075 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSuperindicator, consSepasolSuperindicator, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
2076 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSuperindicator) );
2077 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSuperindicator) );
2078 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphSuperindicator) );
2079 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphSuperindicator) );
2080
2081 /* add dialogs if they are not disabled */
2082 root = SCIPgetRootDialog(scip);
2083 if( root != NULL )
2084 {
2085 /* find change menu */
2086 if( !SCIPdialogHasEntry(root, "change") )
2087 {
2088 SCIP_CALL( SCIPincludeDialog(scip, &changemenu,
2089 NULL,
2090 SCIPdialogExecMenu, NULL, NULL,
2091 "change", "change the problem", TRUE, NULL) );
2092 SCIP_CALL( SCIPaddDialogEntry(scip, root, changemenu) );
2093 SCIP_CALL( SCIPreleaseDialog(scip, &changemenu) );
2094 }
2095
2096 if( SCIPdialogFindEntry(root, "change", &changemenu) != 1 )
2097 {
2098 SCIPerrorMessage("change sub menu not found\n");
2099 return SCIP_PLUGINNOTFOUND;
2100 }
2101
2102 /* add minuc dialog */
2103 if( !SCIPdialogHasEntry(changemenu, "minuc") )
2104 {
2106 NULL,
2107 SCIPdialogExecChangeMinUC, NULL, NULL,
2108 "minuc", "transforms the current problem into a MinUC problem minimizing the number of unsatisfied constraints",
2109 FALSE, NULL) );
2110 SCIP_CALL( SCIPaddDialogEntry(scip, changemenu, dialog) );
2111 SCIP_CALL( SCIPreleaseDialog(scip, &dialog) );
2112 }
2113 }
2114
2115 /* add constraint handler parameters */
2117 "constraints/" CONSHDLR_NAME "/checkslacktype",
2118 "should type of slack constraint be checked when creating superindicator constraint?",
2119 &conshdlrdata->checkslacktype, TRUE, DEFAULT_CHECKSLACKTYPE, NULL, NULL) );
2120
2122 "constraints/" CONSHDLR_NAME "/maxupgdcoeflinear",
2123 "maximum big-M coefficient of binary variable in upgrade to a linear constraint (relative to smallest coefficient)",
2124 &conshdlrdata->maxupgdcoeflinear, TRUE, DEFAULT_MAXUPGDCOEFLINEAR, 0.0, 1e15, NULL, NULL) );
2125
2127 "constraints/" CONSHDLR_NAME "/upgdprioindicator",
2128 "priority for upgrading to an indicator constraint (-1: never)",
2129 &conshdlrdata->upgdprioindicator, TRUE, DEFAULT_UPGDPRIOINDICATOR, -1, INT_MAX, NULL, NULL) );
2130
2132 "constraints/" CONSHDLR_NAME "/upgdpriolinear",
2133 "priority for upgrading to an indicator constraint (-1: never)",
2134 &conshdlrdata->upgdpriolinear, TRUE, DEFAULT_UPGDPRIOLINEAR, -1, INT_MAX, NULL, NULL) );
2135
2136 return SCIP_OKAY;
2137}
2138
2139/** creates and captures a superindicator constraint
2140 *
2141 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2142 */
2144 SCIP* scip, /**< SCIP data structure */
2145 SCIP_CONS** cons, /**< pointer to hold the created constraint */
2146 const char* name, /**< name of constraint */
2147 SCIP_VAR* binvar, /**< pointer to the indicator constraint */
2148 SCIP_CONS* slackcons, /**< constraint corresponding to the handled constraint */
2149 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2150 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2151 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2152 * Usually set to TRUE. */
2153 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2154 * TRUE for model constraints, FALSE for additional, redundant constraints. */
2155 SCIP_Bool check, /**< should the constraint be checked for feasibility?
2156 * TRUE for model constraints, FALSE for additional, redundant constraints. */
2157 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2158 * Usually set to TRUE. */
2159 SCIP_Bool local, /**< is constraint only valid locally?
2160 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2161 SCIP_Bool dynamic, /**< is constraint subject to aging?
2162 * Usually set to FALSE. Set to TRUE for own cuts which
2163 * are separated as constraints. */
2164 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2165 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2166 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2167 * if it may be moved to a more global node?
2168 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2169 )
2170{
2171 SCIP_CONSHDLRDATA* conshdlrdata;
2172 SCIP_CONSHDLR* conshdlr;
2173 SCIP_CONSDATA* consdata;
2174 SCIP_Bool modifiable;
2175
2176 assert(scip != NULL);
2177 assert(cons != NULL);
2178 assert(name != NULL);
2179 assert(binvar != NULL);
2180 assert(slackcons != NULL);
2181
2182 modifiable = FALSE;
2183
2184 /* find the superindicator constraint handler */
2185 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2186 if( conshdlr == NULL )
2187 {
2188 SCIPerrorMessage("superindicator constraint handler not found\n");
2189 return SCIP_PLUGINNOTFOUND;
2190 }
2191
2192 conshdlrdata = SCIPconshdlrGetData(conshdlr);
2193 assert(conshdlrdata != NULL);
2194
2195 /* only allow types of slack constraints that can be handled */
2196 if( conshdlrdata->checkslacktype &&
2197 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "and") != 0 &&
2198 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "bounddisjunction") != 0 &&
2199 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "conjunction") != 0 &&
2200 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "disjunction") != 0 &&
2201 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "knapsack") != 0 &&
2202 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "linear") != 0 &&
2203 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "linking") != 0 &&
2204 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "logicor") != 0 &&
2205 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "nonlinear") != 0 &&
2206 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "or") != 0 &&
2207 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "SOS1") != 0 &&
2208 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "SOS2") != 0 &&
2209 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "cumulative") != 0 &&
2210 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "varbound") != 0 &&
2211 strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)), "superindicator") != 0
2212 )
2213 {
2214 if( conshdlrdata->nrejects < 5 )
2215 {
2216 SCIPwarningMessage(scip, "rejected creation of superindicator with slack constraint <%s> of type <%s> "
2217 "(use parameter <checkslacktype> to disable check)\n",
2218 SCIPconsGetName(slackcons), SCIPconshdlrGetName(SCIPconsGetHdlr(slackcons)));
2219 conshdlrdata->nrejects++;
2220 }
2221
2222 if( conshdlrdata->nrejects == 5 )
2223 {
2224 SCIPwarningMessage(scip, "suppressing further warning messages of this type\n");
2225 conshdlrdata->nrejects++;
2226 }
2227
2228 return SCIP_INVALIDCALL;
2229 }
2230
2231 /* create constraint data */
2232 SCIP_CALL( consdataCreateSuperindicator(scip, &consdata, binvar, slackcons) );
2233 assert(consdata != NULL);
2234
2235 /* create constraint */
2236 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2237 local, modifiable, dynamic, removable, stickingatnode) );
2238
2239 return SCIP_OKAY;
2240}
2241
2242/** creates and captures a superindicator constraint
2243 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
2244 * method SCIPcreateConsSuperindicator(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
2245 *
2246 * @see SCIPcreateConsSuperindicator() for information about the basic constraint flag configuration
2247 *
2248 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2249 */
2251 SCIP* scip, /**< SCIP data structure */
2252 SCIP_CONS** cons, /**< pointer to hold the created constraint */
2253 const char* name, /**< name of constraint */
2254 SCIP_VAR* binvar, /**< pointer to the indicator constraint */
2255 SCIP_CONS* slackcons /**< constraint corresponding to the handled constraint */
2256 )
2257{
2258 assert(scip != NULL);
2259 assert(cons != NULL);
2260 assert(name != NULL);
2261 assert(binvar != NULL);
2262 assert(slackcons != NULL);
2263
2264 SCIP_CALL( SCIPcreateConsSuperindicator(scip, cons, name, binvar, slackcons,
2266
2267 return SCIP_OKAY;
2268}
2269
2270
2271/** gets binary variable corresponding to the general indicator constraint */
2273 SCIP_CONS* cons /**< superindicator constraint */
2274 )
2275{
2276 assert(cons != NULL);
2277 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2278 assert(SCIPconsGetData(cons) != NULL);
2279
2280 return SCIPconsGetData(cons)->binvar;
2281}
2282
2283/** gets the slack constraint corresponding to the general indicator constraint */
2285 SCIP_CONS* cons /**< superindicator constraint */
2286 )
2287{
2288 assert(cons != NULL);
2289 assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2290 assert(SCIPconsGetData(cons) != NULL);
2291
2292 return SCIPconsGetData(cons)->slackcons;
2293}
2294
2295
2296/*
2297 * constraint-dependent SCIP methods
2298 */
2299
2300/** transforms the current problem into a MinUC problem (minimizing the number of unsatisfied constraints),
2301 * a CIP generalization of the MinULR (min. unsatisfied linear relations) problem
2302 */
2304 SCIP* scip, /**< SCIP data structure */
2305 SCIP_Bool* success /**< pointer to store whether all constraints could be transformed */
2306 )
2307{
2308 SCIP_CONS** conss;
2309 SCIP_CONS** probconss;
2310 SCIP_VAR** vars;
2311 char consname[SCIP_MAXSTRLEN];
2312 char varname[SCIP_MAXSTRLEN];
2313 int maxbranchprio;
2314 int ntransconss;
2315 int nconss;
2316 int nvars;
2317 int i;
2318
2319 assert(scip != NULL);
2320 assert(success != NULL);
2321
2322 *success = FALSE;
2323
2325 {
2326 SCIPerrorMessage("method <SCIPtransformMinUC> can only be called in problem stage\n");
2327 return SCIP_INVALIDCALL;
2328 }
2329
2330 /* get variable data */
2331 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2332
2333 /* copy the conss array because it changes when adding and deleting constraints */
2334 nconss = SCIPgetNConss(scip);
2335 probconss = SCIPgetConss(scip);
2336 SCIP_CALL( SCIPduplicateBufferArray(scip, &conss, probconss, nconss) );
2337
2338 /* clear objective function and compute maximal branching priority */
2339 maxbranchprio = 0;
2340 for( i = nvars-1; i >= 0; i-- )
2341 {
2342 SCIP_CALL( SCIPchgVarObj(scip, vars[i], 0.0) );
2343
2344 if( SCIPvarGetBranchPriority(vars[i]) > maxbranchprio )
2345 maxbranchprio = SCIPvarGetBranchPriority(vars[i]);
2346 }
2347
2348 maxbranchprio++;
2349
2350 /* transform each constraint to slack constraint in a newly created superindicator constraint; note that we also need
2351 * to transform superindicator constraints, since their binary variable might have down-locks
2352 */
2353 ntransconss = 0;
2354 for( i = 0; i < nconss; ++i )
2355 {
2356 SCIP_CONS* cons;
2357 SCIP_CONS* supindcons;
2358 SCIP_VAR* binvar;
2359 SCIP_VAR* negbinvar;
2360 SCIP_RETCODE retcode;
2361
2362 cons = conss[i];
2363 assert(cons != NULL);
2364
2365 /* create a new binary variable with objective coefficient one */
2366 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "%s_master", SCIPconsGetName(cons));
2367
2368 SCIP_CALL( SCIPcreateVar(scip, &binvar, varname, 0.0, 1.0, 1.0, SCIP_VARTYPE_BINARY,
2369 TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
2370
2371 /* get negated variable, since we want to minimize the number of violated constraints */
2372 SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &negbinvar) );
2373
2374 /* create superindicator constraint */
2375 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_super", SCIPconsGetName(cons));
2376
2377 retcode = SCIPcreateConsSuperindicator(scip, &supindcons, consname, negbinvar, cons,
2381
2382 if( retcode == SCIP_OKAY )
2383 {
2384 /* add binary variable and increase its branching priority */
2385 SCIP_CALL( SCIPaddVar(scip, binvar) );
2386 SCIP_CALL( SCIPchgVarBranchPriority(scip, binvar, maxbranchprio) );
2387
2388 /* add superindicator constraint */
2389 SCIP_CALL( SCIPaddCons(scip, supindcons) );
2390
2391 /* release binary variable and superindicator constraint */
2392 SCIP_CALL( SCIPreleaseVar(scip, &binvar) );
2393 SCIP_CALL( SCIPreleaseCons(scip, &supindcons) );
2394
2395 /* delete slack constraint; it is still captured by the superindicator constraint */
2396 SCIP_CALL( SCIPdelCons(scip, cons) );
2397
2398 ntransconss++;
2399 }
2400 else if( retcode == SCIP_INVALIDCALL )
2401 {
2402 SCIPdebugMsg(scip, "constraint <%s> of type <%s> could not be transformed to superindicator and was removed\n",
2404
2405 /* release binary variable */
2406 SCIP_CALL( SCIPreleaseVar(scip, &binvar) );
2407
2408 /* delete slack constraint; this is necessary, because, e.g., the indicator expects its linear slack constraint
2409 * present in the problem, but this has just be transformed; hence, it cannot function any more and we have to
2410 * remove it
2411 */
2412 SCIP_CALL( SCIPdelCons(scip, cons) );
2413 }
2414 else
2415 {
2416 /* return all other error codes */
2417 SCIP_CALL( retcode );
2418 }
2419 }
2420
2421 if( ntransconss == nconss )
2422 *success = TRUE;
2423
2424 /* minimize the number of violated constraints */
2426
2427 /* free the allocated memory for the copied constraint array */
2428 SCIPfreeBufferArray(scip, &conss);
2429
2430 return SCIP_OKAY;
2431}
2432
2433
2434/*
2435 * constraint-dependent dialog entries
2436 */
2437
2438/** dialog execution method for the SCIPtransformMinUC() method */
2439SCIP_DECL_DIALOGEXEC(SCIPdialogExecChangeMinUC)
2440{ /*lint --e{715}*/
2441 SCIP_Bool success;
2442
2443 SCIP_CALL( SCIPdialoghdlrAddHistory(dialoghdlr, dialog, NULL, FALSE) );
2444 SCIPdialogMessage(scip, NULL, "\n");
2445
2446 switch( SCIPgetStage(scip) )
2447 {
2448 case SCIP_STAGE_INIT:
2449 SCIPdialogMessage(scip, NULL, "no problem exists\n");
2450 break;
2451 case SCIP_STAGE_PROBLEM:
2452 SCIPdialogMessage(scip, NULL, "change problem to MinUC\n");
2453 SCIPdialogMessage(scip, NULL, "==============\n");
2454
2455 SCIP_CALL( SCIPtransformMinUC(scip, &success) );
2456
2457 if( !success )
2458 {
2459 SCIPdialogMessage(scip, NULL, "some constraints could not be transformed to superindicator constraints and were removed\n");
2460 }
2461
2462 SCIPdialogMessage(scip, NULL, "\n");
2463 SCIPdialogMessage(scip, NULL, "changed problem has %d variables (%d bin, %d int, %d cont) and %d constraints\n",
2467
2468 SCIPdialogMessage(scip, NULL, "increased branching priority of new binary variables");
2469
2470 break;
2476 case SCIP_STAGE_SOLVING:
2477 case SCIP_STAGE_SOLVED:
2482 case SCIP_STAGE_FREE:
2483 SCIPdialogMessage(scip, NULL, "problem has to be in problem stage to create MinUC problem\n");
2484 break;
2485 default:
2486 SCIPerrorMessage("invalid SCIP stage\n");
2487 return SCIP_INVALIDCALL;
2488 } /*lint --e{616}*/
2489
2490 SCIPdialogMessage(scip, NULL, "\n");
2491 *nextdialog = SCIPdialoghdlrGetRoot(dialoghdlr);
2492
2493 return SCIP_OKAY;
2494}
constraint handler for indicator constraints
Constraint handler for linear constraints in their most general form, .
static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSuperindicator)
static SCIP_DECL_CONSENFORELAX(consEnforelaxSuperindicator)
#define DEFAULT_MAXUPGDCOEFLINEAR
#define CONSHDLR_NEEDSCONS
#define CONSHDLR_SEPAFREQ
#define CONSHDLR_CHECKPRIORITY
#define DEFAULT_UPGDPRIOLINEAR
#define CONSHDLR_DESC
static SCIP_DECL_CONSRESPROP(consRespropSuperindicator)
static SCIP_DECL_CONSINITPRE(consInitpreSuperindicator)
#define CONSHDLR_PROP_TIMING
static SCIP_DECL_CONSFREE(consFreeSuperindicator)
#define CONSHDLR_MAXPREROUNDS
#define DEFAULT_CHECKSLACKTYPE
static SCIP_RETCODE upgradeLinearSuperindicator(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success, SCIP_Bool *deleted)
static SCIP_DECL_CONSLOCK(consLockSuperindicator)
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_Bool solinfeasible, SCIP_RESULT *result)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopySuperindicator)
static SCIP_DECL_CONSSEPALP(consSepalpSuperindicator)
#define CONSHDLR_SEPAPRIORITY
static void extractLinearValues(SCIP *scip, SCIP_CONS *cons, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Real *minabscoef)
#define DEFAULT_UPGDPRIOINDICATOR
static SCIP_DECL_CONSPRINT(consPrintSuperindicator)
static SCIP_DECL_CONSDELETE(consDeleteSuperindicator)
static SCIP_DECL_CONSSEPASOL(consSepasolSuperindicator)
static SCIP_RETCODE upgradeSuperindicator(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success, SCIP_Bool *deleted)
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
static SCIP_DECL_CONSGETVARS(consGetVarsSuperindicator)
static SCIP_RETCODE upgradeIndicatorSuperindicator(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success, SCIP_Bool *deleted)
static SCIP_DECL_CONSPARSE(consParseSuperindicator)
static SCIP_RETCODE consdataCheckSuperindicator(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_RESULT *result)
static SCIP_DECL_CONSGETNVARS(consGetNVarsSuperindicator)
static SCIP_DECL_CONSINITLP(consInitlpSuperindicator)
#define CONSHDLR_PROPFREQ
static SCIP_RETCODE consdataCreateSuperindicator(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR *binvar, SCIP_CONS *slackcons)
static SCIP_DECL_CONSCOPY(consCopySuperindicator)
#define CONSHDLR_PRESOLTIMING
static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSuperindicator)
#define CONSHDLR_EAGERFREQ
static SCIP_DECL_CONSCHECK(consCheckSuperindicator)
#define CONSHDLR_ENFOPRIORITY
static SCIP_DECL_CONSENFOLP(consEnfolpSuperindicator)
#define CONSHDLR_DELAYSEPA
static SCIP_DECL_CONSPRESOL(consPresolSuperindicator)
static SCIP_DECL_CONSTRANS(consTransSuperindicator)
static SCIP_DECL_CONSENFOPS(consEnfopsSuperindicator)
#define CONSHDLR_NAME
static SCIP_DECL_CONSPROP(consPropSuperindicator)
#define CONSHDLR_DELAYPROP
constraint handler for indicator constraints over arbitrary constraint types
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_CALL(x)
Definition: def.h:355
default user interface dialog
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetBinaryVarSuperindicator(SCIP_CONS *cons)
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_DECL_DIALOGEXEC(SCIPdialogExecChangeMinUC)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsIndicator(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *binvar, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPtransformMinUC(SCIP *scip, SCIP_Bool *success)
SCIP_CONS * SCIPgetSlackConsSuperindicator(SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsSuperindicator(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *binvar, SCIP_CONS *slackcons, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsBasicSuperindicator(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *binvar, SCIP_CONS *slackcons)
SCIP_RETCODE SCIPincludeConshdlrSuperindicator(SCIP *scip)
SCIP_RETCODE SCIPgetConsCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_CONS *sourcecons, SCIP_CONS **targetcons, SCIP_CONSHDLR *sourceconshdlr, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *name, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
Definition: scip_copy.c:1580
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)
Definition: scip_general.c:647
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_prob.c:1907
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2340
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2569
int SCIPgetNBinImplVars(SCIP *scip)
Definition: scip_prob.c:2432
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
SCIP_CONS ** SCIPgetConss(SCIP *scip)
Definition: scip_prob.c:3666
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
int SCIPgetNConss(SCIP *scip)
Definition: scip_prob.c:3620
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:2201
int SCIPgetNIntImplVars(SCIP *scip)
Definition: scip_prob.c:2477
int SCIPgetNContImplVars(SCIP *scip)
Definition: scip_prob.c:2522
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition: scip_prob.c:1417
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2293
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip_prob.c:3189
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:225
#define SCIPdebugMsgPrint
Definition: scip_message.h:79
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPdialogMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:191
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:139
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 SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:808
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4346
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
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 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_Bool SCIPconshdlrSupportsSignedPermsymDetection(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5456
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
Definition: scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:323
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)))
Definition: scip_cons.c:924
SCIP_Bool SCIPconshdlrSupportsPermsymDetection(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5446
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4336
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_RETCODE SCIPgetConsNVars(SCIP *scip, SCIP_CONS *cons, int *nvars, SCIP_Bool *success)
Definition: scip_cons.c:2621
SCIP_RETCODE SCIPgetConsSignedPermsymGraph(SCIP *scip, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
Definition: scip_cons.c:2687
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8419
SCIP_RETCODE SCIPenfopsCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool solinfeasible, SCIP_Bool objinfeasible, SCIP_RESULT *result)
Definition: scip_cons.c:2163
SCIP_RETCODE SCIPcheckCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_RESULT *result)
Definition: scip_cons.c:2135
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8648
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8558
SCIP_RETCODE SCIPenfolpCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool solinfeasible, SCIP_RESULT *result)
Definition: scip_cons.c:2194
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
SCIP_RETCODE SCIPpropCons(SCIP *scip, SCIP_CONS *cons, SCIP_PROPTIMING proptiming, SCIP_RESULT *result)
Definition: scip_cons.c:2340
SCIP_RETCODE SCIPgetConsPermsymGraph(SCIP *scip, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
Definition: scip_cons.c:2654
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8588
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8518
SCIP_RETCODE SCIPsepalpCons(SCIP *scip, SCIP_CONS *cons, SCIP_RESULT *result)
Definition: scip_cons.c:2283
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8698
SCIP_RETCODE SCIPgetConsVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int varssize, SCIP_Bool *success)
Definition: scip_cons.c:2577
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8578
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:8608
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8628
SCIP_RETCODE SCIPaddConsLocksType(SCIP *scip, SCIP_CONS *cons, SCIP_LOCKTYPE locktype, int nlockspos, int nlocksneg)
Definition: scip_cons.c:2072
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPinitlpCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: scip_cons.c:2256
SCIP_RETCODE SCIPrespropCons(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd, SCIP_RESULT *result)
Definition: scip_cons.c:2371
SCIP_RETCODE SCIPsetConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_Bool local)
Definition: scip_cons.c:1398
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8638
SCIP_RETCODE SCIPgetTransformedCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **transcons)
Definition: scip_cons.c:1674
SCIP_RETCODE SCIPenforelaxCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool solinfeasible, SCIP_RESULT *result)
Definition: scip_cons.c:2224
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8668
SCIP_RETCODE SCIPparseCons(SCIP *scip, SCIP_CONS **cons, const char *str, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool *success)
Definition: scip_cons.c:1081
SCIP_RETCODE SCIPsepasolCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_RESULT *result)
Definition: scip_cons.c:2310
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_RETCODE SCIPtransformCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **transcons)
Definition: scip_cons.c:1584
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8568
SCIP_RETCODE SCIPcaptureCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1138
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8658
SCIP_RETCODE SCIPreleaseDialog(SCIP *scip, SCIP_DIALOG **dialog)
Definition: scip_dialog.c:124
SCIP_DIALOG * SCIPdialoghdlrGetRoot(SCIP_DIALOGHDLR *dialoghdlr)
Definition: dialog.c:436
SCIP_Bool SCIPdialogHasEntry(SCIP_DIALOG *dialog, const char *entryname)
Definition: dialog.c:1013
SCIP_RETCODE SCIPdialoghdlrAddHistory(SCIP_DIALOGHDLR *dialoghdlr, SCIP_DIALOG *dialog, const char *command, SCIP_Bool escapecommand)
Definition: dialog.c:725
SCIP_RETCODE SCIPincludeDialog(SCIP *scip, SCIP_DIALOG **dialog, SCIP_DECL_DIALOGCOPY((*dialogcopy)), SCIP_DECL_DIALOGEXEC((*dialogexec)), SCIP_DECL_DIALOGDESC((*dialogdesc)), SCIP_DECL_DIALOGFREE((*dialogfree)), const char *name, const char *desc, SCIP_Bool issubmenu, SCIP_DIALOGDATA *dialogdata)
Definition: scip_dialog.c:59
SCIP_RETCODE SCIPaddDialogEntry(SCIP *scip, SCIP_DIALOG *dialog, SCIP_DIALOG *subdialog)
Definition: scip_dialog.c:171
SCIP_DIALOG * SCIPgetRootDialog(SCIP *scip)
Definition: scip_dialog.c:157
int SCIPdialogFindEntry(SCIP_DIALOG *dialog, const char *entryname, SCIP_DIALOG **subdialog)
Definition: dialog.c:1046
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1467
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:2349
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:4259
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1765
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(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 SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:23868
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:5118
SCIP_RETCODE SCIPchgVarBranchPriority(SCIP *scip, SCIP_VAR *var, int branchpriority)
Definition: scip_var.c:9917
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:23267
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:2166
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:24462
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:24120
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:361
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_var.c:5372
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:2078
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
SCIP_RETCODE SCIPaddSymgraphEdge(SCIP *scip, SYM_GRAPH *graph, int first, int second, SCIP_Bool hasval, SCIP_Real val)
SCIP_RETCODE SCIPfreeSymgraph(SCIP *scip, SYM_GRAPH **graph)
SCIP_RETCODE SCIPaddSymgraphOpnode(SCIP *scip, SYM_GRAPH *graph, int op, int *nodeidx)
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPcreateSymgraph(SCIP *scip, SYM_SYMTYPE symtype, SYM_GRAPH **graph, SCIP_VAR **symvars, int nsymvars, int nopnodes, int nvalnodes, int nconsnodes, int nedges)
int SCIPgetSymgraphVarnodeidx(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR *var)
SCIP_RETCODE SCIPcopySymgraphAsSubgraph(SCIP *scip, SYM_GRAPH *sourcegraph, SYM_GRAPH *targetgraph, SCIP_CONS *sourcecons, int *rootidx)
SCIP_RETCODE SCIPaddSymgraphConsnode(SCIP *scip, SYM_GRAPH *graph, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, int *nodeidx)
SCIP_RETCODE SCIPaddSymgraphVarAggregation(SCIP *scip, SYM_GRAPH *graph, int rootidx, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Real constant)
int SCIPgetSymgraphNegatedVarnodeidx(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR *var)
memory allocation routines
public methods for managing constraints
public methods for user interface dialog
public methods for primal heuristics
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintf
Definition: pub_message.h:99
public data structures and miscellaneous methods
public methods for primal CIP solutions
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 dialog handler plugins
general public methods
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for solutions
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
Definition: sepa_flower.c:1221
methods for dealing with symmetry detection graphs
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
@ SCIP_VERBLEVEL_MINIMAL
Definition: type_message.h:59
@ SCIP_OBJSENSE_MINIMIZE
Definition: type_prob.h:48
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_FEASIBLE
Definition: type_result.h:45
@ SCIP_DELAYED
Definition: type_result.h:43
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_CONSADDED
Definition: type_result.h:52
@ SCIP_UNBOUNDED
Definition: type_result.h:47
@ SCIP_BRANCHED
Definition: type_result.h:54
@ SCIP_SEPARATED
Definition: type_result.h:49
@ SCIP_SOLVELP
Definition: type_result.h:55
@ SCIP_NEWROUND
Definition: type_result.h:50
@ 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_INVALIDRESULT
Definition: type_retcode.h:53
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_INITPRESOLVE
Definition: type_set.h:48
@ SCIP_STAGE_SOLVED
Definition: type_set.h:54
@ SCIP_STAGE_PRESOLVING
Definition: type_set.h:49
@ SCIP_STAGE_TRANSFORMED
Definition: type_set.h:47
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition: type_set.h:50
@ SCIP_STAGE_EXITSOLVE
Definition: type_set.h:55
@ SCIP_STAGE_INIT
Definition: type_set.h:44
@ SCIP_STAGE_FREE
Definition: type_set.h:57
@ SCIP_STAGE_FREETRANS
Definition: type_set.h:56
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
@ SCIP_STAGE_TRANSFORMING
Definition: type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition: type_set.h:51
enum SYM_Symtype SYM_SYMTYPE
Definition: type_symmetry.h:64
@ SYM_CONSOPTYPE_SUM
Definition: type_symmetry.h:83
@ SYM_SYMTYPE_SIGNPERM
Definition: type_symmetry.h:62
@ SYM_SYMTYPE_PERM
Definition: type_symmetry.h:61
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:57
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141