Scippy

SCIP

Solving Constraint Integer Programs

cons_varbound.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_varbound.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief Constraint handler for variable bound constraints \f$lhs \le x + c y \le rhs\f$.
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Michael Winkler
31 * @author Gerald Gamrath
32 * @author Stefan Heinz
33 *
34 * This constraint handler handles a special type of linear constraints, namely variable bound constraints.
35 * A variable bound constraint has the form
36 * \f[
37 * lhs \leq x + c y \leq rhs
38 * \f]
39 * with coefficient \f$c \in Q\f$, \f$lhs\in Q \cup \{-\infty\}\f$, \f$rhs\in Q \cup \{\infty\}\f$,
40 * and decision variables \f$x\f$ (non-binary) and \f$y\f$ (binary or integer).
41 *
42 * @note Although x must be non-binary when the constraint is created, it can happen that x is upgraded to a binary
43 * variable, e.g. due to aggregations or bound changes in presolving.
44 */
45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46
47#include <ctype.h>
49#include "scip/cons_linear.h"
50#include "scip/cons_setppc.h"
51#include "scip/cons_varbound.h"
52#include "scip/pub_cons.h"
53#include "scip/pub_event.h"
54#include "scip/pub_lp.h"
55#include "scip/pub_message.h"
56#include "scip/pub_misc.h"
57#include "scip/pub_misc_sort.h"
58#include "scip/pub_var.h"
59#include "scip/scip_conflict.h"
60#include "scip/scip_cons.h"
61#include "scip/scip_cut.h"
62#include "scip/scip_event.h"
63#include "scip/scip_general.h"
64#include "scip/scip_lp.h"
65#include "scip/scip_mem.h"
66#include "scip/scip_message.h"
67#include "scip/scip_nlp.h"
68#include "scip/scip_numerics.h"
69#include "scip/scip_param.h"
70#include "scip/scip_prob.h"
71#include "scip/scip_probing.h"
72#include "scip/scip_sol.h"
73#include "scip/scip_tree.h"
74#include "scip/scip_var.h"
75#include "scip/dbldblarith.h"
76#include "scip/symmetry_graph.h"
78#include <ctype.h>
79#include <string.h>
80
81
82/**@name Constraint handler properties
83 *
84 * @{
85 */
86
87/* constraint handler properties */
88#define CONSHDLR_NAME "varbound"
89#define CONSHDLR_DESC "variable bounds lhs <= x + c*y <= rhs, x non-binary, y non-continuous"
90#define CONSHDLR_SEPAPRIORITY +900000 /**< priority of the constraint handler for separation */
91#define CONSHDLR_ENFOPRIORITY -500000 /**< priority of the constraint handler for constraint enforcing */
92#define CONSHDLR_CHECKPRIORITY -500000 /**< priority of the constraint handler for checking feasibility */
93#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
94#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
95#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
96 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
97#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
98#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
99#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
100#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
101
102#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_MEDIUM)
103#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
104
105#define EVENTHDLR_NAME "varbound"
106#define EVENTHDLR_DESC "bound change event handler for variable bound constraints"
107
108#define LINCONSUPGD_PRIORITY +50000 /**< priority of the constraint handler for upgrading of linear constraints */
109
110/**@} */
111
112/**@name Default parameter values
113 *
114 * @{
115 */
116
117#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
118#define DEFAULT_MAXLPCOEF 1e+09 /**< maximum coefficient in varbound constraint to be added as a row into LP */
119#define DEFAULT_USEBDWIDENING TRUE /**< should bound widening be used to initialize conflict analysis? */
120
121
122#define MAXSCALEDCOEF 1000LL /**< maximal coefficient value after scaling */
123
124/**@} */
125
126/** variable bound constraint data */
127struct SCIP_ConsData
128{
129 SCIP_Real vbdcoef; /**< coefficient c of bounding variable y */
130 SCIP_Real lhs; /**< left hand side of variable bound inequality */
131 SCIP_Real rhs; /**< right hand side of variable bound inequality */
132 SCIP_VAR* var; /**< variable x that has variable bound */
133 SCIP_VAR* vbdvar; /**< binary, integer or implicit integer bounding variable y */
134 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
135 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */
136 unsigned int presolved:1; /**< is the variable bound constraint already presolved? */
137 unsigned int varboundsadded:1; /**< are the globally valid variable bounds added? */
138 unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
139 unsigned int tightened:1; /**< were the vbdcoef and all sides already tightened? */
140};
141
142/** constraint handler data */
143struct SCIP_ConshdlrData
144{
145 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
146 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
147 SCIP_Real maxlpcoef; /**< maximum coefficient in varbound constraint to be added as a row into LP */
148 SCIP_Bool usebdwidening; /**< should bound widening be used to in conflict analysis? */
149};
150
151/** Propagation rules */
153{
154 PROPRULE_1, /**< left hand side and bounds on y -> lower bound on x */
155 PROPRULE_2, /**< left hand side and upper bound on x -> bound on y */
156 PROPRULE_3, /**< right hand side and bounds on y -> upper bound on x */
157 PROPRULE_4 /**< right hand side and lower bound on x -> bound on y */
159typedef enum Proprule PROPRULE;
160
161
162/**@name Local methods
163 *
164 * @{
165 */
166
167/** compares two varbound constraints cons1: \f$ lhs1 \le x1 + c1 y1 \le rhs1 \f$ and cons2: \f$ lhs2 \le x2 + c2 y2 \le rhs2 \f$
168 * w.r.t. the indices of the contained variables
169 *
170 * returns -1 if:
171 * - the index of x1 is smaller than the index of x2 or
172 * - x1 = x2 and the index of y1 is smaller than the index of y2 or
173 * - x1 = x2 and y1 = y2 and cons2 was recently changed, but cons1 not
174 *
175 * returns 0 if x1 = x2, y1 = y2, and the changed status of both constraints is the same
176 *
177 * and returns +1 otherwise
178 */
179static
180SCIP_DECL_SORTPTRCOMP(consVarboundComp)
181{
182 SCIP_CONSDATA* consdata1;
183 SCIP_CONSDATA* consdata2;
184
185 assert(elem1 != NULL);
186 assert(elem2 != NULL);
187
188 consdata1 = SCIPconsGetData((SCIP_CONS*) elem1);
189 consdata2 = SCIPconsGetData((SCIP_CONS*) elem2);
190
191 assert(consdata1 != NULL);
192 assert(consdata2 != NULL);
193
194 /* comparison is done over 3 ordered criteria:
195 * (i) variable index of variable 1
196 * (ii) variable index of variable 2.
197 * (iii) changed status
198 */
199 if( SCIPvarGetIndex(consdata1->var) < SCIPvarGetIndex(consdata2->var)
200 || (SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
201 && SCIPvarGetIndex(consdata1->vbdvar) < SCIPvarGetIndex(consdata2->vbdvar))
202 || (SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
203 && SCIPvarGetIndex(consdata1->vbdvar) == SCIPvarGetIndex(consdata2->vbdvar)
204 && !consdata1->changed && consdata2->changed) )
205 return -1;
206 else if( SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
207 && SCIPvarGetIndex(consdata1->vbdvar) == SCIPvarGetIndex(consdata2->vbdvar)
208 && (consdata1->changed == consdata2->changed) )
209 return 0;
210 else
211 return +1;
212}
213
214/** creates constraint handler data for varbound constraint handler */
215static
217 SCIP* scip, /**< SCIP data structure */
218 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
219 SCIP_EVENTHDLR* eventhdlr /**< event handler */
220 )
221{
222 assert(scip != NULL);
223 assert(conshdlrdata != NULL);
224
225 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
226
227 /* set event handler for bound change events */
228 (*conshdlrdata)->eventhdlr = eventhdlr;
229
230 return SCIP_OKAY;
231}
232
233/** frees constraint handler data for varbound constraint handler */
234static
236 SCIP* scip, /**< SCIP data structure */
237 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
238 )
239{
240 assert(scip != NULL);
241 assert(conshdlrdata != NULL);
242 assert(*conshdlrdata != NULL);
243
244 SCIPfreeBlockMemory(scip, conshdlrdata);
245}
246
247/** catches events for variables
248 *
249 * @todo if lhs or rhs is infinite, catch only changes of the bound that could lead to propagation
250 */
251static
253 SCIP* scip, /**< SCIP data structure */
254 SCIP_CONS* cons, /**< variable bound constraint */
255 SCIP_EVENTHDLR* eventhdlr /**< event handler */
256 )
257{
258 SCIP_CONSDATA* consdata;
259 assert(cons != NULL);
260 assert(eventhdlr != NULL);
261 consdata = SCIPconsGetData(cons);
262 assert(consdata != NULL);
263
266
267 return SCIP_OKAY;
268}
269
270/** drops events for variables */
271static
273 SCIP* scip, /**< SCIP data structure */
274 SCIP_CONS* cons, /**< variable bound constraint */
275 SCIP_EVENTHDLR* eventhdlr /**< event handler */
276 )
277{
278 SCIP_CONSDATA* consdata;
279 assert(cons != NULL);
280 assert(eventhdlr != NULL);
281 consdata = SCIPconsGetData(cons);
282 assert(consdata != NULL);
283
286
287 return SCIP_OKAY;
288}
289
290/** creates a variable bound constraint data object */
291static
293 SCIP* scip, /**< SCIP data structure */
294 SCIP_CONSDATA** consdata, /**< pointer to store the variable bound constraint data */
295 SCIP_VAR* var, /**< variable x that has variable bound */
296 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
297 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
298 SCIP_Real lhs, /**< left hand side of variable bound inequality */
299 SCIP_Real rhs /**< right hand side of variable bound inequality */
300 )
301{
302 assert(consdata != NULL);
303 assert(SCIPvarIsIntegral(vbdvar));
304
305 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
306
307 if( SCIPisInfinity(scip, rhs) )
308 rhs = SCIPinfinity(scip);
309 else if( SCIPisInfinity(scip, -rhs) )
310 rhs = -SCIPinfinity(scip);
311
312 if( SCIPisInfinity(scip, -lhs) )
313 lhs = -SCIPinfinity(scip);
314 else if( SCIPisInfinity(scip, lhs) )
315 lhs = SCIPinfinity(scip);
316
317 if( SCIPisGT(scip, lhs, rhs) )
318 {
319 SCIPerrorMessage("left hand side of varbound constraint greater than right hand side\n");
320 SCIPerrorMessage(" -> lhs=%g, rhs=%g\n", lhs, rhs);
321 return SCIP_INVALIDDATA;
322 }
323
324 if( SCIPisZero(scip, vbdcoef) )
325 {
326 SCIPerrorMessage("varbound coefficient must be different to zero.\n");
327 return SCIP_INVALIDDATA;
328 }
329
330 if( SCIPisInfinity(scip, vbdcoef) )
331 vbdcoef = SCIPinfinity(scip);
332 else if( SCIPisInfinity(scip, -vbdcoef) )
333 vbdcoef = -SCIPinfinity(scip);
334
335 (*consdata)->var = var;
336 (*consdata)->vbdvar = vbdvar;
337 (*consdata)->vbdcoef = vbdcoef;
338 (*consdata)->lhs = lhs;
339 (*consdata)->rhs = rhs;
340 (*consdata)->row = NULL;
341 (*consdata)->nlrow = NULL;
342 (*consdata)->presolved = FALSE;
343 (*consdata)->varboundsadded = FALSE;
344 (*consdata)->changed = TRUE;
345 (*consdata)->tightened = FALSE;
346
347 /* if we are in the transformed problem, get transformed variables, add variable bound information, and catch events */
349 {
350 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->var, &(*consdata)->var) );
351 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vbdvar, &(*consdata)->vbdvar) );
352
353#ifndef NDEBUG
354 assert(SCIPvarGetStatus(SCIPvarGetProbvar((*consdata)->var)) != SCIP_VARSTATUS_MULTAGGR);
355 assert(SCIPvarGetStatus(SCIPvarGetProbvar((*consdata)->vbdvar)) != SCIP_VARSTATUS_MULTAGGR);
356#endif
357 }
358
359 /* capture variables */
360 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->var) );
361 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vbdvar) );
362
363 return SCIP_OKAY;
364}
365
366/** frees a variable bound constraint data */
367static
369 SCIP* scip, /**< SCIP data structure */
370 SCIP_CONSDATA** consdata /**< pointer to the variable bound constraint */
371 )
372{
373 assert(consdata != NULL);
374 assert(*consdata != NULL);
375
376 /* release the row */
377 if( (*consdata)->row != NULL )
378 {
379 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
380 }
381
382 /* release the nlrow */
383 if( (*consdata)->nlrow != NULL )
384 {
385 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
386 }
387
388 /* release variables */
389 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->var) );
390 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->vbdvar) );
391
392 SCIPfreeBlockMemory(scip, consdata);
393
394 return SCIP_OKAY;
395}
396
397/** creates LP row corresponding to variable bound constraint */
398static
400 SCIP* scip, /**< SCIP data structure */
401 SCIP_CONS* cons /**< variable bound constraint */
402 )
403{
404 SCIP_CONSDATA* consdata;
405
406 consdata = SCIPconsGetData(cons);
407 assert(consdata != NULL);
408 assert(consdata->row == NULL);
409
410 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
412 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->var, 1.0) );
413 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->vbdvar, consdata->vbdcoef) );
414
415 return SCIP_OKAY;
416}
417
418/** adds linear relaxation of variable bound constraint to the LP */
419static
421 SCIP* scip, /**< SCIP data structure */
422 SCIP_CONS* cons, /**< variable bound constraint */
423 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
424 )
425{
426 SCIP_CONSHDLR* conshdlr;
427 SCIP_CONSHDLRDATA* conshdlrdata;
428 SCIP_CONSDATA* consdata;
429
430 consdata = SCIPconsGetData(cons);
431 assert(consdata != NULL);
432
433 /* find the variable bound constraint handler */
435 if( conshdlr == NULL )
436 {
437 SCIPerrorMessage("variable bound constraint handler not found\n");
438 return SCIP_PLUGINNOTFOUND;
439 }
440
441 conshdlrdata = SCIPconshdlrGetData(conshdlr);
442 assert(conshdlrdata != NULL);
443
444 assert(SCIPvarIsIntegral(consdata->vbdvar));
445
446 /* check whether the coefficient is too large to put the row into the LP */
447 if( SCIPisGT(scip, REALABS(consdata->vbdcoef), conshdlrdata->maxlpcoef) )
448 return SCIP_OKAY;
449
450 if( consdata->row == NULL )
451 {
453 }
454 assert(consdata->row != NULL);
455
456 if( !SCIProwIsInLP(consdata->row) )
457 {
458 SCIPdebugMsg(scip, "adding relaxation of variable bound constraint <%s>: ", SCIPconsGetName(cons));
459 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
460 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, infeasible) );
461 }
462
463 return SCIP_OKAY;
464}
465
466/** adds varbound constraint as row to the NLP, if not added yet */
467static
469 SCIP* scip, /**< SCIP data structure */
470 SCIP_CONS* cons /**< varbound constraint */
471 )
472{
473 SCIP_CONSDATA* consdata;
474
475 assert(SCIPisNLPConstructed(scip));
476
477 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
478 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
479 return SCIP_OKAY;
480
481 consdata = SCIPconsGetData(cons);
482 assert(consdata != NULL);
483
484 if( consdata->nlrow == NULL )
485 {
486 SCIP_VAR* vars[2];
487 SCIP_Real coefs[2];
488
489 assert(consdata->lhs <= consdata->rhs);
490
491 vars[0] = consdata->var;
492 vars[1] = consdata->vbdvar;
493
494 coefs[0] = 1.0;
495 coefs[1] = consdata->vbdcoef;
496
497 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
498 0.0, 2, vars, coefs, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
499
500 assert(consdata->nlrow != NULL);
501 }
502
503 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
504 {
505 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
506 }
507
508 return SCIP_OKAY;
509}
510
511/** returns whether the given solution is feasible for the given variable bound constraint */
512static
514 SCIP* scip, /**< SCIP data structure */
515 SCIP_CONS* cons, /**< variable bound constraint */
516 SCIP_SOL* sol, /**< solution to check, NULL for current solution */
517 SCIP_Bool checklprows /**< Do constraints represented by rows in the current LP have to be checked? */
518 )
519{
520 SCIP_CONSDATA* consdata;
521 SCIP_Real absviol;
522 SCIP_Real relviol;
523
524 consdata = SCIPconsGetData(cons);
525 assert(consdata != NULL);
526
527 SCIPdebugMsg(scip, "checking variable bound constraint <%s> for feasibility of solution %p (lprows=%u)\n",
528 SCIPconsGetName(cons), (void*)sol, checklprows);
529
530 if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
531 {
532 SCIP_Real sum;
533 SCIP_Real lhsrelviol;
534 SCIP_Real rhsrelviol;
535
536 sum = SCIPgetSolVal(scip, sol, consdata->var) + consdata->vbdcoef * SCIPgetSolVal(scip, sol, consdata->vbdvar);
537
538 /* calculate constraint violation and update it in solution */
539 absviol = MAX(consdata->lhs - sum, sum - consdata->rhs);
540 lhsrelviol = SCIPrelDiff(consdata->lhs, sum);
541 rhsrelviol = SCIPrelDiff(sum, consdata->rhs);
542 relviol = MAX(lhsrelviol, rhsrelviol);
543 if( sol != NULL )
544 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
545
546 return (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, sum, consdata->lhs))
547 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, sum, consdata->rhs));
548 }
549 else
550 return TRUE;
551}
552
553
554/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
555 * propagation rule (see propagateCons()):
556 * (1) left hand side and bounds on y -> lower bound on x
557 * (2) left hand side and upper bound on x -> bound on y
558 * (3) right hand side and bounds on y -> upper bound on x
559 * (4) right hand side and lower bound on x -> bound on y
560 */
561static
563 SCIP* scip, /**< SCIP data structure */
564 SCIP_CONS* cons, /**< constraint that inferred the bound change */
565 SCIP_VAR* infervar, /**< variable that was deduced */
566 PROPRULE proprule, /**< propagation rule that deduced the bound change */
567 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
568 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
569 SCIP_Real inferbd, /**< inference bound which needs to be explained */
570 SCIP_Bool usebdwidening /**< should bound widening be used to in conflict analysis? */
571 )
572{
573 SCIP_CONSDATA* consdata;
574 SCIP_VAR* vbdvar;
575 SCIP_VAR* var;
576 SCIP_Real vbdcoef;
577
578 consdata = SCIPconsGetData(cons);
579 assert(consdata != NULL);
580 assert(!SCIPisZero(scip, consdata->vbdcoef));
581
582 var = consdata->var;
583 assert(var != NULL);
584
585 vbdvar = consdata->vbdvar;
586 assert(vbdvar != NULL);
587
588 vbdcoef = consdata->vbdcoef;
589 assert(!SCIPisZero(scip, vbdcoef));
590
591 switch( proprule )
592 {
593 case PROPRULE_1:
594 /* lhs <= x + c*y: left hand side and bounds on y -> lower bound on x */
595 assert(infervar == var);
596 assert(boundtype == SCIP_BOUNDTYPE_LOWER);
597 assert(!SCIPisInfinity(scip, -consdata->lhs));
598
599 if( usebdwidening )
600 {
601 SCIP_Real QUAD(relaxedbd);
602
603 /* For integer variables, we can reduce the inferbound by 1 - z * eps, because this will be adjusted
604 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
605 * too small and too large vbdcoef values.
606 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
607 * arithmetics, so we explicitly check this here.
608 */
609 if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
610 && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
611 {
612 SCIP_Real QUAD(tmp);
613
614 QUAD_ASSIGN(tmp, 2.0);
616
617 SCIPquadprecSumDD(relaxedbd, inferbd, -1.0);
618
619 SCIPquadprecSumQQ(relaxedbd, relaxedbd, tmp);
620 SCIPquadprecSumQD(relaxedbd, -relaxedbd, consdata->lhs);
621
622 SCIPquadprecDivQD(relaxedbd, relaxedbd, vbdcoef);
623 }
624 else
625 {
626 SCIPquadprecSumDD(relaxedbd, consdata->lhs, -inferbd);
627 SCIPquadprecDivQD(relaxedbd, relaxedbd, vbdcoef);
628 }
629
630#ifndef NDEBUG
631 {
632 /* check the computed relaxed lower/upper bound is a proper reason for the inference bound which has to be explained */
633 SCIP_Real QUAD(tmp);
634
635 SCIPquadprecProdQD(tmp, relaxedbd, vbdcoef);
636 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
637
638 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, var, QUAD_TO_DBL(tmp))));
639 }
640#endif
641 if( vbdcoef > 0.0 )
642 {
643 /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual
644 * inference bound due to the integrality condition of the variable bound variable
645 */
646 SCIPquadprecSumQD(relaxedbd, relaxedbd, -SCIPfeastol(scip));
647 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
648 }
649 else
650 {
651 /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference
652 * bound due to the integrality condition of the variable bound variable
653 */
654 SCIPquadprecSumQD(relaxedbd, relaxedbd, SCIPfeastol(scip));
655 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
656 }
657 }
658 else
659 {
660 if( vbdcoef > 0.0 )
661 {
662 SCIP_CALL( SCIPaddConflictUb(scip, vbdvar, bdchgidx) );
663 }
664 else
665 {
666 SCIP_CALL( SCIPaddConflictLb(scip, vbdvar, bdchgidx) );
667 }
668 }
669
670 break;
671
672 case PROPRULE_2:
673 /* lhs <= x + c*y: left hand side and upper bound on x -> bound on y */
674 assert(infervar == vbdvar);
675 assert(SCIPvarIsIntegral(vbdvar));
676 assert(!SCIPisInfinity(scip, -consdata->lhs));
677
678 if( usebdwidening )
679 {
680 SCIP_Real QUAD(relaxedub);
681
682 /* compute the relaxed upper bound of the variable which would be sufficient to reach one less (greater) than the
683 * inference bound
684 */
685 if( vbdcoef > 0.0 )
686 {
687 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
688 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
689 * too small and too large vbdcoef values.
690 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
691 * arithmetics, so we explicitly check this here.
692 */
693 if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
694 && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
695 {
696 SCIP_Real QUAD(tmp);
697
698 QUAD_ASSIGN(tmp, 2.0);
700
701 SCIPquadprecSumDD(relaxedub, inferbd, -1.0);
702
703 SCIPquadprecSumQQ(relaxedub, relaxedub, tmp);
704 SCIPquadprecProdQD(relaxedub, relaxedub, vbdcoef);
705
706 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
707 }
708 else
709 {
710 SCIPquadprecProdDD(relaxedub, inferbd, vbdcoef);
711 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
712 }
713
714#ifndef NDEBUG
715 {
716 /* check the computed relaxed upper bound is a proper reason for the inference bound which has to be explained */
717 SCIP_Real QUAD(tmp);
718
719 SCIPquadprecSumQD(tmp, -relaxedub, consdata->lhs);
720 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
721
722 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, vbdvar, QUAD_TO_DBL(tmp))));
723 }
724#endif
725 }
726 else
727 {
728 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
729 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
730 * too small and too large vbdcoef values.
731 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
732 * arithmetics, so we explicitly check this here.
733 */
734 if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
735 && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
736 {
737 SCIP_Real QUAD(tmp);
738
739 QUAD_ASSIGN(tmp, 2.0);
741
742 SCIPquadprecSumDD(relaxedub, inferbd, 1.0);
743
744 SCIPquadprecSumQQ(relaxedub, relaxedub, -tmp);
745 SCIPquadprecProdQD(relaxedub, relaxedub, vbdcoef);
746
747 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
748 }
749 else
750 {
751 SCIPquadprecProdDD(relaxedub, inferbd, vbdcoef);
752 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
753 }
754
755#ifndef NDEBUG
756 {
757 /* check the computed relaxed upper bound is a proper reason for the inference bound which has to be explained */
758 SCIP_Real QUAD(tmp);
759
760 SCIPquadprecSumQD(tmp, -relaxedub, consdata->lhs);
761 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
762
763 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, vbdvar, QUAD_TO_DBL(tmp))));
764 }
765#endif
766 }
767
768 /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual inference bound due
769 * to the integrality condition of the variable bound variable
770 */
771 SCIPquadprecSumQD(relaxedub, relaxedub, -SCIPfeastol(scip));
772 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, var, bdchgidx, QUAD_TO_DBL(relaxedub)) );
773 }
774 else
775 {
776 SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
777 }
778
779 break;
780
781 case PROPRULE_3:
782 /* x + c*y <= rhs: right hand side and bounds on y -> upper bound on x */
783 assert(infervar == var);
784 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
785 assert(!SCIPisInfinity(scip, consdata->rhs));
786
787 if( usebdwidening )
788 {
789 SCIP_Real QUAD(relaxedbd);
790
791 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
792 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
793 * too small and too large vbdcoef values.
794 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
795 * arithmetics, so we explicitly check this here.
796 */
797 if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
798 && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
799 {
800 SCIP_Real QUAD(tmp);
801
802 QUAD_ASSIGN(tmp, 2.0);
803
805 SCIPquadprecSumDD(relaxedbd, inferbd, 1.0);
806
807 SCIPquadprecSumQQ(relaxedbd, relaxedbd, -tmp);
808 SCIPquadprecSumQD(relaxedbd, relaxedbd, -consdata->rhs);
809
810 SCIPquadprecDivQD(relaxedbd, relaxedbd, -vbdcoef);
811 }
812 else
813 {
814 SCIPquadprecSumDD(relaxedbd, consdata->rhs, -inferbd);
815 SCIPquadprecDivQD(relaxedbd, relaxedbd, vbdcoef);
816 }
817#ifndef NDEBUG
818 {
819 /* check the computed relaxed lower/upper bound is a proper reason for the inference bound which has to be explained */
820 SCIP_Real QUAD(tmp);
821
822 SCIPquadprecProdQD(tmp, relaxedbd, -vbdcoef);
823 SCIPquadprecSumQD(tmp, tmp, consdata->rhs);
824
825 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, var, QUAD_TO_DBL(tmp))));
826 }
827#endif
828 if( vbdcoef > 0.0 )
829 {
830 /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference bound due
831 * to the integrality condition of the variable bound variable
832 */
833 SCIPquadprecSumQD(relaxedbd, relaxedbd, SCIPfeastol(scip));
834 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
835 }
836 else
837 {
838 /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual inference bound due
839 * to the integrality condition of the variable bound variable
840 */
841 SCIPquadprecSumQD(relaxedbd, relaxedbd, -SCIPfeastol(scip));
842 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
843 }
844 }
845 else
846 {
847 if( vbdcoef > 0.0 )
848 {
849 SCIP_CALL( SCIPaddConflictLb(scip, vbdvar, bdchgidx) );
850 }
851 else
852 {
853 SCIP_CALL( SCIPaddConflictUb(scip, vbdvar, bdchgidx) );
854 }
855 }
856
857 break;
858
859 case PROPRULE_4:
860 /* x + c*y <= rhs: right hand side and lower bound on x -> bound on y */
861 assert(infervar == vbdvar);
862 assert(SCIPvarIsIntegral(vbdvar));
863 assert(!SCIPisInfinity(scip, consdata->rhs));
864
865 if( usebdwidening )
866 {
867 SCIP_Real QUAD(relaxedlb);
868
869 /* compute the relaxed lower bound of the variable which would be sufficient to reach one greater (less) than the
870 * inference bound
871 */
872 if( vbdcoef > 0.0 )
873 {
874 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
875 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
876 * too small and too large vbdcoef values.
877 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
878 * arithmetics, so we explicitly check this here.
879 */
880 if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
881 && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
882 {
883 SCIP_Real QUAD(tmp);
884
885 QUAD_ASSIGN(tmp, 2.0);
887
888 SCIPquadprecSumDD(relaxedlb, inferbd, 1.0);
889 SCIPquadprecSumQQ(relaxedlb, relaxedlb, -tmp);
890
891 SCIPquadprecProdQD(relaxedlb, relaxedlb, vbdcoef);
892
893 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
894 }
895 else
896 {
897 SCIPquadprecProdDD(relaxedlb, inferbd, vbdcoef);
898 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
899 }
900#ifndef NDEBUG
901 {
902 /* check the computed relaxed lower bound is a proper reason for the inference bound which has to be explained */
903
904 SCIP_Real QUAD(tmp);
905
906 QUAD_ASSIGN(tmp, consdata->rhs);
907 SCIPquadprecSumQQ(tmp, tmp, -relaxedlb);
908 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
909
910 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, vbdvar, QUAD_TO_DBL(tmp))));
911 }
912#endif
913 }
914 else
915 {
916 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
917 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
918 * too small and too large vbdcoef values.
919 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
920 * arithmetics, so we explicitly check this here.
921 */
922 if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
923 && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
924 {
925 SCIP_Real QUAD(tmp);
926
927 QUAD_ASSIGN(tmp, 2.0);
929
930 SCIPquadprecSumDD(relaxedlb, inferbd, -1.0);
931 SCIPquadprecSumQQ(relaxedlb, relaxedlb, tmp);
932
933 SCIPquadprecProdQD(relaxedlb, relaxedlb, vbdcoef);
934
935 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
936 }
937 else
938 {
939 SCIPquadprecProdDD(relaxedlb, inferbd, vbdcoef);
940 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
941 }
942
943#ifndef NDEBUG
944 {
945 /* check the computed relaxed lower bound is a proper reason for the inference bound which has to be explained */
946
947 SCIP_Real QUAD(tmp);
948
949 QUAD_ASSIGN(tmp, consdata->rhs);
950 SCIPquadprecSumQQ(tmp, tmp, -relaxedlb);
951 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
952
953 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, vbdvar, QUAD_TO_DBL(tmp))));
954 }
955#endif
956 }
957
958 /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference bound due
959 * to the integrality condition of the variable bound variable
960 */
961 SCIPquadprecSumQD(relaxedlb, relaxedlb, SCIPfeastol(scip));
962 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, var, bdchgidx, QUAD_TO_DBL(relaxedlb)) );
963 }
964 else
965 {
966 SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
967 }
968
969 break;
970
971 default:
972 SCIPerrorMessage("invalid inference information %d in variable bound constraint <%s>\n", proprule, SCIPconsGetName(cons));
973 return SCIP_INVALIDDATA;
974 }
975
976 return SCIP_OKAY;
977}
978
979/** analyze infeasibility */
980static
982 SCIP* scip, /**< SCIP data structure */
983 SCIP_CONS* cons, /**< variable bound constraint */
984 SCIP_VAR* infervar, /**< variable that was deduced */
985 SCIP_Real inferbd, /**< bound which led to infeasibility */
986 PROPRULE proprule, /**< propagation rule that deduced the bound change */
987 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
988 SCIP_Bool usebdwidening /**< should bound widening be used to in conflict analysis? */
989 )
990{
991 /* conflict analysis can only be applied in solving stage and if it is applicable */
993 return SCIP_OKAY;
994
995 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
997
998 /* add the bound which got violated */
999 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1000 {
1001 if( usebdwidening )
1002 {
1003 SCIP_Real relaxedub;
1004
1005 /* adjust lower bound */
1006 inferbd = SCIPadjustedVarLb(scip, infervar, inferbd);
1007
1008 /* compute a relaxed upper bound which would be sufficient to be still infeasible */
1009 if( SCIPvarIsIntegral(infervar) )
1010 relaxedub = inferbd - 1.0;
1011 else
1012 {
1013 SCIP_CONSDATA* consdata;
1014 SCIP_Real abscoef;
1015
1016 consdata = SCIPconsGetData(cons);
1017 assert(consdata != NULL);
1018
1019 /* vbdvar can never be of non-integral type */
1020 assert(infervar == consdata->var);
1021
1022 abscoef = REALABS(consdata->vbdcoef);
1023
1024 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1025 * is big enough, therefore we multiply here with the vbdcoef
1026 *
1027 * @note it does not matter if we deceed the current local upper bound, because SCIPaddConflictRelaxedUb()
1028 * is correcting the bound afterwards
1029 */
1030 /* coverity[copy_paste_error] */
1031 relaxedub = inferbd - 2*SCIPfeastol(scip) * MAX(1, abscoef);
1032 }
1033
1034 /* try to relax inference variable upper bound such that the infeasibility is still given */
1035 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, infervar, NULL, relaxedub) );
1036
1037 /* collect the upper bound which is reported to the conflict analysis */
1038 inferbd = SCIPgetConflictVarUb(scip, infervar);
1039
1040 /* adjust inference bound with respect to the upper bound reported to the conflict analysis */
1041 if( SCIPvarIsIntegral(infervar) )
1042 inferbd = inferbd + 1.0;
1043 else
1044 {
1045 SCIP_CONSDATA* consdata;
1046 SCIP_Real abscoef;
1047
1048 consdata = SCIPconsGetData(cons);
1049 assert(consdata != NULL);
1050
1051 /* vbdvar can never be of non-integral type */
1052 assert(infervar == consdata->var);
1053
1054 abscoef = REALABS(consdata->vbdcoef);
1055
1056 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1057 * is big enough, therefore we multiply here with the vbdcoef
1058 */
1059 inferbd = inferbd + 2*SCIPfeastol(scip) * MAX(1, abscoef);
1060 }
1061 }
1062 else
1063 {
1064 SCIP_CALL( SCIPaddConflictUb(scip, infervar, NULL) );
1065 }
1066 }
1067 else
1068 {
1069 if( usebdwidening )
1070 {
1071 SCIP_Real relaxedlb;
1072
1073 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
1074
1075 /* adjust upper bound */
1076 inferbd = SCIPadjustedVarUb(scip, infervar, inferbd);
1077
1078 /* compute a relaxed lower bound which would be sufficient to be still infeasible */
1079 if( SCIPvarIsIntegral(infervar) )
1080 relaxedlb = inferbd + 1.0;
1081 else
1082 {
1083 SCIP_CONSDATA* consdata;
1084 SCIP_Real abscoef;
1085
1086 consdata = SCIPconsGetData(cons);
1087 assert(consdata != NULL);
1088
1089 /* vbdvar can never be of non-integral type */
1090 assert(infervar == consdata->var);
1091
1092 abscoef = REALABS(consdata->vbdcoef);
1093
1094 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1095 * is big enough, therefore we multiply here with the vbdcoef
1096 *
1097 * @note it does not matter if we exceed the current local lower bound, because SCIPaddConflictRelaxedLb()
1098 * is correcting the bound afterwards
1099 */
1100 /* coverity[copy_paste_error] */
1101 relaxedlb = inferbd + 2*SCIPfeastol(scip) * MAX(1, abscoef);
1102 }
1103
1104 /* try to relax inference variable upper bound such that the infeasibility is still given */
1105 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, infervar, NULL, relaxedlb) );
1106
1107 /* collect the lower bound which is reported to the conflict analysis */
1108 inferbd = SCIPgetConflictVarLb(scip, infervar);
1109
1110 /* adjust inference bound with respect to the lower bound reported to the conflict analysis */
1111 if( SCIPvarIsIntegral(infervar) )
1112 inferbd = inferbd - 1.0;
1113 else
1114 {
1115 SCIP_CONSDATA* consdata;
1116 SCIP_Real abscoef;
1117
1118 consdata = SCIPconsGetData(cons);
1119 assert(consdata != NULL);
1120
1121 /* vbdvar can never be of non-integral type */
1122 assert(infervar == consdata->var);
1123
1124 abscoef = REALABS(consdata->vbdcoef);
1125
1126 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1127 * is big enough, therefore we multiply here with the vbdcoef
1128 */
1129 inferbd = inferbd - 2*SCIPfeastol(scip) * MAX(1, abscoef);
1130 }
1131 }
1132 else
1133 {
1134 SCIP_CALL( SCIPaddConflictLb(scip, infervar, NULL) );
1135 }
1136 }
1137
1138 /* add the reason for the violated of the bound */
1139 SCIP_CALL( resolvePropagation(scip, cons, infervar, proprule, boundtype, NULL, inferbd, usebdwidening) );
1140
1141 /* analyze the conflict */
1143
1144 return SCIP_OKAY;
1145}
1146
1147/** separates the given variable bound constraint */
1148static
1150 SCIP* scip, /**< SCIP data structure */
1151 SCIP_CONS* cons, /**< variable bound constraint */
1152 SCIP_Bool usebdwidening, /**< should bound widening be used to in conflict analysis? */
1153 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1154 SCIP_RESULT* result /**< pointer to store the result of the separation call */
1155 )
1156{
1157 SCIP_CONSHDLR* conshdlr;
1158 SCIP_CONSDATA* consdata;
1159 SCIP_VAR* vbdvar;
1160 SCIP_VAR* var;
1161 SCIP_Real vbdcoef;
1162 SCIP_Real feasibility;
1163
1164 assert(cons != NULL);
1165 assert(result != NULL);
1166
1167 consdata = SCIPconsGetData(cons);
1168 assert(consdata != NULL);
1169
1170 /* find the variable bound constraint handler */
1171 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
1172 if( conshdlr == NULL )
1173 {
1174 SCIPerrorMessage("variable bound constraint handler not found\n");
1175 return SCIP_PLUGINNOTFOUND;
1176 }
1177
1178 SCIPdebugMsg(scip, "separating variable bound constraint <%s>\n", SCIPconsGetName(cons));
1179
1180 var = consdata->var;
1181 vbdvar = consdata->vbdvar;
1182 vbdcoef = consdata->vbdcoef;
1183 assert(SCIPvarIsIntegral(vbdvar));
1184
1185 /* if x is not multiaggregated and y is fixed, propagate bounds on x */
1186 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR && SCIPvarGetLbLocal(vbdvar) + 0.5 > SCIPvarGetUbLocal(vbdvar) )
1187 {
1188 assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vbdvar), SCIPvarGetUbLocal(vbdvar)));
1189
1190 if( !SCIPisInfinity(scip, -consdata->lhs) )
1191 {
1192 SCIP_Real newlb;
1193 SCIP_Real QUAD(tmp);
1194 SCIP_Bool cutoff;
1195 SCIP_Bool tightened;
1196
1197 SCIPquadprecProdDD(tmp, vbdcoef, SCIPvarGetLbLocal(vbdvar)); /*lint !e666*/
1198 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1199
1200 newlb = QUAD_TO_DBL(tmp);
1201
1202 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, (int)PROPRULE_1, TRUE,
1203 &cutoff, &tightened) );
1204
1205 if( cutoff )
1206 {
1207 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(var)));
1208
1209 /* analyze infeasibility */
1210 SCIP_CALL( analyzeConflict(scip, cons, var, newlb, PROPRULE_1, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1211 *result = SCIP_CUTOFF;
1212
1213 return SCIP_OKAY;
1214 }
1215 else if( tightened )
1216 {
1217 *result = SCIP_REDUCEDDOM;
1218 }
1219 }
1220
1221 if( !SCIPisInfinity(scip, consdata->rhs) )
1222 {
1223 SCIP_Real newub;
1224 SCIP_Real QUAD(tmp);
1225 SCIP_Bool cutoff;
1226 SCIP_Bool tightened;
1227
1228 SCIPquadprecProdDD(tmp, vbdcoef, SCIPvarGetLbLocal(vbdvar)); /*lint !e666*/
1229 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1230
1231 newub = QUAD_TO_DBL(tmp);
1232
1233 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, (int)PROPRULE_3, TRUE,
1234 &cutoff, &tightened) );
1235
1236 if( cutoff )
1237 {
1238 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(var)));
1239
1240 /* analyze infeasibility */
1241 SCIP_CALL( analyzeConflict(scip, cons, var, newub, PROPRULE_3, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1242 *result = SCIP_CUTOFF;
1243
1244 return SCIP_OKAY;
1245 }
1246 else if( tightened )
1247 {
1248 *result = SCIP_REDUCEDDOM;
1249 }
1250 }
1251 }
1252
1253 /* if we already changed a bound or the coefficient is too large to put the row into the LP, stop here */
1254 if( *result == SCIP_REDUCEDDOM )
1255 return SCIP_OKAY;
1256
1257 /* check constraint for feasibility and create row if constraint is violated */
1258 if( !checkCons(scip, cons, sol, (sol != NULL)) )
1259 {
1260 /* create LP relaxation if not yet existing */
1261 if( consdata->row == NULL )
1262 {
1264 }
1265 assert(consdata->row != NULL);
1266
1267 /* check non-LP rows for feasibility and add them as cut, if violated */
1268 if( !SCIProwIsInLP(consdata->row) )
1269 {
1270 feasibility = SCIPgetRowSolFeasibility(scip, consdata->row, sol);
1271 if( SCIPisFeasNegative(scip, feasibility) )
1272 {
1273 SCIP_Bool infeasible;
1274
1275 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, &infeasible) );
1276 if ( infeasible )
1277 *result = SCIP_CUTOFF;
1278 else
1279 *result = SCIP_SEPARATED;
1280 }
1281 }
1282 }
1283
1284 return SCIP_OKAY;
1285}
1286
1287/** sets left hand side of varbound constraint */
1288static
1290 SCIP* scip, /**< SCIP data structure */
1291 SCIP_CONS* cons, /**< linear constraint */
1292 SCIP_Real lhs /**< new left hand side */
1293 )
1294{
1295 SCIP_CONSDATA* consdata;
1296
1297 assert(scip != NULL);
1298 assert(cons != NULL);
1299 assert(!SCIPisInfinity(scip, lhs));
1300
1301 /* adjust value to not be smaller than -inf */
1302 if( SCIPisInfinity(scip, -lhs) )
1303 lhs = -SCIPinfinity(scip);
1304
1305 consdata = SCIPconsGetData(cons);
1306 assert(consdata != NULL);
1307 assert(consdata->var != NULL && consdata->vbdvar != NULL);
1308 assert(!SCIPisInfinity(scip, consdata->lhs));
1309
1310 /* check whether the side is not changed */
1311 if( SCIPisEQ(scip, consdata->lhs, lhs) )
1312 return SCIP_OKAY;
1313
1314 assert(consdata->row == NULL);
1315
1316 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
1317 if( SCIPisEQ(scip, lhs, consdata->rhs) )
1318 consdata->rhs = lhs;
1319
1320 /* update the rounding locks of variables */
1321
1322 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
1323 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
1324 {
1325 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, TRUE, FALSE) );
1326
1327 if( consdata->vbdcoef > 0.0 )
1328 {
1329 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1330 }
1331 else
1332 {
1333 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1334 }
1335 }
1336 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
1337 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
1338 {
1339 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, TRUE, FALSE) );
1340
1341 if( consdata->vbdcoef > 0.0 )
1342 {
1343 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1344 }
1345 else
1346 {
1347 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1348 }
1349 }
1350
1351 /* if left hand side got tighter, we want to do additional presolving on this constraint */
1352 if( SCIPisLT(scip, consdata->lhs, lhs) )
1353 {
1354 consdata->varboundsadded = FALSE;
1355 consdata->tightened = FALSE;
1356
1358 }
1359
1360 consdata->presolved = FALSE;
1361 consdata->lhs = lhs;
1362 consdata->changed = TRUE;
1363
1364 return SCIP_OKAY;
1365}
1366
1367/** sets right hand side of varbound constraint */
1368static
1370 SCIP* scip, /**< SCIP data structure */
1371 SCIP_CONS* cons, /**< linear constraint */
1372 SCIP_Real rhs /**< new right hand side */
1373 )
1374{
1375 SCIP_CONSDATA* consdata;
1376
1377 assert(scip != NULL);
1378 assert(cons != NULL);
1379 assert(!SCIPisInfinity(scip, -rhs));
1380
1381 /* adjust value to not be larger than inf */
1382 if( SCIPisInfinity(scip, rhs) )
1383 rhs = SCIPinfinity(scip);
1384
1385 consdata = SCIPconsGetData(cons);
1386 assert(consdata != NULL);
1387 assert(consdata->var != NULL && consdata->vbdvar != NULL);
1388 assert(!SCIPisInfinity(scip, -consdata->rhs));
1389
1390 /* check whether the side is not changed */
1391 if( SCIPisEQ(scip, consdata->rhs, rhs) )
1392 return SCIP_OKAY;
1393
1394 assert(consdata->row == NULL);
1395
1396 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
1397 if( SCIPisEQ(scip, rhs, consdata->lhs) )
1398 consdata->lhs = rhs;
1399
1400 /* update the locks of variables */
1401 assert(SCIPconsIsTransformed(cons));
1402
1403 /* the right hand side switched from infinity to a non-infinite value -> install locks */
1404 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
1405 {
1406 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, FALSE, TRUE) );
1407
1408 if( consdata->vbdcoef > 0.0 )
1409 {
1410 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1411 }
1412 else
1413 {
1414 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1415 }
1416 }
1417 /* the right hand side switched from a non-infinite value to infinity -> remove locks */
1418 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
1419 {
1420 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, FALSE, TRUE) );
1421
1422 if( consdata->vbdcoef > 0.0 )
1423 {
1424 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1425 }
1426 else
1427 {
1428 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1429 }
1430 }
1431
1432 /* if right hand side got tighter, we want to do additional presolving on this constraint */
1433 if( SCIPisGT(scip, consdata->rhs, rhs) )
1434 {
1435 consdata->varboundsadded = FALSE;
1436 consdata->tightened = FALSE;
1437
1439 }
1440
1441 consdata->presolved = FALSE;
1442 consdata->rhs = rhs;
1443 consdata->changed = TRUE;
1444
1445 return SCIP_OKAY;
1446}
1447
1448/** propagation method for variable bound constraint */
1449static
1451 SCIP* scip, /**< SCIP data structure */
1452 SCIP_CONS* cons, /**< variable bound constraint */
1453 SCIP_Bool usebdwidening, /**< should bound widening be used to in conflict analysis? */
1454 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1455 int* nchgbds, /**< pointer to count number of bound changes */
1456 int* nchgsides, /**< pointer to count number of side changes */
1457 int* ndelconss /**< pointer to count number of deleted constraints, or NULL */
1458 )
1459{
1460 SCIP_VAR** vars;
1461 SCIP_CONSDATA* consdata;
1463 SCIP_Real xlb;
1464 SCIP_Real xub;
1465 SCIP_Real ylb;
1466 SCIP_Real yub;
1467 SCIP_Real newlb;
1468 SCIP_Real newub;
1469 SCIP_Real constant;
1471 SCIP_Real QUAD(activity);
1472 SCIP_Bool tightened;
1473 SCIP_Bool tightenedround;
1474 SCIP_Bool islhsredundant;
1475 SCIP_Bool isrhsredundant;
1476 int nvars;
1477 int requiredsize;
1478 int i;
1479
1480 assert(cutoff != NULL);
1481 assert(nchgbds != NULL);
1482
1483 consdata = SCIPconsGetData(cons);
1484 assert(consdata != NULL);
1485 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
1486
1487 SCIPdebugMsg(scip, "propagating variable bound constraint <%s>: %.15g <= <%s>[%.9g, %.9g] + %.15g<%s>[%.9g, %.9g] <= %.15g\n",
1488 SCIPconsGetName(cons), consdata->lhs, SCIPvarGetName(consdata->var), SCIPvarGetLbLocal(consdata->var),
1489 SCIPvarGetUbLocal(consdata->var), consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
1490 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), consdata->rhs);
1491
1492 *cutoff = FALSE;
1493
1494 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1496 {
1497 SCIP_CALL( SCIPincConsAge(scip, cons) );
1498 }
1499
1500 /* get current bounds of variables */
1501 xlb = SCIPvarGetLbLocal(consdata->var);
1502 xub = SCIPvarGetUbLocal(consdata->var);
1503 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1504 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1505
1506 /* it can happen that constraint is of form lhs <= x <= rhs */
1507 if( SCIPisZero(scip, consdata->vbdcoef) && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1508 {
1509 SCIP_Bool infeasible;
1510 SCIP_Bool fixed;
1511
1512 SCIP_CALL( SCIPfixVar(scip, consdata->var, consdata->lhs, &infeasible, &fixed) );
1513
1514 if( infeasible )
1515 {
1516 SCIPdebugMsg(scip, "> constraint <%s> is infeasible.\n", SCIPconsGetName(cons));
1517 *cutoff = TRUE;
1518 return SCIP_OKAY;
1519 }
1520 }
1521
1522 /* tighten bounds of variables as long as possible */
1523 do
1524 {
1525 tightenedround = FALSE;
1526
1527 /* propagate left hand side inequality: lhs <= x + c*y */
1528 if( !SCIPisInfinity(scip, -consdata->lhs) )
1529 {
1530 assert(!(*cutoff));
1531
1532 /* propagate bounds on x:
1533 * (1) left hand side and bounds on y -> lower bound on x
1534 */
1535 if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1536 {
1537 if( consdata->vbdcoef > 0.0 )
1538 {
1539 if( !SCIPisInfinity(scip, yub) )
1540 {
1541 SCIP_Real QUAD(tmp);
1542
1543 SCIPquadprecProdDD(tmp, consdata->vbdcoef, yub);
1544 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1545
1546 newlb = SCIPadjustedVarLb(scip, consdata->var, QUAD_TO_DBL(tmp));
1547 }
1548 else
1549 {
1550 newlb = -SCIPinfinity(scip);
1551 }
1552 }
1553 else
1554 {
1555 if( !SCIPisInfinity(scip, -ylb) )
1556 {
1557 SCIP_Real QUAD(tmp);
1558
1559 SCIPquadprecProdDD(tmp, consdata->vbdcoef, ylb);
1560 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1561
1562 newlb = SCIPadjustedVarLb(scip, consdata->var, QUAD_TO_DBL(tmp));
1563 }
1564 else
1565 {
1566 newlb = -SCIPinfinity(scip);
1567 }
1568 }
1569
1570 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->var, newlb, cons, (int)PROPRULE_1, yub < ylb + 0.5, cutoff, &tightened) );
1571
1572 if( *cutoff )
1573 {
1574 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1575 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->var)));
1576
1578
1579 /* analyze infeasibility */
1580 SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newlb, PROPRULE_1, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1581 break;
1582 }
1583
1584 if( tightened )
1585 {
1586 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1587 tightenedround = TRUE;
1588 (*nchgbds)++;
1590 }
1591 xlb = SCIPvarGetLbLocal(consdata->var);
1592 }
1593
1594 assert(!*cutoff);
1595
1596 /* propagate bounds on y:
1597 * (2) left hand side and upper bound on x -> bound on y
1598 */
1599 if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, xub) ) /* cannot change bounds of multaggr vars */
1600 {
1601 if( consdata->vbdcoef > 0.0 )
1602 {
1603 SCIP_Real QUAD(tmp);
1604
1605 SCIPquadprecSumDD(tmp, consdata->lhs, -xub);
1606 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1607
1608 newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1609 if( newlb > ylb + 0.5 )
1610 {
1611 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1612
1613 if( *cutoff )
1614 {
1615 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1616 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)));
1617
1618 /* analyze infeasibility */
1619 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_2, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1620 break;
1621 }
1622
1623 if( tightened )
1624 {
1625 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1626 tightenedround = TRUE;
1627 (*nchgbds)++;
1628 }
1629 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1630 }
1631 }
1632 else
1633 {
1634 SCIP_Real QUAD(tmp);
1635
1636 SCIPquadprecSumDD(tmp, consdata->lhs, -xub);
1637 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1638
1639 newub = SCIPadjustedVarUb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1640
1641 if( newub < yub - 0.5 )
1642 {
1643 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1644
1645 if( *cutoff )
1646 {
1647 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1648 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)));
1649
1651
1652 /* analyze infeasibility */
1653 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_2, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1654 break;
1655 }
1656
1657 if( tightened )
1658 {
1659 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1660 tightenedround = TRUE;
1661 (*nchgbds)++;
1663 }
1664 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1665 }
1666 }
1667 }
1668 }
1669
1670 assert(!*cutoff);
1671
1672 /* propagate right hand side inequality: x + c*y <= rhs */
1673 if( !SCIPisInfinity(scip, consdata->rhs) )
1674 {
1675 /* propagate bounds on x:
1676 * (3) right hand side and bounds on y -> upper bound on x
1677 */
1678 if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1679 {
1680 if( consdata->vbdcoef > 0.0 )
1681 {
1682 if( !SCIPisInfinity(scip, -ylb) )
1683 {
1684 SCIP_Real QUAD(tmp);
1685
1686 SCIPquadprecProdDD(tmp, consdata->vbdcoef, ylb);
1687 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1688
1689 newub = SCIPadjustedVarUb(scip, consdata->var, QUAD_TO_DBL(tmp));
1690 }
1691 else
1692 {
1693 newub = SCIPinfinity(scip);
1694 }
1695 }
1696 else
1697 {
1698 if( !SCIPisInfinity(scip, yub) )
1699 {
1700 SCIP_Real QUAD(tmp);
1701
1702 SCIPquadprecProdDD(tmp, consdata->vbdcoef, yub);
1703 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1704
1705 newub = SCIPadjustedVarUb(scip, consdata->var, QUAD_TO_DBL(tmp));
1706 }
1707 else
1708 {
1709 newub = SCIPinfinity(scip);
1710 }
1711 }
1712
1713 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->var, newub, cons, (int)PROPRULE_3, yub < ylb + 0.5, cutoff, &tightened) );
1714
1715 if( *cutoff )
1716 {
1717 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1718 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->var)));
1719
1721
1722 /* analyze infeasibility */
1723 SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newub, PROPRULE_3, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1724 break;
1725 }
1726
1727 if( tightened )
1728 {
1729 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1730 tightenedround = TRUE;
1731 (*nchgbds)++;
1733 }
1734 xub = SCIPvarGetUbLocal(consdata->var);
1735 }
1736
1737 assert(!*cutoff);
1738
1739 /* propagate bounds on y:
1740 * (4) right hand side and lower bound on x -> bound on y
1741 */
1742 if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, -xlb) ) /* cannot change bounds of multaggr vars */
1743 {
1744 if( consdata->vbdcoef > 0.0 )
1745 {
1746 SCIP_Real QUAD(tmp);
1747
1748 SCIPquadprecSumDD(tmp, consdata->rhs, -xlb);
1749 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1750
1751 newub = SCIPadjustedVarUb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1752 if( newub < yub - 0.5 )
1753 {
1754 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1755
1756 if( *cutoff )
1757 {
1758 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1759 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)));
1760
1762
1763 /* analyze infeasibility */
1764 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_4, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1765 break;
1766 }
1767
1768 if( tightened )
1769 {
1770 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1771 tightenedround = TRUE;
1772 (*nchgbds)++;
1774 }
1775 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1776 }
1777 }
1778 else
1779 {
1780 SCIP_Real QUAD(tmp);
1781
1782 SCIPquadprecSumDD(tmp, consdata->rhs, -xlb);
1783 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1784
1785 newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1786 if( newlb > ylb + 0.5 )
1787 {
1788 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1789
1790 if( *cutoff )
1791 {
1792 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1793 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)));
1794
1796
1797 /* analyze infeasibility */
1798 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_4, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1799 break;
1800 }
1801
1802 if( tightened )
1803 {
1804 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1805 tightenedround = TRUE;
1806 (*nchgbds)++;
1808 }
1809 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1810 }
1811 }
1812 }
1813 }
1814 assert(!(*cutoff));
1815 }
1816 while( tightenedround );
1817
1818 /* check for redundant sides */
1819 if( !(*cutoff) )
1820 {
1821 islhsredundant = TRUE;
1822 isrhsredundant = TRUE;
1823 nvars = 2;
1824
1825 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
1827
1828 constant = 0.0;
1829 vars[0] = consdata->var;
1830 vars[1] = consdata->vbdvar;
1831 scalars[0] = 1.0;
1832 scalars[1] = consdata->vbdcoef;
1833 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, &nvars, nvars, &constant, &requiredsize) );
1834
1835 if( requiredsize > nvars )
1836 {
1837 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
1838 SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
1839
1840 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, &nvars, requiredsize, &constant, &requiredsize) );
1841 assert(requiredsize <= nvars);
1842 }
1843
1844 if( !SCIPisInfinity(scip, -consdata->lhs) )
1845 {
1846 QUAD_ASSIGN(activity, constant);
1847
1848 for( i = 0; i < nvars; ++i )
1849 {
1850 assert(scalars[i] != 0.0);
1851 if( scalars[i] > 0.0 )
1852 {
1853 bound = SCIPvarGetLbLocal(vars[i]);
1854
1855 if( SCIPisInfinity(scip, -bound) )
1856 {
1857 islhsredundant = FALSE;
1858 break;
1859 }
1860 }
1861 else
1862 {
1863 bound = SCIPvarGetUbLocal(vars[i]);
1864
1865 if( SCIPisInfinity(scip, bound) )
1866 {
1867 islhsredundant = FALSE;
1868 break;
1869 }
1870 }
1871
1872 SCIPquadprecSumQD(activity, activity, scalars[i] * bound);
1873 }
1874
1875 if( islhsredundant && SCIPisLT(scip, QUAD_TO_DBL(activity), consdata->lhs) )
1876 islhsredundant = FALSE;
1877 }
1878
1879 if( !SCIPisInfinity(scip, consdata->rhs) )
1880 {
1881 QUAD_ASSIGN(activity, constant);
1882
1883 for( i = 0; i < nvars; ++i )
1884 {
1885 assert(scalars[i] != 0.0);
1886 if( scalars[i] > 0.0 )
1887 {
1888 bound = SCIPvarGetUbLocal(vars[i]);
1889
1890 if( SCIPisInfinity(scip, bound) )
1891 {
1892 isrhsredundant = FALSE;
1893 break;
1894 }
1895 }
1896 else
1897 {
1898 bound = SCIPvarGetLbLocal(vars[i]);
1899
1900 if( SCIPisInfinity(scip, -bound) )
1901 {
1902 isrhsredundant = FALSE;
1903 break;
1904 }
1905 }
1906
1907 SCIPquadprecSumQD(activity, activity, scalars[i] * bound);
1908 }
1909
1910 if( isrhsredundant && SCIPisGT(scip, QUAD_TO_DBL(activity), consdata->rhs) )
1911 isrhsredundant = FALSE;
1912 }
1913
1915 SCIPfreeBufferArray(scip, &vars);
1916
1917 /* check varbound constraint for redundancy */
1918 if( islhsredundant && isrhsredundant )
1919 {
1920 SCIPdebugMsg(scip, "variable bound constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
1921 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
1922
1923 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
1924 if( nvars > 0 )
1926 else
1927 SCIP_CALL( SCIPdelCons(scip, cons) );
1928
1929 /* this did not seem to help but should be tested again, there might also still be a bug in there */
1930#ifdef SCIP_DISABLED_CODE
1931 /* local duality fixing of variables in the constraint */
1932 if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->vbdvar))
1933 && SCIPvarGetNLocksDownType(consdata->vbdvar, SCIP_LOCKTYPE_MODEL) == 1
1934 && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->vbdvar))
1935 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1936 && ((consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1937 || (consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1938 {
1939 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1940 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetLbLocal(consdata->vbdvar));
1941 SCIP_CALL( SCIPchgVarUb(scip, consdata->vbdvar, SCIPvarGetLbLocal(consdata->vbdvar)) );
1942 }
1943 else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->vbdvar))
1944 && SCIPvarGetNLocksUpType(consdata->vbdvar, SCIP_LOCKTYPE_MODEL) == 1
1945 && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->vbdvar))
1946 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1947 && ((consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1948 || (consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1949 {
1950 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1951 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar));
1952 SCIP_CALL( SCIPchgVarLb(scip, consdata->vbdvar, SCIPvarGetUbLocal(consdata->vbdvar)) );
1953 }
1954 if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->var))
1955 && SCIPvarGetNLocksDownType(consdata->var, SCIP_LOCKTYPE_MODEL) == 1
1956 && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->var))
1957 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1958 && !SCIPisInfinity(scip, -consdata->lhs) )
1959 {
1960 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1961 SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetLbLocal(consdata->var));
1962 SCIP_CALL( SCIPchgVarUb(scip, consdata->var, SCIPvarGetLbLocal(consdata->var)) );
1963 }
1964 else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->var))
1965 && SCIPvarGetNLocksUpType(consdata->var, SCIP_LOCKTYPE_MODEL) == 1
1966 && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->var))
1967 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1968 && !SCIPisInfinity(scip, consdata->rhs) )
1969 {
1970 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1971 SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var));
1972 SCIP_CALL( SCIPchgVarLb(scip, consdata->var, SCIPvarGetUbLocal(consdata->var)) );
1973 }
1974#endif
1975 if( ndelconss != NULL )
1976 ++(*ndelconss);
1977 }
1979 {
1980 /* check left hand side for redundancy */
1981 if( islhsredundant )
1982 {
1983 assert(!isrhsredundant);
1984
1985 if( !SCIPisInfinity(scip, -consdata->lhs) )
1986 {
1987 SCIPdebugMsg(scip, "left hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
1988
1989 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
1990
1991 if( nchgsides != NULL )
1992 ++(*nchgsides);
1993 }
1994 }
1995 /* check right hand side for redundancy */
1996 else if( isrhsredundant )
1997 {
1998 assert(!islhsredundant);
1999
2000 if( !SCIPisInfinity(scip, consdata->rhs) )
2001 {
2002 SCIPdebugMsg(scip, "right hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
2003
2005
2006 if( nchgsides != NULL )
2007 ++(*nchgsides);
2008 }
2009 }
2010 }
2011 }
2012
2014
2015 return SCIP_OKAY;
2016}
2017
2018/* check whether one constraint side is redundant to another constraint side by calculating extreme values for
2019 * variables
2020 */
2021static
2023 SCIP* scip, /**< SCIP data structure */
2024 SCIP_VAR* var, /**< variable x that has variable bound */
2025 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
2026 SCIP_Real coef0, /**< coefficient c0 of bounding variable y for constraint 0 */
2027 SCIP_Real coef1, /**< coefficient c1 of bounding variable y for constraint 1 */
2028 SCIP_Real side0, /**< one side of variable bound inequality for constraint 0 */
2029 SCIP_Real side1, /**< one side of variable bound inequality for constraint 1 */
2030 SCIP_Bool* sideequal, /**< pointer to store if both constraints have the same redundancy on the
2031 * given side */
2032 SCIP_Bool* cons0sidered, /**< pointer to store if side of constraint 0 is redundant */
2033 SCIP_Bool* cons1sidered, /**< pointer to store if side of constraint 1 is redundant */
2034 SCIP_Bool islhs /**< do we check the left or the right hand side */
2035 )
2036{
2037 SCIP_Real lbvar;
2038 SCIP_Real ubvar;
2039 SCIP_Real lbvbdvar;
2040 SCIP_Real ubvbdvar;
2041 SCIP_Real boundxlb1;
2042 SCIP_Real boundxlb2;
2043 SCIP_Real boundylb1;
2044 SCIP_Real boundylb2;
2045 SCIP_Real boundxub1;
2046 SCIP_Real boundxub2;
2047 SCIP_Real boundyub1;
2048 SCIP_Real boundyub2;
2049 SCIP_Real boundvaluex1;
2050 SCIP_Real boundvaluex2;
2051 SCIP_Real boundvaluey1;
2052 SCIP_Real boundvaluey2;
2053 SCIP_Real valuex1;
2054 SCIP_Real valuex2;
2055 SCIP_Real valuey1;
2056 SCIP_Real valuey2;
2057 SCIP_Bool* redundant0;
2058 SCIP_Bool* redundant1;
2059
2060 assert(scip != NULL);
2061 assert(var != NULL);
2062 assert(vbdvar != NULL);
2063 assert(sideequal != NULL);
2064 assert(cons0sidered != NULL);
2065 assert(cons1sidered != NULL);
2066 assert(coef0 * coef1 > 0.0);
2067
2068 *cons0sidered = SCIPisInfinity(scip, islhs ? -side0 : side0);
2069 *cons1sidered = SCIPisInfinity(scip, islhs ? -side1 : side1);
2070 *sideequal = FALSE;
2071
2072 if( islhs )
2073 {
2074 redundant0 = cons1sidered;
2075 redundant1 = cons0sidered;
2076 }
2077 else
2078 {
2079 redundant0 = cons0sidered;
2080 redundant1 = cons1sidered;
2081 }
2082
2083 lbvar = SCIPvarGetLbGlobal(var);
2084 assert(!SCIPisInfinity(scip, lbvar));
2085 ubvar = SCIPvarGetUbGlobal(var);
2086 assert(!SCIPisInfinity(scip, -ubvar));
2087 lbvbdvar = SCIPvarGetLbGlobal(vbdvar);
2088 assert(!SCIPisInfinity(scip, lbvbdvar));
2089 ubvbdvar = SCIPvarGetUbGlobal(vbdvar);
2090 assert(!SCIPisInfinity(scip, -ubvbdvar));
2091
2092 /* if both constraints have this side */
2093 if( !*redundant0 && !*redundant1 )
2094 {
2095 /* calculate extreme values, which are reached by setting the other variable to their lower/upper bound */
2096 if( SCIPisInfinity(scip, -lbvbdvar) )
2097 {
2098 if( coef0 > 0.0 )
2099 {
2100 boundxlb1 = SCIPinfinity(scip);
2101 boundxlb2 = SCIPinfinity(scip);
2102 }
2103 else
2104 {
2105 boundxlb1 = -SCIPinfinity(scip);
2106 boundxlb2 = -SCIPinfinity(scip);
2107 }
2108 }
2109 else
2110 {
2111 boundxlb1 = side0 - lbvbdvar * coef0;
2112 boundxlb2 = side1 - lbvbdvar * coef1;
2113 }
2114 if( SCIPisInfinity(scip, -lbvar) )
2115 {
2116 if( coef0 > 0.0 )
2117 {
2118 boundylb1 = SCIPinfinity(scip);
2119 boundylb2 = SCIPinfinity(scip);
2120 }
2121 else
2122 {
2123 boundylb1 = -SCIPinfinity(scip);
2124 boundylb2 = -SCIPinfinity(scip);
2125 }
2126 }
2127 else
2128 {
2129 boundylb1 = (side0 - lbvar) / coef0;
2130 boundylb2 = (side1 - lbvar) / coef1;
2131 }
2132 if( SCIPisInfinity(scip, ubvbdvar) )
2133 {
2134 if( coef0 > 0.0 )
2135 {
2136 boundxub1 = -SCIPinfinity(scip);
2137 boundxub2 = -SCIPinfinity(scip);
2138 }
2139 else
2140 {
2141 boundxub1 = SCIPinfinity(scip);
2142 boundxub2 = SCIPinfinity(scip);
2143 }
2144 }
2145 else
2146 {
2147 boundxub1 = side0 - ubvbdvar * coef0;
2148 boundxub2 = side1 - ubvbdvar * coef1;
2149 }
2150 if( SCIPisInfinity(scip, ubvar) )
2151 {
2152 if( coef0 > 0.0 )
2153 {
2154 boundyub1 = -SCIPinfinity(scip);
2155 boundyub2 = -SCIPinfinity(scip);
2156 }
2157 else
2158 {
2159 boundyub1 = SCIPinfinity(scip);
2160 boundyub2 = SCIPinfinity(scip);
2161 }
2162 }
2163 else
2164 {
2165 boundyub1 = (side0 - ubvar) / coef0;
2166 boundyub2 = (side1 - ubvar) / coef1;
2167 }
2168
2169 if( islhs )
2170 {
2171 boundvaluex1 = MAX(boundxlb1, boundxlb2);
2172 boundvaluex2 = MAX(boundxub1, boundxub2);
2173 }
2174 else
2175 {
2176 boundvaluex1 = MIN(boundxlb1, boundxlb2);
2177 boundvaluex2 = MIN(boundxub1, boundxub2);
2178 }
2179
2180 /* calculate important values for variables */
2181 if( coef0 > 0.0 )
2182 {
2183 valuex1 = MIN(boundvaluex1, ubvar);
2184 valuex1 = MAX(valuex1, lbvar);
2185 valuex2 = MAX(boundvaluex2, lbvar);
2186 valuex2 = MIN(valuex2, ubvar);
2187
2188 /* if variable is of integral type make values integral too */
2189 if( SCIPvarIsIntegral(var) )
2190 {
2191 valuex1 = SCIPfeasFloor(scip, valuex1);
2192 valuex2 = SCIPfeasCeil(scip, valuex2);
2193 }
2194 }
2195 else
2196 {
2197 valuex1 = MAX(boundvaluex1, lbvar);
2198 valuex1 = MIN(valuex1, ubvar);
2199 valuex2 = MIN(boundvaluex2, ubvar);
2200 valuex2 = MAX(valuex2, lbvar);
2201
2202 /* if variable is of integral type make values integral too */
2203 if( SCIPvarIsIntegral(var) )
2204 {
2205 valuex1 = SCIPfeasCeil(scip, valuex1);
2206 valuex2 = SCIPfeasFloor(scip, valuex2);
2207 }
2208 }
2209
2210 /* calculate resulting values of variable y by setting x to valuex1 */
2211 if( SCIPisInfinity(scip, ABS(valuex1)) )
2212 {
2213 /* only consider sides if coefficients are equal */
2214 if( SCIPisEQ(scip, coef0, coef1) )
2215 {
2216 valuey1 = side0 / coef0;
2217 valuey2 = side1 / coef1;
2218 }
2219 /* only consider original coefficients if otherwise x approaches plus infinity */
2220 else if( valuex1 > 0.0 )
2221 {
2222 valuey1 = coef0;
2223 valuey2 = coef1;
2224 }
2225 /* only consider swapped coefficients if otherwise x approaches minus infinity */
2226 else
2227 {
2228 valuey1 = coef1;
2229 valuey2 = coef0;
2230 }
2231 }
2232 else
2233 {
2234 valuey1 = (side0 - valuex1) / coef0;
2235 valuey2 = (side1 - valuex1) / coef1;
2236 }
2237
2238 /* determine redundancy of one constraints side */
2239 if( SCIPisEQ(scip, valuey1, valuey2) )
2240 *sideequal = TRUE;
2241 else if( coef0 > 0.0 )
2242 {
2243 if( valuey1 < valuey2 )
2244 *redundant1 = TRUE;
2245 else
2246 *redundant0 = TRUE;
2247 }
2248 else
2249 {
2250 if( valuey1 < valuey2 )
2251 *redundant0 = TRUE;
2252 else
2253 *redundant1 = TRUE;
2254 }
2255
2256 /* calculate resulting values of variable y by setting x to valuex2 */
2257 if( SCIPisInfinity(scip, ABS(valuex2)) )
2258 {
2259 /* only consider sides if coefficients are equal */
2260 if( SCIPisEQ(scip, coef0, coef1) )
2261 {
2262 valuey1 = side0 / coef0;
2263 valuey2 = side1 / coef1;
2264 }
2265 /* only consider original coefficients if otherwise x approaches plus infinity */
2266 else if( valuex2 > 0.0 )
2267 {
2268 valuey1 = coef0;
2269 valuey2 = coef1;
2270 }
2271 /* only consider swapped coefficients if otherwise x approaches minus infinity */
2272 else
2273 {
2274 valuey1 = coef1;
2275 valuey2 = coef0;
2276 }
2277 }
2278 else
2279 {
2280 valuey1 = (side0 - valuex2) / coef0;
2281 valuey2 = (side1 - valuex2) / coef1;
2282 }
2283
2284 /* determine redundancy of one constraints side by checking for the first valuex2 */
2285 if( coef0 > 0.0 )
2286 {
2287 /* if both constraints are equal on one value, only consider the other value */
2288 if( *sideequal )
2289 {
2290 assert(!(*redundant0));
2291 assert(!(*redundant1));
2292
2293 if( SCIPisLT(scip, valuey1, valuey2) )
2294 {
2295 *sideequal = FALSE;
2296 *redundant1 = TRUE;
2297 }
2298 else if( SCIPisGT(scip, valuey1, valuey2) )
2299 {
2300 *sideequal = FALSE;
2301 *redundant0 = TRUE;
2302 }
2303 }
2304 /* if both constraints are weaker than the other on one value, we have no redundancy */
2305 else if( ( *redundant1 && SCIPisGT(scip, valuey1, valuey2) )
2306 || ( *redundant0 && SCIPisLT(scip, valuey1, valuey2) ) )
2307 {
2308 *redundant0 = FALSE;
2309 *redundant1 = FALSE;
2310 return;
2311 }
2312 }
2313 else
2314 {
2315 /* if both constraints are equal on one value, only consider the other value */
2316 if( *sideequal )
2317 {
2318 assert(!(*redundant0));
2319 assert(!(*redundant1));
2320
2321 if( SCIPisLT(scip, valuey1, valuey2) )
2322 {
2323 *sideequal = FALSE;
2324 *redundant0 = TRUE;
2325 }
2326 else if( SCIPisGT(scip, valuey1, valuey2) )
2327 {
2328 *sideequal = FALSE;
2329 *redundant1 = TRUE;
2330 }
2331 }
2332 /* if both constraints are weaker than the other one on one value, we have no redundancy */
2333 else if( ( *redundant0 && SCIPisGT(scip, valuey1, valuey2) )
2334 || ( *redundant1 && SCIPisLT(scip, valuey1, valuey2) ) )
2335 {
2336 *redundant0 = FALSE;
2337 *redundant1 = FALSE;
2338 return;
2339 }
2340 }
2341 assert(*sideequal || *redundant0 || *redundant1);
2342
2343 /* calculate feasibility domain values for variable y concerning these both constraints */
2344 if( coef0 > 0.0 )
2345 {
2346 if( islhs )
2347 {
2348 boundvaluey1 = MAX(boundylb1, boundylb2);
2349 boundvaluey2 = MAX(boundyub1, boundyub2);
2350 }
2351 else
2352 {
2353 boundvaluey1 = MIN(boundylb1, boundylb2);
2354 boundvaluey2 = MIN(boundyub1, boundyub2);
2355 }
2356
2357 valuey1 = MIN(boundvaluey1, ubvbdvar);
2358 valuey1 = MAX(valuey1, lbvbdvar);
2359 valuey2 = MAX(boundvaluey2, lbvbdvar);
2360 valuey2 = MIN(valuey2, ubvbdvar);
2361
2362 valuey1 = SCIPfeasFloor(scip, valuey1);
2363 valuey2 = SCIPfeasCeil(scip, valuey2);
2364 }
2365 else
2366 {
2367 if( islhs )
2368 {
2369 boundvaluey1 = MIN(boundylb1, boundylb2);
2370 boundvaluey2 = MIN(boundyub1, boundyub2);
2371 }
2372 else
2373 {
2374 boundvaluey1 = MAX(boundylb1, boundylb2);
2375 boundvaluey2 = MAX(boundyub1, boundyub2);
2376 }
2377
2378 valuey1 = MAX(boundvaluey1, lbvbdvar);
2379 valuey1 = MIN(valuey1, ubvbdvar);
2380 valuey2 = MIN(boundvaluey2, ubvbdvar);
2381 valuey2 = MAX(valuey2, lbvbdvar);
2382
2383 valuey1 = SCIPfeasCeil(scip, valuey1);
2384 valuey2 = SCIPfeasFloor(scip, valuey2);
2385 }
2386
2387 /* calculate resulting values of variable x by setting y to valuey1 */
2388 if( SCIPisInfinity(scip, ABS(valuey1)) )
2389 {
2390 /* only consider sides if coefficients are equal */
2391 if( SCIPisEQ(scip, coef0, coef1) )
2392 {
2393 valuex1 = side0;
2394 valuex2 = side1;
2395 }
2396 /* only consider swapped coefficients if otherwise y approaches plus infinity */
2397 else if( valuey1 > 0.0 )
2398 {
2399 valuex1 = coef1;
2400 valuex2 = coef0;
2401 }
2402 /* only consider original coefficients if otherwise y approaches minus infinity */
2403 else
2404 {
2405 valuex1 = coef0;
2406 valuex2 = coef1;
2407 }
2408 }
2409 else
2410 {
2411 valuex1 = side0 - valuey1 * coef0;
2412 valuex2 = side1 - valuey1 * coef1;
2413 }
2414
2415 /* determine redundancy of one constraints side by checking for the first valuey1 */
2416 if( *sideequal )
2417 {
2418 assert(!(*redundant0));
2419 assert(!(*redundant1));
2420
2421 if( SCIPisLT(scip, valuex1, valuex2) )
2422 {
2423 *sideequal = FALSE;
2424 *redundant1 = TRUE;
2425 }
2426 else if( SCIPisGT(scip, valuex1, valuex2) )
2427 {
2428 *sideequal = FALSE;
2429 *redundant0 = TRUE;
2430 }
2431 }
2432 else if( ( *redundant1 && SCIPisGT(scip, valuex1, valuex2) )
2433 || ( *redundant0 && SCIPisLT(scip, valuex1, valuex2) ) )
2434 {
2435 *redundant0 = FALSE;
2436 *redundant1 = FALSE;
2437 return;
2438 }
2439
2440 /* calculate resulting values of variable x by setting y to valuey2 */
2441 if( SCIPisInfinity(scip, ABS(valuey2)) )
2442 {
2443 /* only consider sides if coefficients are equal */
2444 if( SCIPisEQ(scip, coef0, coef1) )
2445 {
2446 valuex1 = side0;
2447 valuex2 = side1;
2448 }
2449 /* only consider swapped coefficients if otherwise y approaches plus infinity */
2450 else if( valuey2 > 0.0 )
2451 {
2452 valuex1 = coef1;
2453 valuex2 = coef0;
2454 }
2455 /* only consider original coefficients if otherwise y approaches minus infinity */
2456 else
2457 {
2458 valuex1 = coef0;
2459 valuex2 = coef1;
2460 }
2461 }
2462 else
2463 {
2464 valuex1 = side0 - valuey2 * coef0;
2465 valuex2 = side1 - valuey2 * coef1;
2466 }
2467
2468 /* determine redundancy of one constraints side by checking for the second valuey2 */
2469 if( *sideequal )
2470 {
2471 assert(!(*redundant0));
2472 assert(!(*redundant1));
2473
2474 if( SCIPisLT(scip, valuex1, valuex2) )
2475 {
2476 *sideequal = FALSE;
2477 *redundant1 = TRUE;
2478 }
2479 else if( SCIPisGT(scip, valuex1, valuex2) )
2480 {
2481 *sideequal = FALSE;
2482 *redundant0 = TRUE;
2483 }
2484 }
2485 else if( ( *redundant1 && SCIPisGT(scip, valuex1, valuex2) )
2486 || ( *redundant0 && SCIPisLT(scip, valuex1, valuex2) ) )
2487 {
2488 *redundant0 = FALSE;
2489 *redundant1 = FALSE;
2490 return;
2491 }
2492 assert(*redundant0 || *redundant1 || *sideequal);
2493 }
2494}
2495
2496/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
2497 *
2498 * we will order all constraint to have constraints with same variables next to each other to speed up presolving
2499 *
2500 * consider two constraints like lhs1 <= x + b1*y <= rhs1 and lhs2 <= x + b2*y <= rhs2
2501 * we are doing the following presolving steps:
2502 *
2503 * if( b1 == b2 )
2504 * newlhs = MAX(lhs1, lhs2)
2505 * newrhs = MIN(rhs1, rhs2)
2506 * updateSides
2507 * delete one constraint
2508 * else if( ((b1 > 0) == (b2 > 0)) && (lhs1 != -inf && lhs2 != -inf) || (rhs1 != inf && rhs2 != inf) )
2509 *
2510 * (i.e. both constraint have either a valid lhs or a valid rhs and infinity is on the same side and the
2511 * coeffcients have the same size )
2512 *
2513 * if( y is binary )
2514 * if( lhs1 != -inf )
2515 * newlhs = MAX(lhs1, lhs2)
2516 * newb = newlhs - MAX(lhs1 - b1, lhs2 - b2)
2517 * else
2518 * newrhs = MIN(lhs1, lhs2)
2519 * newb = newrhs - MIN(rhs1 - b1, rhs2 - b2)
2520 * updateSidesAndCoef
2521 * delete one constraint
2522 * else
2523 * we calculate possible values for both variables and check which constraint is tighter
2524 * else
2525 * nothing possible
2526 *
2527 * We also try to tighten bounds in the case of two constraints lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2.
2528 * Eliminiating one variable and inserting into the second yields the following bounds:
2529 * If b2 > 0:
2530 * (1 - b1 * b2) * y >= lhs2 - b2 * rhs1
2531 * (1 - b1 * b2) * y <= rhs2 - b2 * lhs1
2532 * If b2 < 0:
2533 * (1 - b1 * b2) * y >= lhs2 - b2 * lhs1
2534 * (1 - b1 * b2) * y <= rhs2 - b2 * rhs1
2535 * The case of x is similar.
2536 */
2537static
2539 SCIP* scip, /**< SCIP data structure */
2540 SCIP_CONS** conss, /**< constraint set */
2541 int nconss, /**< number of constraints in constraint set */
2542 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
2543 int* nchgbds, /**< pointer to count number of bound changes */
2544 int* ndelconss, /**< pointer to count number of deleted constraints */
2545 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
2546 int* nchgsides /**< pointer to count number of changed left/right hand sides */
2547 )
2548{
2549 SCIP_CONS** sortedconss;
2550 int c;
2551 int s;
2552
2553 assert(scip != NULL);
2554 assert(conss != NULL);
2555 assert(cutoff != NULL);
2556 assert(nchgbds != NULL);
2557 assert(ndelconss != NULL);
2558 assert(nchgcoefs != NULL);
2559 assert(nchgsides != NULL);
2560
2561 /* create our temporary working array */
2562 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedconss, conss, nconss) );
2563
2564 /* sort all constraints, so that all constraints with same variables stand next to each other */
2565 SCIPsortPtr((void**)sortedconss, consVarboundComp, nconss);
2566
2567 /* check all constraints for redundancy */
2568 for( c = nconss - 1; c > 0 && !(*cutoff); --c )
2569 {
2570 SCIP_CONS* cons0;
2571 SCIP_CONSDATA* consdata0;
2572
2573 cons0 = sortedconss[c];
2574
2575 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
2576 continue;
2577
2578 consdata0 = SCIPconsGetData(cons0);
2579 assert(consdata0 != NULL);
2580 assert(consdata0->var != NULL);
2581 assert(consdata0->vbdvar != NULL);
2582
2583 /* do not check for already redundant constraints */
2584 assert(!SCIPisZero(scip, consdata0->vbdcoef));
2585 assert(!SCIPisInfinity(scip, -consdata0->lhs) || !SCIPisInfinity(scip, consdata0->rhs));
2586
2587 if( !consdata0->changed )
2588 continue;
2589
2590 consdata0->changed = FALSE;
2591
2592 for( s = c - 1; s >= 0; --s )
2593 {
2594 SCIP_CONS* cons1;
2595 SCIP_CONSDATA* consdata1;
2596 SCIP_Real lhs;
2597 SCIP_Real rhs;
2598 SCIP_Real coef;
2599 SCIP_Bool deletecons1;
2600
2601 cons1 = sortedconss[s];
2602
2603 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
2604 continue;
2605
2606 consdata1 = SCIPconsGetData(cons1);
2607 assert(consdata1 != NULL);
2608 assert(consdata1->var != NULL);
2609 assert(consdata1->vbdvar != NULL);
2610
2611 /* do not check for already redundant constraints */
2612 assert(!SCIPisZero(scip, consdata1->vbdcoef));
2613 assert(!SCIPisInfinity(scip, -consdata1->lhs) || !SCIPisInfinity(scip, consdata1->rhs));
2614
2615 lhs = consdata0->lhs;
2616 rhs = consdata0->rhs;
2617 coef = consdata0->vbdcoef;
2618
2619 /* check for propagation in the case: lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2. */
2620 if ( consdata0->var == consdata1->vbdvar && consdata0->vbdvar == consdata1->var &&
2621 !SCIPisFeasZero(scip, 1.0 - coef * consdata1->vbdcoef) )
2622 {
2623 SCIP_Bool tightened = FALSE;
2624 SCIP_Real bnd = SCIP_UNKNOWN;
2625 SCIP_Real scalar;
2626 SCIP_Real newbnd;
2627
2628 scalar = (1.0 - coef * consdata1->vbdcoef);
2629
2630 assert( ! SCIPisInfinity(scip, REALABS(scalar)) );
2631 assert( ! SCIPisZero(scip, consdata0->vbdcoef) );
2632 assert( ! SCIPisZero(scip, consdata1->vbdcoef) );
2633
2634 /* lower bounds for consdata0->var */
2635 if ( ! SCIPisInfinity(scip, -lhs) )
2636 {
2637 if ( SCIPisPositive(scip, coef) )
2638 {
2639 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2640 bnd = (lhs - coef * consdata1->rhs)/scalar;
2641 }
2642 else
2643 {
2644 assert( SCIPisNegative(scip, coef) );
2645 if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2646 bnd = (lhs - coef * consdata1->lhs)/scalar;
2647 }
2648
2649 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2650 {
2651 if ( SCIPisFeasPositive(scip, scalar) )
2652 {
2653 newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2654 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2655 if ( *cutoff )
2656 {
2657 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2658 SCIPvarGetName(consdata0->var), newbnd);
2659 break;
2660 }
2661 if ( tightened )
2662 {
2663 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2664 SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2665 (*nchgbds)++;
2666 }
2667 }
2668 else if ( SCIPisFeasNegative(scip, scalar) )
2669 {
2670 newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2671 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2672 if ( *cutoff )
2673 {
2674 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2675 SCIPvarGetName(consdata0->var), newbnd);
2676 break;
2677 }
2678 if ( tightened )
2679 {
2680 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2681 SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2682 (*nchgbds)++;
2683 }
2684 }
2685 }
2686 }
2687
2688 /* upper bound for consdata0>var */
2689 if ( ! SCIPisInfinity(scip, rhs) )
2690 {
2691 bnd = SCIP_UNKNOWN;
2692 if ( SCIPisPositive(scip, coef) )
2693 {
2694 if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2695 bnd = (rhs - coef * consdata1->lhs)/scalar;
2696 }
2697 else
2698 {
2699 assert( SCIPisNegative(scip, coef) );
2700 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2701 bnd = (rhs - coef * consdata1->rhs)/scalar;
2702 }
2703
2704 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2705 {
2706 if ( SCIPisFeasPositive(scip, scalar) )
2707 {
2708 newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2709 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2710 if ( *cutoff )
2711 {
2712 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2713 SCIPvarGetName(consdata0->var), newbnd);
2714 break;
2715 }
2716 if ( tightened )
2717 {
2718 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2719 SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2720 (*nchgbds)++;
2721 }
2722 }
2723 else if ( SCIPisFeasNegative(scip, scalar) )
2724 {
2725 newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2726 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2727 if ( *cutoff )
2728 {
2729 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2730 SCIPvarGetName(consdata0->var), newbnd);
2731 break;
2732 }
2733 if ( tightened )
2734 {
2735 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2736 SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2737 (*nchgbds)++;
2738 }
2739 }
2740 }
2741 }
2742
2743 /* lower bounds for consdata1->var */
2744 if ( ! SCIPisInfinity(scip, -consdata1->lhs) )
2745 {
2746 bnd = SCIP_UNKNOWN;
2747 if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2748 {
2749 if ( ! SCIPisInfinity(scip, rhs) )
2750 bnd = (consdata1->lhs - consdata1->vbdcoef * rhs)/scalar;
2751 }
2752 else
2753 {
2754 assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2755 if ( ! SCIPisInfinity(scip, lhs) )
2756 bnd = (consdata1->lhs - consdata1->vbdcoef * lhs)/scalar;
2757 }
2758
2759 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2760 {
2761 if ( SCIPisFeasPositive(scip, scalar) )
2762 {
2763 newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2764 SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2765 if ( *cutoff )
2766 {
2767 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2768 SCIPvarGetName(consdata1->var), newbnd);
2769 break;
2770 }
2771 if ( tightened )
2772 {
2773 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2774 SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2775 (*nchgbds)++;
2776 }
2777 }
2778 else if ( SCIPisFeasNegative(scip, scalar) )
2779 {
2780 newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2781 SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2782 if ( *cutoff )
2783 {
2784 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2785 SCIPvarGetName(consdata1->var), newbnd);
2786 break;
2787 }
2788 if ( tightened )
2789 {
2790 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2791 SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2792 (*nchgbds)++;
2793 }
2794 }
2795 }
2796 }
2797
2798 /* upper bound for consdata1->var */
2799 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2800 {
2801 bnd = SCIP_UNKNOWN;
2802 if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2803 {
2804 if ( ! SCIPisInfinity(scip, lhs) )
2805 bnd = (consdata1->rhs - consdata1->vbdcoef * lhs)/scalar;
2806 }
2807 else
2808 {
2809 assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2810 if ( ! SCIPisInfinity(scip, rhs) )
2811 bnd = (consdata1->rhs - consdata1->vbdcoef * rhs)/scalar;
2812 }
2813
2814 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2815 {
2816 if ( SCIPisFeasPositive(scip, scalar) )
2817 {
2818 newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2819 SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2820 if ( *cutoff )
2821 {
2822 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2823 SCIPvarGetName(consdata1->var), newbnd);
2824 break;
2825 }
2826 if ( tightened )
2827 {
2828 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2829 SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2830 (*nchgbds)++;
2831 }
2832 }
2833 else if ( SCIPisFeasNegative(scip, scalar) )
2834 {
2835 newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2836 SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2837 if ( *cutoff )
2838 {
2839 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2840 SCIPvarGetName(consdata1->var), newbnd);
2841 break;
2842 }
2843 if ( tightened )
2844 {
2845 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2846 SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2847 (*nchgbds)++;
2848 }
2849 }
2850 }
2851 }
2852 }
2853
2854 /* check for equal variables */
2855 if( consdata0->var != consdata1->var || consdata0->vbdvar != consdata1->vbdvar )
2856 break;
2857
2858 /* mark constraint1 for deletion if possible */
2859 deletecons1 = TRUE;
2860
2861 /* the coefficients of both constraints are equal */
2862 if( SCIPisEQ(scip, coef, consdata1->vbdcoef) )
2863 {
2864 lhs = MAX(consdata1->lhs, lhs);
2865 rhs = MIN(consdata1->rhs, rhs);
2866 }
2867 /* now only one side and in both constraints the same side should be infinity and the vbdvar should be binary
2868 * then we neither do not need to have the same side nor the same coefficient
2869 */
2870 else if( SCIPvarIsBinary(consdata0->vbdvar)
2871 && (SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs))
2872 && (SCIPisInfinity(scip, -consdata1->lhs) || SCIPisInfinity(scip, consdata1->rhs))
2873 && (SCIPisInfinity(scip, -lhs) == SCIPisInfinity(scip, -consdata1->lhs)) )
2874 {
2875 /* lhs <= x + b*y <= +inf */
2876 if( !SCIPisInfinity(scip, -lhs) )
2877 {
2878 lhs = MAX(consdata1->lhs, lhs);
2879 coef = lhs - MAX(consdata1->lhs - consdata1->vbdcoef, consdata0->lhs - coef);
2880 }
2881 /* -inf <= x + b*y <= rhs */
2882 else
2883 {
2884 rhs = MIN(consdata1->rhs, rhs);
2885 coef = rhs - MIN(consdata1->rhs - consdata1->vbdcoef, consdata0->rhs - coef);
2886 }
2887
2889 }
2890 else if( SCIPisPositive(scip, coef) == SCIPisPositive(scip, consdata1->vbdcoef)
2891 && ((!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, -consdata1->lhs))
2892 || (!SCIPisInfinity(scip, rhs) && !SCIPisInfinity(scip, consdata1->rhs))) )
2893 {
2894 SCIP_Bool cons0lhsred;
2895 SCIP_Bool cons0rhsred;
2896 SCIP_Bool cons1lhsred;
2897 SCIP_Bool cons1rhsred;
2898 SCIP_Bool lhsequal;
2899 SCIP_Bool rhsequal;
2900
2901 assert(!SCIPisInfinity(scip, lhs));
2902 assert(!SCIPisInfinity(scip, consdata1->lhs));
2903 assert(!SCIPisInfinity(scip, -rhs));
2904 assert(!SCIPisInfinity(scip, -consdata1->rhs));
2905
2906 /* check if a left hand side of one constraints is redundant */
2907 checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, lhs, consdata1->lhs, &lhsequal, &cons0lhsred, &cons1lhsred, TRUE);
2908
2909 /* check if a right hand side of one constraints is redundant */
2910 checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, rhs, consdata1->rhs, &rhsequal, &cons0rhsred, &cons1rhsred, FALSE);
2911
2912 /* if cons0 is redundant, update cons1 and delete cons0 */
2913 if( (lhsequal || cons0lhsred) && (rhsequal || cons0rhsred) )
2914 {
2915 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2916 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2917
2918 SCIPdebugMsg(scip, "constraint: ");
2919 SCIPdebugPrintCons(scip, cons0, NULL);
2920 SCIPdebugMsg(scip, "is redundant to constraint: ");
2921 SCIPdebugPrintCons(scip, cons1, NULL);
2922
2923 SCIP_CALL( SCIPdelCons(scip, cons0) );
2924 ++(*ndelconss);
2925
2926 /* get next cons0 */
2927 break;
2928 }
2929 /* if cons1 is redundant, update cons0 and delete cons1 */
2930 else if( cons1lhsred && cons1rhsred )
2931 {
2932 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2933 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2934
2935 SCIPdebugMsg(scip, "constraint: ");
2936 SCIPdebugPrintCons(scip, cons1, NULL);
2937 SCIPdebugMsg(scip, "is redundant to constraint: ");
2938 SCIPdebugPrintCons(scip, cons0, NULL);
2939
2940 SCIP_CALL( SCIPdelCons(scip, cons1) );
2941 ++(*ndelconss);
2942
2943 /* get next cons1 */
2944 continue;
2945 }
2946 /* if left hand side of cons0 is redundant set it to -infinity */
2947 else if( (lhsequal || cons0lhsred) && !SCIPisInfinity(scip, -lhs) )
2948 {
2949 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2950 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2951
2952 lhs = -SCIPinfinity(scip);
2953
2954 /* if right hand side of cons1 is redundant too, set it to infinity */
2955 if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
2956 {
2957 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2958 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2959
2960 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
2961 ++(*nchgsides);
2962
2963 SCIPdebugMsg(scip, "deleted rhs of constraint: ");
2964 SCIPdebugPrintCons(scip, cons1, NULL);
2965 SCIPdebugMsg(scip, "due to constraint: ");
2966 SCIPdebugPrintCons(scip, cons0, NULL);
2967 }
2968
2969 /* later on we do not want to delete cons1 */
2970 deletecons1 = FALSE;
2971 }
2972 /* if right hand side of cons0 is redundant set it to infinity */
2973 else if( (rhsequal || cons0rhsred) && !SCIPisInfinity(scip, rhs) )
2974 {
2975 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2976 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2977
2978 rhs = SCIPinfinity(scip);
2979
2980 /* if left hand side of cons1 is redundant too, set it to -infinity */
2981 if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
2982 {
2983 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2984 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2985
2986 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
2987 ++(*nchgsides);
2988
2989 SCIPdebugMsg(scip, "deleted lhs of constraint: ");
2990 SCIPdebugPrintCons(scip, cons1, NULL);
2991 SCIPdebugMsg(scip, "due to constraint: ");
2992 SCIPdebugPrintCons(scip, cons0, NULL);
2993 }
2994
2995 /* later on we do not want to delete cons1 */
2996 deletecons1 = FALSE;
2997 }
2998 /* if left hand side of cons1 is redundant set it to -infinity */
2999 else if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
3000 {
3001 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3002 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3003
3004 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
3005 ++(*nchgsides);
3006
3007 SCIPdebugMsg(scip, "deleted lhs of constraint: ");
3008 SCIPdebugPrintCons(scip, cons1, NULL);
3009 SCIPdebugMsg(scip, "due to constraint: ");
3010 SCIPdebugPrintCons(scip, cons0, NULL);
3011
3012 continue;
3013 }
3014 /* if right hand side of cons1 is redundant set it to infinity */
3015 else if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
3016 {
3017 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3018 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3019
3020 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
3021 ++(*nchgsides);
3022
3023 SCIPdebugMsg(scip, "deleted rhs of constraint: ");
3024 SCIPdebugPrintCons(scip, cons1, NULL);
3025 SCIPdebugMsg(scip, "due to constraint: ");
3026 SCIPdebugPrintCons(scip, cons0, NULL);
3027
3028 continue;
3029 }
3030 else /* nothing was redundant */
3031 continue;
3032 }
3033 else
3034 {
3035 /* there is no redundancy in both constraints with same variables */
3036 continue;
3037 }
3038
3039 if( SCIPisFeasLT(scip, rhs, lhs) )
3040 {
3041 SCIPdebugMsg(scip, "constraint <%s> and <%s> lead to infeasibility due to their sides\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
3042 *cutoff = TRUE;
3043 break;
3044 }
3045
3046 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
3047 if( lhs > rhs )
3048 {
3049 rhs = (lhs + rhs)/2;
3050 lhs = rhs;
3051 }
3052
3053 /* we decide to let constraint cons0 stay, so update data structure consdata0 */
3054
3055 /* update coefficient of cons0 */
3056
3057 /* special case if new coefficient becomes zero, both constraints are redundant but we may tighten the bounds */
3058 if( SCIPisZero(scip, coef) )
3059 {
3060 SCIP_Bool tightened;
3061
3062 SCIPdebugMsg(scip, "constraint: ");
3063 SCIPdebugPrintCons(scip, cons1, NULL);
3064 SCIPdebugMsg(scip, "and constraint: ");
3065 SCIPdebugPrintCons(scip, cons0, NULL);
3066 SCIPdebugMsg(scip, "are both redundant and lead to bounding of <%s> in [%g, %g]\n", SCIPvarGetName(consdata0->var), lhs, rhs);
3067
3068 /* delete cons1 */
3069 SCIP_CALL( SCIPdelCons(scip, cons1) );
3070 ++(*ndelconss);
3071
3072 /* update upper bound if possible
3073 *
3074 * @note we need to force the bound change since we are deleting the constraint afterwards
3075 */
3076 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, rhs, TRUE, cutoff, &tightened) );
3077 if( *cutoff )
3078 break;
3079 if( tightened )
3080 ++(*nchgbds);
3081
3082 /* update lower bound if possible
3083 *
3084 * @note we need to force the bound change since we are deleting the constraint afterwards
3085 */
3086 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, lhs, TRUE, cutoff, &tightened) );
3087 if( *cutoff )
3088 break;
3089 if( tightened )
3090 ++(*nchgbds);
3091
3092 /* delete cons0 */
3093 SCIP_CALL( SCIPdelCons(scip, cons0) );
3094 ++(*ndelconss);
3095
3096 /* get next cons0 */
3097 break;
3098 }
3099
3100 SCIPdebugMsg(scip, "constraint: ");
3101 SCIPdebugPrintCons(scip, cons1, NULL);
3102 SCIPdebugMsg(scip, "and constraint: ");
3103 SCIPdebugPrintCons(scip, cons0, NULL);
3104
3105 /* if sign of coefficient switches, update the locks of the variable */
3106 if( consdata0->vbdcoef * coef < 0.0 )
3107 {
3108 assert(SCIPconsIsTransformed(cons0));
3109
3110 /* remove locks for variable with old coefficient and install locks for variable with new
3111 * coefficient
3112 */
3113 if( consdata0->vbdcoef > 0.0 )
3114 {
3115 SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, -consdata0->lhs),
3116 !SCIPisInfinity(scip, consdata0->rhs)) );
3117 SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, consdata0->rhs),
3118 !SCIPisInfinity(scip, -consdata0->lhs)) );
3119 }
3120 else
3121 {
3122 SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, consdata0->rhs),
3123 !SCIPisInfinity(scip, -consdata0->lhs)) );
3124 SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, -consdata0->lhs),
3125 !SCIPisInfinity(scip, consdata0->rhs)) );
3126 }
3127 }
3128
3129 /* now change the coefficient */
3130 if( !SCIPisEQ(scip, consdata0->vbdcoef, coef) )
3131 {
3132 ++(*nchgcoefs);
3133
3134 /* mark to add new varbound information */
3135 consdata0->varboundsadded = FALSE;
3136 consdata0->tightened = FALSE;
3137 consdata0->presolved = FALSE;
3138 consdata0->changed = FALSE;
3139
3140 consdata0->vbdcoef = coef;
3141
3143 }
3144
3145 /* update lhs and rhs of cons0 */
3146 if( !SCIPisEQ(scip, consdata0->lhs, lhs) )
3147 {
3148 SCIP_CALL( chgLhs(scip, cons0, lhs) );
3149 ++(*nchgsides);
3150 }
3151 if( !SCIPisEQ(scip, consdata0->rhs, rhs) )
3152 {
3153 SCIP_CALL( chgRhs(scip, cons0, rhs) );
3154 ++(*nchgsides);
3155 }
3156
3157 SCIPdebugMsg(scip, "lead to new constraint: ");
3158 SCIPdebugPrintCons(scip, cons0, NULL);
3159
3160 /* if cons1 is still marked for deletion, delete it */
3161 if( deletecons1 )
3162 {
3163 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3164 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3165
3166 /* delete cons1 */
3167 SCIP_CALL( SCIPdelCons(scip, cons1) );
3168 ++(*ndelconss);
3169 }
3170
3171 assert(SCIPconsIsActive(cons0));
3172 }
3173 }
3174
3175 /* free temporary memory */
3176 SCIPfreeBufferArray(scip, &sortedconss);
3177
3178 return SCIP_OKAY;
3179}
3180
3181/** for all varbound constraints with two integer variables make the coefficients integral */
3182static
3184 SCIP* scip, /**< SCIP data structure */
3185 SCIP_CONS** conss, /**< constraint set */
3186 int nconss, /**< number of constraints in constraint set */
3187 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3188 int* nchgsides /**< pointer to count number of changed left/right hand sides */
3189 )
3190{
3191 SCIP_CONSDATA* consdata;
3192 int c;
3193
3194 assert(scip != NULL);
3195 assert(conss != NULL || nconss == 0);
3196 assert(nchgcoefs != NULL);
3197 assert(nchgsides != NULL);
3198
3199 /* if we cannot find any constraint for prettifying, stop */
3201 return;
3202
3203 for( c = nconss - 1; c >= 0; --c )
3204 {
3205 assert(conss != NULL);
3206
3207 if( SCIPconsIsDeleted(conss[c]) )
3208 continue;
3209
3210 consdata = SCIPconsGetData(conss[c]);
3211 assert(consdata != NULL);
3212
3213 /* check for integer variables and one coefficient with an absolute value smaller than 1 */
3214 /* @note: we allow that the variable type of the bounded variable can be smaller than the variable type of the
3215 * bounding variable
3216 */
3217 if( SCIPvarIsIntegral(consdata->var) && SCIPvarIsIntegral(consdata->vbdvar)
3218 && SCIPvarGetType(consdata->vbdvar) != SCIP_VARTYPE_BINARY
3219 && SCIPisLT(scip, REALABS(consdata->vbdcoef), 1.0) )
3220 {
3221 SCIP_Real epsilon;
3224 SCIP_Longint maxmult;
3225 SCIP_Bool success;
3226
3228 maxmult = MIN(maxmult, MAXSCALEDCOEF);
3229
3230 /* this ensures that one coefficient in the scaled constraint will be one as asserted below; 0.9 to be safe */
3231 epsilon = SCIPepsilon(scip) / (SCIP_Real)maxmult;
3232 epsilon *= 0.9;
3233
3234 success = SCIPrealToRational(consdata->vbdcoef, -epsilon, epsilon , maxmult, &numerator, &denominator);
3235
3236 if( success )
3237 {
3238 /* it is possible that the dominator is a multiple of the numerator */
3240 {
3242 numerator = 1;
3243 }
3244
3245 success = success && (denominator <= maxmult);
3246
3247 /* scale the constraint denominator/numerator */
3248 if( success && ABS(denominator) > 1 && numerator == 1 )
3249 {
3250 SCIP_VAR* swapvar;
3251
3252 /* print constraint before scaling */
3253 SCIPdebugPrintCons(scip, conss[c], NULL);
3254
3255 assert(SCIPisEQ(scip, consdata->vbdcoef * denominator, 1.0));
3256
3257 /* need to switch sides if coefficient is smaller then 0 */
3258 if( consdata->vbdcoef < 0 )
3259 {
3260 assert(denominator < 0);
3261
3262 /* compute new sides */
3263
3264 /* only right hand side exists */
3265 if( SCIPisInfinity(scip, -consdata->lhs) )
3266 {
3267 consdata->lhs = consdata->rhs * denominator;
3268 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs));
3269
3270 consdata->rhs = SCIPinfinity(scip);
3271 }
3272 /* only left hand side exists */
3273 else if( SCIPisInfinity(scip, consdata->rhs) )
3274 {
3275 consdata->rhs = consdata->lhs * denominator;
3276 assert(!SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs));
3277
3278 consdata->lhs = -SCIPinfinity(scip);
3279 }
3280 /* both sides exist */
3281 else
3282 {
3283 SCIP_Real tmp;
3284
3285 tmp = consdata->lhs;
3286 consdata->lhs = consdata->rhs * denominator;
3287 consdata->rhs = tmp * denominator;
3288 consdata->tightened = FALSE;
3289
3290 assert(!SCIPisInfinity(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs));
3291 assert(SCIPisGE(scip, consdata->rhs, consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
3292 }
3293 *nchgsides += 2;
3294 }
3295 /* coefficient > 0 */
3296 else
3297 {
3298 assert(denominator > 0);
3299
3300 /* compute new left hand side */
3301 if( !SCIPisInfinity(scip, -consdata->lhs) )
3302 {
3303 consdata->lhs *= denominator;
3304 assert(!SCIPisInfinity(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs));
3305 ++(*nchgsides);
3306 }
3307
3308 /* compute new right hand side */
3309 if( !SCIPisInfinity(scip, consdata->rhs) )
3310 {
3311 consdata->rhs *= denominator;
3312 assert(!SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs));
3313 ++(*nchgsides);
3314 }
3315
3316 assert(SCIPisGE(scip, consdata->rhs, consdata->lhs));
3317 }
3318
3319 /* swap both variables */
3320 swapvar = consdata->var;
3321 consdata->var = consdata->vbdvar;
3322 consdata->vbdvar = swapvar;
3323
3324 /* swap coefficient */
3325 consdata->vbdcoef = (SCIP_Real)denominator;
3326 ++(*nchgcoefs);
3327
3328 /* mark to add new varbound information */
3329 consdata->varboundsadded = FALSE;
3330 consdata->tightened = FALSE;
3331
3332 /* print constraint after scaling */
3333 SCIPdebugMsg(scip, "transformed into:");
3334 SCIPdebugPrintCons(scip, conss[c], NULL);
3335 }
3336 }
3337 }
3338 }
3339}
3340
3341/** replaces fixed and aggregated variables in variable bound constraint by active problem variables */
3342static
3344 SCIP* scip, /**< SCIP data structure */
3345 SCIP_CONS* cons, /**< variable bound constraint */
3346 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
3347 SCIP_Bool* cutoff, /**< pointer to store whether an infeasibility was detected */
3348 int* nchgbds, /**< pointer to count number of bound changes */
3349 int* ndelconss, /**< pointer to count number of deleted constraints */
3350 int* naddconss /**< pointer to count number of added constraints */
3351 )
3352{
3353 SCIP_CONSDATA* consdata;
3354 SCIP_VAR* var;
3355 SCIP_VAR* vbdvar;
3356 SCIP_Real varscalar;
3357 SCIP_Real varconstant;
3358 SCIP_Real vbdvarscalar;
3359 SCIP_Real vbdvarconstant;
3360 SCIP_Real newbnd;
3361 SCIP_Bool varschanged;
3362 SCIP_Bool redundant;
3363
3364 assert(scip != NULL);
3365 assert(cons != NULL);
3366 assert(cutoff != NULL);
3367 assert(nchgbds != NULL);
3368 assert(ndelconss != NULL);
3369 assert(naddconss != NULL);
3370
3371 *cutoff = FALSE;
3372 redundant = FALSE;
3373
3374 /* the variable bound constraint is: lhs <= x + c*y <= rhs */
3375 consdata = SCIPconsGetData(cons);
3376 assert(consdata != NULL);
3377
3378 /* get active problem variables of x and y */
3379 var = consdata->var;
3380 varscalar = 1.0;
3381 varconstant = 0.0;
3382 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &varscalar, &varconstant) );
3383 vbdvar = consdata->vbdvar;
3384 vbdvarscalar = 1.0;
3385 vbdvarconstant = 0.0;
3386 SCIP_CALL( SCIPgetProbvarSum(scip, &vbdvar, &vbdvarscalar, &vbdvarconstant) );
3387 varschanged = (var != consdata->var || vbdvar != consdata->vbdvar);
3388
3389 /* if the variables are equal, the variable bound constraint reduces to standard bounds on the single variable */
3390 if( var == vbdvar && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
3391 {
3392 SCIP_Real scalar;
3393 SCIP_Real constant;
3394
3395 SCIPdebugMsg(scip, "variable bound constraint <%s> has equal variable and vbd variable <%s>\n",
3396 SCIPconsGetName(cons), SCIPvarGetName(var));
3397
3398 /* lhs <= a1*z + b1 + c(a2*z + b2) <= rhs
3399 * <=> lhs <= (a1 + c*a2)z + (b1 + c*b2) <= rhs
3400 */
3401 scalar = varscalar + consdata->vbdcoef * vbdvarscalar;
3402 constant = varconstant + consdata->vbdcoef * vbdvarconstant;
3403 if( SCIPisZero(scip, scalar) )
3404 {
3405 /* no variable is left: the constraint is redundant or infeasible */
3406 if( SCIPisFeasLT(scip, constant, consdata->lhs) || SCIPisFeasGT(scip, constant, consdata->rhs) )
3407 {
3408 *cutoff = TRUE;
3409 return SCIP_OKAY;
3410 }
3411 }
3412 else if( scalar > 0.0 )
3413 {
3414 if( !SCIPisInfinity(scip, -consdata->lhs) )
3415 {
3416 SCIP_Bool tightened;
3417
3418 newbnd = (consdata->lhs - constant) / scalar;
3419 SCIP_CALL( SCIPtightenVarLb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3420 if( *cutoff )
3421 {
3422 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3423 return SCIP_OKAY;
3424 }
3425 if( tightened )
3426 {
3427 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var));
3428 (*nchgbds)++;
3429 }
3430 }
3431 if( !SCIPisInfinity(scip, consdata->rhs) )
3432 {
3433 SCIP_Bool tightened;
3434
3435 newbnd = (consdata->rhs - constant) / scalar;
3436 SCIP_CALL( SCIPtightenVarUb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3437 if( *cutoff )
3438 {
3439 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3440 return SCIP_OKAY;
3441 }
3442 if( tightened )
3443 {
3444 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(var), SCIPvarGetUbGlobal(var));
3445 (*nchgbds)++;
3446 }
3447 }
3448 }
3449 else
3450 {
3451 if( !SCIPisInfinity(scip, -consdata->lhs) )
3452 {
3453 SCIP_Bool tightened;
3454
3455 newbnd = (consdata->lhs - constant) / scalar;
3456 SCIP_CALL( SCIPtightenVarUb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3457 if( *cutoff )
3458 {
3459 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3460 return SCIP_OKAY;
3461 }
3462 if( tightened )
3463 {
3464 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(var), SCIPvarGetUbGlobal(var));
3465 (*nchgbds)++;
3466 }
3467 }
3468 if( !SCIPisInfinity(scip, consdata->rhs) )
3469 {
3470 SCIP_Bool tightened;
3471
3472 newbnd = (consdata->rhs - constant) / scalar;
3473 SCIP_CALL( SCIPtightenVarLb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3474 if( *cutoff )
3475 {
3476 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3477 return SCIP_OKAY;
3478 }
3479 if( tightened )
3480 {
3481 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var));
3482 (*nchgbds)++;
3483 }
3484 }
3485 }
3486 redundant = TRUE;
3487 }
3488 else
3489 {
3490 /* if the variables should be replaced, drop the events and catch the events on the new variables afterwards */
3491 if( varschanged )
3492 {
3493 SCIP_CALL( dropEvents(scip, cons, eventhdlr) );
3494 }
3495
3496 /* apply aggregation on x */
3497 if( SCIPisZero(scip, varscalar) )
3498 {
3499 /* the variable being fixed or corresponding to an aggregation might lead to numerical difficulties */
3500 if( SCIPisZero(scip, consdata->vbdcoef * vbdvarscalar) )
3501 {
3502 SCIP_Real activity = varconstant + consdata->vbdcoef * vbdvarconstant;
3503
3504 SCIPdebugMsg(scip, "variable bound constraint <%s>: variable <%s> is fixed to %.15g\n",
3505 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), varconstant);
3506
3507 assert(SCIPisGE(scip, varconstant, SCIPvarGetLbGlobal(consdata->var)));
3508 assert(SCIPisLE(scip, varconstant, SCIPvarGetUbGlobal(consdata->var)));
3509 assert(SCIPisGE(scip, vbdvarconstant, SCIPvarGetLbGlobal(consdata->vbdvar)));
3510 assert(SCIPisLE(scip, vbdvarconstant, SCIPvarGetUbGlobal(consdata->vbdvar)));
3511
3512 if( ( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasLT(scip, activity, consdata->lhs) )
3513 || ( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasGT(scip, activity, consdata->rhs) ) )
3514 *cutoff = TRUE;
3515
3516 redundant = TRUE;
3517 }
3518 /* cannot change bounds on multi-aggregated variables */
3519 else if( SCIPvarGetStatus(vbdvar) != SCIP_VARSTATUS_MULTAGGR )
3520 {
3521 assert( consdata->vbdcoef != 0.0 );
3522 assert( vbdvarscalar != 0.0 );
3523
3524 /* x is fixed to varconstant: update bounds of y and delete the variable bound constraint */
3525 if( !(*cutoff) && !SCIPisInfinity(scip, -consdata->lhs) )
3526 {
3527 if( consdata->vbdcoef > 0.0 )
3528 {
3529 SCIP_Bool tightened;
3530
3531 newbnd = (consdata->lhs - varconstant) / consdata->vbdcoef;
3532 SCIP_CALL( SCIPtightenVarLb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3533 if( *cutoff )
3534 {
3535 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3536 }
3537 else if( tightened )
3538 {
3539 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbGlobal(consdata->vbdvar));
3540 (*nchgbds)++;
3541 }
3542 }
3543 else
3544 {
3545 SCIP_Bool tightened;
3546
3547 newbnd = (consdata->lhs - varconstant) / consdata->vbdcoef;
3548 SCIP_CALL( SCIPtightenVarUb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3549 if( *cutoff )
3550 {
3551 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3552 }
3553 else if( tightened )
3554 {
3555 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetUbGlobal(consdata->vbdvar));
3556 (*nchgbds)++;
3557 }
3558 }
3559 }
3560 if( !(*cutoff) && !SCIPisInfinity(scip, consdata->rhs) )
3561 {
3562 if( consdata->vbdcoef > 0.0 )
3563 {
3564 SCIP_Bool tightened;
3565
3566 newbnd = (consdata->rhs - varconstant) / consdata->vbdcoef;
3567 SCIP_CALL( SCIPtightenVarUb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3568 if( *cutoff )
3569 {
3570 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3571 }
3572 else if( tightened )
3573 {
3574 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetUbGlobal(consdata->vbdvar));
3575 (*nchgbds)++;
3576 }
3577 }
3578 else
3579 {
3580 SCIP_Bool tightened;
3581
3582 newbnd = (consdata->rhs - varconstant) / consdata->vbdcoef;
3583 SCIP_CALL( SCIPtightenVarLb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3584 if( *cutoff )
3585 {
3586 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3587 }
3588 else if( tightened )
3589 {
3590 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbGlobal(consdata->vbdvar));
3591 (*nchgbds)++;
3592 }
3593 }
3594 }
3595 redundant = TRUE;
3596 }
3597 }
3598 else if( var != consdata->var )
3599 {
3600 /* release and unlock old variable */
3601 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3602 !SCIPisInfinity(scip, consdata->rhs)) );
3603 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->var)) );
3604
3605 /* unlock vbdvar, because we possibly change lhs/rhs/vbdcoef */
3606 if( consdata->vbdcoef > 0.0 )
3607 {
3608 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3609 !SCIPisInfinity(scip, consdata->rhs)) );
3610 }
3611 else
3612 {
3613 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3614 !SCIPisInfinity(scip, -consdata->lhs)) );
3615 }
3616
3617 /* replace aggregated variable x in the constraint by its aggregation */
3618 if( varscalar > 0.0 )
3619 {
3620 /* lhs := (lhs - varconstant) / varscalar
3621 * rhs := (rhs - varconstant) / varscalar
3622 * c := c / varscalar
3623 */
3624 if( !SCIPisInfinity(scip, -consdata->lhs) )
3625 consdata->lhs = (consdata->lhs - varconstant)/varscalar;
3626 if( !SCIPisInfinity(scip, consdata->rhs) )
3627 consdata->rhs = (consdata->rhs - varconstant)/varscalar;
3628 consdata->vbdcoef /= varscalar;
3629
3630 /* try to avoid numerical troubles */
3631 if( SCIPisIntegral(scip, consdata->vbdcoef) )
3632 consdata->vbdcoef = SCIPround(scip, consdata->vbdcoef);
3633
3634 consdata->tightened = FALSE;
3635 }
3636 else
3637 {
3638 SCIP_Real lhs;
3639
3640 assert(varscalar != 0.0);
3641
3642 /* lhs := (rhs - varconstant) / varscalar
3643 * rhs := (lhs - varconstant) / varscalar
3644 * c := c / varscalar
3645 */
3646 lhs = consdata->lhs;
3647 consdata->lhs = -consdata->rhs;
3648 consdata->rhs = -lhs;
3649 if( !SCIPisInfinity(scip, -consdata->lhs) )
3650 consdata->lhs = (consdata->lhs + varconstant)/(-varscalar);
3651 if( !SCIPisInfinity(scip, consdata->rhs) )
3652 consdata->rhs = (consdata->rhs + varconstant)/(-varscalar);
3653 consdata->vbdcoef /= varscalar;
3654
3655 /* try to avoid numerical troubles */
3656 if( SCIPisIntegral(scip, consdata->vbdcoef) )
3657 consdata->vbdcoef = SCIPround(scip, consdata->vbdcoef);
3658
3659 consdata->tightened = FALSE;
3660 }
3661
3662 consdata->var = var;
3663
3664 /* capture and lock new variable */
3665 SCIP_CALL( SCIPcaptureVar(scip, consdata->var) );
3666 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3667 !SCIPisInfinity(scip, consdata->rhs)) );
3668
3669 /* lock vbdvar */
3670 if( consdata->vbdcoef > 0.0 )
3671 {
3672 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3673 !SCIPisInfinity(scip, consdata->rhs)) );
3674 }
3675 else
3676 {
3677 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3678 !SCIPisInfinity(scip, -consdata->lhs)) );
3679 }
3680 }
3681
3682 /* apply aggregation on y */
3683 if( SCIPisZero(scip, consdata->vbdcoef * vbdvarscalar) )
3684 {
3685 SCIPdebugMsg(scip, "variable bound constraint <%s>: vbd variable <%s> is fixed to %.15g\n",
3686 SCIPconsGetName(cons), SCIPvarGetName(consdata->vbdvar), vbdvarconstant);
3687
3688 /* cannot change bounds on multi-aggregated variables */
3689 if( !redundant && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
3690 {
3691 assert( SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED );
3692 assert( !SCIPisZero(scip, varscalar) );
3693
3694 /* y is fixed to vbdvarconstant: update bounds of x and delete the variable bound constraint */
3695 if( !(*cutoff) && !SCIPisInfinity(scip, -consdata->lhs) )
3696 {
3697 SCIP_Bool tightened;
3698
3699 newbnd = consdata->lhs - consdata->vbdcoef * vbdvarconstant;
3700 SCIP_CALL( SCIPtightenVarLb(scip, consdata->var, newbnd, TRUE, cutoff, &tightened) );
3701 if( *cutoff )
3702 {
3703 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(consdata->var), newbnd);
3704 }
3705 else if( tightened )
3706 {
3707 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->var), SCIPvarGetLbGlobal(consdata->var));
3708 (*nchgbds)++;
3709 }
3710 }
3711 if( !(*cutoff) && !SCIPisInfinity(scip, consdata->rhs) )
3712 {
3713 SCIP_Bool tightened;
3714
3715 newbnd = consdata->rhs - consdata->vbdcoef * vbdvarconstant;
3716 SCIP_CALL( SCIPtightenVarUb(scip, consdata->var, newbnd, TRUE, cutoff, &tightened) );
3717 if( *cutoff )
3718 {
3719 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(consdata->var), newbnd);
3720 }
3721 else if( tightened )
3722 {
3723 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->var), SCIPvarGetUbGlobal(consdata->var));
3724 (*nchgbds)++;
3725 }
3726 }
3727 redundant = TRUE;
3728 }
3729 }
3730 else if( !(*cutoff) && vbdvar != consdata->vbdvar )
3731 {
3732 /* release and unlock old variable */
3733 if( consdata->vbdcoef > 0.0 )
3734 {
3735 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3736 !SCIPisInfinity(scip, consdata->rhs)) );
3737 }
3738 else
3739 {
3740 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3741 !SCIPisInfinity(scip, -consdata->lhs)) );
3742 }
3743 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->vbdvar)) );
3744
3745 /* also unlock var, because we possibly change lhs/rhs/vbdcoef */
3746 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3747 !SCIPisInfinity(scip, consdata->rhs)) );
3748
3749 /* replace aggregated variable y in the constraint by its aggregation:
3750 * lhs := lhs - c * vbdvarconstant
3751 * rhs := rhs - c * vbdvarconstant
3752 * c := c * vbdvarscalar
3753 */
3754 if( !SCIPisInfinity(scip, -consdata->lhs) )
3755 consdata->lhs -= consdata->vbdcoef * vbdvarconstant;
3756 if( !SCIPisInfinity(scip, consdata->rhs) )
3757 consdata->rhs -= consdata->vbdcoef * vbdvarconstant;
3758
3759 consdata->tightened = FALSE;
3760 consdata->vbdcoef *= vbdvarscalar;
3761 consdata->vbdvar = vbdvar;
3762
3763 /* capture and lock new variable */
3764 SCIP_CALL( SCIPcaptureVar(scip, consdata->vbdvar) );
3765 if( consdata->vbdcoef > 0.0 )
3766 {
3767 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3768 !SCIPisInfinity(scip, consdata->rhs)) );
3769 }
3770 else
3771 {
3772 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3773 !SCIPisInfinity(scip, -consdata->lhs)) );
3774 }
3775 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3776 !SCIPisInfinity(scip, consdata->rhs)) );
3777 }
3778
3779 /* catch the events again on the new variables */
3780 if( varschanged )
3781 {
3782 SCIP_CALL( catchEvents(scip, cons, eventhdlr) );
3783 }
3784
3785 /* terminate on cutoff after catching events */
3786 if( *cutoff )
3787 return SCIP_OKAY;
3788 }
3789
3790 /* mark constraint changed, if a variable was exchanged */
3791 if( varschanged )
3792 {
3793 consdata->changed = TRUE;
3794 }
3795
3796 /* active multi aggregations are now resolved by creating a new linear constraint */
3797 if( !redundant && (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR || SCIPvarGetStatus(vbdvar) == SCIP_VARSTATUS_MULTAGGR) )
3798 {
3799 SCIP_CONS* newcons;
3800 SCIP_Real lhs;
3801 SCIP_Real rhs;
3802
3803 lhs = consdata->lhs;
3804 rhs = consdata->rhs;
3805
3806 /* create upgraded linear constraint */
3807 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons), 0, NULL, NULL, lhs, rhs,
3812
3813 /* if var was fixed, then the case that vbdvar was multi-aggregated, was not yet resolved */
3814 if( var != consdata->var )
3815 {
3816 assert(SCIPvarGetStatus(vbdvar) == SCIP_VARSTATUS_MULTAGGR);
3817 assert(SCIPisZero(scip, varscalar)); /* this means that var was fixed */
3818
3819 /* add offset that results from the fixed variable */
3820 if( ! SCIPisZero(scip, varconstant) )
3821 {
3822 if( !SCIPisInfinity(scip, rhs) )
3823 {
3824 SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs - varconstant) );
3825 }
3826 if( !SCIPisInfinity(scip, -lhs) )
3827 {
3828 SCIP_CALL( SCIPchgLhsLinear(scip, newcons, lhs - varconstant) );
3829 }
3830 }
3831 }
3832 else
3833 {
3834 assert(var == consdata->var);
3835
3836 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, consdata->var, 1.0) );
3837 }
3838
3839 /* if vbdvar was fixed, then the case that var was multi-aggregated, was not yet resolved */
3840 if( vbdvar != consdata->vbdvar )
3841 {
3843 assert(SCIPisZero(scip, vbdvarscalar)); /* this means that var was fixed */
3844
3845 /* add offset that results from the fixed variable */
3846 if( ! SCIPisZero(scip, vbdvarconstant) )
3847 {
3848 if( !SCIPisInfinity(scip, rhs) )
3849 {
3850 SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs - consdata->vbdcoef * vbdvarconstant) );
3851 }
3852 if( !SCIPisInfinity(scip, -lhs) )
3853 {
3854 SCIP_CALL( SCIPchgLhsLinear(scip, newcons, lhs - consdata->vbdcoef * vbdvarconstant) );
3855 }
3856 }
3857 }
3858 else
3859 {
3860 assert(vbdvar == consdata->vbdvar);
3861
3862 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, consdata->vbdvar, consdata->vbdcoef) );
3863 }
3864
3865 SCIPdebugMsg(scip, "resolved multi aggregation in varbound constraint <%s> by creating a new linear constraint\n", SCIPconsGetName(cons));
3866 SCIPdebugPrintCons(scip, newcons, NULL);
3867
3868 SCIP_CALL( SCIPaddCons(scip, newcons) );
3869 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3870
3871 redundant = TRUE;
3872 ++(*naddconss);
3873 }
3874
3875 /* delete a redundant constraint */
3876 if( redundant )
3877 {
3878 SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
3879 SCIP_CALL( SCIPdelCons(scip, cons) );
3880 (*ndelconss)++;
3881 }
3882
3883 return SCIP_OKAY;
3884}
3885
3886/** tightens variable bound coefficient by inspecting the global bounds of the involved variables; note: this is also
3887 * performed by the linear constraint handler - only necessary if the user directly creates variable bound constraints
3888 */
3889static
3891 SCIP* scip, /**< SCIP data structure */
3892 SCIP_CONS* cons, /**< variable bound constraint */
3893 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3894 int* nchgsides, /**< pointer to count the number of left and right hand sides */
3895 int* ndelconss, /**< pointer to count number of deleted constraints */
3896 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3897 int* nchgbds /**< pointer to count number of bound changes */
3898 )
3899{
3900 SCIP_CONSDATA* consdata;
3901 SCIP_Real xlb;
3902 SCIP_Real xub;
3903 SCIP_Real oldcoef;
3904 int oldnchgcoefs;
3905 int oldnchgsides;
3906
3907 assert(nchgcoefs != NULL);
3908 assert(nchgsides != NULL);
3909 assert(ndelconss != NULL);
3910
3911 consdata = SCIPconsGetData(cons);
3912 assert(consdata != NULL);
3913
3914 /* tightening already done */
3915 if( consdata->tightened )
3916 return SCIP_OKAY;
3917
3918 SCIPdebugMsg(scip, "tightening coefficients on variable bound constraint <%s>\n", SCIPconsGetName(cons));
3919
3920 consdata->tightened = TRUE;
3921
3922 /* if values and variable are integral the sides should it be too */
3923 if( SCIPvarIsIntegral(consdata->var) && SCIPvarIsIntegral(consdata->vbdvar)
3924 && SCIPisIntegral(scip, consdata->vbdcoef) )
3925 {
3926 if( !SCIPisIntegral(scip, consdata->lhs) )
3927 {
3928 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3929 ++(*nchgsides);
3930 consdata->changed = TRUE;
3931 }
3932 if( !SCIPisIntegral(scip, consdata->rhs) )
3933 {
3934 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3935 ++(*nchgsides);
3936 consdata->changed = TRUE;
3937 }
3938 }
3939
3940 /* coefficient tightening only works for binary bound variable */
3941 if( !SCIPvarIsBinary(consdata->vbdvar) )
3942 return SCIP_OKAY;
3943
3944 oldnchgcoefs = *nchgcoefs;
3945 oldnchgsides = *nchgsides;
3946 oldcoef = consdata->vbdcoef;
3947
3948 /* coefficients tightening when all variables are integer */
3949 /* we consider the following varbound constraint: lhs <= x + b*y <= rhs (sides are possibly infinity)
3950 * y should always be binary and x of integral type and b not integral, we also need at least one side with infinity
3951 * or not integral value.
3952 *
3953 * 1. if( (lhs is integral and not -infinity) and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3954 *
3955 * lhs <= x + b*y <= rhs => lhs <= x + floor(b)*y <= floor(rhs)
3956 *
3957 * 2. if( (rhs is integral and not infinity) and ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs))) ):
3958 *
3959 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= rhs
3960 *
3961 * 3. if( ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs)))
3962 * and ((rhs is infinity) or (b - floor(b) > rhs - floor(rhs))) ):
3963 *
3964 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= floor(rhs)
3965 *
3966 * 4. if( ((lhs is -infinity) or (b - floor(b) < lhs - floor(lhs)))
3967 * and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3968 *
3969 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + floor(b)*y <= floor(rhs)
3970 *
3971 * 5. if( (lhs is not integral) or (rhs is not integral) )
3972 *
3973 * if (lhs is not -infinity)
3974 * if (b - floor(b) < lhs - floor(lhs)):
3975 *
3976 * lhs <= x + b*y => ceil(lhs) <= x + b*y
3977 *
3978 * else if (b - floor(b) > lhs - floor(lhs)):
3979 *
3980 * lhs <= x + b*y => floor(lhs) + b - floor(b) <= x + b*y
3981 *
3982 * if (rhs is not infinity)
3983 * if (b - floor(b) < rhs - floor(rhs)):
3984 *
3985 * x + b*y <= rhs => x + b*y <= floor(rhs) + b - floor(b)
3986 *
3987 * else if (b - floor(b) > rhs - floor(rhs)):
3988 *
3989 * x + b*y <= rhs => x + b*y <= floor(rhs)
3990 */
3991 if( SCIPvarIsIntegral(consdata->var) && !SCIPisIntegral(scip, consdata->vbdcoef)
3992 && ( !SCIPisIntegral(scip, consdata->lhs) || SCIPisInfinity(scip, -consdata->lhs)
3993 || !SCIPisIntegral(scip, consdata->rhs) || SCIPisInfinity(scip, consdata->rhs) ) )
3994 {
3995 /* infinity should be an integral value */
3996 assert(!SCIPisInfinity(scip, -consdata->lhs) || SCIPisIntegral(scip, consdata->lhs));
3997 assert(!SCIPisInfinity(scip, consdata->rhs) || SCIPisIntegral(scip, consdata->rhs));
3998
3999 /* should not be a redundant constraint */
4000 assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
4001
4002 /* case 1 */
4003 if( SCIPisIntegral(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs) &&
4004 (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
4005 {
4006 consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
4007 ++(*nchgcoefs);
4008
4009 if( !SCIPisInfinity(scip, consdata->rhs) )
4010 {
4011 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4012 ++(*nchgsides);
4013 }
4014 }
4015 /* case 2 */
4016 else if( SCIPisIntegral(scip, consdata->rhs) && !SCIPisInfinity(scip, consdata->rhs) &&
4017 (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) )
4018 {
4019 consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
4020 ++(*nchgcoefs);
4021
4022 if( !SCIPisInfinity(scip, -consdata->lhs) )
4023 {
4024 if( !SCIPisIntegral(scip, consdata->lhs) )
4025 ++(*nchgsides);
4026
4027 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4028 }
4029 }
4030 /* case 3 */
4031 else if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
4032 {
4033 consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
4034 ++(*nchgcoefs);
4035
4036 if( !SCIPisInfinity(scip, -consdata->lhs) )
4037 {
4038 if( !SCIPisIntegral(scip, consdata->lhs) )
4039 ++(*nchgsides);
4040
4041 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4042 }
4043 if( !SCIPisInfinity(scip, consdata->rhs) )
4044 {
4045 if( !SCIPisIntegral(scip, consdata->rhs) )
4046 ++(*nchgsides);
4047
4048 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4049 }
4050 }
4051 /* case 4 */
4052 else if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
4053 {
4054 consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
4055 ++(*nchgcoefs);
4056
4057 if( !SCIPisInfinity(scip, -consdata->lhs) )
4058 {
4059 if( !SCIPisIntegral(scip, consdata->lhs) )
4060 ++(*nchgsides);
4061
4062 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4063 }
4064 if( !SCIPisInfinity(scip, consdata->rhs) )
4065 {
4066 if( !SCIPisIntegral(scip, consdata->rhs) )
4067 ++(*nchgsides);
4068
4069 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4070 }
4071 }
4072 /* case 5 */
4073 if( !SCIPisFeasIntegral(scip, consdata->lhs) || !SCIPisFeasIntegral(scip, consdata->rhs) )
4074 {
4075 if( !SCIPisInfinity(scip, -consdata->lhs) )
4076 {
4077 if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
4078 {
4079 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4080 ++(*nchgsides);
4081 }
4082 else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
4083 {
4084 consdata->lhs = SCIPfeasFloor(scip, consdata->lhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
4085 ++(*nchgsides);
4086 }
4087 }
4088 if( !SCIPisInfinity(scip, consdata->rhs) )
4089 {
4090 if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
4091 {
4092 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
4093 ++(*nchgsides);
4094 }
4095 else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
4096 {
4097 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4098 ++(*nchgsides);
4099 }
4100 }
4101 }
4102 }
4103
4104 /* check if due to tightening the constraint got redundant */
4105 if( SCIPisZero(scip, consdata->vbdcoef) )
4106 {
4107 /* we have to make sure that the induced bound(s) is (are) actually applied;
4108 * if the relative change is too small, this may have been skipped in propagation
4109 */
4110 if( SCIPisLT(scip, SCIPvarGetLbGlobal(consdata->var), consdata->lhs) )
4111 {
4112 SCIP_Bool tightened;
4113
4114 SCIP_CALL( SCIPtightenVarLbGlobal(scip, consdata->var, consdata->lhs, TRUE, cutoff, &tightened) );
4115 if( *cutoff )
4116 {
4117 SCIPdebugMsg(scip, " -> tightening lower bound of <%s> to %.15g infeasible\n", SCIPvarGetName(consdata->var),
4118 consdata->lhs);
4119 return SCIP_OKAY;
4120 }
4121 if( tightened )
4122 {
4123 SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
4124 SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
4125 (*nchgbds)++;
4126 }
4127 }
4128 if( SCIPisGT(scip, SCIPvarGetUbGlobal(consdata->var), consdata->rhs) )
4129 {
4130 SCIP_Bool tightened;
4131
4132 SCIP_CALL( SCIPtightenVarUbGlobal(scip, consdata->var, consdata->rhs, TRUE, cutoff, &tightened) );
4133 if( *cutoff )
4134 {
4135 SCIPdebugMsg(scip, " -> tightening upper bound of <%s> to %.15g infeasible\n", SCIPvarGetName(consdata->var),
4136 consdata->rhs);
4137 return SCIP_OKAY;
4138 }
4139 if( tightened )
4140 {
4141 SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
4142 SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
4143 (*nchgbds)++;
4144 }
4145 }
4146
4147 SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
4148
4149 /* in order to correctly update the rounding locks, we need the coefficient to have the same sign as before the
4150 * coefficient tightening
4151 */
4152 consdata->vbdcoef = oldcoef;
4153
4154 SCIP_CALL( SCIPdelCons(scip, cons) );
4155 ++(*ndelconss);
4156
4157 return SCIP_OKAY;
4158 }
4159
4160 /* get bounds of variable x */
4161 xlb = SCIPvarGetLbGlobal(consdata->var);
4162 xub = SCIPvarGetUbGlobal(consdata->var);
4163
4164 /* it can happen that var is not of varstatus SCIP_VARSTATUS_FIXED but the bounds are equal, in this case we need to
4165 * stop
4166 */
4167 if( SCIPisEQ(scip, xlb, xub) )
4168 return SCIP_OKAY;
4169
4170 /* modification of coefficient checking for slack in constraints */
4171 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
4172 {
4173 /* lhs <= x + c*y <= rhs => lhs - c*y <= x <= rhs - c*y */
4174 if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) && SCIPisFeasLT(scip, xub, consdata->rhs) )
4175 {
4176 SCIP_Real newcoef;
4177 SCIP_Real newrhs;
4178 SCIP_Real oldrhs;
4179
4180 oldrhs = consdata->rhs;
4181
4182 /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
4183 * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
4184 * -> c' = MAX(c - rhs + xub, lhs - xlb), rhs' = rhs - c + c'
4185 */
4186 newcoef = MAX(consdata->vbdcoef - consdata->rhs + xub, consdata->lhs - xlb);
4187
4188 /* in this case both sides are redundant and the constraint can be removed */
4189 if( SCIPisLE(scip, newcoef, 0.0) )
4190 {
4191 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4192 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4193
4194 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4195 SCIP_CALL( SCIPdelCons(scip, cons) );
4196 ++(*ndelconss);
4197 }
4198 else
4199 {
4200 newrhs = consdata->rhs - consdata->vbdcoef + newcoef;
4201
4203 "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
4204 consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef,
4205 SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4206 consdata->lhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar),
4207 newrhs);
4208
4209 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4210 assert(consdata->vbdcoef * newcoef > 0);
4211
4212 consdata->vbdcoef = newcoef;
4213 consdata->rhs = MAX(newrhs, consdata->lhs);
4214 (*nchgcoefs)++;
4215 (*nchgsides)++;
4216
4217 /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
4218 * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
4219 * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
4220 */
4221 if( !SCIPisFeasIntegral(scip, oldrhs) && SCIPisFeasIntegral(scip, newrhs))
4222 {
4223 consdata->tightened = FALSE;
4224 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4225 assert(consdata->tightened);
4226 assert(!(*cutoff));
4227 }
4228 else
4229 consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->rhs));
4230 }
4231 }
4232 else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
4233 {
4234 SCIP_Real newcoef;
4235 SCIP_Real newlhs;
4236 SCIP_Real oldlhs;
4237
4238 oldlhs = consdata->lhs;
4239
4240 /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
4241 * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
4242 * -> c' = MIN(c - lhs + xlb, rhs - xub), lhs' = lhs - c + c'
4243 */
4244 newcoef = MIN(consdata->vbdcoef - consdata->lhs + xlb, consdata->rhs - xub);
4245
4246 /* in this case both sides are redundant and the constraint can be removed */
4247 if( SCIPisGE(scip, newcoef, 0.0) )
4248 {
4249 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4250 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4251
4252 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4253 SCIP_CALL( SCIPdelCons(scip, cons) );
4254 ++(*ndelconss);
4255 }
4256 else
4257 {
4258 newlhs = consdata->lhs - consdata->vbdcoef + newcoef;
4259
4261 "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
4262 consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef,
4263 SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4264 newlhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar),
4265 consdata->rhs);
4266
4267 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4268 assert(consdata->vbdcoef * newcoef > 0);
4269
4270 consdata->vbdcoef = newcoef;
4271 consdata->lhs = MIN(newlhs, consdata->rhs);
4272 (*nchgcoefs)++;
4273 (*nchgsides)++;
4274
4275 /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
4276 * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
4277 * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
4278 */
4279 if( !SCIPisFeasIntegral(scip, oldlhs) && SCIPisFeasIntegral(scip, newlhs))
4280 {
4281 consdata->tightened = FALSE;
4282 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4283 assert(consdata->tightened);
4284 assert(!(*cutoff));
4285 }
4286 else
4287 consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->lhs));
4288 }
4289 }
4290 }
4291 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, consdata->rhs) )
4292 {
4293 /* lhs <= x + c*y => x >= lhs - c*y */
4294 if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) )
4295 {
4296 SCIP_Real newcoef;
4297
4298 /* constraint has positive slack for the non-restricting case y = 1
4299 * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
4300 * -> c' = lhs - xlb
4301 */
4302 newcoef = consdata->lhs - xlb;
4303
4304 /* in this case the constraint is redundant and can be removed */
4305 if( SCIPisLE(scip, newcoef, 0.0) )
4306 {
4307 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4308
4309 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4310 SCIP_CALL( SCIPdelCons(scip, cons) );
4311 ++(*ndelconss);
4312 }
4313 else
4314 {
4315 SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
4316 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4317 consdata->lhs,
4318 SCIPvarGetName(consdata->var), consdata->lhs - xlb, SCIPvarGetName(consdata->vbdvar),
4319 consdata->lhs);
4320
4321 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4322 assert(consdata->vbdcoef * newcoef > 0);
4323
4324 consdata->vbdcoef = newcoef;
4325 (*nchgcoefs)++;
4326 }
4327 }
4328 else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) )
4329 {
4330 SCIP_Real newcoef;
4331
4332 /* constraint has positive slack for the non-restricting case y = 0
4333 * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
4334 * -> c' = c - lhs + xlb, lhs' = xlb
4335 */
4336 newcoef = consdata->vbdcoef - consdata->lhs + xlb;
4337
4338 /* in this case the constraint is redundant and can be removed */
4339 if( SCIPisGE(scip, newcoef, 0.0) )
4340 {
4341 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4342
4343 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4344 SCIP_CALL( SCIPdelCons(scip, cons) );
4345 ++(*ndelconss);
4346 }
4347 else
4348 {
4349 SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
4350 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4351 consdata->lhs,
4352 SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->lhs + xlb,
4353 SCIPvarGetName(consdata->vbdvar), xlb);
4354
4355 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4356 assert(consdata->vbdcoef * newcoef > 0);
4357
4358 consdata->vbdcoef = newcoef;
4359 consdata->lhs = xlb;
4360 (*nchgcoefs)++;
4361 (*nchgsides)++;
4362 }
4363 }
4364 }
4365 else if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
4366 {
4367 /* x + c*y <= rhs => x <= rhs - c*y */
4368 if( consdata->vbdcoef > 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs) )
4369 {
4370 SCIP_Real newcoef;
4371
4372 /* constraint has positive slack for the non-restricting case y = 0
4373 * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
4374 * -> c' = c - rhs + xub, rhs' = xub
4375 */
4376 newcoef = consdata->vbdcoef - consdata->rhs + xub;
4377
4378 /* in this case the constraint is redundant and can be removed */
4379 if( SCIPisLE(scip, newcoef, 0.0) )
4380 {
4381 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4382
4383 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4384 SCIP_CALL( SCIPdelCons(scip, cons) );
4385 ++(*ndelconss);
4386 }
4387 else
4388 {
4389 SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
4390 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4391 consdata->rhs,
4392 SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->rhs + xub,
4393 SCIPvarGetName(consdata->vbdvar), xub);
4394
4395 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4396 assert(consdata->vbdcoef * newcoef > 0);
4397
4398 consdata->vbdcoef = newcoef;
4399 consdata->rhs = xub;
4400 (*nchgcoefs)++;
4401 (*nchgsides)++;
4402 }
4403 }
4404 else if( consdata->vbdcoef < 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
4405 {
4406 SCIP_Real newcoef;
4407
4408 /* constraint has positive slack for the non-restricting case y = 1
4409 * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
4410 * -> c' = rhs - xub
4411 */
4412 newcoef = consdata->rhs - xub;
4413
4414 /* in this case the constraint is redundant and can be removed */
4415 if( SCIPisGE(scip, newcoef, 0.0) )
4416 {
4417 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4418
4419 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4420 SCIP_CALL( SCIPdelCons(scip, cons) );
4421 ++(*ndelconss);
4422 }
4423 else
4424 {
4425 SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
4426 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4427 SCIPvarGetName(consdata->var), consdata->rhs - xub, SCIPvarGetName(consdata->vbdvar), consdata->rhs);
4428
4429 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4430 assert(consdata->vbdcoef * newcoef > 0);
4431
4432 consdata->vbdcoef = newcoef;
4433 (*nchgcoefs)++;
4434 }
4435 }
4436 }
4437
4438 /* if something a coefficient or side of the varbound constraint was changed, ensure that the variable lower or
4439 * upper bounds of the variables are informed
4440 */
4441 if( *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
4442 {
4443 consdata->varboundsadded = FALSE;
4444 consdata->changed = TRUE;
4445
4447 }
4448
4449 return SCIP_OKAY;
4450}
4451
4452/** check if we can upgrade to a set-packing constraint */
4453static
4455 SCIP* scip, /**< SCIP data structure */
4456 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
4457 SCIP_CONS** conss, /**< constraint set */
4458 int nconss, /**< number of constraints in constraint set */
4459 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4460 int* naggrvars, /**< pointer to count the number of aggregated variables */
4461 int* nchgbds, /**< pointer to count number of bound changes */
4462 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
4463 int* nchgsides, /**< pointer to count the number of left and right hand sides */
4464 int* ndelconss, /**< pointer to count the number of deleted constraints */
4465 int* naddconss /**< pointer to count the number of added constraints */
4466 )
4467{
4468 SCIP_VAR* vars[2];
4469 SCIP_CONS* newcons;
4470 SCIP_CONS* cons;
4471 SCIP_CONSDATA* consdata;
4472 int c;
4473
4474 assert(scip != NULL);
4475 assert(conshdlrdata != NULL);
4476 assert(conss != NULL || nconss == 0);
4477 assert(cutoff != NULL);
4478 assert(naggrvars != NULL);
4479 assert(nchgbds != NULL);
4480 assert(nchgcoefs != NULL);
4481 assert(nchgsides != NULL);
4482 assert(ndelconss != NULL);
4483 assert(naddconss != NULL);
4484
4485 /* if we cannot find any constraint for upgrading, stop */
4487 return SCIP_OKAY;
4488
4489 if( nconss == 0 )
4490 return SCIP_OKAY;
4491
4492 assert(conss != NULL);
4493
4494 for( c = nconss - 1; c >= 0; --c )
4495 {
4496 cons = conss[c];
4497 assert(cons != NULL);
4498
4499 if( !SCIPconsIsActive(cons) || SCIPconsGetNUpgradeLocks(cons) >= 1 )
4500 continue;
4501
4502 consdata = SCIPconsGetData(cons);
4503 assert(consdata != NULL);
4504 assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
4505
4506 if( !consdata->presolved )
4507 {
4508 /* incorporate fixings and aggregations in constraint */
4509 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, cutoff, nchgbds, ndelconss, naddconss) );
4510
4511 if( *cutoff )
4512 return SCIP_OKAY;
4513 if( !SCIPconsIsActive(cons) )
4514 continue;
4515 }
4516
4517 if( SCIPconsIsMarkedPropagate(cons) )
4518 {
4519 /* propagate constraint */
4520 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, cutoff, nchgbds, nchgsides, ndelconss) );
4521
4522 if( *cutoff )
4523 return SCIP_OKAY;
4524 if( !SCIPconsIsActive(cons) )
4525 continue;
4526 }
4527
4528 if( !consdata->tightened )
4529 {
4530 /* tighten variable bound coefficient */
4531 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4532
4533 if( *cutoff )
4534 return SCIP_OKAY;
4535 if( !SCIPconsIsActive(cons) )
4536 continue;
4537
4538 assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
4539 }
4540
4541 /* check if both variables are of binary type */
4542 if( SCIPvarIsBinary(consdata->vbdvar) && SCIPvarIsBinary(consdata->var) )
4543 {
4544 /* coefficient and sides should be tightened and we assume that the constraint is not redundant */
4545 assert(SCIPisEQ(scip, REALABS(consdata->vbdcoef), 1.0));
4546 assert(SCIPisZero(scip, consdata->rhs) || SCIPisEQ(scip, consdata->rhs, 1.0) || SCIPisInfinity(scip, consdata->rhs));
4547 assert(SCIPisZero(scip, consdata->lhs) || SCIPisEQ(scip, consdata->lhs, 1.0) || SCIPisInfinity(scip, -consdata->lhs));
4548 assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
4549
4550 /* the case x + y <= 1 or x + y >= 1 */
4551 if( consdata->vbdcoef > 0.0 )
4552 {
4553 if( SCIPisEQ(scip, consdata->rhs, 1.0) )
4554 {
4555 /* check for aggregations like x + y == 1 */
4556 if( SCIPisEQ(scip, consdata->lhs, 1.0) )
4557 {
4558 SCIP_Bool infeasible;
4559 SCIP_Bool redundant;
4560 SCIP_Bool aggregated;
4561
4562 SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> + <%s> == 1\n",
4563 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
4564
4565 /* aggregate both variables */
4566 SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
4567 assert(!infeasible);
4568 ++(*naggrvars);
4569
4570 SCIP_CALL( SCIPdelCons(scip, cons) );
4571 ++(*ndelconss);
4572
4573 continue;
4574 }
4575 assert(consdata->lhs < 0.5);
4576
4577 vars[0] = consdata->var;
4578 vars[1] = consdata->vbdvar;
4579 }
4580 else
4581 {
4582 assert(SCIPisEQ(scip, consdata->lhs, 1.0));
4583
4584 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
4585 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
4586 }
4587 }
4588 /* the case x - y <= 0 or x - y >= 0 */
4589 else
4590 {
4591 /* the case x - y <= 0 */
4592 if( SCIPisZero(scip, consdata->rhs) )
4593 {
4594 /* check for aggregations like x - y == 0 */
4595 if( SCIPisZero(scip, consdata->lhs) )
4596 {
4597 SCIP_Bool infeasible;
4598 SCIP_Bool redundant;
4599 SCIP_Bool aggregated;
4600
4601 SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> - <%s> == 0\n",
4602 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
4603
4604 /* aggregate both variables */
4605 SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
4606 assert(!infeasible);
4607 ++(*naggrvars);
4608
4609 SCIP_CALL( SCIPdelCons(scip, cons) );
4610 ++(*ndelconss);
4611
4612 continue;
4613 }
4614 assert(consdata->lhs < -0.5);
4615
4616 vars[0] = consdata->var;
4617 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
4618 }
4619 /* the case x - y >= 0 */
4620 else
4621 {
4622 assert(SCIPisZero(scip, consdata->lhs));
4623
4624 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
4625 vars[1] = consdata->vbdvar;
4626 }
4627 }
4628
4629 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
4634
4635 SCIPdebugMsg(scip, "upgraded varbound constraint <%s> to a set-packing constraint\n", SCIPconsGetName(cons));
4636 SCIPdebugPrintCons(scip, newcons, NULL);
4637
4638 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
4639 ++(*naddconss);
4640
4641 SCIP_CALL( SCIPdelCons(scip, cons) );
4642 ++(*ndelconss);
4643 }
4644 }
4645
4646 return SCIP_OKAY;
4647}
4648
4649/**@} */
4650
4651
4652/**@name Linear constraint upgrading
4653 *
4654 * @{
4655 */
4656
4657/** tries to upgrade a linear constraint into a variable bound constraint */
4658static
4659SCIP_DECL_LINCONSUPGD(linconsUpgdVarbound)
4660{ /*lint --e{715}*/
4661 SCIP_Bool upgrade;
4662
4663 assert(upgdcons != NULL);
4664
4665 /* check, if linear constraint can be upgraded to a variable bound constraint lhs <= x + a*y <= rhs
4666 * - there are exactly two variables
4667 * - one of the variables is non-binary (called the bounded variable x)
4668 * - one of the variables is non-continuous (called the bounding variable y)
4669 */
4670 upgrade = (nvars == 2) && (nposbin + nnegbin <= 1) && (nposcont + nnegcont <= 1);
4671
4672 if( upgrade )
4673 {
4674 SCIP_VAR* var;
4675 SCIP_VAR* vbdvar;
4676 SCIP_Real vbdcoef;
4677 SCIP_Real vbdlhs;
4678 SCIP_Real vbdrhs;
4681 int vbdind;
4682
4683 /* decide which variable we want to use as bounding variable y */
4684 if( zerotype < onetype )
4685 vbdind = 0;
4686 else if( zerotype > onetype )
4687 vbdind = 1;
4688 else if( SCIPisIntegral(scip, vals[0]) && !SCIPisIntegral(scip, vals[1]) )
4689 vbdind = 0;
4690 else if( !SCIPisIntegral(scip, vals[0]) && SCIPisIntegral(scip, vals[1]) )
4691 vbdind = 1;
4692 else if( REALABS(REALABS(vals[0]) - 1.0) < REALABS(REALABS(vals[1]) - 1.0) )
4693 vbdind = 1;
4694 else
4695 vbdind = 0;
4696
4697 /* do not upgrade when it is numerical unstable */
4698 if( SCIPisZero(scip, vals[vbdind]/vals[1-vbdind]) )
4699 return SCIP_OKAY;
4700
4701 SCIPdebugMsg(scip, "upgrading constraint <%s> to variable bound constraint\n", SCIPconsGetName(cons));
4702
4703 var = vars[1-vbdind];
4704 vbdvar = vars[vbdind];
4705
4706 assert(!SCIPisZero(scip, vals[1-vbdind]));
4707 vbdcoef = vals[vbdind]/vals[1-vbdind];
4708
4709 if( vals[1-vbdind] > 0.0 )
4710 {
4711 vbdlhs = SCIPisInfinity(scip, -lhs) ? -SCIPinfinity(scip) : lhs/vals[1-vbdind];
4712 vbdrhs = SCIPisInfinity(scip, rhs) ? SCIPinfinity(scip) : rhs/vals[1-vbdind];
4713 }
4714 else
4715 {
4716 vbdlhs = SCIPisInfinity(scip, rhs) ? -SCIPinfinity(scip) : rhs/vals[1-vbdind];
4717 vbdrhs = SCIPisInfinity(scip, -lhs) ? SCIPinfinity(scip) : lhs/vals[1-vbdind];
4718 }
4719
4720 /* create the bin variable bound constraint (an automatically upgraded constraint is always unmodifiable) */
4721 assert(!SCIPconsIsModifiable(cons));
4722 SCIP_CALL( SCIPcreateConsVarbound(scip, upgdcons, SCIPconsGetName(cons), var, vbdvar, vbdcoef, vbdlhs, vbdrhs,
4727 }
4728
4729 return SCIP_OKAY;
4730}
4731
4732/** adds symmetry information of constraint to a symmetry detection graph */
4733static
4735 SCIP* scip, /**< SCIP pointer */
4736 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
4737 SCIP_CONS* cons, /**< constraint */
4738 SYM_GRAPH* graph, /**< symmetry detection graph */
4739 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
4740 )
4741{
4742 SCIP_VAR** vars;
4743 SCIP_Real* vals;
4744 SCIP_Real constant = 0.0;
4745 SCIP_Real lhs;
4746 SCIP_Real rhs;
4747 int nlocvars;
4748 int nvars;
4749
4750 assert(scip != NULL);
4751 assert(cons != NULL);
4752 assert(graph != NULL);
4753 assert(success != NULL);
4754
4755 /* get active variables of the constraint */
4756 nvars = SCIPgetNVars(scip);
4757 nlocvars = 2;
4758
4759 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
4760 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
4761
4762 vars[0] = SCIPgetVarVarbound(scip, cons);
4763 vars[1] = SCIPgetVbdvarVarbound(scip, cons);
4764 vals[0] = 1.0;
4765 vals[1] = SCIPgetVbdcoefVarbound(scip, cons);
4766
4767 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
4768 lhs = SCIPgetLhsVarbound(scip, cons) - constant;
4769 rhs = SCIPgetRhsVarbound(scip, cons) - constant;
4770
4771 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
4772 cons, lhs, rhs, success) );
4773
4774 SCIPfreeBufferArray(scip, &vals);
4775 SCIPfreeBufferArray(scip, &vars);
4776
4777 return SCIP_OKAY;
4778}
4779
4780/**@} */
4781
4782
4783/**@name Callback methods
4784 *
4785 * @{
4786 */
4787
4788/** copy method for constraint handler plugins (called when SCIP copies plugins) */
4789static
4790SCIP_DECL_CONSHDLRCOPY(conshdlrCopyVarbound)
4791{ /*lint --e{715}*/
4792 assert(scip != NULL);
4793 assert(conshdlr != NULL);
4794 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4795
4796 /* call inclusion method of constraint handler */
4798
4799 *valid = TRUE;
4800
4801 return SCIP_OKAY;
4802}
4803
4804/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
4805static
4806SCIP_DECL_CONSFREE(consFreeVarbound)
4807{ /*lint --e{715}*/
4808 SCIP_CONSHDLRDATA* conshdlrdata;
4809
4810 assert(scip != NULL);
4811 assert(conshdlr != NULL);
4812 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4813
4814 /* free constraint handler data */
4815 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4816 assert(conshdlrdata != NULL);
4817
4818 conshdlrdataFree(scip, &conshdlrdata);
4819
4820 SCIPconshdlrSetData(conshdlr, NULL);
4821
4822 return SCIP_OKAY;
4823}
4824
4825/** solving process initialization method of constraint handler */
4826static
4827SCIP_DECL_CONSINITSOL(consInitsolVarbound)
4828{ /*lint --e{715}*/
4829 /* add nlrow representation to NLP, if NLP had been constructed */
4831 {
4832 int c;
4833 for( c = 0; c < nconss; ++c )
4834 {
4835 SCIP_CALL( addNlrow(scip, conss[c]) );
4836 }
4837 }
4838
4839 return SCIP_OKAY;
4840}
4841
4842/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4843static
4844SCIP_DECL_CONSEXITSOL(consExitsolVarbound)
4845{ /*lint --e{715}*/
4846 SCIP_CONSDATA* consdata;
4847 int c;
4848
4849 /* release the rows and nlrows of all constraints */
4850 for( c = 0; c < nconss; ++c )
4851 {
4852 consdata = SCIPconsGetData(conss[c]);
4853 assert(consdata != NULL);
4854
4855 if( consdata->row != NULL )
4856 {
4857 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
4858 }
4859
4860 if( consdata->nlrow != NULL )
4861 {
4862 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
4863 }
4864 }
4865
4866 return SCIP_OKAY;
4867}
4868
4869
4870/** frees specific constraint data */
4871static
4872SCIP_DECL_CONSDELETE(consDeleteVarbound)
4873{ /*lint --e{715}*/
4874 SCIP_CONSHDLRDATA* conshdlrdata;
4875
4876 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4877 assert(conshdlrdata != NULL);
4878
4879 /* drop events */
4880 if( SCIPisTransformed(scip) )
4881 {
4882 SCIP_CALL( dropEvents(scip, cons, conshdlrdata->eventhdlr) );
4883 }
4884
4885 SCIP_CALL( consdataFree(scip, consdata) );
4886
4887 return SCIP_OKAY;
4888}
4889
4890
4891/** transforms constraint data into data belonging to the transformed problem */
4892static
4893SCIP_DECL_CONSTRANS(consTransVarbound)
4894{ /*lint --e{715}*/
4895 SCIP_CONSHDLRDATA* conshdlrdata;
4896 SCIP_CONSDATA* sourcedata;
4897 SCIP_CONSDATA* targetdata;
4898
4899 assert(conshdlr != NULL);
4900
4901 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4902 assert(conshdlrdata != NULL);
4903
4904 sourcedata = SCIPconsGetData(sourcecons);
4905 assert(sourcedata != NULL);
4906
4907 /* create target constraint data */
4908 SCIP_CALL( consdataCreate(scip, &targetdata,
4909 sourcedata->var, sourcedata->vbdvar, sourcedata->vbdcoef, sourcedata->lhs, sourcedata->rhs) );
4910
4911 /* create target constraint */
4912 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
4913 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
4914 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
4915 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
4916 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
4917
4918 /* catch events for variables */
4919 SCIP_CALL( catchEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
4920
4921 return SCIP_OKAY;
4922}
4923
4924
4925/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
4926static
4927SCIP_DECL_CONSINITLP(consInitlpVarbound)
4928{ /*lint --e{715}*/
4929 int i;
4930
4931 *infeasible = FALSE;
4932
4933 for( i = 0; i < nconss && !(*infeasible); i++ )
4934 {
4935 assert(SCIPconsIsInitial(conss[i]));
4936 SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
4937 }
4938
4939 return SCIP_OKAY;
4940}
4941
4942
4943/** separation method of constraint handler for LP solutions */
4944static
4945SCIP_DECL_CONSSEPALP(consSepalpVarbound)
4946{ /*lint --e{715}*/
4947 SCIP_CONSHDLRDATA* conshdlrdata;
4948 int i;
4949
4950 assert(conshdlr != NULL);
4951
4952 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4953 assert(conshdlrdata != NULL);
4954
4955 *result = SCIP_DIDNOTFIND;
4956
4957 /* separate useful constraints */
4958 for( i = 0; i < nusefulconss; ++i )
4959 {
4960 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
4961 }
4962
4963 /* separate remaining constraints */
4964 for( i = nusefulconss; i < nconss && *result == SCIP_DIDNOTFIND; ++i )
4965 {
4966 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
4967 }
4968
4969 return SCIP_OKAY;
4970}
4971
4972
4973/** separation method of constraint handler for arbitrary primal solutions */
4974static
4975SCIP_DECL_CONSSEPASOL(consSepasolVarbound)
4976{ /*lint --e{715}*/
4977 SCIP_CONSHDLRDATA* conshdlrdata;
4978 int i;
4979
4980 assert(conshdlr != NULL);
4981
4982 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4983 assert(conshdlrdata != NULL);
4984
4985 *result = SCIP_DIDNOTFIND;
4986
4987 /* separate useful constraints */
4988 for( i = 0; i < nusefulconss; ++i )
4989 {
4990 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4991 }
4992
4993 /* separate remaining constraints */
4994 for( i = nusefulconss; i < nconss && *result == SCIP_DIDNOTFIND; ++i )
4995 {
4996 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4997 }
4998
4999 return SCIP_OKAY;
5000}
5001
5002
5003/** constraint enforcing method of constraint handler for LP solutions */
5004static
5005SCIP_DECL_CONSENFOLP(consEnfolpVarbound)
5006{ /*lint --e{715}*/
5007 SCIP_CONSHDLRDATA* conshdlrdata;
5008 int i;
5009
5010 assert(conshdlr != NULL);
5011
5012 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5013 assert(conshdlrdata != NULL);
5014
5015 *result = SCIP_FEASIBLE;
5016
5017 for( i = 0; i < nconss; i++ )
5018 {
5019 if( !checkCons(scip, conss[i], NULL, FALSE) )
5020 {
5021 assert((*result) == SCIP_INFEASIBLE || (*result) == SCIP_FEASIBLE);
5022 (*result) = SCIP_INFEASIBLE;
5023
5024 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
5025
5026 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
5027 assert((*result) != SCIP_FEASIBLE);
5028
5029 if( (*result) != SCIP_INFEASIBLE )
5030 break;
5031 }
5032 else
5033 {
5034 /* increase age of constraint */
5035 SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
5036 }
5037 }
5038
5039 return SCIP_OKAY;
5040}
5041
5042
5043/** constraint enforcing method of constraint handler for relaxation solutions */
5044static
5045SCIP_DECL_CONSENFORELAX(consEnforelaxVarbound)
5046{ /*lint --e{715}*/
5047 SCIP_CONSHDLRDATA* conshdlrdata;
5048 int i;
5049
5050 assert(conshdlr != NULL);
5051
5052 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5053 assert(conshdlrdata != NULL);
5054
5055 *result = SCIP_FEASIBLE;
5056
5057 for( i = 0; i < nconss; i++ )
5058 {
5059 if( !checkCons(scip, conss[i], sol, FALSE) )
5060 {
5061 assert((*result) == SCIP_INFEASIBLE || (*result) == SCIP_FEASIBLE);
5062 (*result) = SCIP_INFEASIBLE;
5063
5064 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
5065
5066 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
5067 assert((*result) != SCIP_FEASIBLE);
5068
5069 if( (*result) != SCIP_INFEASIBLE )
5070 break;
5071 }
5072 else
5073 {
5074 /* increase age of constraint */
5075 SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
5076 }
5077 }
5078
5079 return SCIP_OKAY;
5080}
5081
5082
5083/** constraint enforcing method of constraint handler for pseudo solutions */
5084static
5085SCIP_DECL_CONSENFOPS(consEnfopsVarbound)
5086{ /*lint --e{715}*/
5087 int i;
5088
5089 for( i = 0; i < nconss; i++ )
5090 {
5091 if( !checkCons(scip, conss[i], NULL, TRUE) )
5092 {
5093 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
5094
5095 *result = SCIP_INFEASIBLE;
5096 return SCIP_OKAY;
5097 }
5098 else
5099 {
5100 /* increase age of constraint */
5101 SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
5102 }
5103 }
5104 *result = SCIP_FEASIBLE;
5105
5106 return SCIP_OKAY;
5107}
5108
5109
5110/** feasibility check method of constraint handler for integral solutions */
5111static
5112SCIP_DECL_CONSCHECK(consCheckVarbound)
5113{ /*lint --e{715}*/
5114 int i;
5115
5116 *result = SCIP_FEASIBLE;
5117
5118 for( i = 0; i < nconss && (*result == SCIP_FEASIBLE || completely); i++ )
5119 {
5120 if( !checkCons(scip, conss[i], sol, checklprows) )
5121 {
5122 *result = SCIP_INFEASIBLE;
5123
5124 if( printreason )
5125 {
5126 SCIP_CONSDATA* consdata;
5127 SCIP_Real sum;
5128
5129 consdata = SCIPconsGetData(conss[i]);
5130 assert( consdata != NULL );
5131
5132 sum = SCIPgetSolVal(scip, sol, consdata->var) + consdata->vbdcoef * SCIPgetSolVal(scip, sol, consdata->vbdvar);
5133
5134 SCIP_CALL( SCIPprintCons(scip, conss[i], NULL) );
5135 SCIPinfoMessage(scip, NULL, ";\n");
5136
5137 if( !SCIPisFeasGE(scip, sum, consdata->lhs) )
5138 {
5139 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - sum);
5140 }
5141 if( !SCIPisFeasLE(scip, sum, consdata->rhs) )
5142 {
5143 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", sum - consdata->rhs);
5144 }
5145 }
5146 }
5147 }
5148
5149 return SCIP_OKAY;
5150}
5151
5152
5153/** domain propagation method of constraint handler */
5154static
5155SCIP_DECL_CONSPROP(consPropVarbound)
5156{ /*lint --e{715}*/
5157 SCIP_CONSHDLRDATA* conshdlrdata;
5158 SCIP_Bool cutoff;
5159 int nchgbds = 0;
5160 int nchgsides = 0;
5161 int i;
5162
5163 assert(conshdlr != NULL);
5164
5165 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5166 assert(conshdlrdata != NULL);
5167
5168 cutoff = FALSE;
5169
5170 SCIPdebugMsg(scip, "propagating %d variable bound constraints\n", nmarkedconss);
5171
5172 /* process constraints marked for propagation */
5173 for( i = 0; i < nmarkedconss && !cutoff; i++ )
5174 {
5175 SCIP_CALL( propagateCons(scip, conss[i], conshdlrdata->usebdwidening, &cutoff, &nchgbds, &nchgsides, NULL) );
5176 }
5177
5178 if( cutoff )
5179 *result = SCIP_CUTOFF;
5180 else if( nchgbds > 0 )
5181 *result = SCIP_REDUCEDDOM;
5182 else
5183 *result = SCIP_DIDNOTFIND;
5184
5185 return SCIP_OKAY;
5186}
5187
5188
5189/** presolving method of constraint handler */
5190static
5191SCIP_DECL_CONSPRESOL(consPresolVarbound)
5192{ /*lint --e{715}*/
5193 SCIP_CONSHDLRDATA* conshdlrdata;
5194 SCIP_CONS* cons;
5195 SCIP_CONSDATA* consdata;
5196 SCIP_Bool cutoff;
5197 int oldnchgbds;
5198 int oldndelconss;
5199 int oldnaddconss;
5200 int oldnchgcoefs;
5201 int oldnchgsides;
5202 int oldnaggrvars;
5203 int i;
5204
5205 assert(scip != NULL);
5206 assert(conshdlr != NULL);
5207 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5208 assert(result != NULL);
5209
5210 /* get constraint handler data */
5211 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5212 assert(conshdlrdata != NULL);
5213
5214 cutoff = FALSE;
5215 oldnchgbds = *nchgbds;
5216 oldndelconss = *ndelconss;
5217 oldnaddconss = *naddconss;
5218 oldnchgcoefs = *nchgcoefs;
5219 oldnchgsides = *nchgsides;
5220 oldnaggrvars = *naggrvars;
5221
5222 for( i = 0; i < nconss; i++ )
5223 {
5224 cons = conss[i];
5225 assert(cons != NULL);
5226
5227 assert(!SCIPconsIsModifiable(cons));
5228
5229 consdata = SCIPconsGetData(cons);
5230 assert(consdata != NULL);
5231
5232 if( i % 1000 == 0 && SCIPisStopped(scip) )
5233 break;
5234
5235 /* force presolving the constraint in the initial round */
5236 if( nrounds == 0 )
5237 consdata->presolved = FALSE;
5238
5239 if( consdata->presolved )
5240 continue;
5241 consdata->presolved = TRUE;
5242
5243 /* incorporate fixings and aggregations in constraint */
5244 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &cutoff, nchgbds, ndelconss, naddconss) );
5245
5246 if( cutoff )
5247 break;
5248 if( !SCIPconsIsActive(cons) )
5249 continue;
5250
5251 /* propagate constraint */
5252 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, &cutoff, nchgbds, nchgsides, ndelconss) );
5253
5254 if( cutoff )
5255 break;
5256 if( !SCIPconsIsActive(cons) )
5257 continue;
5258
5259 /* tighten variable bound coefficient */
5260 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
5261 if( cutoff )
5262 break;
5263 if( !SCIPconsIsActive(cons) )
5264 continue;
5265
5266 /* informs once variable x about a globally valid variable lower or upper bound */
5267 if( !consdata->varboundsadded )
5268 {
5269 SCIP_Bool infeasible;
5270 int nlocalchgbds;
5271 int localoldnchgbds;
5272
5273 localoldnchgbds = *nchgbds;
5274
5275 /* if lhs is finite, we have a variable lower bound: lhs <= x + c*y => x >= -c*y + lhs */
5276 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, REALABS(consdata->vbdcoef)) )
5277 {
5278 SCIPdebugMsg(scip, "adding variable lower bound <%s> >= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
5279 SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->lhs,
5280 SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? ">=" : "<="), 1.0/-consdata->vbdcoef,
5281 SCIPvarGetName(consdata->var), consdata->lhs/consdata->vbdcoef);
5282
5283 SCIP_CALL( SCIPaddVarVlb(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->lhs,
5284 &infeasible, &nlocalchgbds) );
5285 assert(!infeasible);
5286
5287 *nchgbds += nlocalchgbds;
5288 }
5289
5290 /* if rhs is finite, we have a variable upper bound: x + c*y <= rhs => x <= -c*y + rhs */
5291 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, REALABS(consdata->vbdcoef)) )
5292 {
5293 SCIPdebugMsg(scip, "adding variable upper bound <%s> <= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
5294 SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
5295 SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? "<=" : ">="), 1.0/-consdata->vbdcoef,
5296 SCIPvarGetName(consdata->var), consdata->rhs/consdata->vbdcoef);
5297
5298 SCIP_CALL( SCIPaddVarVub(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->rhs,
5299 &infeasible, &nlocalchgbds) );
5300 assert(!infeasible);
5301
5302 *nchgbds += nlocalchgbds;
5303 }
5304 consdata->varboundsadded = TRUE;
5305
5306 if( *nchgbds > localoldnchgbds )
5307 {
5308 /* tighten variable bound coefficient */
5309 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
5310 if( cutoff )
5311 break;
5312 }
5313 }
5314 }
5315
5316 if( !cutoff )
5317 {
5318 /* for varbound constraint with two integer variables make coefficients integral */
5319 prettifyConss(scip, conss, nconss, nchgcoefs, nchgsides);
5320
5321 /* check if we can upgrade to a set-packing constraint */
5322 SCIP_CALL( upgradeConss(scip, conshdlrdata, conss, nconss, &cutoff, naggrvars, nchgbds, nchgcoefs, nchgsides, ndelconss, naddconss) );
5323
5324 if( !cutoff && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
5325 {
5326 /* preprocess pairs of variable bound constraints */
5327 SCIP_CALL( preprocessConstraintPairs(scip, conss, nconss, &cutoff, nchgbds, ndelconss, nchgcoefs, nchgsides) );
5328 }
5329 }
5330
5331 /* return the correct result code */
5332 if( cutoff )
5333 *result = SCIP_CUTOFF;
5334 else if( *nchgbds > oldnchgbds || *ndelconss > oldndelconss || *naddconss > oldnaddconss
5335 || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides || *naggrvars > oldnaggrvars )
5336 *result = SCIP_SUCCESS;
5337 else
5338 *result = SCIP_DIDNOTFIND;
5339
5340 return SCIP_OKAY;
5341}
5342
5343
5344/** propagation conflict resolving method of constraint handler */
5345static
5346SCIP_DECL_CONSRESPROP(consRespropVarbound)
5347{ /*lint --e{715}*/
5348 SCIP_CONSHDLRDATA* conshdlrdata;
5349
5350 assert(conshdlr != NULL);
5351
5352 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5353 assert(conshdlrdata != NULL);
5354
5355 SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, boundtype, bdchgidx, relaxedbd, conshdlrdata->usebdwidening) );
5356
5357 *result = SCIP_SUCCESS;
5358
5359 return SCIP_OKAY;
5360}
5361
5362
5363/** variable rounding lock method of constraint handler */
5364static
5365SCIP_DECL_CONSLOCK(consLockVarbound)
5366{ /*lint --e{715}*/
5367 SCIP_CONSDATA* consdata;
5368
5369 consdata = SCIPconsGetData(cons);
5370 assert(consdata != NULL);
5371
5372 if( !SCIPisInfinity(scip, -consdata->lhs) )
5373 {
5374 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->var, locktype, nlockspos, nlocksneg) );
5375 if( consdata->vbdcoef > 0.0 )
5376 {
5377 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlockspos, nlocksneg) );
5378 }
5379 else
5380 {
5381 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlocksneg, nlockspos) );
5382 }
5383 }
5384
5385 if( !SCIPisInfinity(scip, consdata->rhs) )
5386 {
5387 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->var, locktype, nlocksneg, nlockspos) );
5388 if( consdata->vbdcoef > 0.0 )
5389 {
5390 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlocksneg, nlockspos) );
5391 }
5392 else
5393 {
5394 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlockspos, nlocksneg) );
5395 }
5396 }
5397
5398 return SCIP_OKAY;
5399}
5400
5401/** constraint activation notification method of constraint handler */
5402static
5403SCIP_DECL_CONSACTIVE(consActiveVarbound)
5404{ /*lint --e{715}*/
5406 {
5407 SCIP_CALL( addNlrow(scip, cons) );
5408 }
5409
5410 return SCIP_OKAY;
5411}
5412
5413/** constraint deactivation notification method of constraint handler */
5414static
5415SCIP_DECL_CONSDEACTIVE(consDeactiveVarbound)
5416{ /*lint --e{715}*/
5417 SCIP_CONSDATA* consdata;
5418
5419 assert(cons != NULL);
5420
5421 consdata = SCIPconsGetData(cons);
5422 assert(consdata != NULL);
5423
5424 /* remove row from NLP, if still in solving
5425 * if we are in exitsolve, the whole NLP will be freed anyway
5426 */
5427 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
5428 {
5429 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
5430 }
5431
5432 return SCIP_OKAY;
5433}
5434
5435/** constraint display method of constraint handler */
5436static
5437SCIP_DECL_CONSPRINT(consPrintVarbound)
5438{ /*lint --e{715}*/
5439 SCIP_CONSDATA* consdata;
5440
5441 assert(scip != NULL);
5442 assert(conshdlr != NULL);
5443 assert(cons != NULL);
5444
5445 consdata = SCIPconsGetData(cons);
5446 assert(consdata != NULL);
5447
5448 /* print left hand side for ranged rows */
5449 if( !SCIPisInfinity(scip, -consdata->lhs)
5450 && !SCIPisInfinity(scip, consdata->rhs)
5451 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5452 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
5453
5454 /* print variables and coefficient */
5455 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->var, TRUE) );
5456 SCIPinfoMessage(scip, file, " %+.15g", consdata->vbdcoef);
5457 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vbdvar, TRUE) );
5458
5459 /* print right hand side */
5460 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5461 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
5462 else if( !SCIPisInfinity(scip, consdata->rhs) )
5463 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
5464 else if( !SCIPisInfinity(scip, -consdata->lhs) )
5465 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
5466 else
5467 SCIPinfoMessage(scip, file, " [free]");
5468
5469 return SCIP_OKAY;
5470}
5471
5472/** constraint copying method of constraint handler */
5473static
5474SCIP_DECL_CONSCOPY(consCopyVarbound)
5475{ /*lint --e{715}*/
5476 SCIP_VAR** vars;
5477 SCIP_Real* coefs;
5478 const char* consname;
5479
5480 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
5481 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, 2) );
5482
5483 vars[0] = SCIPgetVarVarbound(sourcescip, sourcecons);
5484 vars[1] = SCIPgetVbdvarVarbound(sourcescip, sourcecons);
5485
5486 coefs[0] = 1.0;
5487 coefs[1] = SCIPgetVbdcoefVarbound(sourcescip, sourcecons);
5488
5489 if( name != NULL )
5490 consname = name;
5491 else
5492 consname = SCIPconsGetName(sourcecons);
5493
5494 /* copy the varbound using the linear constraint copy method */
5495 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, 2, vars, coefs,
5496 SCIPgetLhsVarbound(sourcescip, sourcecons), SCIPgetRhsVarbound(sourcescip, sourcecons), varmap, consmap,
5497 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
5498
5499 SCIPfreeBufferArray(scip, &coefs);
5500 SCIPfreeBufferArray(scip, &vars);
5501
5502 return SCIP_OKAY;
5503}
5504
5505/** constraint parsing method of constraint handler */
5506static
5507SCIP_DECL_CONSPARSE(consParseVarbound)
5508{ /*lint --e{715}*/
5509 SCIP_VAR** vars;
5510 SCIP_Real* coefs;
5511 SCIP_Real lhs;
5512 SCIP_Real rhs;
5513 char* endstr;
5514 int requiredsize;
5515 int nvars;
5516
5517 assert(scip != NULL);
5518 assert(success != NULL);
5519 assert(str != NULL);
5520 assert(name != NULL);
5521 assert(cons != NULL);
5522
5523 /* set left and right hand side to their default values */
5524 lhs = -SCIPinfinity(scip);
5525 rhs = SCIPinfinity(scip);
5526
5527 (*success) = FALSE;
5528
5529 /* return of string empty */
5530 if( !*str )
5531 return SCIP_OKAY;
5532
5533 /* ignore whitespace */
5534 SCIP_CALL( SCIPskipSpace((char**)&str) );
5535
5536 if( isdigit((unsigned char)str[0]) || ((str[0] == '-' || str[0] == '+') && isdigit((unsigned char)str[1])) )
5537 {
5538 if( !SCIPparseReal(scip, str, &lhs, &endstr) )
5539 {
5540 SCIPerrorMessage("error parsing left hand side\n");
5541 return SCIP_OKAY;
5542 }
5543
5544 /* ignore whitespace */
5545 SCIP_CALL( SCIPskipSpace(&endstr) );
5546
5547 if( endstr[0] != '<' || endstr[1] != '=' )
5548 {
5549 SCIPerrorMessage("missing \"<=\" after left hand side(, found %c%c)\n", endstr[0], endstr[1]);
5550 return SCIP_OKAY;
5551 }
5552
5553 SCIPdebugMsg(scip, "found left hand side <%g>\n", lhs);
5554
5555 /* it was indeed a left-hand-side, so continue parsing after it */
5556 str = endstr + 2;
5557 }
5558
5559 /* pares x + c*y as linear sum */
5560 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
5561 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, 2) );
5562
5563 /* parse linear sum to get variables and coefficients */
5564 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, 2, &requiredsize, &endstr, success) );
5565
5566 if( requiredsize == 2 && *success )
5567 {
5568 SCIP_Real value;
5569
5570 assert(nvars == 2);
5571 assert(SCIPisEQ(scip, coefs[0], 1.0));
5572
5573 SCIPdebugMsg(scip, "found linear sum <%s> + %g <%s>\n", SCIPvarGetName(vars[0]), coefs[1], SCIPvarGetName(vars[1]));
5574
5575 /* ignore whitespace */
5576 SCIP_CALL( SCIPskipSpace(&endstr) );
5577
5578 str = endstr;
5579
5580 if( *str != '\0' && *(str+1) != '\0' && SCIPparseReal(scip, str+2, &value, &endstr) )
5581 {
5582 /* search for end of linear sum: either '<=', '>=', '==', or '[free]' */
5583 switch( *str )
5584 {
5585 case '<':
5586 assert(str[1] == '=');
5587 rhs = value;
5588 break;
5589 case '=':
5590 assert(str[1] == '=');
5591 assert(SCIPisInfinity(scip, -lhs));
5592 lhs = value;
5593 rhs = value;
5594 break;
5595 case '>':
5596 assert(str[1] == '=');
5597 assert(SCIPisInfinity(scip, -lhs));
5598 lhs = value;
5599 break;
5600 default:
5601 SCIPerrorMessage("missing relation symbol after linear sum\n");
5602 *success = FALSE;
5603 }
5604 }
5605 else if( strncmp(str, "[free]", 6) != 0 )
5606 *success = FALSE;
5607 }
5608
5609 if( *success )
5610 {
5611 SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, vars[0], vars[1], coefs[1], lhs, rhs,
5612 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
5613 }
5614
5615 /* free buffer arrays */
5616 SCIPfreeBufferArray(scip, &coefs);
5617 SCIPfreeBufferArray(scip, &vars);
5618
5619 return SCIP_OKAY;
5620}
5621
5622/** constraint method of constraint handler which returns the variables (if possible) */
5623static
5624SCIP_DECL_CONSGETVARS(consGetVarsVarbound)
5625{ /*lint --e{715}*/
5626 assert( success != NULL );
5627
5628 if( varssize < 2 )
5629 (*success) = FALSE;
5630 else
5631 {
5632 SCIP_CONSDATA* consdata;
5633 assert(cons != NULL);
5634 assert(vars != NULL);
5635
5636 consdata = SCIPconsGetData(cons);
5637 assert(consdata != NULL);
5638
5639 vars[0] = consdata->var;
5640 vars[1] = consdata->vbdvar;
5641 (*success) = TRUE;
5642 }
5643
5644 return SCIP_OKAY;
5645}
5646
5647/** constraint method of constraint handler which returns the number of variables (if possible) */
5648static
5649SCIP_DECL_CONSGETNVARS(consGetNVarsVarbound)
5650{ /*lint --e{715}*/
5651 (*nvars) = 2;
5652 (*success) = TRUE;
5653
5654 return SCIP_OKAY;
5655}
5656
5657/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
5658static
5659SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphVarbound)
5660{ /*lint --e{715}*/
5661 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
5662
5663 return SCIP_OKAY;
5664}
5665
5666/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
5667static
5668SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphVarbound)
5669{ /*lint --e{715}*/
5670 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
5671
5672 return SCIP_OKAY;
5673}
5674
5675/*
5676 * Event Handler
5677 */
5678
5679/** execution method of bound change event handler */
5680static
5681SCIP_DECL_EVENTEXEC(eventExecVarbound)
5682{ /*lint --e{715}*/
5683 SCIP_CONS* cons;
5684 SCIP_CONSDATA* consdata;
5685
5686 assert(event != NULL);
5687 cons = (SCIP_CONS*)eventdata;
5688 assert(cons != NULL);
5689 consdata = SCIPconsGetData(cons);
5690 assert(consdata != NULL);
5691
5693 {
5694 consdata->presolved = FALSE;
5695 }
5696 else
5697 {
5698 assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0);
5699
5700 consdata->presolved = FALSE;
5701 consdata->tightened = FALSE;
5702
5704 }
5705
5706 return SCIP_OKAY;
5707}
5708
5709/**@} */
5710
5711
5712/** creates the handler for variable bound constraints and includes it in SCIP */
5714 SCIP* scip /**< SCIP data structure */
5715 )
5716{
5717 SCIP_CONSHDLRDATA* conshdlrdata;
5718 SCIP_EVENTHDLR* eventhdlr;
5719 SCIP_CONSHDLR* conshdlr;
5720
5721 /* include event handler for bound change events */
5723 eventExecVarbound, NULL) );
5724
5725 /* create variable bound constraint handler data */
5726 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
5727
5728 /* include constraint handler */
5731 consEnfolpVarbound, consEnfopsVarbound, consCheckVarbound, consLockVarbound,
5732 conshdlrdata) );
5733 assert(conshdlr != NULL);
5734
5735 /* set non-fundamental callbacks via specific setter functions */
5736 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyVarbound, consCopyVarbound) );
5737 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveVarbound) );
5738 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveVarbound) );
5739 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteVarbound) );
5740 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolVarbound) );
5741 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolVarbound) );
5742 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeVarbound) );
5743 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsVarbound) );
5744 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsVarbound) );
5745 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpVarbound) );
5746 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseVarbound) );
5748 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintVarbound) );
5751 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropVarbound) );
5752 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpVarbound, consSepasolVarbound, CONSHDLR_SEPAFREQ,
5754 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransVarbound) );
5755 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxVarbound) );
5756 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphVarbound) );
5757 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphVarbound) );
5758
5759 if( SCIPfindConshdlr(scip,"linear") != NULL )
5760 {
5761 /* include the linear constraint to varbound constraint upgrade in the linear constraint handler */
5763 }
5764
5765 /* add varbound constraint handler parameters */
5767 "constraints/" CONSHDLR_NAME "/presolpairwise",
5768 "should pairwise constraint comparison be performed in presolving?",
5769 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
5771 "constraints/" CONSHDLR_NAME "/maxlpcoef",
5772 "maximum coefficient in varbound constraint to be added as a row into LP",
5773 &conshdlrdata->maxlpcoef, TRUE, DEFAULT_MAXLPCOEF, 0.0, 1e+20, NULL, NULL) );
5775 "constraints/" CONSHDLR_NAME "/usebdwidening", "should bound widening be used in conflict analysis?",
5776 &conshdlrdata->usebdwidening, FALSE, DEFAULT_USEBDWIDENING, NULL, NULL) );
5777
5778 return SCIP_OKAY;
5779}
5780
5781/** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
5782 *
5783 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5784 */
5786 SCIP* scip, /**< SCIP data structure */
5787 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5788 const char* name, /**< name of constraint */
5789 SCIP_VAR* var, /**< variable x that has variable bound */
5790 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
5791 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
5792 SCIP_Real lhs, /**< left hand side of variable bound inequality */
5793 SCIP_Real rhs, /**< right hand side of variable bound inequality */
5794 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
5795 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5796 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
5797 * Usually set to TRUE. */
5798 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
5799 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5800 SCIP_Bool check, /**< should the constraint be checked for feasibility?
5801 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5802 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
5803 * Usually set to TRUE. */
5804 SCIP_Bool local, /**< is constraint only valid locally?
5805 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5806 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
5807 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
5808 * adds coefficients to this constraint. */
5809 SCIP_Bool dynamic, /**< is constraint subject to aging?
5810 * Usually set to FALSE. Set to TRUE for own cuts which
5811 * are separated as constraints. */
5812 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
5813 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5814 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
5815 * if it may be moved to a more global node?
5816 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
5817 )
5818{
5819 SCIP_CONSHDLR* conshdlr;
5820 SCIP_CONSHDLRDATA* conshdlrdata;
5821 SCIP_CONSDATA* consdata;
5822
5823 /* check that the given parameters are sensible, i.e., not nan or inf */
5824 assert( SCIPisFinite(vbdcoef) );
5825 assert( SCIPisFinite(lhs) );
5826 assert( SCIPisFinite(rhs) );
5827
5828 /* find the variable bound constraint handler */
5829 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5830 if( conshdlr == NULL )
5831 {
5832 SCIPerrorMessage("variable bound constraint handler not found\n");
5833 return SCIP_PLUGINNOTFOUND;
5834 }
5835
5836 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5837 assert(conshdlrdata != NULL);
5838
5839 /* create constraint data */
5840 SCIP_CALL( consdataCreate(scip, &consdata, var, vbdvar, vbdcoef, lhs, rhs) );
5841
5842 /* create constraint */
5843 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5844 local, modifiable, dynamic, removable, stickingatnode) );
5845
5846 if( SCIPisTransformed(scip) )
5847 {
5848 /* catch events for variables */
5849 SCIP_CALL( catchEvents(scip, *cons, conshdlrdata->eventhdlr) );
5850 }
5851
5852 return SCIP_OKAY;
5853}
5854
5855/** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
5856 * with all constraint flags set to their default values
5857 *
5858 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5859 */
5861 SCIP* scip, /**< SCIP data structure */
5862 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5863 const char* name, /**< name of constraint */
5864 SCIP_VAR* var, /**< variable x that has variable bound */
5865 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
5866 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
5867 SCIP_Real lhs, /**< left hand side of variable bound inequality */
5868 SCIP_Real rhs /**< right hand side of variable bound inequality */
5869 )
5870{
5871 SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, var, vbdvar,vbdcoef, lhs, rhs,
5873
5874 return SCIP_OKAY;
5875}
5876
5877/** gets left hand side of variable bound constraint lhs <= x + c*y <= rhs */
5879 SCIP* scip, /**< SCIP data structure */
5880 SCIP_CONS* cons /**< constraint data */
5881 )
5882{
5883 SCIP_CONSDATA* consdata;
5884
5885 assert(scip != NULL);
5886
5887 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5888 {
5889 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5890 SCIPABORT();
5891 return SCIP_INVALID; /*lint !e527*/
5892 }
5893
5894 consdata = SCIPconsGetData(cons);
5895 assert(consdata != NULL);
5896
5897 return consdata->lhs;
5898}
5899
5900/** gets right hand side of variable bound constraint lhs <= x + c*y <= rhs */
5902 SCIP* scip, /**< SCIP data structure */
5903 SCIP_CONS* cons /**< constraint data */
5904 )
5905{
5906 SCIP_CONSDATA* consdata;
5907
5908 assert(scip != NULL);
5909
5910 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5911 {
5912 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5913 SCIPABORT();
5914 return SCIP_INVALID; /*lint !e527*/
5915 }
5916
5917 consdata = SCIPconsGetData(cons);
5918 assert(consdata != NULL);
5919
5920 return consdata->rhs;
5921}
5922
5923/** gets bounded variable x of variable bound constraint lhs <= x + c*y <= rhs */
5925 SCIP* scip, /**< SCIP data structure */
5926 SCIP_CONS* cons /**< constraint data */
5927 )
5928{
5929 SCIP_CONSDATA* consdata;
5930
5931 assert(scip != NULL);
5932
5933 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5934 {
5935 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5936 SCIPABORT();
5937 return NULL; /*lint !e527*/
5938 }
5939
5940 consdata = SCIPconsGetData(cons);
5941 assert(consdata != NULL);
5942
5943 return consdata->var;
5944}
5945
5946/** gets bounding variable y of variable bound constraint lhs <= x + c*y <= rhs */
5948 SCIP* scip, /**< SCIP data structure */
5949 SCIP_CONS* cons /**< constraint data */
5950 )
5951{
5952 SCIP_CONSDATA* consdata;
5953
5954 assert(scip != NULL);
5955
5956 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5957 {
5958 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5959 SCIPABORT();
5960 return NULL; /*lint !e527*/
5961 }
5962
5963 consdata = SCIPconsGetData(cons);
5964 assert(consdata != NULL);
5965
5966 return consdata->vbdvar;
5967}
5968
5969/** gets bound coefficient c of variable bound constraint lhs <= x + c*y <= rhs */
5971 SCIP* scip, /**< SCIP data structure */
5972 SCIP_CONS* cons /**< constraint data */
5973 )
5974{
5975 SCIP_CONSDATA* consdata;
5976
5977 assert(scip != NULL);
5978
5979 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5980 {
5981 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5982 SCIPABORT();
5983 return SCIP_INVALID; /*lint !e527*/
5984 }
5985
5986 consdata = SCIPconsGetData(cons);
5987 assert(consdata != NULL);
5988
5989 return consdata->vbdcoef;
5990}
5991
5992/** gets the dual solution of the variable bound constraint in the current LP */
5994 SCIP* scip, /**< SCIP data structure */
5995 SCIP_CONS* cons /**< constraint data */
5996 )
5997{
5998 SCIP_CONSDATA* consdata;
5999
6000 assert(scip != NULL);
6001
6002 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
6003 {
6004 SCIPerrorMessage("constraint is not a variable bound constraint\n");
6005 SCIPABORT();
6006 return SCIP_INVALID; /*lint !e527*/
6007 }
6008
6009 consdata = SCIPconsGetData(cons);
6010 assert(consdata != NULL);
6011
6012 if( consdata->row != NULL )
6013 return SCIProwGetDualsol(consdata->row);
6014 else
6015 return 0.0;
6016}
6017
6018/** gets the dual Farkas value of the variable bound constraint in the current infeasible LP */
6020 SCIP* scip, /**< SCIP data structure */
6021 SCIP_CONS* cons /**< constraint data */
6022 )
6023{
6024 SCIP_CONSDATA* consdata;
6025
6026 assert(scip != NULL);
6027
6028 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
6029 {
6030 SCIPerrorMessage("constraint is not a variable bound constraint\n");
6031 SCIPABORT();
6032 return SCIP_INVALID; /*lint !e527*/
6033 }
6034
6035 consdata = SCIPconsGetData(cons);
6036 assert(consdata != NULL);
6037
6038 if( consdata->row != NULL )
6039 return SCIProwGetDualfarkas(consdata->row);
6040 else
6041 return 0.0;
6042}
6043
6044/** returns the linear relaxation of the given variable bound constraint; may return NULL if no LP row was yet created;
6045 * the user must not modify the row!
6046 */
6048 SCIP* scip, /**< SCIP data structure */
6049 SCIP_CONS* cons /**< constraint data */
6050 )
6051{
6052 SCIP_CONSDATA* consdata;
6053
6054 assert(scip != NULL);
6055
6056 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
6057 {
6058 SCIPerrorMessage("constraint is not a variable bound constraint\n");
6059 SCIPABORT();
6060 return NULL; /*lint !e527*/
6061 }
6062
6063 consdata = SCIPconsGetData(cons);
6064 assert(consdata != NULL);
6065
6066 return consdata->row;
6067}
6068
6069/** creates and returns the row of the given varbound constraint */
6071 SCIP* scip, /**< SCIP data structure */
6072 SCIP_CONS* cons /**< constraint data */
6073 )
6074{
6075 SCIP_CONSDATA* consdata;
6076
6077 assert(scip != NULL);
6078
6079 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
6080 {
6081 SCIPerrorMessage("constraint is not a variable bound constraint\n");
6082 SCIPABORT();
6083 return SCIP_ERROR; /*lint !e527*/
6084 }
6085
6086 consdata = SCIPconsGetData(cons);
6087 assert(consdata != NULL);
6088 assert(consdata->row == NULL);
6089
6090 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
6092 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->var, 1.0) );
6093 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->vbdvar, consdata->vbdcoef) );
6094
6095 return SCIP_OKAY;
6096}
6097
6098/** cleans up (multi-)aggregations and fixings from varbound constraints */
6100 SCIP* scip, /**< SCIP data structure */
6101 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
6102 SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
6103 int* naddconss, /**< pointer to count number of added (linear) constraints */
6104 int* ndelconss, /**< pointer to count number of deleted (varbound) constraints */
6105 int* nchgbds /**< pointer to count number of bound changes */
6106 )
6107{
6108 SCIP_CONSHDLR* conshdlr;
6109 SCIP_CONSHDLRDATA* conshdlrdata;
6110 SCIP_EVENTHDLR* eventhdlr;
6111 SCIP_CONS** conss;
6112 int nconss;
6113 int i;
6114
6115 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
6116 if( conshdlr == NULL )
6117 return SCIP_OKAY;
6118
6119 assert(infeasible != NULL);
6120 *infeasible = FALSE;
6121
6122 assert(naddconss != NULL);
6123 assert(ndelconss != NULL);
6124 assert(nchgbds != NULL);
6125
6126 conshdlrdata = SCIPconshdlrGetData(conshdlr);
6127 assert(conshdlrdata != NULL);
6128
6129 eventhdlr = conshdlrdata->eventhdlr;
6130 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
6131 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
6132
6133 /* loop backwards since then deleted constraints do not interfere with the loop */
6134 for( i = nconss - 1; i >= 0; --i )
6135 {
6136 SCIP_CALL( applyFixings(scip, conss[i], eventhdlr, infeasible, nchgbds, ndelconss, naddconss) );
6137
6138 if( *infeasible )
6139 break;
6140 }
6141
6142 return SCIP_OKAY;
6143}
static long bound
enum Proprule PROPRULE
Definition: cons_and.c:173
Proprule
Definition: cons_and.c:166
Constraint handler for linear constraints in their most general form, .
Constraint handler for the set partitioning / packing / covering constraints .
static SCIP_DECL_CONSCHECK(consCheckVarbound)
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static SCIP_DECL_CONSRESPROP(consRespropVarbound)
enum Proprule PROPRULE
static SCIP_DECL_SORTPTRCOMP(consVarboundComp)
static SCIP_RETCODE dropEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
#define DEFAULT_USEBDWIDENING
#define CONSHDLR_NEEDSCONS
#define CONSHDLR_SEPAFREQ
Definition: cons_varbound.c:93
static SCIP_DECL_EVENTEXEC(eventExecVarbound)
static SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphVarbound)
static SCIP_DECL_CONSACTIVE(consActiveVarbound)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_varbound.c:92
#define CONSHDLR_DESC
Definition: cons_varbound.c:89
static SCIP_DECL_CONSINITSOL(consInitsolVarbound)
static SCIP_DECL_CONSPROP(consPropVarbound)
static SCIP_DECL_CONSLOCK(consLockVarbound)
static SCIP_RETCODE upgradeConss(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *naggrvars, int *nchgbds, int *nchgcoefs, int *nchgsides, int *ndelconss, int *naddconss)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nchgbds, int *ndelconss, int *naddconss)
static SCIP_DECL_CONSPRESOL(consPresolVarbound)
static SCIP_DECL_CONSGETNVARS(consGetNVarsVarbound)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs)
static SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphVarbound)
static SCIP_RETCODE tightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, int *ndelconss, SCIP_Bool *cutoff, int *nchgbds)
static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSEXITSOL(consExitsolVarbound)
#define CONSHDLR_PROP_TIMING
static void checkRedundancySide(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real coef0, SCIP_Real coef1, SCIP_Real side0, SCIP_Real side1, SCIP_Bool *sideequal, SCIP_Bool *cons0sidered, SCIP_Bool *cons1sidered, SCIP_Bool islhs)
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
static SCIP_DECL_CONSGETVARS(consGetVarsVarbound)
static SCIP_DECL_CONSCOPY(consCopyVarbound)
#define CONSHDLR_MAXPREROUNDS
Definition: cons_varbound.c:97
static SCIP_Bool checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows)
#define DEFAULT_PRESOLPAIRWISE
static SCIP_DECL_CONSSEPASOL(consSepasolVarbound)
static SCIP_DECL_CONSFREE(consFreeVarbound)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_varbound.c:90
#define DEFAULT_MAXLPCOEF
static SCIP_DECL_CONSPRINT(consPrintVarbound)
static void prettifyConss(SCIP *scip, SCIP_CONS **conss, int nconss, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE addSymmetryInformation(SCIP *scip, SYM_SYMTYPE symtype, SCIP_CONS *cons, SYM_GRAPH *graph, SCIP_Bool *success)
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds, int *ndelconss, int *nchgcoefs, int *nchgsides)
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
static SCIP_DECL_CONSDEACTIVE(consDeactiveVarbound)
@ PROPRULE_2
@ PROPRULE_1
@ PROPRULE_3
@ PROPRULE_4
static SCIP_DECL_CONSSEPALP(consSepalpVarbound)
static SCIP_DECL_CONSDELETE(consDeleteVarbound)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_Real inferbd, PROPRULE proprule, SCIP_BOUNDTYPE boundtype, SCIP_Bool usebdwidening)
static SCIP_DECL_CONSTRANS(consTransVarbound)
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
#define CONSHDLR_PROPFREQ
Definition: cons_varbound.c:94
static SCIP_DECL_CONSPARSE(consParseVarbound)
static SCIP_DECL_CONSENFOPS(consEnfopsVarbound)
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real inferbd, SCIP_Bool usebdwidening)
static SCIP_DECL_CONSENFORELAX(consEnforelaxVarbound)
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool usebdwidening, SCIP_Bool *cutoff, int *nchgbds, int *nchgsides, int *ndelconss)
#define CONSHDLR_PRESOLTIMING
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static SCIP_DECL_LINCONSUPGD(linconsUpgdVarbound)
static SCIP_DECL_CONSINITLP(consInitlpVarbound)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
#define CONSHDLR_EAGERFREQ
Definition: cons_varbound.c:95
#define EVENTHDLR_DESC
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static SCIP_DECL_CONSENFOLP(consEnfolpVarbound)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_varbound.c:91
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyVarbound)
static SCIP_RETCODE catchEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
#define LINCONSUPGD_PRIORITY
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool usebdwidening, SCIP_SOL *sol, SCIP_RESULT *result)
#define CONSHDLR_DELAYSEPA
Definition: cons_varbound.c:98
#define MAXSCALEDCOEF
#define CONSHDLR_NAME
Definition: cons_varbound.c:88
#define EVENTHDLR_NAME
#define CONSHDLR_DELAYPROP
Definition: cons_varbound.c:99
Constraint handler for variable bound constraints .
defines macros for basic operations in double-double arithmetic giving roughly twice the precision of...
#define SCIPquadprecDivQD(r, a, b)
Definition: dbldblarith.h:65
#define SCIPquadprecProdDD(r, a, b)
Definition: dbldblarith.h:58
#define SCIPquadprecProdQD(r, a, b)
Definition: dbldblarith.h:63
#define SCIPquadprecSumQD(r, a, b)
Definition: dbldblarith.h:62
#define QUAD_ASSIGN(a, constant)
Definition: dbldblarith.h:51
#define QUAD(x)
Definition: dbldblarith.h:47
#define SCIPquadprecSumDD(r, a, b)
Definition: dbldblarith.h:60
#define SCIPquadprecSumQQ(r, a, b)
Definition: dbldblarith.h:67
#define QUAD_TO_DBL(x)
Definition: dbldblarith.h:49
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define SCIP_UNKNOWN
Definition: def.h:179
#define ABS(x)
Definition: def.h:216
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIPABORT()
Definition: def.h:327
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_Real SCIPgetDualfarkasVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPcreateConsBasicVarbound(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs)
SCIP_ROW * SCIPgetRowVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:9460
SCIP_RETCODE SCIPcleanupConssVarbound(SCIP *scip, SCIP_Bool onlychecked, SCIP_Bool *infeasible, int *naddconss, int *ndelconss, int *nchgbds)
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetDualsolVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsVarbound(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, 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 SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_RETCODE SCIPcreateRowVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeConshdlrVarbound(SCIP *scip)
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:647
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2340
SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
Definition: scip_prob.c:3368
int SCIPgetNImplVars(SCIP *scip)
Definition: scip_prob.c:2387
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 SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2293
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:4067
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition: misc.c:9470
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11162
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 SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPaddConflictRelaxedLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedlb)
SCIP_RETCODE SCIPaddConflictRelaxedUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedub)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_Real SCIPgetConflictVarUb(SCIP *scip, SCIP_VAR *var)
SCIP_Real SCIPgetConflictVarLb(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4798
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_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4755
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 SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip_cons.c:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:281
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:181
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:693
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)))
Definition: scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:323
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c: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_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:468
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:444
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c: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
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4812
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4735
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:670
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8419
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 SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8841
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8598
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8588
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8518
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8698
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8578
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8450
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
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1812
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2014
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8638
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip_cons.c:1524
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8668
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8568
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8658
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:225
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:413
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1058
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition: nlp.c:1953
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition: scip_nlp.c:954
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1398
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2176
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2131
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1508
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17719
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17917
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17706
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1765
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:469
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:146
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6401
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:5210
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:8257
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5697
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition: var.c:23498
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip_var.c:10550
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:7069
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:5875
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:17550
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6651
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:2499
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
SCIP_RETCODE SCIPaddVarVub(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip_var.c:8680
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:23652
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:5118
SCIP_RETCODE SCIPaddVarVlb(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip_var.c:8621
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:5296
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:5634
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip_var.c:899
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition: scip_var.c:2378
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:5570
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
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
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:10318
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6964
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:361
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:2078
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1853
SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:8026
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10816
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
static const SCIP_Real scalars[]
Definition: lp.c:5959
memory allocation routines
SCIP_Longint denominator(Rational &r)
SCIP_Longint numerator(Rational &r)
public methods for managing constraints
public methods for managing events
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
public data structures and miscellaneous methods
#define SCIPisFinite(x)
Definition: pub_misc.h:82
methods for sorting joint arrays of various types
public methods for problem variables
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for the branch-and-bound tree
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
Definition: sepa_flower.c:1221
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:62
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:179
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:125
@ SCIP_EXPRCURV_LINEAR
Definition: type_expr.h:65
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_FEASIBLE
Definition: type_result.h:45
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_SEPARATED
Definition: type_result.h:49
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_INFEASIBLE
Definition: type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PRESOLVING
Definition: type_set.h:49
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53
enum SYM_Symtype SYM_SYMTYPE
Definition: type_symmetry.h:64
@ SYM_SYMTYPE_SIGNPERM
Definition: type_symmetry.h:62
@ SYM_SYMTYPE_PERM
Definition: type_symmetry.h:61
#define SCIP_PRESOLTIMING_MEDIUM
Definition: type_timing.h:53
#define SCIP_DEPRECATED_VARTYPE_IMPLINT
Definition: type_var.h:79
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:54
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73