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(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
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(SCIPvarGetType(consdata->vbdvar) != SCIP_VARTYPE_CONTINUOUS);
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(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
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(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
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(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
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_CONSDATA* consdata;
1461 SCIP_Real xlb;
1462 SCIP_Real xub;
1463 SCIP_Real ylb;
1464 SCIP_Real yub;
1465 SCIP_Real newlb;
1466 SCIP_Real newub;
1467 SCIP_Bool tightened;
1468 SCIP_Bool tightenedround;
1469
1470 assert(cutoff != NULL);
1471 assert(nchgbds != NULL);
1472
1473 consdata = SCIPconsGetData(cons);
1474 assert(consdata != NULL);
1475
1476 SCIPdebugMsg(scip, "propagating variable bound constraint <%s>: %.15g <= <%s>[%.9g, %.9g] + %.15g<%s>[%.9g, %.9g] <= %.15g\n",
1477 SCIPconsGetName(cons), consdata->lhs, SCIPvarGetName(consdata->var), SCIPvarGetLbLocal(consdata->var),
1478 SCIPvarGetUbLocal(consdata->var), consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
1479 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), consdata->rhs);
1480
1481 *cutoff = FALSE;
1482
1483 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1485 {
1486 SCIP_CALL( SCIPincConsAge(scip, cons) );
1487 }
1488
1489 /* get current bounds of variables */
1490 xlb = SCIPvarGetLbLocal(consdata->var);
1491 xub = SCIPvarGetUbLocal(consdata->var);
1492 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1493 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1494
1495 /* it can happen that constraint is of form lhs <= x <= rhs */
1496 if( SCIPisZero(scip, consdata->vbdcoef) && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1497 {
1498 SCIP_Bool infeasible;
1499 SCIP_Bool fixed;
1500
1501 SCIP_CALL( SCIPfixVar(scip, consdata->var, consdata->lhs, &infeasible, &fixed) );
1502
1503 if( infeasible )
1504 {
1505 SCIPdebugMsg(scip, "> constraint <%s> is infeasible.\n", SCIPconsGetName(cons));
1506 *cutoff = TRUE;
1507 return SCIP_OKAY;
1508 }
1509 }
1510
1511 /* tighten bounds of variables as long as possible */
1512 do
1513 {
1514 tightenedround = FALSE;
1515
1516 /* propagate left hand side inequality: lhs <= x + c*y */
1517 if( !SCIPisInfinity(scip, -consdata->lhs) )
1518 {
1519 assert(!(*cutoff));
1520
1521 /* propagate bounds on x:
1522 * (1) left hand side and bounds on y -> lower bound on x
1523 */
1524 if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1525 {
1526 if( consdata->vbdcoef > 0.0 )
1527 {
1528 if( !SCIPisInfinity(scip, yub) )
1529 {
1530 SCIP_Real QUAD(tmp);
1531
1532 SCIPquadprecProdDD(tmp, consdata->vbdcoef, yub);
1533 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1534
1535 newlb = SCIPadjustedVarLb(scip, consdata->var, QUAD_TO_DBL(tmp));
1536 }
1537 else
1538 {
1539 newlb = -SCIPinfinity(scip);
1540 }
1541 }
1542 else
1543 {
1544 if( !SCIPisInfinity(scip, -ylb) )
1545 {
1546 SCIP_Real QUAD(tmp);
1547
1548 SCIPquadprecProdDD(tmp, consdata->vbdcoef, ylb);
1549 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1550
1551 newlb = SCIPadjustedVarLb(scip, consdata->var, QUAD_TO_DBL(tmp));
1552 }
1553 else
1554 {
1555 newlb = -SCIPinfinity(scip);
1556 }
1557 }
1558
1559 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->var, newlb, cons, (int)PROPRULE_1, yub < ylb + 0.5, cutoff, &tightened) );
1560
1561 if( *cutoff )
1562 {
1563 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1564 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->var)));
1565
1567
1568 /* analyze infeasibility */
1569 SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newlb, PROPRULE_1, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1570 break;
1571 }
1572
1573 if( tightened )
1574 {
1575 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1576 tightenedround = TRUE;
1577 (*nchgbds)++;
1579 }
1580 xlb = SCIPvarGetLbLocal(consdata->var);
1581 }
1582
1583 assert(!*cutoff);
1584
1585 /* propagate bounds on y:
1586 * (2) left hand side and upper bound on x -> bound on y
1587 */
1588 if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, xub) ) /* cannot change bounds of multaggr vars */
1589 {
1590 if( consdata->vbdcoef > 0.0 )
1591 {
1592 SCIP_Real QUAD(tmp);
1593
1594 SCIPquadprecSumDD(tmp, consdata->lhs, -xub);
1595 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1596
1597 newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1598 if( newlb > ylb + 0.5 )
1599 {
1600 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1601
1602 if( *cutoff )
1603 {
1604 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1605 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)));
1606
1607 /* analyze infeasibility */
1608 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_2, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1609 break;
1610 }
1611
1612 if( tightened )
1613 {
1614 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1615 tightenedround = TRUE;
1616 (*nchgbds)++;
1617 }
1618 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1619 }
1620 }
1621 else
1622 {
1623 SCIP_Real QUAD(tmp);
1624
1625 SCIPquadprecSumDD(tmp, consdata->lhs, -xub);
1626 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1627
1628 newub = SCIPadjustedVarUb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1629
1630 if( newub < yub - 0.5 )
1631 {
1632 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1633
1634 if( *cutoff )
1635 {
1636 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1637 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)));
1638
1640
1641 /* analyze infeasibility */
1642 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_2, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1643 break;
1644 }
1645
1646 if( tightened )
1647 {
1648 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1649 tightenedround = TRUE;
1650 (*nchgbds)++;
1652 }
1653 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1654 }
1655 }
1656 }
1657 }
1658
1659 assert(!*cutoff);
1660
1661 /* propagate right hand side inequality: x + c*y <= rhs */
1662 if( !SCIPisInfinity(scip, consdata->rhs) )
1663 {
1664 /* propagate bounds on x:
1665 * (3) right hand side and bounds on y -> upper bound on x
1666 */
1667 if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1668 {
1669 if( consdata->vbdcoef > 0.0 )
1670 {
1671 if( !SCIPisInfinity(scip, -ylb) )
1672 {
1673 SCIP_Real QUAD(tmp);
1674
1675 SCIPquadprecProdDD(tmp, consdata->vbdcoef, ylb);
1676 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1677
1678 newub = SCIPadjustedVarUb(scip, consdata->var, QUAD_TO_DBL(tmp));
1679 }
1680 else
1681 {
1682 newub = SCIPinfinity(scip);
1683 }
1684 }
1685 else
1686 {
1687 if( !SCIPisInfinity(scip, yub) )
1688 {
1689 SCIP_Real QUAD(tmp);
1690
1691 SCIPquadprecProdDD(tmp, consdata->vbdcoef, yub);
1692 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1693
1694 newub = SCIPadjustedVarUb(scip, consdata->var, QUAD_TO_DBL(tmp));
1695 }
1696 else
1697 {
1698 newub = SCIPinfinity(scip);
1699 }
1700 }
1701
1702 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->var, newub, cons, (int)PROPRULE_3, yub < ylb + 0.5, cutoff, &tightened) );
1703
1704 if( *cutoff )
1705 {
1706 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1707 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->var)));
1708
1710
1711 /* analyze infeasibility */
1712 SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newub, PROPRULE_3, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1713 break;
1714 }
1715
1716 if( tightened )
1717 {
1718 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1719 tightenedround = TRUE;
1720 (*nchgbds)++;
1722 }
1723 xub = SCIPvarGetUbLocal(consdata->var);
1724 }
1725
1726 assert(!*cutoff);
1727
1728 /* propagate bounds on y:
1729 * (4) right hand side and lower bound on x -> bound on y
1730 */
1731 if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, -xlb) ) /* cannot change bounds of multaggr vars */
1732 {
1733 if( consdata->vbdcoef > 0.0 )
1734 {
1735 SCIP_Real QUAD(tmp);
1736
1737 SCIPquadprecSumDD(tmp, consdata->rhs, -xlb);
1738 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1739
1740 newub = SCIPadjustedVarUb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1741 if( newub < yub - 0.5 )
1742 {
1743 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1744
1745 if( *cutoff )
1746 {
1747 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1748 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)));
1749
1751
1752 /* analyze infeasibility */
1753 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_4, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1754 break;
1755 }
1756
1757 if( tightened )
1758 {
1759 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1760 tightenedround = TRUE;
1761 (*nchgbds)++;
1763 }
1764 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1765 }
1766 }
1767 else
1768 {
1769 SCIP_Real QUAD(tmp);
1770
1771 SCIPquadprecSumDD(tmp, consdata->rhs, -xlb);
1772 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1773
1774 newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1775 if( newlb > ylb + 0.5 )
1776 {
1777 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1778
1779 if( *cutoff )
1780 {
1781 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1782 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)));
1783
1785
1786 /* analyze infeasibility */
1787 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_4, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1788 break;
1789 }
1790
1791 if( tightened )
1792 {
1793 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1794 tightenedround = TRUE;
1795 (*nchgbds)++;
1797 }
1798 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1799 }
1800 }
1801 }
1802 }
1803 assert(!(*cutoff));
1804 }
1805 while( tightenedround );
1806
1807 /* check for redundant sides */
1808 if( !(*cutoff) && SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && !SCIPinProbing(scip) )
1809 {
1810 /* check left hand side for redundancy */
1811 if( !SCIPisInfinity(scip, -consdata->lhs) &&
1812 ((consdata->vbdcoef > 0.0 && SCIPisGE(scip, xlb + consdata->vbdcoef * ylb, consdata->lhs))
1813 || (consdata->vbdcoef < 0.0 && SCIPisGE(scip, xlb + consdata->vbdcoef * yub, consdata->lhs))) )
1814 {
1815 SCIPdebugMsg(scip, "left hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
1816
1817 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
1818 ++(*nchgsides);
1819 }
1820
1821 /* check right hand side for redundancy */
1822 if( !SCIPisInfinity(scip, consdata->rhs) &&
1823 ((consdata->vbdcoef > 0.0 && SCIPisLE(scip, xub + consdata->vbdcoef * yub, consdata->rhs))
1824 || (consdata->vbdcoef < 0.0 && SCIPisLE(scip, xub + consdata->vbdcoef * ylb, consdata->rhs))) )
1825 {
1826 SCIPdebugMsg(scip, "right hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
1827
1829 ++(*nchgsides);
1830 }
1831 }
1832 /* check varbound constraint for redundancy */
1833 if( !(*cutoff) && (SCIPisInfinity(scip, -consdata->lhs)
1834 || (consdata->vbdcoef > 0.0 && SCIPisGE(scip, xlb + consdata->vbdcoef * ylb, consdata->lhs))
1835 || (consdata->vbdcoef < 0.0 && SCIPisGE(scip, xlb + consdata->vbdcoef * yub, consdata->lhs)))
1836 && (SCIPisInfinity(scip, consdata->rhs)
1837 || (consdata->vbdcoef > 0.0 && SCIPisLE(scip, xub + consdata->vbdcoef * yub, consdata->rhs))
1838 || (consdata->vbdcoef < 0.0 && SCIPisLE(scip, xub + consdata->vbdcoef * ylb, consdata->rhs))) )
1839 {
1840 SCIPdebugMsg(scip, "variable bound constraint <%s> is redundant: <%s>[%.15g,%.15g], <%s>[%.15g,%.15g]\n",
1841 SCIPconsGetName(cons),
1842 SCIPvarGetName(consdata->var), SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var),
1843 SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar));
1845
1846 /* this did not seem to help but should be tested again, there might also still be a bug in there */
1847#ifdef SCIP_DISABLED_CODE
1848 /* local duality fixing of variables in the constraint */
1849 if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->vbdvar))
1850 && SCIPvarGetNLocksDownType(consdata->vbdvar, SCIP_LOCKTYPE_MODEL) == 1
1851 && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->vbdvar))
1852 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1853 && ((consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1854 || (consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1855 {
1856 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1857 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetLbLocal(consdata->vbdvar));
1858 SCIP_CALL( SCIPchgVarUb(scip, consdata->vbdvar, SCIPvarGetLbLocal(consdata->vbdvar)) );
1859 }
1860 else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->vbdvar))
1861 && SCIPvarGetNLocksUpType(consdata->vbdvar, SCIP_LOCKTYPE_MODEL) == 1
1862 && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->vbdvar))
1863 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1864 && ((consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1865 || (consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1866 {
1867 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1868 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar));
1869 SCIP_CALL( SCIPchgVarLb(scip, consdata->vbdvar, SCIPvarGetUbLocal(consdata->vbdvar)) );
1870 }
1871 if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->var))
1872 && SCIPvarGetNLocksDownType(consdata->var, SCIP_LOCKTYPE_MODEL) == 1
1873 && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->var))
1874 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1875 && !SCIPisInfinity(scip, -consdata->lhs) )
1876 {
1877 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1878 SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetLbLocal(consdata->var));
1879 SCIP_CALL( SCIPchgVarUb(scip, consdata->var, SCIPvarGetLbLocal(consdata->var)) );
1880 }
1881 else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->var))
1882 && SCIPvarGetNLocksUpType(consdata->var, SCIP_LOCKTYPE_MODEL) == 1
1883 && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->var))
1884 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1885 && !SCIPisInfinity(scip, consdata->rhs) )
1886 {
1887 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1888 SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var));
1889 SCIP_CALL( SCIPchgVarLb(scip, consdata->var, SCIPvarGetUbLocal(consdata->var)) );
1890 }
1891#endif
1892 if( ndelconss != NULL )
1893 (*ndelconss)++;
1894 }
1895
1897
1898 return SCIP_OKAY;
1899}
1900
1901/* check whether one constraint side is redundant to another constraint side by calculating extreme values for
1902 * variables
1903 */
1904static
1906 SCIP* scip, /**< SCIP data structure */
1907 SCIP_VAR* var, /**< variable x that has variable bound */
1908 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
1909 SCIP_Real coef0, /**< coefficient c0 of bounding variable y for constraint 0 */
1910 SCIP_Real coef1, /**< coefficient c1 of bounding variable y for constraint 1 */
1911 SCIP_Real side0, /**< one side of variable bound inequality for constraint 0 */
1912 SCIP_Real side1, /**< one side of variable bound inequality for constraint 1 */
1913 SCIP_Bool* sideequal, /**< pointer to store if both constraints have the same redundancy on the
1914 * given side */
1915 SCIP_Bool* cons0sidered, /**< pointer to store if side of constraint 0 is redundant */
1916 SCIP_Bool* cons1sidered, /**< pointer to store if side of constraint 1 is redundant */
1917 SCIP_Bool islhs /**< do we check the left or the right hand side */
1918 )
1919{
1920 SCIP_Real lbvar;
1921 SCIP_Real ubvar;
1922 SCIP_Real lbvbdvar;
1923 SCIP_Real ubvbdvar;
1924 SCIP_Real boundxlb1;
1925 SCIP_Real boundxlb2;
1926 SCIP_Real boundylb1;
1927 SCIP_Real boundylb2;
1928 SCIP_Real boundxub1;
1929 SCIP_Real boundxub2;
1930 SCIP_Real boundyub1;
1931 SCIP_Real boundyub2;
1932 SCIP_Real boundvaluex1;
1933 SCIP_Real boundvaluex2;
1934 SCIP_Real boundvaluey1;
1935 SCIP_Real boundvaluey2;
1936 SCIP_Real valuex1;
1937 SCIP_Real valuex2;
1938 SCIP_Real valuey1;
1939 SCIP_Real valuey2;
1940 SCIP_Bool* redundant0;
1941 SCIP_Bool* redundant1;
1942
1943 assert(scip != NULL);
1944 assert(var != NULL);
1945 assert(vbdvar != NULL);
1946 assert(sideequal != NULL);
1947 assert(cons0sidered != NULL);
1948 assert(cons1sidered != NULL);
1949 assert(coef0 * coef1 > 0.0);
1950
1951 *cons0sidered = SCIPisInfinity(scip, islhs ? -side0 : side0);
1952 *cons1sidered = SCIPisInfinity(scip, islhs ? -side1 : side1);
1953 *sideequal = FALSE;
1954
1955 if( islhs )
1956 {
1957 redundant0 = cons1sidered;
1958 redundant1 = cons0sidered;
1959 }
1960 else
1961 {
1962 redundant0 = cons0sidered;
1963 redundant1 = cons1sidered;
1964 }
1965
1966 lbvar = SCIPvarGetLbGlobal(var);
1967 assert(!SCIPisInfinity(scip, lbvar));
1968 ubvar = SCIPvarGetUbGlobal(var);
1969 assert(!SCIPisInfinity(scip, -ubvar));
1970 lbvbdvar = SCIPvarGetLbGlobal(vbdvar);
1971 assert(!SCIPisInfinity(scip, lbvbdvar));
1972 ubvbdvar = SCIPvarGetUbGlobal(vbdvar);
1973 assert(!SCIPisInfinity(scip, -ubvbdvar));
1974
1975 /* if both constraints have this side */
1976 if( !*redundant0 && !*redundant1 )
1977 {
1978 /* calculate extreme values, which are reached by setting the other variable to their lower/upper bound */
1979 if( SCIPisInfinity(scip, -lbvbdvar) )
1980 {
1981 if( coef0 > 0.0 )
1982 {
1983 boundxlb1 = SCIPinfinity(scip);
1984 boundxlb2 = SCIPinfinity(scip);
1985 }
1986 else
1987 {
1988 boundxlb1 = -SCIPinfinity(scip);
1989 boundxlb2 = -SCIPinfinity(scip);
1990 }
1991 }
1992 else
1993 {
1994 boundxlb1 = side0 - lbvbdvar * coef0;
1995 boundxlb2 = side1 - lbvbdvar * coef1;
1996 }
1997 if( SCIPisInfinity(scip, -lbvar) )
1998 {
1999 if( coef0 > 0.0 )
2000 {
2001 boundylb1 = SCIPinfinity(scip);
2002 boundylb2 = SCIPinfinity(scip);
2003 }
2004 else
2005 {
2006 boundylb1 = -SCIPinfinity(scip);
2007 boundylb2 = -SCIPinfinity(scip);
2008 }
2009 }
2010 else
2011 {
2012 boundylb1 = (side0 - lbvar) / coef0;
2013 boundylb2 = (side1 - lbvar) / coef1;
2014 }
2015 if( SCIPisInfinity(scip, ubvbdvar) )
2016 {
2017 if( coef0 > 0.0 )
2018 {
2019 boundxub1 = -SCIPinfinity(scip);
2020 boundxub2 = -SCIPinfinity(scip);
2021 }
2022 else
2023 {
2024 boundxub1 = SCIPinfinity(scip);
2025 boundxub2 = SCIPinfinity(scip);
2026 }
2027 }
2028 else
2029 {
2030 boundxub1 = side0 - ubvbdvar * coef0;
2031 boundxub2 = side1 - ubvbdvar * coef1;
2032 }
2033 if( SCIPisInfinity(scip, ubvar) )
2034 {
2035 if( coef0 > 0.0 )
2036 {
2037 boundyub1 = -SCIPinfinity(scip);
2038 boundyub2 = -SCIPinfinity(scip);
2039 }
2040 else
2041 {
2042 boundyub1 = SCIPinfinity(scip);
2043 boundyub2 = SCIPinfinity(scip);
2044 }
2045 }
2046 else
2047 {
2048 boundyub1 = (side0 - ubvar) / coef0;
2049 boundyub2 = (side1 - ubvar) / coef1;
2050 }
2051
2052 if( islhs )
2053 {
2054 boundvaluex1 = MAX(boundxlb1, boundxlb2);
2055 boundvaluex2 = MAX(boundxub1, boundxub2);
2056 }
2057 else
2058 {
2059 boundvaluex1 = MIN(boundxlb1, boundxlb2);
2060 boundvaluex2 = MIN(boundxub1, boundxub2);
2061 }
2062
2063 /* calculate important values for variables */
2064 if( coef0 > 0.0 )
2065 {
2066 valuex1 = MIN(boundvaluex1, ubvar);
2067 valuex1 = MAX(valuex1, lbvar);
2068 valuex2 = MAX(boundvaluex2, lbvar);
2069 valuex2 = MIN(valuex2, ubvar);
2070
2071 /* if variable is of integral type make values integral too */
2073 {
2074 valuex1 = SCIPfeasFloor(scip, valuex1);
2075 valuex2 = SCIPfeasCeil(scip, valuex2);
2076 }
2077 }
2078 else
2079 {
2080 valuex1 = MAX(boundvaluex1, lbvar);
2081 valuex1 = MIN(valuex1, ubvar);
2082 valuex2 = MIN(boundvaluex2, ubvar);
2083 valuex2 = MAX(valuex2, lbvar);
2084
2085 /* if variable is of integral type make values integral too */
2087 {
2088 valuex1 = SCIPfeasCeil(scip, valuex1);
2089 valuex2 = SCIPfeasFloor(scip, valuex2);
2090 }
2091 }
2092
2093 /* calculate resulting values of variable y by setting x to valuex1 */
2094 if( SCIPisInfinity(scip, ABS(valuex1)) )
2095 {
2096 /* only consider sides if coefficients are equal */
2097 if( SCIPisEQ(scip, coef0, coef1) )
2098 {
2099 valuey1 = side0 / coef0;
2100 valuey2 = side1 / coef1;
2101 }
2102 /* only consider original coefficients if otherwise x approaches plus infinity */
2103 else if( valuex1 > 0.0 )
2104 {
2105 valuey1 = coef0;
2106 valuey2 = coef1;
2107 }
2108 /* only consider swapped coefficients if otherwise x approaches minus infinity */
2109 else
2110 {
2111 valuey1 = coef1;
2112 valuey2 = coef0;
2113 }
2114 }
2115 else
2116 {
2117 valuey1 = (side0 - valuex1) / coef0;
2118 valuey2 = (side1 - valuex1) / coef1;
2119 }
2120
2121 /* determine redundancy of one constraints side */
2122 if( SCIPisEQ(scip, valuey1, valuey2) )
2123 *sideequal = TRUE;
2124 else if( coef0 > 0.0 )
2125 {
2126 if( valuey1 < valuey2 )
2127 *redundant1 = TRUE;
2128 else
2129 *redundant0 = TRUE;
2130 }
2131 else
2132 {
2133 if( valuey1 < valuey2 )
2134 *redundant0 = TRUE;
2135 else
2136 *redundant1 = TRUE;
2137 }
2138
2139 /* calculate resulting values of variable y by setting x to valuex2 */
2140 if( SCIPisInfinity(scip, ABS(valuex2)) )
2141 {
2142 /* only consider sides if coefficients are equal */
2143 if( SCIPisEQ(scip, coef0, coef1) )
2144 {
2145 valuey1 = side0 / coef0;
2146 valuey2 = side1 / coef1;
2147 }
2148 /* only consider original coefficients if otherwise x approaches plus infinity */
2149 else if( valuex2 > 0.0 )
2150 {
2151 valuey1 = coef0;
2152 valuey2 = coef1;
2153 }
2154 /* only consider swapped coefficients if otherwise x approaches minus infinity */
2155 else
2156 {
2157 valuey1 = coef1;
2158 valuey2 = coef0;
2159 }
2160 }
2161 else
2162 {
2163 valuey1 = (side0 - valuex2) / coef0;
2164 valuey2 = (side1 - valuex2) / coef1;
2165 }
2166
2167 /* determine redundancy of one constraints side by checking for the first valuex2 */
2168 if( coef0 > 0.0 )
2169 {
2170 /* if both constraints are equal on one value, only consider the other value */
2171 if( *sideequal )
2172 {
2173 assert(!(*redundant0));
2174 assert(!(*redundant1));
2175
2176 if( SCIPisLT(scip, valuey1, valuey2) )
2177 {
2178 *sideequal = FALSE;
2179 *redundant1 = TRUE;
2180 }
2181 else if( SCIPisGT(scip, valuey1, valuey2) )
2182 {
2183 *sideequal = FALSE;
2184 *redundant0 = TRUE;
2185 }
2186 }
2187 /* if both constraints are weaker than the other on one value, we have no redundancy */
2188 else if( ( *redundant1 && SCIPisGT(scip, valuey1, valuey2) )
2189 || ( *redundant0 && SCIPisLT(scip, valuey1, valuey2) ) )
2190 {
2191 *redundant0 = FALSE;
2192 *redundant1 = FALSE;
2193 return;
2194 }
2195 }
2196 else
2197 {
2198 /* if both constraints are equal on one value, only consider the other value */
2199 if( *sideequal )
2200 {
2201 assert(!(*redundant0));
2202 assert(!(*redundant1));
2203
2204 if( SCIPisLT(scip, valuey1, valuey2) )
2205 {
2206 *sideequal = FALSE;
2207 *redundant0 = TRUE;
2208 }
2209 else if( SCIPisGT(scip, valuey1, valuey2) )
2210 {
2211 *sideequal = FALSE;
2212 *redundant1 = TRUE;
2213 }
2214 }
2215 /* if both constraints are weaker than the other one on one value, we have no redundancy */
2216 else if( ( *redundant0 && SCIPisGT(scip, valuey1, valuey2) )
2217 || ( *redundant1 && SCIPisLT(scip, valuey1, valuey2) ) )
2218 {
2219 *redundant0 = FALSE;
2220 *redundant1 = FALSE;
2221 return;
2222 }
2223 }
2224 assert(*sideequal || *redundant0 || *redundant1);
2225
2226 /* calculate feasibility domain values for variable y concerning these both constraints */
2227 if( coef0 > 0.0 )
2228 {
2229 if( islhs )
2230 {
2231 boundvaluey1 = MAX(boundylb1, boundylb2);
2232 boundvaluey2 = MAX(boundyub1, boundyub2);
2233 }
2234 else
2235 {
2236 boundvaluey1 = MIN(boundylb1, boundylb2);
2237 boundvaluey2 = MIN(boundyub1, boundyub2);
2238 }
2239
2240 valuey1 = MIN(boundvaluey1, ubvbdvar);
2241 valuey1 = MAX(valuey1, lbvbdvar);
2242 valuey2 = MAX(boundvaluey2, lbvbdvar);
2243 valuey2 = MIN(valuey2, ubvbdvar);
2244
2245 valuey1 = SCIPfeasFloor(scip, valuey1);
2246 valuey2 = SCIPfeasCeil(scip, valuey2);
2247 }
2248 else
2249 {
2250 if( islhs )
2251 {
2252 boundvaluey1 = MIN(boundylb1, boundylb2);
2253 boundvaluey2 = MIN(boundyub1, boundyub2);
2254 }
2255 else
2256 {
2257 boundvaluey1 = MAX(boundylb1, boundylb2);
2258 boundvaluey2 = MAX(boundyub1, boundyub2);
2259 }
2260
2261 valuey1 = MAX(boundvaluey1, lbvbdvar);
2262 valuey1 = MIN(valuey1, ubvbdvar);
2263 valuey2 = MIN(boundvaluey2, ubvbdvar);
2264 valuey2 = MAX(valuey2, lbvbdvar);
2265
2266 valuey1 = SCIPfeasCeil(scip, valuey1);
2267 valuey2 = SCIPfeasFloor(scip, valuey2);
2268 }
2269
2270 /* calculate resulting values of variable x by setting y to valuey1 */
2271 if( SCIPisInfinity(scip, ABS(valuey1)) )
2272 {
2273 /* only consider sides if coefficients are equal */
2274 if( SCIPisEQ(scip, coef0, coef1) )
2275 {
2276 valuex1 = side0;
2277 valuex2 = side1;
2278 }
2279 /* only consider swapped coefficients if otherwise y approaches plus infinity */
2280 else if( valuey1 > 0.0 )
2281 {
2282 valuex1 = coef1;
2283 valuex2 = coef0;
2284 }
2285 /* only consider original coefficients if otherwise y approaches minus infinity */
2286 else
2287 {
2288 valuex1 = coef0;
2289 valuex2 = coef1;
2290 }
2291 }
2292 else
2293 {
2294 valuex1 = side0 - valuey1 * coef0;
2295 valuex2 = side1 - valuey1 * coef1;
2296 }
2297
2298 /* determine redundancy of one constraints side by checking for the first valuey1 */
2299 if( *sideequal )
2300 {
2301 assert(!(*redundant0));
2302 assert(!(*redundant1));
2303
2304 if( SCIPisLT(scip, valuex1, valuex2) )
2305 {
2306 *sideequal = FALSE;
2307 *redundant1 = TRUE;
2308 }
2309 else if( SCIPisGT(scip, valuex1, valuex2) )
2310 {
2311 *sideequal = FALSE;
2312 *redundant0 = TRUE;
2313 }
2314 }
2315 else if( ( *redundant1 && SCIPisGT(scip, valuex1, valuex2) )
2316 || ( *redundant0 && SCIPisLT(scip, valuex1, valuex2) ) )
2317 {
2318 *redundant0 = FALSE;
2319 *redundant1 = FALSE;
2320 return;
2321 }
2322
2323 /* calculate resulting values of variable x by setting y to valuey2 */
2324 if( SCIPisInfinity(scip, ABS(valuey2)) )
2325 {
2326 /* only consider sides if coefficients are equal */
2327 if( SCIPisEQ(scip, coef0, coef1) )
2328 {
2329 valuex1 = side0;
2330 valuex2 = side1;
2331 }
2332 /* only consider swapped coefficients if otherwise y approaches plus infinity */
2333 else if( valuey2 > 0.0 )
2334 {
2335 valuex1 = coef1;
2336 valuex2 = coef0;
2337 }
2338 /* only consider original coefficients if otherwise y approaches minus infinity */
2339 else
2340 {
2341 valuex1 = coef0;
2342 valuex2 = coef1;
2343 }
2344 }
2345 else
2346 {
2347 valuex1 = side0 - valuey2 * coef0;
2348 valuex2 = side1 - valuey2 * coef1;
2349 }
2350
2351 /* determine redundancy of one constraints side by checking for the second valuey2 */
2352 if( *sideequal )
2353 {
2354 assert(!(*redundant0));
2355 assert(!(*redundant1));
2356
2357 if( SCIPisLT(scip, valuex1, valuex2) )
2358 {
2359 *sideequal = FALSE;
2360 *redundant1 = TRUE;
2361 }
2362 else if( SCIPisGT(scip, valuex1, valuex2) )
2363 {
2364 *sideequal = FALSE;
2365 *redundant0 = TRUE;
2366 }
2367 }
2368 else if( ( *redundant1 && SCIPisGT(scip, valuex1, valuex2) )
2369 || ( *redundant0 && SCIPisLT(scip, valuex1, valuex2) ) )
2370 {
2371 *redundant0 = FALSE;
2372 *redundant1 = FALSE;
2373 return;
2374 }
2375 assert(*redundant0 || *redundant1 || *sideequal);
2376 }
2377}
2378
2379/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
2380 *
2381 * we will order all constraint to have constraints with same variables next to each other to speed up presolving
2382 *
2383 * consider two constraints like lhs1 <= x + b1*y <= rhs1 and lhs2 <= x + b2*y <= rhs2
2384 * we are doing the following presolving steps:
2385 *
2386 * if( b1 == b2 )
2387 * newlhs = MAX(lhs1, lhs2)
2388 * newrhs = MIN(rhs1, rhs2)
2389 * updateSides
2390 * delete one constraint
2391 * else if( ((b1 > 0) == (b2 > 0)) && (lhs1 != -inf && lhs2 != -inf) || (rhs1 != inf && rhs2 != inf) )
2392 *
2393 * (i.e. both constraint have either a valid lhs or a valid rhs and infinity is on the same side and the
2394 * coeffcients have the same size )
2395 *
2396 * if( y is binary )
2397 * if( lhs1 != -inf )
2398 * newlhs = MAX(lhs1, lhs2)
2399 * newb = newlhs - MAX(lhs1 - b1, lhs2 - b2)
2400 * else
2401 * newrhs = MIN(lhs1, lhs2)
2402 * newb = newrhs - MIN(rhs1 - b1, rhs2 - b2)
2403 * updateSidesAndCoef
2404 * delete one constraint
2405 * else
2406 * we calculate possible values for both variables and check which constraint is tighter
2407 * else
2408 * nothing possible
2409 *
2410 * We also try to tighten bounds in the case of two constraints lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2.
2411 * Eliminiating one variable and inserting into the second yields the following bounds:
2412 * If b2 > 0:
2413 * (1 - b1 * b2) * y >= lhs2 - b2 * rhs1
2414 * (1 - b1 * b2) * y <= rhs2 - b2 * lhs1
2415 * If b2 < 0:
2416 * (1 - b1 * b2) * y >= lhs2 - b2 * lhs1
2417 * (1 - b1 * b2) * y <= rhs2 - b2 * rhs1
2418 * The case of x is similar.
2419 */
2420static
2422 SCIP* scip, /**< SCIP data structure */
2423 SCIP_CONS** conss, /**< constraint set */
2424 int nconss, /**< number of constraints in constraint set */
2425 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
2426 int* nchgbds, /**< pointer to count number of bound changes */
2427 int* ndelconss, /**< pointer to count number of deleted constraints */
2428 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
2429 int* nchgsides /**< pointer to count number of changed left/right hand sides */
2430 )
2431{
2432 SCIP_CONS** sortedconss;
2433 int c;
2434 int s;
2435
2436 assert(scip != NULL);
2437 assert(conss != NULL);
2438 assert(cutoff != NULL);
2439 assert(nchgbds != NULL);
2440 assert(ndelconss != NULL);
2441 assert(nchgcoefs != NULL);
2442 assert(nchgsides != NULL);
2443
2444 /* create our temporary working array */
2445 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedconss, conss, nconss) );
2446
2447 /* sort all constraints, so that all constraints with same variables stand next to each other */
2448 SCIPsortPtr((void**)sortedconss, consVarboundComp, nconss);
2449
2450 /* check all constraints for redundancy */
2451 for( c = nconss - 1; c > 0 && !(*cutoff); --c )
2452 {
2453 SCIP_CONS* cons0;
2454 SCIP_CONSDATA* consdata0;
2455
2456 cons0 = sortedconss[c];
2457
2458 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
2459 continue;
2460
2461 consdata0 = SCIPconsGetData(cons0);
2462 assert(consdata0 != NULL);
2463 assert(consdata0->var != NULL);
2464 assert(consdata0->vbdvar != NULL);
2465
2466 /* do not check for already redundant constraints */
2467 assert(!SCIPisZero(scip, consdata0->vbdcoef));
2468 assert(!SCIPisInfinity(scip, -consdata0->lhs) || !SCIPisInfinity(scip, consdata0->rhs));
2469
2470 if( !consdata0->changed )
2471 continue;
2472
2473 consdata0->changed = FALSE;
2474
2475 for( s = c - 1; s >= 0; --s )
2476 {
2477 SCIP_CONS* cons1;
2478 SCIP_CONSDATA* consdata1;
2479 SCIP_Real lhs;
2480 SCIP_Real rhs;
2481 SCIP_Real coef;
2482 SCIP_Bool deletecons1;
2483
2484 cons1 = sortedconss[s];
2485
2486 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
2487 continue;
2488
2489 consdata1 = SCIPconsGetData(cons1);
2490 assert(consdata1 != NULL);
2491 assert(consdata1->var != NULL);
2492 assert(consdata1->vbdvar != NULL);
2493
2494 /* do not check for already redundant constraints */
2495 assert(!SCIPisZero(scip, consdata1->vbdcoef));
2496 assert(!SCIPisInfinity(scip, -consdata1->lhs) || !SCIPisInfinity(scip, consdata1->rhs));
2497
2498 lhs = consdata0->lhs;
2499 rhs = consdata0->rhs;
2500 coef = consdata0->vbdcoef;
2501
2502 /* check for propagation in the case: lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2. */
2503 if ( consdata0->var == consdata1->vbdvar && consdata0->vbdvar == consdata1->var &&
2504 !SCIPisFeasZero(scip, 1.0 - coef * consdata1->vbdcoef) )
2505 {
2506 SCIP_Bool tightened = FALSE;
2507 SCIP_Real bnd = SCIP_UNKNOWN;
2508 SCIP_Real scalar;
2509 SCIP_Real newbnd;
2510
2511 scalar = (1.0 - coef * consdata1->vbdcoef);
2512
2513 assert( ! SCIPisInfinity(scip, REALABS(scalar)) );
2514 assert( ! SCIPisZero(scip, consdata0->vbdcoef) );
2515 assert( ! SCIPisZero(scip, consdata1->vbdcoef) );
2516
2517 /* lower bounds for consdata0->var */
2518 if ( ! SCIPisInfinity(scip, -lhs) )
2519 {
2520 if ( SCIPisPositive(scip, coef) )
2521 {
2522 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2523 bnd = (lhs - coef * consdata1->rhs)/scalar;
2524 }
2525 else
2526 {
2527 assert( SCIPisNegative(scip, coef) );
2528 if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2529 bnd = (lhs - coef * consdata1->lhs)/scalar;
2530 }
2531
2532 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2533 {
2534 if ( SCIPisFeasPositive(scip, scalar) )
2535 {
2536 newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2537 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2538 if ( *cutoff )
2539 {
2540 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2541 SCIPvarGetName(consdata0->var), newbnd);
2542 break;
2543 }
2544 if ( tightened )
2545 {
2546 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2547 SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2548 (*nchgbds)++;
2549 }
2550 }
2551 else if ( SCIPisFeasNegative(scip, scalar) )
2552 {
2553 newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2554 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2555 if ( *cutoff )
2556 {
2557 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2558 SCIPvarGetName(consdata0->var), newbnd);
2559 break;
2560 }
2561 if ( tightened )
2562 {
2563 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2564 SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2565 (*nchgbds)++;
2566 }
2567 }
2568 }
2569 }
2570
2571 /* upper bound for consdata0>var */
2572 if ( ! SCIPisInfinity(scip, rhs) )
2573 {
2574 bnd = SCIP_UNKNOWN;
2575 if ( SCIPisPositive(scip, coef) )
2576 {
2577 if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2578 bnd = (rhs - coef * consdata1->lhs)/scalar;
2579 }
2580 else
2581 {
2582 assert( SCIPisNegative(scip, coef) );
2583 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2584 bnd = (rhs - coef * consdata1->rhs)/scalar;
2585 }
2586
2587 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2588 {
2589 if ( SCIPisFeasPositive(scip, scalar) )
2590 {
2591 newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2592 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2593 if ( *cutoff )
2594 {
2595 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2596 SCIPvarGetName(consdata0->var), newbnd);
2597 break;
2598 }
2599 if ( tightened )
2600 {
2601 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2602 SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2603 (*nchgbds)++;
2604 }
2605 }
2606 else if ( SCIPisFeasNegative(scip, scalar) )
2607 {
2608 newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2609 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2610 if ( *cutoff )
2611 {
2612 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2613 SCIPvarGetName(consdata0->var), newbnd);
2614 break;
2615 }
2616 if ( tightened )
2617 {
2618 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2619 SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2620 (*nchgbds)++;
2621 }
2622 }
2623 }
2624 }
2625
2626 /* lower bounds for consdata1->var */
2627 if ( ! SCIPisInfinity(scip, -consdata1->lhs) )
2628 {
2629 bnd = SCIP_UNKNOWN;
2630 if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2631 {
2632 if ( ! SCIPisInfinity(scip, rhs) )
2633 bnd = (consdata1->lhs - consdata1->vbdcoef * rhs)/scalar;
2634 }
2635 else
2636 {
2637 assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2638 if ( ! SCIPisInfinity(scip, lhs) )
2639 bnd = (consdata1->lhs - consdata1->vbdcoef * lhs)/scalar;
2640 }
2641
2642 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2643 {
2644 if ( SCIPisFeasPositive(scip, scalar) )
2645 {
2646 newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2647 SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2648 if ( *cutoff )
2649 {
2650 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2651 SCIPvarGetName(consdata1->var), newbnd);
2652 break;
2653 }
2654 if ( tightened )
2655 {
2656 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2657 SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2658 (*nchgbds)++;
2659 }
2660 }
2661 else if ( SCIPisFeasNegative(scip, scalar) )
2662 {
2663 newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2664 SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2665 if ( *cutoff )
2666 {
2667 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2668 SCIPvarGetName(consdata1->var), newbnd);
2669 break;
2670 }
2671 if ( tightened )
2672 {
2673 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2674 SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2675 (*nchgbds)++;
2676 }
2677 }
2678 }
2679 }
2680
2681 /* upper bound for consdata1->var */
2682 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2683 {
2684 bnd = SCIP_UNKNOWN;
2685 if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2686 {
2687 if ( ! SCIPisInfinity(scip, lhs) )
2688 bnd = (consdata1->rhs - consdata1->vbdcoef * lhs)/scalar;
2689 }
2690 else
2691 {
2692 assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2693 if ( ! SCIPisInfinity(scip, rhs) )
2694 bnd = (consdata1->rhs - consdata1->vbdcoef * rhs)/scalar;
2695 }
2696
2697 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2698 {
2699 if ( SCIPisFeasPositive(scip, scalar) )
2700 {
2701 newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2702 SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2703 if ( *cutoff )
2704 {
2705 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2706 SCIPvarGetName(consdata1->var), newbnd);
2707 break;
2708 }
2709 if ( tightened )
2710 {
2711 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2712 SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2713 (*nchgbds)++;
2714 }
2715 }
2716 else if ( SCIPisFeasNegative(scip, scalar) )
2717 {
2718 newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2719 SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2720 if ( *cutoff )
2721 {
2722 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2723 SCIPvarGetName(consdata1->var), newbnd);
2724 break;
2725 }
2726 if ( tightened )
2727 {
2728 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2729 SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2730 (*nchgbds)++;
2731 }
2732 }
2733 }
2734 }
2735 }
2736
2737 /* check for equal variables */
2738 if( consdata0->var != consdata1->var || consdata0->vbdvar != consdata1->vbdvar )
2739 break;
2740
2741 /* mark constraint1 for deletion if possible */
2742 deletecons1 = TRUE;
2743
2744 /* the coefficients of both constraints are equal */
2745 if( SCIPisEQ(scip, coef, consdata1->vbdcoef) )
2746 {
2747 lhs = MAX(consdata1->lhs, lhs);
2748 rhs = MIN(consdata1->rhs, rhs);
2749 }
2750 /* now only one side and in both constraints the same side should be infinity and the vbdvar should be binary
2751 * then we neither do not need to have the same side nor the same coefficient
2752 */
2753 else if( SCIPvarIsBinary(consdata0->vbdvar)
2754 && (SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs))
2755 && (SCIPisInfinity(scip, -consdata1->lhs) || SCIPisInfinity(scip, consdata1->rhs))
2756 && (SCIPisInfinity(scip, -lhs) == SCIPisInfinity(scip, -consdata1->lhs)) )
2757 {
2758 /* lhs <= x + b*y <= +inf */
2759 if( !SCIPisInfinity(scip, -lhs) )
2760 {
2761 lhs = MAX(consdata1->lhs, lhs);
2762 coef = lhs - MAX(consdata1->lhs - consdata1->vbdcoef, consdata0->lhs - coef);
2763 }
2764 /* -inf <= x + b*y <= rhs */
2765 else
2766 {
2767 rhs = MIN(consdata1->rhs, rhs);
2768 coef = rhs - MIN(consdata1->rhs - consdata1->vbdcoef, consdata0->rhs - coef);
2769 }
2770
2772 }
2773 else if( SCIPisPositive(scip, coef) == SCIPisPositive(scip, consdata1->vbdcoef)
2774 && ((!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, -consdata1->lhs))
2775 || (!SCIPisInfinity(scip, rhs) && !SCIPisInfinity(scip, consdata1->rhs))) )
2776 {
2777 SCIP_Bool cons0lhsred;
2778 SCIP_Bool cons0rhsred;
2779 SCIP_Bool cons1lhsred;
2780 SCIP_Bool cons1rhsred;
2781 SCIP_Bool lhsequal;
2782 SCIP_Bool rhsequal;
2783
2784 assert(!SCIPisInfinity(scip, lhs));
2785 assert(!SCIPisInfinity(scip, consdata1->lhs));
2786 assert(!SCIPisInfinity(scip, -rhs));
2787 assert(!SCIPisInfinity(scip, -consdata1->rhs));
2788
2789 /* check if a left hand side of one constraints is redundant */
2790 checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, lhs, consdata1->lhs, &lhsequal, &cons0lhsred, &cons1lhsred, TRUE);
2791
2792 /* check if a right hand side of one constraints is redundant */
2793 checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, rhs, consdata1->rhs, &rhsequal, &cons0rhsred, &cons1rhsred, FALSE);
2794
2795 /* if cons0 is redundant, update cons1 and delete cons0 */
2796 if( (lhsequal || cons0lhsred) && (rhsequal || cons0rhsred) )
2797 {
2798 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2799 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2800
2801 SCIPdebugMsg(scip, "constraint: ");
2802 SCIPdebugPrintCons(scip, cons0, NULL);
2803 SCIPdebugMsg(scip, "is redundant to constraint: ");
2804 SCIPdebugPrintCons(scip, cons1, NULL);
2805
2806 SCIP_CALL( SCIPdelCons(scip, cons0) );
2807 ++(*ndelconss);
2808
2809 /* get next cons0 */
2810 break;
2811 }
2812 /* if cons1 is redundant, update cons0 and delete cons1 */
2813 else if( cons1lhsred && cons1rhsred )
2814 {
2815 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2816 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2817
2818 SCIPdebugMsg(scip, "constraint: ");
2819 SCIPdebugPrintCons(scip, cons1, NULL);
2820 SCIPdebugMsg(scip, "is redundant to constraint: ");
2821 SCIPdebugPrintCons(scip, cons0, NULL);
2822
2823 SCIP_CALL( SCIPdelCons(scip, cons1) );
2824 ++(*ndelconss);
2825
2826 /* get next cons1 */
2827 continue;
2828 }
2829 /* if left hand side of cons0 is redundant set it to -infinity */
2830 else if( (lhsequal || cons0lhsred) && !SCIPisInfinity(scip, -lhs) )
2831 {
2832 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2833 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2834
2835 lhs = -SCIPinfinity(scip);
2836
2837 /* if right hand side of cons1 is redundant too, set it to infinity */
2838 if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
2839 {
2840 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2841 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2842
2843 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
2844 ++(*nchgsides);
2845
2846 SCIPdebugMsg(scip, "deleted rhs of constraint: ");
2847 SCIPdebugPrintCons(scip, cons1, NULL);
2848 SCIPdebugMsg(scip, "due to constraint: ");
2849 SCIPdebugPrintCons(scip, cons0, NULL);
2850 }
2851
2852 /* later on we do not want to delete cons1 */
2853 deletecons1 = FALSE;
2854 }
2855 /* if right hand side of cons0 is redundant set it to infinity */
2856 else if( (rhsequal || cons0rhsred) && !SCIPisInfinity(scip, rhs) )
2857 {
2858 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2859 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2860
2861 rhs = SCIPinfinity(scip);
2862
2863 /* if left hand side of cons1 is redundant too, set it to -infinity */
2864 if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
2865 {
2866 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2867 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2868
2869 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
2870 ++(*nchgsides);
2871
2872 SCIPdebugMsg(scip, "deleted lhs of constraint: ");
2873 SCIPdebugPrintCons(scip, cons1, NULL);
2874 SCIPdebugMsg(scip, "due to constraint: ");
2875 SCIPdebugPrintCons(scip, cons0, NULL);
2876 }
2877
2878 /* later on we do not want to delete cons1 */
2879 deletecons1 = FALSE;
2880 }
2881 /* if left hand side of cons1 is redundant set it to -infinity */
2882 else if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
2883 {
2884 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2885 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2886
2887 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
2888 ++(*nchgsides);
2889
2890 SCIPdebugMsg(scip, "deleted lhs of constraint: ");
2891 SCIPdebugPrintCons(scip, cons1, NULL);
2892 SCIPdebugMsg(scip, "due to constraint: ");
2893 SCIPdebugPrintCons(scip, cons0, NULL);
2894
2895 continue;
2896 }
2897 /* if right hand side of cons1 is redundant set it to infinity */
2898 else if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
2899 {
2900 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2901 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2902
2903 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
2904 ++(*nchgsides);
2905
2906 SCIPdebugMsg(scip, "deleted rhs of constraint: ");
2907 SCIPdebugPrintCons(scip, cons1, NULL);
2908 SCIPdebugMsg(scip, "due to constraint: ");
2909 SCIPdebugPrintCons(scip, cons0, NULL);
2910
2911 continue;
2912 }
2913 else /* nothing was redundant */
2914 continue;
2915 }
2916 else
2917 {
2918 /* there is no redundancy in both constraints with same variables */
2919 continue;
2920 }
2921
2922 if( SCIPisFeasLT(scip, rhs, lhs) )
2923 {
2924 SCIPdebugMsg(scip, "constraint <%s> and <%s> lead to infeasibility due to their sides\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
2925 *cutoff = TRUE;
2926 break;
2927 }
2928
2929 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
2930 if( lhs > rhs )
2931 {
2932 rhs = (lhs + rhs)/2;
2933 lhs = rhs;
2934 }
2935
2936 /* we decide to let constraint cons0 stay, so update data structure consdata0 */
2937
2938 /* update coefficient of cons0 */
2939
2940 /* special case if new coefficient becomes zero, both constraints are redundant but we may tighten the bounds */
2941 if( SCIPisZero(scip, coef) )
2942 {
2943 SCIP_Bool tightened;
2944
2945 SCIPdebugMsg(scip, "constraint: ");
2946 SCIPdebugPrintCons(scip, cons1, NULL);
2947 SCIPdebugMsg(scip, "and constraint: ");
2948 SCIPdebugPrintCons(scip, cons0, NULL);
2949 SCIPdebugMsg(scip, "are both redundant and lead to bounding of <%s> in [%g, %g]\n", SCIPvarGetName(consdata0->var), lhs, rhs);
2950
2951 /* delete cons1 */
2952 SCIP_CALL( SCIPdelCons(scip, cons1) );
2953 ++(*ndelconss);
2954
2955 /* update upper bound if possible
2956 *
2957 * @note we need to force the bound change since we are deleting the constraint afterwards
2958 */
2959 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, rhs, TRUE, cutoff, &tightened) );
2960 if( *cutoff )
2961 break;
2962 if( tightened )
2963 ++(*nchgbds);
2964
2965 /* update lower bound if possible
2966 *
2967 * @note we need to force the bound change since we are deleting the constraint afterwards
2968 */
2969 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, lhs, TRUE, cutoff, &tightened) );
2970 if( *cutoff )
2971 break;
2972 if( tightened )
2973 ++(*nchgbds);
2974
2975 /* delete cons0 */
2976 SCIP_CALL( SCIPdelCons(scip, cons0) );
2977 ++(*ndelconss);
2978
2979 /* get next cons0 */
2980 break;
2981 }
2982
2983 SCIPdebugMsg(scip, "constraint: ");
2984 SCIPdebugPrintCons(scip, cons1, NULL);
2985 SCIPdebugMsg(scip, "and constraint: ");
2986 SCIPdebugPrintCons(scip, cons0, NULL);
2987
2988 /* if sign of coefficient switches, update the locks of the variable */
2989 if( consdata0->vbdcoef * coef < 0.0 )
2990 {
2991 assert(SCIPconsIsTransformed(cons0));
2992
2993 /* remove locks for variable with old coefficient and install locks for variable with new
2994 * coefficient
2995 */
2996 if( consdata0->vbdcoef > 0.0 )
2997 {
2998 SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, -consdata0->lhs),
2999 !SCIPisInfinity(scip, consdata0->rhs)) );
3000 SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, consdata0->rhs),
3001 !SCIPisInfinity(scip, -consdata0->lhs)) );
3002 }
3003 else
3004 {
3005 SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, consdata0->rhs),
3006 !SCIPisInfinity(scip, -consdata0->lhs)) );
3007 SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, -consdata0->lhs),
3008 !SCIPisInfinity(scip, consdata0->rhs)) );
3009 }
3010 }
3011
3012 /* now change the coefficient */
3013 if( !SCIPisEQ(scip, consdata0->vbdcoef, coef) )
3014 {
3015 ++(*nchgcoefs);
3016
3017 /* mark to add new varbound information */
3018 consdata0->varboundsadded = FALSE;
3019 consdata0->tightened = FALSE;
3020 consdata0->presolved = FALSE;
3021 consdata0->changed = FALSE;
3022
3023 consdata0->vbdcoef = coef;
3024
3026 }
3027
3028 /* update lhs and rhs of cons0 */
3029 if( !SCIPisEQ(scip, consdata0->lhs, lhs) )
3030 {
3031 SCIP_CALL( chgLhs(scip, cons0, lhs) );
3032 ++(*nchgsides);
3033 }
3034 if( !SCIPisEQ(scip, consdata0->rhs, rhs) )
3035 {
3036 SCIP_CALL( chgRhs(scip, cons0, rhs) );
3037 ++(*nchgsides);
3038 }
3039
3040 SCIPdebugMsg(scip, "lead to new constraint: ");
3041 SCIPdebugPrintCons(scip, cons0, NULL);
3042
3043 /* if cons1 is still marked for deletion, delete it */
3044 if( deletecons1 )
3045 {
3046 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3047 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3048
3049 /* delete cons1 */
3050 SCIP_CALL( SCIPdelCons(scip, cons1) );
3051 ++(*ndelconss);
3052 }
3053
3054 assert(SCIPconsIsActive(cons0));
3055 }
3056 }
3057
3058 /* free temporary memory */
3059 SCIPfreeBufferArray(scip, &sortedconss);
3060
3061 return SCIP_OKAY;
3062}
3063
3064/** for all varbound constraints with two integer variables make the coefficients integral */
3065static
3067 SCIP* scip, /**< SCIP data structure */
3068 SCIP_CONS** conss, /**< constraint set */
3069 int nconss, /**< number of constraints in constraint set */
3070 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3071 int* nchgsides /**< pointer to count number of changed left/right hand sides */
3072 )
3073{
3074 SCIP_CONSDATA* consdata;
3075 int c;
3076
3077 assert(scip != NULL);
3078 assert(conss != NULL || nconss == 0);
3079 assert(nchgcoefs != NULL);
3080 assert(nchgsides != NULL);
3081
3082 /* if we cannot find any constraint for prettifying, stop */
3084 return;
3085
3086 for( c = nconss - 1; c >= 0; --c )
3087 {
3088 assert(conss != NULL);
3089
3090 if( SCIPconsIsDeleted(conss[c]) )
3091 continue;
3092
3093 consdata = SCIPconsGetData(conss[c]);
3094 assert(consdata != NULL);
3095
3096 /* check for integer variables and one coefficient with an absolute value smaller than 1 */
3097 /* @note: we allow that the variable type of the bounded variable can be smaller than the variable type of the
3098 * bounding variable
3099 */
3100 if( (SCIPvarGetType(consdata->var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_INTEGER
3101 || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_IMPLINT)
3102 && (SCIPvarGetType(consdata->vbdvar) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(consdata->vbdvar) == SCIP_VARTYPE_IMPLINT)
3103 && SCIPisLT(scip, REALABS(consdata->vbdcoef), 1.0) )
3104 {
3105 SCIP_Real epsilon;
3106 SCIP_Longint numerator;
3107 SCIP_Longint denominator;
3108 SCIP_Longint maxmult;
3109 SCIP_Bool success;
3110
3112 maxmult = MIN(maxmult, MAXSCALEDCOEF);
3113
3114 /* this ensures that one coefficient in the scaled constraint will be one as asserted below; 0.9 to be safe */
3115 epsilon = SCIPepsilon(scip) / (SCIP_Real)maxmult;
3116 epsilon *= 0.9;
3117
3118 success = SCIPrealToRational(consdata->vbdcoef, -epsilon, epsilon , maxmult, &numerator, &denominator);
3119
3120 if( success )
3121 {
3122 /* it is possible that the dominator is a multiple of the numerator */
3123 if( SCIPisIntegral(scip, (SCIP_Real) denominator / (SCIP_Real) numerator) )
3124 {
3125 denominator /= numerator;
3126 numerator = 1;
3127 }
3128
3129 success = success && (denominator <= maxmult);
3130
3131 /* scale the constraint denominator/numerator */
3132 if( success && ABS(denominator) > 1 && numerator == 1 )
3133 {
3134 SCIP_VAR* swapvar;
3135
3136 /* print constraint before scaling */
3137 SCIPdebugPrintCons(scip, conss[c], NULL);
3138
3139 assert(SCIPisEQ(scip, consdata->vbdcoef * denominator, 1.0));
3140
3141 /* need to switch sides if coefficient is smaller then 0 */
3142 if( consdata->vbdcoef < 0 )
3143 {
3144 assert(denominator < 0);
3145
3146 /* compute new sides */
3147
3148 /* only right hand side exists */
3149 if( SCIPisInfinity(scip, -consdata->lhs) )
3150 {
3151 consdata->lhs = consdata->rhs * denominator;
3152 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs));
3153
3154 consdata->rhs = SCIPinfinity(scip);
3155 }
3156 /* only left hand side exists */
3157 else if( SCIPisInfinity(scip, consdata->rhs) )
3158 {
3159 consdata->rhs = consdata->lhs * denominator;
3160 assert(!SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs));
3161
3162 consdata->lhs = -SCIPinfinity(scip);
3163 }
3164 /* both sides exist */
3165 else
3166 {
3167 SCIP_Real tmp;
3168
3169 tmp = consdata->lhs;
3170 consdata->lhs = consdata->rhs * denominator;
3171 consdata->rhs = tmp * denominator;
3172 consdata->tightened = FALSE;
3173
3174 assert(!SCIPisInfinity(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs));
3175 assert(SCIPisGE(scip, consdata->rhs, consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
3176 }
3177 *nchgsides += 2;
3178 }
3179 /* coefficient > 0 */
3180 else
3181 {
3182 assert(denominator > 0);
3183
3184 /* compute new left hand side */
3185 if( !SCIPisInfinity(scip, -consdata->lhs) )
3186 {
3187 consdata->lhs *= denominator;
3188 assert(!SCIPisInfinity(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs));
3189 ++(*nchgsides);
3190 }
3191
3192 /* compute new right hand side */
3193 if( !SCIPisInfinity(scip, consdata->rhs) )
3194 {
3195 consdata->rhs *= denominator;
3196 assert(!SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs));
3197 ++(*nchgsides);
3198 }
3199
3200 assert(SCIPisGE(scip, consdata->rhs, consdata->lhs));
3201 }
3202
3203 /* swap both variables */
3204 swapvar = consdata->var;
3205 consdata->var = consdata->vbdvar;
3206 consdata->vbdvar = swapvar;
3207
3208 /* swap coefficient */
3209 consdata->vbdcoef = (SCIP_Real)denominator;
3210 ++(*nchgcoefs);
3211
3212 /* mark to add new varbound information */
3213 consdata->varboundsadded = FALSE;
3214 consdata->tightened = FALSE;
3215
3216 /* print constraint after scaling */
3217 SCIPdebugMsg(scip, "transformed into:");
3218 SCIPdebugPrintCons(scip, conss[c], NULL);
3219 }
3220 }
3221 }
3222 }
3223}
3224
3225/** replaces fixed and aggregated variables in variable bound constraint by active problem variables */
3226static
3228 SCIP* scip, /**< SCIP data structure */
3229 SCIP_CONS* cons, /**< variable bound constraint */
3230 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
3231 SCIP_Bool* cutoff, /**< pointer to store whether an infeasibility was detected */
3232 int* nchgbds, /**< pointer to count number of bound changes */
3233 int* ndelconss, /**< pointer to count number of deleted constraints */
3234 int* naddconss /**< pointer to count number of added constraints */
3235 )
3236{
3237 SCIP_CONSDATA* consdata;
3238 SCIP_VAR* var;
3239 SCIP_VAR* vbdvar;
3240 SCIP_Real varscalar;
3241 SCIP_Real varconstant;
3242 SCIP_Real vbdvarscalar;
3243 SCIP_Real vbdvarconstant;
3244 SCIP_Real newbnd;
3245 SCIP_Bool varschanged;
3246 SCIP_Bool redundant;
3247
3248 assert(scip != NULL);
3249 assert(cons != NULL);
3250 assert(cutoff != NULL);
3251 assert(nchgbds != NULL);
3252 assert(ndelconss != NULL);
3253 assert(naddconss != NULL);
3254
3255 *cutoff = FALSE;
3256 redundant = FALSE;
3257
3258 /* the variable bound constraint is: lhs <= x + c*y <= rhs */
3259 consdata = SCIPconsGetData(cons);
3260 assert(consdata != NULL);
3261
3262 /* get active problem variables of x and y */
3263 var = consdata->var;
3264 varscalar = 1.0;
3265 varconstant = 0.0;
3266 SCIP_CALL( SCIPgetProbvarSum(scip, &var, &varscalar, &varconstant) );
3267 vbdvar = consdata->vbdvar;
3268 vbdvarscalar = 1.0;
3269 vbdvarconstant = 0.0;
3270 SCIP_CALL( SCIPgetProbvarSum(scip, &vbdvar, &vbdvarscalar, &vbdvarconstant) );
3271 varschanged = (var != consdata->var || vbdvar != consdata->vbdvar);
3272
3273 /* if the variables are equal, the variable bound constraint reduces to standard bounds on the single variable */
3274 if( var == vbdvar && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
3275 {
3276 SCIP_Real scalar;
3277 SCIP_Real constant;
3278
3279 SCIPdebugMsg(scip, "variable bound constraint <%s> has equal variable and vbd variable <%s>\n",
3280 SCIPconsGetName(cons), SCIPvarGetName(var));
3281
3282 /* lhs <= a1*z + b1 + c(a2*z + b2) <= rhs
3283 * <=> lhs <= (a1 + c*a2)z + (b1 + c*b2) <= rhs
3284 */
3285 scalar = varscalar + consdata->vbdcoef * vbdvarscalar;
3286 constant = varconstant + consdata->vbdcoef * vbdvarconstant;
3287 if( SCIPisZero(scip, scalar) )
3288 {
3289 /* no variable is left: the constraint is redundant or infeasible */
3290 if( SCIPisFeasLT(scip, constant, consdata->lhs) || SCIPisFeasGT(scip, constant, consdata->rhs) )
3291 {
3292 *cutoff = TRUE;
3293 return SCIP_OKAY;
3294 }
3295 }
3296 else if( scalar > 0.0 )
3297 {
3298 if( !SCIPisInfinity(scip, -consdata->lhs) )
3299 {
3300 SCIP_Bool tightened;
3301
3302 newbnd = (consdata->lhs - constant) / scalar;
3303 SCIP_CALL( SCIPtightenVarLb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3304 if( *cutoff )
3305 {
3306 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3307 return SCIP_OKAY;
3308 }
3309 if( tightened )
3310 {
3311 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var));
3312 (*nchgbds)++;
3313 }
3314 }
3315 if( !SCIPisInfinity(scip, consdata->rhs) )
3316 {
3317 SCIP_Bool tightened;
3318
3319 newbnd = (consdata->rhs - constant) / scalar;
3320 SCIP_CALL( SCIPtightenVarUb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3321 if( *cutoff )
3322 {
3323 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3324 return SCIP_OKAY;
3325 }
3326 if( tightened )
3327 {
3328 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(var), SCIPvarGetUbGlobal(var));
3329 (*nchgbds)++;
3330 }
3331 }
3332 }
3333 else
3334 {
3335 if( !SCIPisInfinity(scip, -consdata->lhs) )
3336 {
3337 SCIP_Bool tightened;
3338
3339 newbnd = (consdata->lhs - constant) / scalar;
3340 SCIP_CALL( SCIPtightenVarUb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3341 if( *cutoff )
3342 {
3343 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3344 return SCIP_OKAY;
3345 }
3346 if( tightened )
3347 {
3348 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(var), SCIPvarGetUbGlobal(var));
3349 (*nchgbds)++;
3350 }
3351 }
3352 if( !SCIPisInfinity(scip, consdata->rhs) )
3353 {
3354 SCIP_Bool tightened;
3355
3356 newbnd = (consdata->rhs - constant) / scalar;
3357 SCIP_CALL( SCIPtightenVarLb(scip, var, newbnd, TRUE, cutoff, &tightened) );
3358 if( *cutoff )
3359 {
3360 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(var), newbnd);
3361 return SCIP_OKAY;
3362 }
3363 if( tightened )
3364 {
3365 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var));
3366 (*nchgbds)++;
3367 }
3368 }
3369 }
3370 redundant = TRUE;
3371 }
3372 else
3373 {
3374 /* if the variables should be replaced, drop the events and catch the events on the new variables afterwards */
3375 if( varschanged )
3376 {
3377 SCIP_CALL( dropEvents(scip, cons, eventhdlr) );
3378 }
3379
3380 /* apply aggregation on x */
3381 if( SCIPisZero(scip, varscalar) )
3382 {
3383 /* the variable being fixed or corresponding to an aggregation might lead to numerical difficulties */
3384 if( SCIPisZero(scip, consdata->vbdcoef * vbdvarscalar) )
3385 {
3386 assert(SCIPisEQ(scip, varconstant, SCIPvarGetLbGlobal(consdata->var)));
3387 assert(SCIPisEQ(scip, varconstant, SCIPvarGetUbGlobal(consdata->var)));
3388 assert(SCIPisEQ(scip, vbdvarconstant, SCIPvarGetLbGlobal(consdata->vbdvar)));
3389 assert(SCIPisEQ(scip, vbdvarconstant, SCIPvarGetUbGlobal(consdata->vbdvar)));
3390 SCIP_Real activity = varconstant + consdata->vbdcoef * vbdvarconstant;
3391
3392 SCIPdebugMsg(scip, "variable bound constraint <%s>: variable <%s> is fixed to %.15g\n",
3393 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), varconstant);
3394
3395 if( ( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasLT(scip, activity, consdata->lhs) )
3396 || ( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasGT(scip, activity, consdata->rhs) ) )
3397 *cutoff = TRUE;
3398
3399 redundant = TRUE;
3400 }
3401 /* cannot change bounds on multi-aggregated variables */
3402 else if( SCIPvarGetStatus(vbdvar) != SCIP_VARSTATUS_MULTAGGR )
3403 {
3404 assert( consdata->vbdcoef != 0.0 );
3405 assert( vbdvarscalar != 0.0 );
3406
3407 /* x is fixed to varconstant: update bounds of y and delete the variable bound constraint */
3408 if( !(*cutoff) && !SCIPisInfinity(scip, -consdata->lhs) )
3409 {
3410 if( consdata->vbdcoef > 0.0 )
3411 {
3412 SCIP_Bool tightened;
3413
3414 newbnd = (consdata->lhs - varconstant) / consdata->vbdcoef;
3415 SCIP_CALL( SCIPtightenVarLb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3416 if( *cutoff )
3417 {
3418 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3419 }
3420 else if( tightened )
3421 {
3422 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbGlobal(consdata->vbdvar));
3423 (*nchgbds)++;
3424 }
3425 }
3426 else
3427 {
3428 SCIP_Bool tightened;
3429
3430 newbnd = (consdata->lhs - varconstant) / consdata->vbdcoef;
3431 SCIP_CALL( SCIPtightenVarUb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3432 if( *cutoff )
3433 {
3434 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3435 }
3436 else if( tightened )
3437 {
3438 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetUbGlobal(consdata->vbdvar));
3439 (*nchgbds)++;
3440 }
3441 }
3442 }
3443 if( !(*cutoff) && !SCIPisInfinity(scip, consdata->rhs) )
3444 {
3445 if( consdata->vbdcoef > 0.0 )
3446 {
3447 SCIP_Bool tightened;
3448
3449 newbnd = (consdata->rhs - varconstant) / consdata->vbdcoef;
3450 SCIP_CALL( SCIPtightenVarUb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3451 if( *cutoff )
3452 {
3453 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3454 }
3455 else if( tightened )
3456 {
3457 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetUbGlobal(consdata->vbdvar));
3458 (*nchgbds)++;
3459 }
3460 }
3461 else
3462 {
3463 SCIP_Bool tightened;
3464
3465 newbnd = (consdata->rhs - varconstant) / consdata->vbdcoef;
3466 SCIP_CALL( SCIPtightenVarLb(scip, consdata->vbdvar, newbnd, TRUE, cutoff, &tightened) );
3467 if( *cutoff )
3468 {
3469 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(consdata->vbdvar), newbnd);
3470 }
3471 else if( tightened )
3472 {
3473 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbGlobal(consdata->vbdvar));
3474 (*nchgbds)++;
3475 }
3476 }
3477 }
3478 redundant = TRUE;
3479 }
3480 }
3481 else if( var != consdata->var )
3482 {
3483 /* release and unlock old variable */
3484 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3485 !SCIPisInfinity(scip, consdata->rhs)) );
3486 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->var)) );
3487
3488 /* unlock vbdvar, because we possibly change lhs/rhs/vbdcoef */
3489 if( consdata->vbdcoef > 0.0 )
3490 {
3491 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3492 !SCIPisInfinity(scip, consdata->rhs)) );
3493 }
3494 else
3495 {
3496 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3497 !SCIPisInfinity(scip, -consdata->lhs)) );
3498 }
3499
3500 /* replace aggregated variable x in the constraint by its aggregation */
3501 if( varscalar > 0.0 )
3502 {
3503 /* lhs := (lhs - varconstant) / varscalar
3504 * rhs := (rhs - varconstant) / varscalar
3505 * c := c / varscalar
3506 */
3507 if( !SCIPisInfinity(scip, -consdata->lhs) )
3508 consdata->lhs = (consdata->lhs - varconstant)/varscalar;
3509 if( !SCIPisInfinity(scip, consdata->rhs) )
3510 consdata->rhs = (consdata->rhs - varconstant)/varscalar;
3511 consdata->vbdcoef /= varscalar;
3512
3513 /* try to avoid numerical troubles */
3514 if( SCIPisIntegral(scip, consdata->vbdcoef) )
3515 consdata->vbdcoef = SCIPround(scip, consdata->vbdcoef);
3516
3517 consdata->tightened = FALSE;
3518 }
3519 else
3520 {
3521 SCIP_Real lhs;
3522
3523 assert(varscalar != 0.0);
3524
3525 /* lhs := (rhs - varconstant) / varscalar
3526 * rhs := (lhs - varconstant) / varscalar
3527 * c := c / varscalar
3528 */
3529 lhs = consdata->lhs;
3530 consdata->lhs = -consdata->rhs;
3531 consdata->rhs = -lhs;
3532 if( !SCIPisInfinity(scip, -consdata->lhs) )
3533 consdata->lhs = (consdata->lhs + varconstant)/(-varscalar);
3534 if( !SCIPisInfinity(scip, consdata->rhs) )
3535 consdata->rhs = (consdata->rhs + varconstant)/(-varscalar);
3536 consdata->vbdcoef /= varscalar;
3537
3538 /* try to avoid numerical troubles */
3539 if( SCIPisIntegral(scip, consdata->vbdcoef) )
3540 consdata->vbdcoef = SCIPround(scip, consdata->vbdcoef);
3541
3542 consdata->tightened = FALSE;
3543 }
3544
3545 consdata->var = var;
3546
3547 /* capture and lock new variable */
3548 SCIP_CALL( SCIPcaptureVar(scip, consdata->var) );
3549 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3550 !SCIPisInfinity(scip, consdata->rhs)) );
3551
3552 /* lock vbdvar */
3553 if( consdata->vbdcoef > 0.0 )
3554 {
3555 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3556 !SCIPisInfinity(scip, consdata->rhs)) );
3557 }
3558 else
3559 {
3560 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3561 !SCIPisInfinity(scip, -consdata->lhs)) );
3562 }
3563 }
3564
3565 /* apply aggregation on y */
3566 if( SCIPisZero(scip, consdata->vbdcoef * vbdvarscalar) )
3567 {
3568 SCIPdebugMsg(scip, "variable bound constraint <%s>: vbd variable <%s> is fixed to %.15g\n",
3569 SCIPconsGetName(cons), SCIPvarGetName(consdata->vbdvar), vbdvarconstant);
3570
3571 /* cannot change bounds on multi-aggregated variables */
3572 if( !redundant && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
3573 {
3574 assert( SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED );
3575 assert( !SCIPisZero(scip, varscalar) );
3576
3577 /* y is fixed to vbdvarconstant: update bounds of x and delete the variable bound constraint */
3578 if( !(*cutoff) && !SCIPisInfinity(scip, -consdata->lhs) )
3579 {
3580 SCIP_Bool tightened;
3581
3582 newbnd = consdata->lhs - consdata->vbdcoef * vbdvarconstant;
3583 SCIP_CALL( SCIPtightenVarLb(scip, consdata->var, newbnd, TRUE, cutoff, &tightened) );
3584 if( *cutoff )
3585 {
3586 SCIPdebugMsg(scip, " -> tightening <%s> >= %.15g infeasible\n", SCIPvarGetName(consdata->var), newbnd);
3587 }
3588 else if( tightened )
3589 {
3590 SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->var), SCIPvarGetLbGlobal(consdata->var));
3591 (*nchgbds)++;
3592 }
3593 }
3594 if( !(*cutoff) && !SCIPisInfinity(scip, consdata->rhs) )
3595 {
3596 SCIP_Bool tightened;
3597
3598 newbnd = consdata->rhs - consdata->vbdcoef * vbdvarconstant;
3599 SCIP_CALL( SCIPtightenVarUb(scip, consdata->var, newbnd, TRUE, cutoff, &tightened) );
3600 if( *cutoff )
3601 {
3602 SCIPdebugMsg(scip, " -> tightening <%s> <= %.15g infeasible\n", SCIPvarGetName(consdata->var), newbnd);
3603 }
3604 else if( tightened )
3605 {
3606 SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->var), SCIPvarGetUbGlobal(consdata->var));
3607 (*nchgbds)++;
3608 }
3609 }
3610 redundant = TRUE;
3611 }
3612 }
3613 else if( !(*cutoff) && vbdvar != consdata->vbdvar )
3614 {
3615 /* release and unlock old variable */
3616 if( consdata->vbdcoef > 0.0 )
3617 {
3618 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3619 !SCIPisInfinity(scip, consdata->rhs)) );
3620 }
3621 else
3622 {
3623 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3624 !SCIPisInfinity(scip, -consdata->lhs)) );
3625 }
3626 SCIP_CALL( SCIPreleaseVar(scip, &(consdata->vbdvar)) );
3627
3628 /* also unlock var, because we possibly change lhs/rhs/vbdcoef */
3629 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3630 !SCIPisInfinity(scip, consdata->rhs)) );
3631
3632 /* replace aggregated variable y in the constraint by its aggregation:
3633 * lhs := lhs - c * vbdvarconstant
3634 * rhs := rhs - c * vbdvarconstant
3635 * c := c * vbdvarscalar
3636 */
3637 if( !SCIPisInfinity(scip, -consdata->lhs) )
3638 consdata->lhs -= consdata->vbdcoef * vbdvarconstant;
3639 if( !SCIPisInfinity(scip, consdata->rhs) )
3640 consdata->rhs -= consdata->vbdcoef * vbdvarconstant;
3641
3642 consdata->tightened = FALSE;
3643 consdata->vbdcoef *= vbdvarscalar;
3644 consdata->vbdvar = vbdvar;
3645
3646 /* capture and lock new variable */
3647 SCIP_CALL( SCIPcaptureVar(scip, consdata->vbdvar) );
3648 if( consdata->vbdcoef > 0.0 )
3649 {
3650 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, -consdata->lhs),
3651 !SCIPisInfinity(scip, consdata->rhs)) );
3652 }
3653 else
3654 {
3655 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, !SCIPisInfinity(scip, consdata->rhs),
3656 !SCIPisInfinity(scip, -consdata->lhs)) );
3657 }
3658 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, !SCIPisInfinity(scip, -consdata->lhs),
3659 !SCIPisInfinity(scip, consdata->rhs)) );
3660 }
3661
3662 /* catch the events again on the new variables */
3663 if( varschanged )
3664 {
3665 SCIP_CALL( catchEvents(scip, cons, eventhdlr) );
3666 }
3667
3668 /* terminate on cutoff after catching events */
3669 if( *cutoff )
3670 return SCIP_OKAY;
3671 }
3672
3673 /* mark constraint changed, if a variable was exchanged */
3674 if( varschanged )
3675 {
3676 consdata->changed = TRUE;
3677 }
3678
3679 /* active multi aggregations are now resolved by creating a new linear constraint */
3680 if( !redundant && (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR || SCIPvarGetStatus(vbdvar) == SCIP_VARSTATUS_MULTAGGR) )
3681 {
3682 SCIP_CONS* newcons;
3683 SCIP_Real lhs;
3684 SCIP_Real rhs;
3685
3686 lhs = consdata->lhs;
3687 rhs = consdata->rhs;
3688
3689 /* create upgraded linear constraint */
3690 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons), 0, NULL, NULL, lhs, rhs,
3695
3696 /* if var was fixed, then the case that vbdvar was multi-aggregated, was not yet resolved */
3697 if( var != consdata->var )
3698 {
3699 assert(SCIPvarGetStatus(vbdvar) == SCIP_VARSTATUS_MULTAGGR);
3700 assert(SCIPisZero(scip, varscalar)); /* this means that var was fixed */
3701
3702 /* add offset that results from the fixed variable */
3703 if( ! SCIPisZero(scip, varconstant) )
3704 {
3705 if( !SCIPisInfinity(scip, rhs) )
3706 {
3707 SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs - varconstant) );
3708 }
3709 if( !SCIPisInfinity(scip, -lhs) )
3710 {
3711 SCIP_CALL( SCIPchgLhsLinear(scip, newcons, lhs - varconstant) );
3712 }
3713 }
3714 }
3715 else
3716 {
3717 assert(var == consdata->var);
3718
3719 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, consdata->var, 1.0) );
3720 }
3721
3722 /* if vbdvar was fixed, then the case that var was multi-aggregated, was not yet resolved */
3723 if( vbdvar != consdata->vbdvar )
3724 {
3726 assert(SCIPisZero(scip, vbdvarscalar)); /* this means that var was fixed */
3727
3728 /* add offset that results from the fixed variable */
3729 if( ! SCIPisZero(scip, vbdvarconstant) )
3730 {
3731 if( !SCIPisInfinity(scip, rhs) )
3732 {
3733 SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs - consdata->vbdcoef * vbdvarconstant) );
3734 }
3735 if( !SCIPisInfinity(scip, -lhs) )
3736 {
3737 SCIP_CALL( SCIPchgLhsLinear(scip, newcons, lhs - consdata->vbdcoef * vbdvarconstant) );
3738 }
3739 }
3740 }
3741 else
3742 {
3743 assert(vbdvar == consdata->vbdvar);
3744
3745 SCIP_CALL( SCIPaddCoefLinear(scip, newcons, consdata->vbdvar, consdata->vbdcoef) );
3746 }
3747
3748 SCIP_CALL( SCIPaddCons(scip, newcons) );
3749
3750 SCIPdebugMsg(scip, "resolved multi aggregation in varbound constraint <%s> by creating a new linear constraint\n", SCIPconsGetName(cons));
3751 SCIPdebugPrintCons(scip, newcons, NULL);
3752
3753 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3754
3755 redundant = TRUE;
3756 ++(*naddconss);
3757 }
3758
3759 /* delete a redundant constraint */
3760 if( redundant )
3761 {
3762 SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
3763 SCIP_CALL( SCIPdelCons(scip, cons) );
3764 (*ndelconss)++;
3765 }
3766
3767 return SCIP_OKAY;
3768}
3769
3770/** tightens variable bound coefficient by inspecting the global bounds of the involved variables; note: this is also
3771 * performed by the linear constraint handler - only necessary if the user directly creates variable bound constraints
3772 */
3773static
3775 SCIP* scip, /**< SCIP data structure */
3776 SCIP_CONS* cons, /**< variable bound constraint */
3777 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3778 int* nchgsides, /**< pointer to count the number of left and right hand sides */
3779 int* ndelconss, /**< pointer to count number of deleted constraints */
3780 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3781 int* nchgbds /**< pointer to count number of bound changes */
3782 )
3783{
3784 SCIP_CONSDATA* consdata;
3785 SCIP_Real xlb;
3786 SCIP_Real xub;
3787 SCIP_Real oldcoef;
3788 int oldnchgcoefs;
3789 int oldnchgsides;
3790
3791 assert(nchgcoefs != NULL);
3792 assert(nchgsides != NULL);
3793 assert(ndelconss != NULL);
3794
3795 consdata = SCIPconsGetData(cons);
3796 assert(consdata != NULL);
3797
3798 /* tightening already done */
3799 if( consdata->tightened )
3800 return SCIP_OKAY;
3801
3802 SCIPdebugMsg(scip, "tightening coefficients on variable bound constraint <%s>\n", SCIPconsGetName(cons));
3803
3804 consdata->tightened = TRUE;
3805
3806 /* if values and variable are integral the sides should it be too */
3807 if( SCIPvarGetType(consdata->var) <= SCIP_VARTYPE_IMPLINT
3808 && SCIPvarGetType(consdata->vbdvar) <= SCIP_VARTYPE_IMPLINT
3809 && SCIPisIntegral(scip, consdata->vbdcoef) )
3810 {
3811 if( !SCIPisIntegral(scip, consdata->lhs) )
3812 {
3813 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3814 ++(*nchgsides);
3815 consdata->changed = TRUE;
3816 }
3817 if( !SCIPisIntegral(scip, consdata->rhs) )
3818 {
3819 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3820 ++(*nchgsides);
3821 consdata->changed = TRUE;
3822 }
3823 }
3824
3825 /* coefficient tightening only works for binary bound variable */
3826 if( !SCIPvarIsBinary(consdata->vbdvar) )
3827 return SCIP_OKAY;
3828
3829 oldnchgcoefs = *nchgcoefs;
3830 oldnchgsides = *nchgsides;
3831 oldcoef = consdata->vbdcoef;
3832
3833 /* coefficients tightening when all variables are integer */
3834 /* we consider the following varbound constraint: lhs <= x + b*y <= rhs (sides are possibly infinity)
3835 * y should always be binary and x of integral type and b not integral, we also need at least one side with infinity
3836 * or not integral value.
3837 *
3838 * 1. if( (lhs is integral and not -infinity) and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3839 *
3840 * lhs <= x + b*y <= rhs => lhs <= x + floor(b)*y <= floor(rhs)
3841 *
3842 * 2. if( (rhs is integral and not infinity) and ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs))) ):
3843 *
3844 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= rhs
3845 *
3846 * 3. if( ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs)))
3847 * and ((rhs is infinity) or (b - floor(b) > rhs - floor(rhs))) ):
3848 *
3849 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= floor(rhs)
3850 *
3851 * 4. if( ((lhs is -infinity) or (b - floor(b) < lhs - floor(lhs)))
3852 * and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3853 *
3854 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + floor(b)*y <= floor(rhs)
3855 *
3856 * 5. if( (lhs is not integral) or (rhs is not integral) )
3857 *
3858 * if (lhs is not -infinity)
3859 * if (b - floor(b) < lhs - floor(lhs)):
3860 *
3861 * lhs <= x + b*y => ceil(lhs) <= x + b*y
3862 *
3863 * else if (b - floor(b) > lhs - floor(lhs)):
3864 *
3865 * lhs <= x + b*y => floor(lhs) + b - floor(b) <= x + b*y
3866 *
3867 * if (rhs is not infinity)
3868 * if (b - floor(b) < rhs - floor(rhs)):
3869 *
3870 * x + b*y <= rhs => x + b*y <= floor(rhs) + b - floor(b)
3871 *
3872 * else if (b - floor(b) > rhs - floor(rhs)):
3873 *
3874 * x + b*y <= rhs => x + b*y <= floor(rhs)
3875 */
3876 if( (SCIPvarGetType(consdata->var) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_IMPLINT || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_BINARY)
3877 && !SCIPisIntegral(scip, consdata->vbdcoef)
3878 && (!SCIPisIntegral(scip, consdata->lhs) || SCIPisInfinity(scip, -consdata->lhs)
3879 || !SCIPisIntegral(scip, consdata->rhs) || SCIPisInfinity(scip, consdata->rhs)) )
3880 {
3881 /* infinity should be an integral value */
3882 assert(!SCIPisInfinity(scip, -consdata->lhs) || SCIPisIntegral(scip, consdata->lhs));
3883 assert(!SCIPisInfinity(scip, consdata->rhs) || SCIPisIntegral(scip, consdata->rhs));
3884
3885 /* should not be a redundant constraint */
3886 assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
3887
3888 /* case 1 */
3889 if( SCIPisIntegral(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs) &&
3890 (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
3891 {
3892 consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
3893 ++(*nchgcoefs);
3894
3895 if( !SCIPisInfinity(scip, consdata->rhs) )
3896 {
3897 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3898 ++(*nchgsides);
3899 }
3900 }
3901 /* case 2 */
3902 else if( SCIPisIntegral(scip, consdata->rhs) && !SCIPisInfinity(scip, consdata->rhs) &&
3903 (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) )
3904 {
3905 consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
3906 ++(*nchgcoefs);
3907
3908 if( !SCIPisInfinity(scip, -consdata->lhs) )
3909 {
3910 if( !SCIPisIntegral(scip, consdata->lhs) )
3911 ++(*nchgsides);
3912
3913 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3914 }
3915 }
3916 /* case 3 */
3917 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))) )
3918 {
3919 consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
3920 ++(*nchgcoefs);
3921
3922 if( !SCIPisInfinity(scip, -consdata->lhs) )
3923 {
3924 if( !SCIPisIntegral(scip, consdata->lhs) )
3925 ++(*nchgsides);
3926
3927 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3928 }
3929 if( !SCIPisInfinity(scip, consdata->rhs) )
3930 {
3931 if( !SCIPisIntegral(scip, consdata->rhs) )
3932 ++(*nchgsides);
3933
3934 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3935 }
3936 }
3937 /* case 4 */
3938 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))) )
3939 {
3940 consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
3941 ++(*nchgcoefs);
3942
3943 if( !SCIPisInfinity(scip, -consdata->lhs) )
3944 {
3945 if( !SCIPisIntegral(scip, consdata->lhs) )
3946 ++(*nchgsides);
3947
3948 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3949 }
3950 if( !SCIPisInfinity(scip, consdata->rhs) )
3951 {
3952 if( !SCIPisIntegral(scip, consdata->rhs) )
3953 ++(*nchgsides);
3954
3955 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3956 }
3957 }
3958 /* case 5 */
3959 if( !SCIPisFeasIntegral(scip, consdata->lhs) || !SCIPisFeasIntegral(scip, consdata->rhs) )
3960 {
3961 if( !SCIPisInfinity(scip, -consdata->lhs) )
3962 {
3963 if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
3964 {
3965 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3966 ++(*nchgsides);
3967 }
3968 else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
3969 {
3970 consdata->lhs = SCIPfeasFloor(scip, consdata->lhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
3971 ++(*nchgsides);
3972 }
3973 }
3974 if( !SCIPisInfinity(scip, consdata->rhs) )
3975 {
3976 if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
3977 {
3978 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
3979 ++(*nchgsides);
3980 }
3981 else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
3982 {
3983 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3984 ++(*nchgsides);
3985 }
3986 }
3987 }
3988 }
3989
3990 /* check if due to tightening the constraint got redundant */
3991 if( SCIPisZero(scip, consdata->vbdcoef) )
3992 {
3993 /* we have to make sure that the induced bound(s) is (are) actually applied;
3994 * if the relative change is too small, this may have been skipped in propagation
3995 */
3996 if( SCIPisLT(scip, SCIPvarGetLbGlobal(consdata->var), consdata->lhs) )
3997 {
3998 SCIP_Bool tightened;
3999
4000 SCIP_CALL( SCIPtightenVarLbGlobal(scip, consdata->var, consdata->lhs, TRUE, cutoff, &tightened) );
4001 if( *cutoff )
4002 {
4003 SCIPdebugMsg(scip, " -> tightening lower bound of <%s> to %.15g infeasible\n", SCIPvarGetName(consdata->var),
4004 consdata->lhs);
4005 return SCIP_OKAY;
4006 }
4007 if( tightened )
4008 {
4009 SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
4010 SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
4011 (*nchgbds)++;
4012 }
4013 }
4014 if( SCIPisGT(scip, SCIPvarGetUbGlobal(consdata->var), consdata->rhs) )
4015 {
4016 SCIP_Bool tightened;
4017
4018 SCIP_CALL( SCIPtightenVarUbGlobal(scip, consdata->var, consdata->rhs, TRUE, cutoff, &tightened) );
4019 if( *cutoff )
4020 {
4021 SCIPdebugMsg(scip, " -> tightening upper bound of <%s> to %.15g infeasible\n", SCIPvarGetName(consdata->var),
4022 consdata->rhs);
4023 return SCIP_OKAY;
4024 }
4025 if( tightened )
4026 {
4027 SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
4028 SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
4029 (*nchgbds)++;
4030 }
4031 }
4032
4033 SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
4034
4035 /* in order to correctly update the rounding locks, we need the coefficient to have the same sign as before the
4036 * coefficient tightening
4037 */
4038 consdata->vbdcoef = oldcoef;
4039
4040 SCIP_CALL( SCIPdelCons(scip, cons) );
4041 ++(*ndelconss);
4042
4043 return SCIP_OKAY;
4044 }
4045
4046 /* get bounds of variable x */
4047 xlb = SCIPvarGetLbGlobal(consdata->var);
4048 xub = SCIPvarGetUbGlobal(consdata->var);
4049
4050 /* it can happen that var is not of varstatus SCIP_VARSTATUS_FIXED but the bounds are equal, in this case we need to
4051 * stop
4052 */
4053 if( SCIPisEQ(scip, xlb, xub) )
4054 return SCIP_OKAY;
4055
4056 /* modification of coefficient checking for slack in constraints */
4057 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
4058 {
4059 /* lhs <= x + c*y <= rhs => lhs - c*y <= x <= rhs - c*y */
4060 if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) && SCIPisFeasLT(scip, xub, consdata->rhs) )
4061 {
4062 SCIP_Real newcoef;
4063 SCIP_Real newrhs;
4064 SCIP_Real oldrhs;
4065
4066 oldrhs = consdata->rhs;
4067
4068 /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
4069 * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
4070 * -> c' = MAX(c - rhs + xub, lhs - xlb), rhs' = rhs - c + c'
4071 */
4072 newcoef = MAX(consdata->vbdcoef - consdata->rhs + xub, consdata->lhs - xlb);
4073
4074 /* in this case both sides are redundant and the constraint can be removed */
4075 if( SCIPisLE(scip, newcoef, 0.0) )
4076 {
4077 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4078 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4079
4080 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4081 SCIP_CALL( SCIPdelCons(scip, cons) );
4082 ++(*ndelconss);
4083 }
4084 else
4085 {
4086 newrhs = consdata->rhs - consdata->vbdcoef + newcoef;
4087
4089 "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
4090 consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef,
4091 SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4092 consdata->lhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar),
4093 newrhs);
4094
4095 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4096 assert(consdata->vbdcoef * newcoef > 0);
4097
4098 consdata->vbdcoef = newcoef;
4099 consdata->rhs = MAX(newrhs, consdata->lhs);
4100 (*nchgcoefs)++;
4101 (*nchgsides)++;
4102
4103 /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
4104 * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
4105 * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
4106 */
4107 if( !SCIPisFeasIntegral(scip, oldrhs) && SCIPisFeasIntegral(scip, newrhs))
4108 {
4109 consdata->tightened = FALSE;
4110 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4111 assert(consdata->tightened);
4112 assert(!(*cutoff));
4113 }
4114 else
4115 consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->rhs));
4116 }
4117 }
4118 else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
4119 {
4120 SCIP_Real newcoef;
4121 SCIP_Real newlhs;
4122 SCIP_Real oldlhs;
4123
4124 oldlhs = consdata->lhs;
4125
4126 /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
4127 * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
4128 * -> c' = MIN(c - lhs + xlb, rhs - xub), lhs' = lhs - c + c'
4129 */
4130 newcoef = MIN(consdata->vbdcoef - consdata->lhs + xlb, consdata->rhs - xub);
4131
4132 /* in this case both sides are redundant and the constraint can be removed */
4133 if( SCIPisGE(scip, newcoef, 0.0) )
4134 {
4135 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4136 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4137
4138 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4139 SCIP_CALL( SCIPdelCons(scip, cons) );
4140 ++(*ndelconss);
4141 }
4142 else
4143 {
4144 newlhs = consdata->lhs - consdata->vbdcoef + newcoef;
4145
4147 "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
4148 consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef,
4149 SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4150 newlhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar),
4151 consdata->rhs);
4152
4153 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4154 assert(consdata->vbdcoef * newcoef > 0);
4155
4156 consdata->vbdcoef = newcoef;
4157 consdata->lhs = MIN(newlhs, consdata->rhs);
4158 (*nchgcoefs)++;
4159 (*nchgsides)++;
4160
4161 /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
4162 * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
4163 * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
4164 */
4165 if( !SCIPisFeasIntegral(scip, oldlhs) && SCIPisFeasIntegral(scip, newlhs))
4166 {
4167 consdata->tightened = FALSE;
4168 SCIP_CALL(tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds));
4169 assert(consdata->tightened);
4170 assert(!(*cutoff));
4171 }
4172 else
4173 consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->lhs));
4174 }
4175 }
4176 }
4177 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, consdata->rhs) )
4178 {
4179 /* lhs <= x + c*y => x >= lhs - c*y */
4180 if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) )
4181 {
4182 SCIP_Real newcoef;
4183
4184 /* constraint has positive slack for the non-restricting case y = 1
4185 * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
4186 * -> c' = lhs - xlb
4187 */
4188 newcoef = consdata->lhs - xlb;
4189
4190 /* in this case the constraint is redundant and can be removed */
4191 if( SCIPisLE(scip, newcoef, 0.0) )
4192 {
4193 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4194
4195 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4196 SCIP_CALL( SCIPdelCons(scip, cons) );
4197 ++(*ndelconss);
4198 }
4199 else
4200 {
4201 SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
4202 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4203 consdata->lhs,
4204 SCIPvarGetName(consdata->var), consdata->lhs - xlb, SCIPvarGetName(consdata->vbdvar),
4205 consdata->lhs);
4206
4207 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4208 assert(consdata->vbdcoef * newcoef > 0);
4209
4210 consdata->vbdcoef = newcoef;
4211 (*nchgcoefs)++;
4212 }
4213 }
4214 else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) )
4215 {
4216 SCIP_Real newcoef;
4217
4218 /* constraint has positive slack for the non-restricting case y = 0
4219 * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
4220 * -> c' = c - lhs + xlb, lhs' = xlb
4221 */
4222 newcoef = consdata->vbdcoef - consdata->lhs + xlb;
4223
4224 /* in this case the constraint is redundant and can be removed */
4225 if( SCIPisGE(scip, newcoef, 0.0) )
4226 {
4227 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4228
4229 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4230 SCIP_CALL( SCIPdelCons(scip, cons) );
4231 ++(*ndelconss);
4232 }
4233 else
4234 {
4235 SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
4236 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4237 consdata->lhs,
4238 SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->lhs + xlb,
4239 SCIPvarGetName(consdata->vbdvar), xlb);
4240
4241 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4242 assert(consdata->vbdcoef * newcoef > 0);
4243
4244 consdata->vbdcoef = newcoef;
4245 consdata->lhs = xlb;
4246 (*nchgcoefs)++;
4247 (*nchgsides)++;
4248 }
4249 }
4250 }
4251 else if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
4252 {
4253 /* x + c*y <= rhs => x <= rhs - c*y */
4254 if( consdata->vbdcoef > 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs) )
4255 {
4256 SCIP_Real newcoef;
4257
4258 /* constraint has positive slack for the non-restricting case y = 0
4259 * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
4260 * -> c' = c - rhs + xub, rhs' = xub
4261 */
4262 newcoef = consdata->vbdcoef - consdata->rhs + xub;
4263
4264 /* in this case the constraint is redundant and can be removed */
4265 if( SCIPisLE(scip, newcoef, 0.0) )
4266 {
4267 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4268
4269 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4270 SCIP_CALL( SCIPdelCons(scip, cons) );
4271 ++(*ndelconss);
4272 }
4273 else
4274 {
4275 SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
4276 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4277 consdata->rhs,
4278 SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->rhs + xub,
4279 SCIPvarGetName(consdata->vbdvar), xub);
4280
4281 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4282 assert(consdata->vbdcoef * newcoef > 0);
4283
4284 consdata->vbdcoef = newcoef;
4285 consdata->rhs = xub;
4286 (*nchgcoefs)++;
4287 (*nchgsides)++;
4288 }
4289 }
4290 else if( consdata->vbdcoef < 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
4291 {
4292 SCIP_Real newcoef;
4293
4294 /* constraint has positive slack for the non-restricting case y = 1
4295 * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
4296 * -> c' = rhs - xub
4297 */
4298 newcoef = consdata->rhs - xub;
4299
4300 /* in this case the constraint is redundant and can be removed */
4301 if( SCIPisGE(scip, newcoef, 0.0) )
4302 {
4303 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4304
4305 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4306 SCIP_CALL( SCIPdelCons(scip, cons) );
4307 ++(*ndelconss);
4308 }
4309 else
4310 {
4311 SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
4312 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4313 SCIPvarGetName(consdata->var), consdata->rhs - xub, SCIPvarGetName(consdata->vbdvar), consdata->rhs);
4314
4315 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4316 assert(consdata->vbdcoef * newcoef > 0);
4317
4318 consdata->vbdcoef = newcoef;
4319 (*nchgcoefs)++;
4320 }
4321 }
4322 }
4323
4324 /* if something a coefficient or side of the varbound constraint was changed, ensure that the variable lower or
4325 * upper bounds of the variables are informed
4326 */
4327 if( *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
4328 {
4329 consdata->varboundsadded = FALSE;
4330 consdata->changed = TRUE;
4331
4333 }
4334
4335 return SCIP_OKAY;
4336}
4337
4338/** check if we can upgrade to a set-packing constraint */
4339static
4341 SCIP* scip, /**< SCIP data structure */
4342 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
4343 SCIP_CONS** conss, /**< constraint set */
4344 int nconss, /**< number of constraints in constraint set */
4345 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4346 int* naggrvars, /**< pointer to count the number of aggregated variables */
4347 int* nchgbds, /**< pointer to count number of bound changes */
4348 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
4349 int* nchgsides, /**< pointer to count the number of left and right hand sides */
4350 int* ndelconss, /**< pointer to count the number of deleted constraints */
4351 int* naddconss /**< pointer to count the number of added constraints */
4352 )
4353{
4354 SCIP_VAR* vars[2];
4355 SCIP_CONS* newcons;
4356 SCIP_CONS* cons;
4357 SCIP_CONSDATA* consdata;
4358 int c;
4359
4360 assert(scip != NULL);
4361 assert(conshdlrdata != NULL);
4362 assert(conss != NULL || nconss == 0);
4363 assert(cutoff != NULL);
4364 assert(naggrvars != NULL);
4365 assert(nchgbds != NULL);
4366 assert(nchgcoefs != NULL);
4367 assert(nchgsides != NULL);
4368 assert(ndelconss != NULL);
4369 assert(naddconss != NULL);
4370
4371 /* if we cannot find any constraint for upgrading, stop */
4373 return SCIP_OKAY;
4374
4375 if( nconss == 0 )
4376 return SCIP_OKAY;
4377
4378 assert(conss != NULL);
4379
4380 for( c = nconss - 1; c >= 0; --c )
4381 {
4382 cons = conss[c];
4383 assert(cons != NULL);
4384
4385 if( !SCIPconsIsActive(cons) )
4386 continue;
4387
4388 consdata = SCIPconsGetData(cons);
4389 assert(consdata != NULL);
4390 assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
4391
4392 if( !consdata->presolved )
4393 {
4394 /* incorporate fixings and aggregations in constraint */
4395 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, cutoff, nchgbds, ndelconss, naddconss) );
4396
4397 if( *cutoff )
4398 return SCIP_OKAY;
4399 if( !SCIPconsIsActive(cons) )
4400 continue;
4401 }
4402
4403 if( SCIPconsIsMarkedPropagate(cons) )
4404 {
4405 /* propagate constraint */
4406 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, cutoff, nchgbds, nchgsides, ndelconss) );
4407
4408 if( *cutoff )
4409 return SCIP_OKAY;
4410 if( !SCIPconsIsActive(cons) )
4411 continue;
4412 }
4413
4414 if( !consdata->tightened )
4415 {
4416 /* tighten variable bound coefficient */
4417 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4418
4419 if( *cutoff )
4420 return SCIP_OKAY;
4421 if( !SCIPconsIsActive(cons) )
4422 continue;
4423
4424 assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
4425 }
4426
4427 /* check if both variables are of binary type */
4428 if( SCIPvarIsBinary(consdata->vbdvar) && SCIPvarIsBinary(consdata->var) )
4429 {
4430 /* coefficient and sides should be tightened and we assume that the constraint is not redundant */
4431 assert(SCIPisEQ(scip, REALABS(consdata->vbdcoef), 1.0));
4432 assert(SCIPisZero(scip, consdata->rhs) || SCIPisEQ(scip, consdata->rhs, 1.0) || SCIPisInfinity(scip, consdata->rhs));
4433 assert(SCIPisZero(scip, consdata->lhs) || SCIPisEQ(scip, consdata->lhs, 1.0) || SCIPisInfinity(scip, -consdata->lhs));
4434 assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
4435
4436 /* the case x + y <= 1 or x + y >= 1 */
4437 if( consdata->vbdcoef > 0.0 )
4438 {
4439 if( SCIPisEQ(scip, consdata->rhs, 1.0) )
4440 {
4441 /* check for aggregations like x + y == 1 */
4442 if( SCIPisEQ(scip, consdata->lhs, 1.0) )
4443 {
4444 SCIP_Bool infeasible;
4445 SCIP_Bool redundant;
4446 SCIP_Bool aggregated;
4447
4448 SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> + <%s> == 1\n",
4449 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
4450
4451 /* aggregate both variables */
4452 SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
4453 assert(!infeasible);
4454 ++(*naggrvars);
4455
4456 SCIP_CALL( SCIPdelCons(scip, cons) );
4457 ++(*ndelconss);
4458
4459 continue;
4460 }
4461 assert(consdata->lhs < 0.5);
4462
4463 vars[0] = consdata->var;
4464 vars[1] = consdata->vbdvar;
4465 }
4466 else
4467 {
4468 assert(SCIPisEQ(scip, consdata->lhs, 1.0));
4469
4470 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
4471 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
4472 }
4473 }
4474 /* the case x - y <= 0 or x - y >= 0 */
4475 else
4476 {
4477 /* the case x - y <= 0 */
4478 if( SCIPisZero(scip, consdata->rhs) )
4479 {
4480 /* check for aggregations like x - y == 0 */
4481 if( SCIPisZero(scip, consdata->lhs) )
4482 {
4483 SCIP_Bool infeasible;
4484 SCIP_Bool redundant;
4485 SCIP_Bool aggregated;
4486
4487 SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> - <%s> == 0\n",
4488 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
4489
4490 /* aggregate both variables */
4491 SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
4492 assert(!infeasible);
4493 ++(*naggrvars);
4494
4495 SCIP_CALL( SCIPdelCons(scip, cons) );
4496 ++(*ndelconss);
4497
4498 continue;
4499 }
4500 assert(consdata->lhs < -0.5);
4501
4502 vars[0] = consdata->var;
4503 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
4504 }
4505 /* the case x - y >= 0 */
4506 else
4507 {
4508 assert(SCIPisZero(scip, consdata->lhs));
4509
4510 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
4511 vars[1] = consdata->vbdvar;
4512 }
4513 }
4514
4515 SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
4520
4521 SCIP_CALL( SCIPaddCons(scip, newcons) );
4522 SCIPdebugMsg(scip, "upgraded varbound constraint <%s> to a set-packing constraint\n", SCIPconsGetName(cons));
4523 SCIPdebugPrintCons(scip, newcons, NULL);
4524
4525 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
4526 ++(*naddconss);
4527
4528 SCIP_CALL( SCIPdelCons(scip, cons) );
4529 ++(*ndelconss);
4530 }
4531 }
4532
4533 return SCIP_OKAY;
4534}
4535
4536/**@} */
4537
4538
4539/**@name Linear constraint upgrading
4540 *
4541 * @{
4542 */
4543
4544/** tries to upgrade a linear constraint into a variable bound constraint */
4545static
4546SCIP_DECL_LINCONSUPGD(linconsUpgdVarbound)
4547{ /*lint --e{715}*/
4548 SCIP_Bool upgrade;
4549
4550 assert(upgdcons != NULL);
4551
4552 /* check, if linear constraint can be upgraded to a variable bound constraint lhs <= x + a*y <= rhs
4553 * - there are exactly two variables
4554 * - one of the variables is non-binary (called the bounded variable x)
4555 * - one of the variables is non-continuous (called the bounding variable y)
4556 */
4557 upgrade = (nvars == 2) && (nposbin + nnegbin <= 1) && (nposcont + nnegcont <= 1);
4558
4559 if( upgrade )
4560 {
4561 SCIP_VAR* var;
4562 SCIP_VAR* vbdvar;
4563 SCIP_Real vbdcoef;
4564 SCIP_Real vbdlhs;
4565 SCIP_Real vbdrhs;
4566 int vbdind;
4567
4568 /* decide which variable we want to use as bounding variable y */
4569 if( SCIPvarGetType(vars[0]) < SCIPvarGetType(vars[1]) )
4570 vbdind = 0;
4571 else if( SCIPvarGetType(vars[0]) > SCIPvarGetType(vars[1]) )
4572 vbdind = 1;
4573 else if( SCIPisIntegral(scip, vals[0]) && !SCIPisIntegral(scip, vals[1]) )
4574 vbdind = 0;
4575 else if( !SCIPisIntegral(scip, vals[0]) && SCIPisIntegral(scip, vals[1]) )
4576 vbdind = 1;
4577 else if( REALABS(REALABS(vals[0]) - 1.0) < REALABS(REALABS(vals[1]) - 1.0) )
4578 vbdind = 1;
4579 else
4580 vbdind = 0;
4581
4582 /* do not upgrade when it is numerical unstable */
4583 if( SCIPisZero(scip, vals[vbdind]/vals[1-vbdind]) )
4584 return SCIP_OKAY;
4585
4586 SCIPdebugMsg(scip, "upgrading constraint <%s> to variable bound constraint\n", SCIPconsGetName(cons));
4587
4588 var = vars[1-vbdind];
4589 vbdvar = vars[vbdind];
4590
4591 assert(!SCIPisZero(scip, vals[1-vbdind]));
4592 vbdcoef = vals[vbdind]/vals[1-vbdind];
4593
4594 if( vals[1-vbdind] > 0.0 )
4595 {
4596 vbdlhs = SCIPisInfinity(scip, -lhs) ? -SCIPinfinity(scip) : lhs/vals[1-vbdind];
4597 vbdrhs = SCIPisInfinity(scip, rhs) ? SCIPinfinity(scip) : rhs/vals[1-vbdind];
4598 }
4599 else
4600 {
4601 vbdlhs = SCIPisInfinity(scip, rhs) ? -SCIPinfinity(scip) : rhs/vals[1-vbdind];
4602 vbdrhs = SCIPisInfinity(scip, -lhs) ? SCIPinfinity(scip) : lhs/vals[1-vbdind];
4603 }
4604
4605 /* create the bin variable bound constraint (an automatically upgraded constraint is always unmodifiable) */
4606 assert(!SCIPconsIsModifiable(cons));
4607 SCIP_CALL( SCIPcreateConsVarbound(scip, upgdcons, SCIPconsGetName(cons), var, vbdvar, vbdcoef, vbdlhs, vbdrhs,
4612 }
4613
4614 return SCIP_OKAY;
4615}
4616
4617/** adds symmetry information of constraint to a symmetry detection graph */
4618static
4620 SCIP* scip, /**< SCIP pointer */
4621 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
4622 SCIP_CONS* cons, /**< constraint */
4623 SYM_GRAPH* graph, /**< symmetry detection graph */
4624 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
4625 )
4626{
4627 SCIP_VAR** vars;
4628 SCIP_Real* vals;
4629 SCIP_Real constant = 0.0;
4630 SCIP_Real lhs;
4631 SCIP_Real rhs;
4632 int nlocvars;
4633 int nvars;
4634
4635 assert(scip != NULL);
4636 assert(cons != NULL);
4637 assert(graph != NULL);
4638 assert(success != NULL);
4639
4640 /* get active variables of the constraint */
4641 nvars = SCIPgetNVars(scip);
4642 nlocvars = 2;
4643
4644 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
4645 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
4646
4647 vars[0] = SCIPgetVarVarbound(scip, cons);
4648 vars[1] = SCIPgetVbdvarVarbound(scip, cons);
4649 vals[0] = 1.0;
4650 vals[1] = SCIPgetVbdcoefVarbound(scip, cons);
4651
4652 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
4653 lhs = SCIPgetLhsVarbound(scip, cons) - constant;
4654 rhs = SCIPgetRhsVarbound(scip, cons) - constant;
4655
4656 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
4657 cons, lhs, rhs, success) );
4658
4659 SCIPfreeBufferArray(scip, &vals);
4660 SCIPfreeBufferArray(scip, &vars);
4661
4662 return SCIP_OKAY;
4663}
4664
4665/**@} */
4666
4667
4668/**@name Callback methods
4669 *
4670 * @{
4671 */
4672
4673/** copy method for constraint handler plugins (called when SCIP copies plugins) */
4674static
4675SCIP_DECL_CONSHDLRCOPY(conshdlrCopyVarbound)
4676{ /*lint --e{715}*/
4677 assert(scip != NULL);
4678 assert(conshdlr != NULL);
4679 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4680
4681 /* call inclusion method of constraint handler */
4683
4684 *valid = TRUE;
4685
4686 return SCIP_OKAY;
4687}
4688
4689/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
4690static
4691SCIP_DECL_CONSFREE(consFreeVarbound)
4692{ /*lint --e{715}*/
4693 SCIP_CONSHDLRDATA* conshdlrdata;
4694
4695 assert(scip != NULL);
4696 assert(conshdlr != NULL);
4697 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4698
4699 /* free constraint handler data */
4700 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4701 assert(conshdlrdata != NULL);
4702
4703 conshdlrdataFree(scip, &conshdlrdata);
4704
4705 SCIPconshdlrSetData(conshdlr, NULL);
4706
4707 return SCIP_OKAY;
4708}
4709
4710/** solving process initialization method of constraint handler */
4711static
4712SCIP_DECL_CONSINITSOL(consInitsolVarbound)
4713{ /*lint --e{715}*/
4714 /* add nlrow representation to NLP, if NLP had been constructed */
4716 {
4717 int c;
4718 for( c = 0; c < nconss; ++c )
4719 {
4720 SCIP_CALL( addNlrow(scip, conss[c]) );
4721 }
4722 }
4723
4724 return SCIP_OKAY;
4725}
4726
4727/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4728static
4729SCIP_DECL_CONSEXITSOL(consExitsolVarbound)
4730{ /*lint --e{715}*/
4731 SCIP_CONSDATA* consdata;
4732 int c;
4733
4734 /* release the rows and nlrows of all constraints */
4735 for( c = 0; c < nconss; ++c )
4736 {
4737 consdata = SCIPconsGetData(conss[c]);
4738 assert(consdata != NULL);
4739
4740 if( consdata->row != NULL )
4741 {
4742 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
4743 }
4744
4745 if( consdata->nlrow != NULL )
4746 {
4747 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
4748 }
4749 }
4750
4751 return SCIP_OKAY;
4752}
4753
4754
4755/** frees specific constraint data */
4756static
4757SCIP_DECL_CONSDELETE(consDeleteVarbound)
4758{ /*lint --e{715}*/
4759 SCIP_CONSHDLRDATA* conshdlrdata;
4760
4761 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4762 assert(conshdlrdata != NULL);
4763
4764 /* drop events */
4765 if( SCIPisTransformed(scip) )
4766 {
4767 SCIP_CALL( dropEvents(scip, cons, conshdlrdata->eventhdlr) );
4768 }
4769
4770 SCIP_CALL( consdataFree(scip, consdata) );
4771
4772 return SCIP_OKAY;
4773}
4774
4775
4776/** transforms constraint data into data belonging to the transformed problem */
4777static
4778SCIP_DECL_CONSTRANS(consTransVarbound)
4779{ /*lint --e{715}*/
4780 SCIP_CONSHDLRDATA* conshdlrdata;
4781 SCIP_CONSDATA* sourcedata;
4782 SCIP_CONSDATA* targetdata;
4783
4784 assert(conshdlr != NULL);
4785
4786 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4787 assert(conshdlrdata != NULL);
4788
4789 sourcedata = SCIPconsGetData(sourcecons);
4790 assert(sourcedata != NULL);
4791
4792 /* create target constraint data */
4793 SCIP_CALL( consdataCreate(scip, &targetdata,
4794 sourcedata->var, sourcedata->vbdvar, sourcedata->vbdcoef, sourcedata->lhs, sourcedata->rhs) );
4795
4796 /* create target constraint */
4797 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
4798 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
4799 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
4800 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
4801 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
4802
4803 /* catch events for variables */
4804 SCIP_CALL( catchEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
4805
4806 return SCIP_OKAY;
4807}
4808
4809
4810/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
4811static
4812SCIP_DECL_CONSINITLP(consInitlpVarbound)
4813{ /*lint --e{715}*/
4814 int i;
4815
4816 *infeasible = FALSE;
4817
4818 for( i = 0; i < nconss && !(*infeasible); i++ )
4819 {
4820 assert(SCIPconsIsInitial(conss[i]));
4821 SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
4822 }
4823
4824 return SCIP_OKAY;
4825}
4826
4827
4828/** separation method of constraint handler for LP solutions */
4829static
4830SCIP_DECL_CONSSEPALP(consSepalpVarbound)
4831{ /*lint --e{715}*/
4832 SCIP_CONSHDLRDATA* conshdlrdata;
4833 int i;
4834
4835 assert(conshdlr != NULL);
4836
4837 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4838 assert(conshdlrdata != NULL);
4839
4840 *result = SCIP_DIDNOTFIND;
4841
4842 /* separate useful constraints */
4843 for( i = 0; i < nusefulconss; ++i )
4844 {
4845 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
4846 }
4847
4848 /* separate remaining constraints */
4849 for( i = nusefulconss; i < nconss && *result == SCIP_DIDNOTFIND; ++i )
4850 {
4851 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
4852 }
4853
4854 return SCIP_OKAY;
4855}
4856
4857
4858/** separation method of constraint handler for arbitrary primal solutions */
4859static
4860SCIP_DECL_CONSSEPASOL(consSepasolVarbound)
4861{ /*lint --e{715}*/
4862 SCIP_CONSHDLRDATA* conshdlrdata;
4863 int i;
4864
4865 assert(conshdlr != NULL);
4866
4867 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4868 assert(conshdlrdata != NULL);
4869
4870 *result = SCIP_DIDNOTFIND;
4871
4872 /* separate useful constraints */
4873 for( i = 0; i < nusefulconss; ++i )
4874 {
4875 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4876 }
4877
4878 /* separate remaining constraints */
4879 for( i = nusefulconss; i < nconss && *result == SCIP_DIDNOTFIND; ++i )
4880 {
4881 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4882 }
4883
4884 return SCIP_OKAY;
4885}
4886
4887
4888/** constraint enforcing method of constraint handler for LP solutions */
4889static
4890SCIP_DECL_CONSENFOLP(consEnfolpVarbound)
4891{ /*lint --e{715}*/
4892 SCIP_CONSHDLRDATA* conshdlrdata;
4893 int i;
4894
4895 assert(conshdlr != NULL);
4896
4897 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4898 assert(conshdlrdata != NULL);
4899
4900 *result = SCIP_FEASIBLE;
4901
4902 for( i = 0; i < nconss; i++ )
4903 {
4904 if( !checkCons(scip, conss[i], NULL, FALSE) )
4905 {
4906 assert((*result) == SCIP_INFEASIBLE || (*result) == SCIP_FEASIBLE);
4907 (*result) = SCIP_INFEASIBLE;
4908
4909 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
4910
4911 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
4912 assert((*result) != SCIP_FEASIBLE);
4913
4914 if( (*result) != SCIP_INFEASIBLE )
4915 break;
4916 }
4917 else
4918 {
4919 /* increase age of constraint */
4920 SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
4921 }
4922 }
4923
4924 return SCIP_OKAY;
4925}
4926
4927
4928/** constraint enforcing method of constraint handler for relaxation solutions */
4929static
4930SCIP_DECL_CONSENFORELAX(consEnforelaxVarbound)
4931{ /*lint --e{715}*/
4932 SCIP_CONSHDLRDATA* conshdlrdata;
4933 int i;
4934
4935 assert(conshdlr != NULL);
4936
4937 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4938 assert(conshdlrdata != NULL);
4939
4940 *result = SCIP_FEASIBLE;
4941
4942 for( i = 0; i < nconss; i++ )
4943 {
4944 if( !checkCons(scip, conss[i], sol, FALSE) )
4945 {
4946 assert((*result) == SCIP_INFEASIBLE || (*result) == SCIP_FEASIBLE);
4947 (*result) = SCIP_INFEASIBLE;
4948
4949 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
4950
4951 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4952 assert((*result) != SCIP_FEASIBLE);
4953
4954 if( (*result) != SCIP_INFEASIBLE )
4955 break;
4956 }
4957 else
4958 {
4959 /* increase age of constraint */
4960 SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
4961 }
4962 }
4963
4964 return SCIP_OKAY;
4965}
4966
4967
4968/** constraint enforcing method of constraint handler for pseudo solutions */
4969static
4970SCIP_DECL_CONSENFOPS(consEnfopsVarbound)
4971{ /*lint --e{715}*/
4972 int i;
4973
4974 for( i = 0; i < nconss; i++ )
4975 {
4976 if( !checkCons(scip, conss[i], NULL, TRUE) )
4977 {
4978 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
4979
4980 *result = SCIP_INFEASIBLE;
4981 return SCIP_OKAY;
4982 }
4983 else
4984 {
4985 /* increase age of constraint */
4986 SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
4987 }
4988 }
4989 *result = SCIP_FEASIBLE;
4990
4991 return SCIP_OKAY;
4992}
4993
4994
4995/** feasibility check method of constraint handler for integral solutions */
4996static
4997SCIP_DECL_CONSCHECK(consCheckVarbound)
4998{ /*lint --e{715}*/
4999 int i;
5000
5001 *result = SCIP_FEASIBLE;
5002
5003 for( i = 0; i < nconss && (*result == SCIP_FEASIBLE || completely); i++ )
5004 {
5005 if( !checkCons(scip, conss[i], sol, checklprows) )
5006 {
5007 *result = SCIP_INFEASIBLE;
5008
5009 if( printreason )
5010 {
5011 SCIP_CONSDATA* consdata;
5012 SCIP_Real sum;
5013
5014 consdata = SCIPconsGetData(conss[i]);
5015 assert( consdata != NULL );
5016
5017 sum = SCIPgetSolVal(scip, sol, consdata->var) + consdata->vbdcoef * SCIPgetSolVal(scip, sol, consdata->vbdvar);
5018
5019 SCIP_CALL( SCIPprintCons(scip, conss[i], NULL) );
5020 SCIPinfoMessage(scip, NULL, ";\n");
5021
5022 if( !SCIPisFeasGE(scip, sum, consdata->lhs) )
5023 {
5024 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - sum);
5025 }
5026 if( !SCIPisFeasLE(scip, sum, consdata->rhs) )
5027 {
5028 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", sum - consdata->rhs);
5029 }
5030 }
5031 }
5032 }
5033
5034 return SCIP_OKAY;
5035}
5036
5037
5038/** domain propagation method of constraint handler */
5039static
5040SCIP_DECL_CONSPROP(consPropVarbound)
5041{ /*lint --e{715}*/
5042 SCIP_CONSHDLRDATA* conshdlrdata;
5043 SCIP_Bool cutoff;
5044 int nchgbds = 0;
5045 int nchgsides = 0;
5046 int i;
5047
5048 assert(conshdlr != NULL);
5049
5050 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5051 assert(conshdlrdata != NULL);
5052
5053 cutoff = FALSE;
5054
5055 SCIPdebugMsg(scip, "propagating %d variable bound constraints\n", nmarkedconss);
5056
5057 /* process constraints marked for propagation */
5058 for( i = 0; i < nmarkedconss && !cutoff; i++ )
5059 {
5060 SCIP_CALL( propagateCons(scip, conss[i], conshdlrdata->usebdwidening, &cutoff, &nchgbds, &nchgsides, NULL) );
5061 }
5062
5063 if( cutoff )
5064 *result = SCIP_CUTOFF;
5065 else if( nchgbds > 0 )
5066 *result = SCIP_REDUCEDDOM;
5067 else
5068 *result = SCIP_DIDNOTFIND;
5069
5070 return SCIP_OKAY;
5071}
5072
5073
5074/** presolving method of constraint handler */
5075static
5076SCIP_DECL_CONSPRESOL(consPresolVarbound)
5077{ /*lint --e{715}*/
5078 SCIP_CONSHDLRDATA* conshdlrdata;
5079 SCIP_CONS* cons;
5080 SCIP_CONSDATA* consdata;
5081 SCIP_Bool cutoff;
5082 int oldnchgbds;
5083 int oldndelconss;
5084 int oldnaddconss;
5085 int oldnchgcoefs;
5086 int oldnchgsides;
5087 int oldnaggrvars;
5088 int i;
5089
5090 assert(scip != NULL);
5091 assert(conshdlr != NULL);
5092 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5093 assert(result != NULL);
5094
5095 /* get constraint handler data */
5096 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5097 assert(conshdlrdata != NULL);
5098
5099 cutoff = FALSE;
5100 oldnchgbds = *nchgbds;
5101 oldndelconss = *ndelconss;
5102 oldnaddconss = *naddconss;
5103 oldnchgcoefs = *nchgcoefs;
5104 oldnchgsides = *nchgsides;
5105 oldnaggrvars = *naggrvars;
5106
5107 for( i = 0; i < nconss; i++ )
5108 {
5109 cons = conss[i];
5110 assert(cons != NULL);
5111
5112 assert(!SCIPconsIsModifiable(cons));
5113
5114 consdata = SCIPconsGetData(cons);
5115 assert(consdata != NULL);
5116
5117 if( i % 1000 == 0 && SCIPisStopped(scip) )
5118 break;
5119
5120 /* force presolving the constraint in the initial round */
5121 if( nrounds == 0 )
5122 consdata->presolved = FALSE;
5123
5124 if( consdata->presolved )
5125 continue;
5126 consdata->presolved = TRUE;
5127
5128 /* incorporate fixings and aggregations in constraint */
5129 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &cutoff, nchgbds, ndelconss, naddconss) );
5130
5131 if( cutoff )
5132 break;
5133 if( !SCIPconsIsActive(cons) )
5134 continue;
5135
5136 /* propagate constraint */
5137 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, &cutoff, nchgbds, nchgsides, ndelconss) );
5138
5139 if( cutoff )
5140 break;
5141 if( !SCIPconsIsActive(cons) )
5142 continue;
5143
5144 /* tighten variable bound coefficient */
5145 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
5146 if( cutoff )
5147 break;
5148 if( !SCIPconsIsActive(cons) )
5149 continue;
5150
5151 /* informs once variable x about a globally valid variable lower or upper bound */
5152 if( !consdata->varboundsadded )
5153 {
5154 SCIP_Bool infeasible;
5155 int nlocalchgbds;
5156 int localoldnchgbds;
5157
5158 localoldnchgbds = *nchgbds;
5159
5160 /* if lhs is finite, we have a variable lower bound: lhs <= x + c*y => x >= -c*y + lhs */
5161 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, REALABS(consdata->vbdcoef)) )
5162 {
5163 SCIPdebugMsg(scip, "adding variable lower bound <%s> >= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
5164 SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->lhs,
5165 SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? ">=" : "<="), 1.0/-consdata->vbdcoef,
5166 SCIPvarGetName(consdata->var), consdata->lhs/consdata->vbdcoef);
5167
5168 SCIP_CALL( SCIPaddVarVlb(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->lhs,
5169 &infeasible, &nlocalchgbds) );
5170 assert(!infeasible);
5171
5172 *nchgbds += nlocalchgbds;
5173 }
5174
5175 /* if rhs is finite, we have a variable upper bound: x + c*y <= rhs => x <= -c*y + rhs */
5176 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, REALABS(consdata->vbdcoef)) )
5177 {
5178 SCIPdebugMsg(scip, "adding variable upper bound <%s> <= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
5179 SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
5180 SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? "<=" : ">="), 1.0/-consdata->vbdcoef,
5181 SCIPvarGetName(consdata->var), consdata->rhs/consdata->vbdcoef);
5182
5183 SCIP_CALL( SCIPaddVarVub(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->rhs,
5184 &infeasible, &nlocalchgbds) );
5185 assert(!infeasible);
5186
5187 *nchgbds += nlocalchgbds;
5188 }
5189 consdata->varboundsadded = TRUE;
5190
5191 if( *nchgbds > localoldnchgbds )
5192 {
5193 /* tighten variable bound coefficient */
5194 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
5195 if( cutoff )
5196 break;
5197 }
5198 }
5199 }
5200
5201 if( !cutoff )
5202 {
5203 /* for varbound constraint with two integer variables make coefficients integral */
5204 prettifyConss(scip, conss, nconss, nchgcoefs, nchgsides);
5205
5206 /* check if we can upgrade to a set-packing constraint */
5207 SCIP_CALL( upgradeConss(scip, conshdlrdata, conss, nconss, &cutoff, naggrvars, nchgbds, nchgcoefs, nchgsides, ndelconss, naddconss) );
5208
5209 if( !cutoff && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
5210 {
5211 /* preprocess pairs of variable bound constraints */
5212 SCIP_CALL( preprocessConstraintPairs(scip, conss, nconss, &cutoff, nchgbds, ndelconss, nchgcoefs, nchgsides) );
5213 }
5214 }
5215
5216 /* return the correct result code */
5217 if( cutoff )
5218 *result = SCIP_CUTOFF;
5219 else if( *nchgbds > oldnchgbds || *ndelconss > oldndelconss || *naddconss > oldnaddconss
5220 || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides || *naggrvars > oldnaggrvars )
5221 *result = SCIP_SUCCESS;
5222 else
5223 *result = SCIP_DIDNOTFIND;
5224
5225 return SCIP_OKAY;
5226}
5227
5228
5229/** propagation conflict resolving method of constraint handler */
5230static
5231SCIP_DECL_CONSRESPROP(consRespropVarbound)
5232{ /*lint --e{715}*/
5233 SCIP_CONSHDLRDATA* conshdlrdata;
5234
5235 assert(conshdlr != NULL);
5236
5237 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5238 assert(conshdlrdata != NULL);
5239
5240 SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, boundtype, bdchgidx, relaxedbd, conshdlrdata->usebdwidening) );
5241
5242 *result = SCIP_SUCCESS;
5243
5244 return SCIP_OKAY;
5245}
5246
5247
5248/** variable rounding lock method of constraint handler */
5249static
5250SCIP_DECL_CONSLOCK(consLockVarbound)
5251{ /*lint --e{715}*/
5252 SCIP_CONSDATA* consdata;
5253
5254 consdata = SCIPconsGetData(cons);
5255 assert(consdata != NULL);
5256
5257 if( !SCIPisInfinity(scip, -consdata->lhs) )
5258 {
5259 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->var, locktype, nlockspos, nlocksneg) );
5260 if( consdata->vbdcoef > 0.0 )
5261 {
5262 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlockspos, nlocksneg) );
5263 }
5264 else
5265 {
5266 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlocksneg, nlockspos) );
5267 }
5268 }
5269
5270 if( !SCIPisInfinity(scip, consdata->rhs) )
5271 {
5272 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->var, locktype, nlocksneg, nlockspos) );
5273 if( consdata->vbdcoef > 0.0 )
5274 {
5275 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlocksneg, nlockspos) );
5276 }
5277 else
5278 {
5279 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlockspos, nlocksneg) );
5280 }
5281 }
5282
5283 return SCIP_OKAY;
5284}
5285
5286/** constraint activation notification method of constraint handler */
5287static
5288SCIP_DECL_CONSACTIVE(consActiveVarbound)
5289{ /*lint --e{715}*/
5291 {
5292 SCIP_CALL( addNlrow(scip, cons) );
5293 }
5294
5295 return SCIP_OKAY;
5296}
5297
5298/** constraint deactivation notification method of constraint handler */
5299static
5300SCIP_DECL_CONSDEACTIVE(consDeactiveVarbound)
5301{ /*lint --e{715}*/
5302 SCIP_CONSDATA* consdata;
5303
5304 assert(cons != NULL);
5305
5306 consdata = SCIPconsGetData(cons);
5307 assert(consdata != NULL);
5308
5309 /* remove row from NLP, if still in solving
5310 * if we are in exitsolve, the whole NLP will be freed anyway
5311 */
5312 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
5313 {
5314 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
5315 }
5316
5317 return SCIP_OKAY;
5318}
5319
5320/** constraint display method of constraint handler */
5321static
5322SCIP_DECL_CONSPRINT(consPrintVarbound)
5323{ /*lint --e{715}*/
5324 SCIP_CONSDATA* consdata;
5325
5326 assert(scip != NULL);
5327 assert(conshdlr != NULL);
5328 assert(cons != NULL);
5329
5330 consdata = SCIPconsGetData(cons);
5331 assert(consdata != NULL);
5332
5333 /* print left hand side for ranged rows */
5334 if( !SCIPisInfinity(scip, -consdata->lhs)
5335 && !SCIPisInfinity(scip, consdata->rhs)
5336 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5337 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
5338
5339 /* print coefficients and variables */
5340 SCIPinfoMessage(scip, file, "<%s>[%c] %+.15g<%s>[%c]", SCIPvarGetName(consdata->var),
5344 consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
5348
5349 /* print right hand side */
5350 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5351 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
5352 else if( !SCIPisInfinity(scip, consdata->rhs) )
5353 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
5354 else if( !SCIPisInfinity(scip, -consdata->lhs) )
5355 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
5356 else
5357 SCIPinfoMessage(scip, file, " [free]");
5358
5359 return SCIP_OKAY;
5360}
5361
5362/** constraint copying method of constraint handler */
5363static
5364SCIP_DECL_CONSCOPY(consCopyVarbound)
5365{ /*lint --e{715}*/
5366 SCIP_VAR** vars;
5367 SCIP_Real* coefs;
5368 const char* consname;
5369
5370 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
5371 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, 2) );
5372
5373 vars[0] = SCIPgetVarVarbound(sourcescip, sourcecons);
5374 vars[1] = SCIPgetVbdvarVarbound(sourcescip, sourcecons);
5375
5376 coefs[0] = 1.0;
5377 coefs[1] = SCIPgetVbdcoefVarbound(sourcescip, sourcecons);
5378
5379 if( name != NULL )
5380 consname = name;
5381 else
5382 consname = SCIPconsGetName(sourcecons);
5383
5384 /* copy the varbound using the linear constraint copy method */
5385 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, 2, vars, coefs,
5386 SCIPgetLhsVarbound(sourcescip, sourcecons), SCIPgetRhsVarbound(sourcescip, sourcecons), varmap, consmap,
5387 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
5388
5389 SCIPfreeBufferArray(scip, &coefs);
5390 SCIPfreeBufferArray(scip, &vars);
5391
5392 return SCIP_OKAY;
5393}
5394
5395/** constraint parsing method of constraint handler */
5396static
5397SCIP_DECL_CONSPARSE(consParseVarbound)
5398{ /*lint --e{715}*/
5399 SCIP_VAR** vars;
5400 SCIP_Real* coefs;
5401 SCIP_Real lhs;
5402 SCIP_Real rhs;
5403 char* endstr;
5404 int requiredsize;
5405 int nvars;
5406
5407 assert(scip != NULL);
5408 assert(success != NULL);
5409 assert(str != NULL);
5410 assert(name != NULL);
5411 assert(cons != NULL);
5412
5413 /* set left and right hand side to their default values */
5414 lhs = -SCIPinfinity(scip);
5415 rhs = SCIPinfinity(scip);
5416
5417 (*success) = FALSE;
5418
5419 /* return of string empty */
5420 if( !*str )
5421 return SCIP_OKAY;
5422
5423 /* ignore whitespace */
5424 SCIP_CALL( SCIPskipSpace((char**)&str) );
5425
5426 if( isdigit(str[0]) || ((str[0] == '-' || str[0] == '+') && isdigit(str[1])) )
5427 {
5428 if( !SCIPparseReal(scip, str, &lhs, &endstr) )
5429 {
5430 SCIPerrorMessage("error parsing left hand side\n");
5431 return SCIP_OKAY;
5432 }
5433
5434 /* ignore whitespace */
5435 SCIP_CALL( SCIPskipSpace(&endstr) );
5436
5437 if( endstr[0] != '<' || endstr[1] != '=' )
5438 {
5439 SCIPerrorMessage("missing \"<=\" after left hand side(, found %c%c)\n", endstr[0], endstr[1]);
5440 return SCIP_OKAY;
5441 }
5442
5443 SCIPdebugMsg(scip, "found left hand side <%g>\n", lhs);
5444
5445 /* it was indeed a left-hand-side, so continue parsing after it */
5446 str = endstr + 2;
5447 }
5448
5449 /* pares x + c*y as linear sum */
5450 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
5451 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, 2) );
5452
5453 /* parse linear sum to get variables and coefficients */
5454 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, 2, &requiredsize, &endstr, success) );
5455
5456 if( requiredsize == 2 && *success )
5457 {
5458 SCIP_Real value;
5459
5460 assert(nvars == 2);
5461 assert(SCIPisEQ(scip, coefs[0], 1.0));
5462
5463 SCIPdebugMsg(scip, "found linear sum <%s> + %g <%s>\n", SCIPvarGetName(vars[0]), coefs[1], SCIPvarGetName(vars[1]));
5464
5465 /* ignore whitespace */
5466 SCIP_CALL( SCIPskipSpace(&endstr) );
5467
5468 str = endstr;
5469
5470 if( *str != '\0' && *(str+1) != '\0' && SCIPparseReal(scip, str+2, &value, &endstr) )
5471 {
5472 /* search for end of linear sum: either '<=', '>=', '==', or '[free]' */
5473 switch( *str )
5474 {
5475 case '<':
5476 assert(str[1] == '=');
5477 rhs = value;
5478 break;
5479 case '=':
5480 assert(str[1] == '=');
5481 assert(SCIPisInfinity(scip, -lhs));
5482 lhs = value;
5483 rhs = value;
5484 break;
5485 case '>':
5486 assert(str[1] == '=');
5487 assert(SCIPisInfinity(scip, -lhs));
5488 lhs = value;
5489 break;
5490 default:
5491 SCIPerrorMessage("missing relation symbol after linear sum\n");
5492 *success = FALSE;
5493 }
5494 }
5495 else if( strncmp(str, "[free]", 6) != 0 )
5496 *success = FALSE;
5497 }
5498
5499 if( *success )
5500 {
5501 SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, vars[0], vars[1], coefs[1], lhs, rhs,
5502 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
5503 }
5504
5505 /* free buffer arrays */
5506 SCIPfreeBufferArray(scip, &coefs);
5507 SCIPfreeBufferArray(scip, &vars);
5508
5509 return SCIP_OKAY;
5510}
5511
5512/** constraint method of constraint handler which returns the variables (if possible) */
5513static
5514SCIP_DECL_CONSGETVARS(consGetVarsVarbound)
5515{ /*lint --e{715}*/
5516 assert( success != NULL );
5517
5518 if( varssize < 2 )
5519 (*success) = FALSE;
5520 else
5521 {
5522 SCIP_CONSDATA* consdata;
5523 assert(cons != NULL);
5524 assert(vars != NULL);
5525
5526 consdata = SCIPconsGetData(cons);
5527 assert(consdata != NULL);
5528
5529 vars[0] = consdata->var;
5530 vars[1] = consdata->vbdvar;
5531 (*success) = TRUE;
5532 }
5533
5534 return SCIP_OKAY;
5535}
5536
5537/** constraint method of constraint handler which returns the number of variables (if possible) */
5538static
5539SCIP_DECL_CONSGETNVARS(consGetNVarsVarbound)
5540{ /*lint --e{715}*/
5541 (*nvars) = 2;
5542 (*success) = TRUE;
5543
5544 return SCIP_OKAY;
5545}
5546
5547/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
5548static
5549SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphVarbound)
5550{ /*lint --e{715}*/
5551 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
5552
5553 return SCIP_OKAY;
5554}
5555
5556/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
5557static
5558SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphVarbound)
5559{ /*lint --e{715}*/
5560 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
5561
5562 return SCIP_OKAY;
5563}
5564
5565/*
5566 * Event Handler
5567 */
5568
5569/** execution method of bound change event handler */
5570static
5571SCIP_DECL_EVENTEXEC(eventExecVarbound)
5572{ /*lint --e{715}*/
5573 SCIP_CONS* cons;
5574 SCIP_CONSDATA* consdata;
5575
5576 assert(event != NULL);
5577 cons = (SCIP_CONS*)eventdata;
5578 assert(cons != NULL);
5579 consdata = SCIPconsGetData(cons);
5580 assert(consdata != NULL);
5581
5583 {
5584 consdata->presolved = FALSE;
5585 }
5586 else
5587 {
5588 assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0);
5589
5590 consdata->presolved = FALSE;
5591 consdata->tightened = FALSE;
5592
5594 }
5595
5596 return SCIP_OKAY;
5597}
5598
5599/**@} */
5600
5601
5602/** creates the handler for variable bound constraints and includes it in SCIP */
5604 SCIP* scip /**< SCIP data structure */
5605 )
5606{
5607 SCIP_CONSHDLRDATA* conshdlrdata;
5608 SCIP_EVENTHDLR* eventhdlr;
5609 SCIP_CONSHDLR* conshdlr;
5610
5611 /* include event handler for bound change events */
5613 eventExecVarbound, NULL) );
5614
5615 /* create variable bound constraint handler data */
5616 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
5617
5618 /* include constraint handler */
5621 consEnfolpVarbound, consEnfopsVarbound, consCheckVarbound, consLockVarbound,
5622 conshdlrdata) );
5623 assert(conshdlr != NULL);
5624
5625 /* set non-fundamental callbacks via specific setter functions */
5626 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyVarbound, consCopyVarbound) );
5627 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveVarbound) );
5628 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveVarbound) );
5629 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteVarbound) );
5630 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolVarbound) );
5631 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolVarbound) );
5632 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeVarbound) );
5633 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsVarbound) );
5634 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsVarbound) );
5635 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpVarbound) );
5636 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseVarbound) );
5638 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintVarbound) );
5641 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropVarbound) );
5642 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpVarbound, consSepasolVarbound, CONSHDLR_SEPAFREQ,
5644 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransVarbound) );
5645 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxVarbound) );
5646 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphVarbound) );
5647 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphVarbound) );
5648
5649 if( SCIPfindConshdlr(scip,"linear") != NULL )
5650 {
5651 /* include the linear constraint to varbound constraint upgrade in the linear constraint handler */
5653 }
5654
5655 /* add varbound constraint handler parameters */
5657 "constraints/" CONSHDLR_NAME "/presolpairwise",
5658 "should pairwise constraint comparison be performed in presolving?",
5659 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
5661 "constraints/" CONSHDLR_NAME "/maxlpcoef",
5662 "maximum coefficient in varbound constraint to be added as a row into LP",
5663 &conshdlrdata->maxlpcoef, TRUE, DEFAULT_MAXLPCOEF, 0.0, 1e+20, NULL, NULL) );
5665 "constraints/" CONSHDLR_NAME "/usebdwidening", "should bound widening be used in conflict analysis?",
5666 &conshdlrdata->usebdwidening, FALSE, DEFAULT_USEBDWIDENING, NULL, NULL) );
5667
5668 return SCIP_OKAY;
5669}
5670
5671/** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
5672 *
5673 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5674 */
5676 SCIP* scip, /**< SCIP data structure */
5677 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5678 const char* name, /**< name of constraint */
5679 SCIP_VAR* var, /**< variable x that has variable bound */
5680 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
5681 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
5682 SCIP_Real lhs, /**< left hand side of variable bound inequality */
5683 SCIP_Real rhs, /**< right hand side of variable bound inequality */
5684 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
5685 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5686 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
5687 * Usually set to TRUE. */
5688 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
5689 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5690 SCIP_Bool check, /**< should the constraint be checked for feasibility?
5691 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5692 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
5693 * Usually set to TRUE. */
5694 SCIP_Bool local, /**< is constraint only valid locally?
5695 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5696 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
5697 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
5698 * adds coefficients to this constraint. */
5699 SCIP_Bool dynamic, /**< is constraint subject to aging?
5700 * Usually set to FALSE. Set to TRUE for own cuts which
5701 * are separated as constraints. */
5702 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
5703 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5704 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
5705 * if it may be moved to a more global node?
5706 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
5707 )
5708{
5709 SCIP_CONSHDLR* conshdlr;
5710 SCIP_CONSHDLRDATA* conshdlrdata;
5711 SCIP_CONSDATA* consdata;
5712
5713 /* find the variable bound constraint handler */
5714 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5715 if( conshdlr == NULL )
5716 {
5717 SCIPerrorMessage("variable bound constraint handler not found\n");
5718 return SCIP_PLUGINNOTFOUND;
5719 }
5720
5721 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5722 assert(conshdlrdata != NULL);
5723
5724 /* create constraint data */
5725 SCIP_CALL( consdataCreate(scip, &consdata, var, vbdvar, vbdcoef, lhs, rhs) );
5726
5727 /* create constraint */
5728 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5729 local, modifiable, dynamic, removable, stickingatnode) );
5730
5731 if( SCIPisTransformed(scip) )
5732 {
5733 /* catch events for variables */
5734 SCIP_CALL( catchEvents(scip, *cons, conshdlrdata->eventhdlr) );
5735 }
5736
5737 return SCIP_OKAY;
5738}
5739
5740/** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
5741 * with all constraint flags set to their default values
5742 *
5743 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5744 */
5746 SCIP* scip, /**< SCIP data structure */
5747 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5748 const char* name, /**< name of constraint */
5749 SCIP_VAR* var, /**< variable x that has variable bound */
5750 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
5751 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
5752 SCIP_Real lhs, /**< left hand side of variable bound inequality */
5753 SCIP_Real rhs /**< right hand side of variable bound inequality */
5754 )
5755{
5756 SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, var, vbdvar,vbdcoef, lhs, rhs,
5758
5759 return SCIP_OKAY;
5760}
5761
5762/** gets left hand side of variable bound constraint lhs <= x + c*y <= rhs */
5764 SCIP* scip, /**< SCIP data structure */
5765 SCIP_CONS* cons /**< constraint data */
5766 )
5767{
5768 SCIP_CONSDATA* consdata;
5769
5770 assert(scip != NULL);
5771
5772 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5773 {
5774 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5775 SCIPABORT();
5776 return SCIP_INVALID; /*lint !e527*/
5777 }
5778
5779 consdata = SCIPconsGetData(cons);
5780 assert(consdata != NULL);
5781
5782 return consdata->lhs;
5783}
5784
5785/** gets right hand side of variable bound constraint lhs <= x + c*y <= rhs */
5787 SCIP* scip, /**< SCIP data structure */
5788 SCIP_CONS* cons /**< constraint data */
5789 )
5790{
5791 SCIP_CONSDATA* consdata;
5792
5793 assert(scip != NULL);
5794
5795 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5796 {
5797 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5798 SCIPABORT();
5799 return SCIP_INVALID; /*lint !e527*/
5800 }
5801
5802 consdata = SCIPconsGetData(cons);
5803 assert(consdata != NULL);
5804
5805 return consdata->rhs;
5806}
5807
5808/** gets bounded variable x of variable bound constraint lhs <= x + c*y <= rhs */
5810 SCIP* scip, /**< SCIP data structure */
5811 SCIP_CONS* cons /**< constraint data */
5812 )
5813{
5814 SCIP_CONSDATA* consdata;
5815
5816 assert(scip != NULL);
5817
5818 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5819 {
5820 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5821 SCIPABORT();
5822 return NULL; /*lint !e527*/
5823 }
5824
5825 consdata = SCIPconsGetData(cons);
5826 assert(consdata != NULL);
5827
5828 return consdata->var;
5829}
5830
5831/** gets bounding variable y of variable bound constraint lhs <= x + c*y <= rhs */
5833 SCIP* scip, /**< SCIP data structure */
5834 SCIP_CONS* cons /**< constraint data */
5835 )
5836{
5837 SCIP_CONSDATA* consdata;
5838
5839 assert(scip != NULL);
5840
5841 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5842 {
5843 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5844 SCIPABORT();
5845 return NULL; /*lint !e527*/
5846 }
5847
5848 consdata = SCIPconsGetData(cons);
5849 assert(consdata != NULL);
5850
5851 return consdata->vbdvar;
5852}
5853
5854/** gets bound coefficient c of variable bound constraint lhs <= x + c*y <= rhs */
5856 SCIP* scip, /**< SCIP data structure */
5857 SCIP_CONS* cons /**< constraint data */
5858 )
5859{
5860 SCIP_CONSDATA* consdata;
5861
5862 assert(scip != NULL);
5863
5864 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5865 {
5866 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5867 SCIPABORT();
5868 return SCIP_INVALID; /*lint !e527*/
5869 }
5870
5871 consdata = SCIPconsGetData(cons);
5872 assert(consdata != NULL);
5873
5874 return consdata->vbdcoef;
5875}
5876
5877/** gets the dual solution of the variable bound constraint in the current LP */
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 if( consdata->row != NULL )
5898 return SCIProwGetDualsol(consdata->row);
5899 else
5900 return 0.0;
5901}
5902
5903/** gets the dual Farkas value of the variable bound constraint in the current infeasible LP */
5905 SCIP* scip, /**< SCIP data structure */
5906 SCIP_CONS* cons /**< constraint data */
5907 )
5908{
5909 SCIP_CONSDATA* consdata;
5910
5911 assert(scip != NULL);
5912
5913 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5914 {
5915 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5916 SCIPABORT();
5917 return SCIP_INVALID; /*lint !e527*/
5918 }
5919
5920 consdata = SCIPconsGetData(cons);
5921 assert(consdata != NULL);
5922
5923 if( consdata->row != NULL )
5924 return SCIProwGetDualfarkas(consdata->row);
5925 else
5926 return 0.0;
5927}
5928
5929/** returns the linear relaxation of the given variable bound constraint; may return NULL if no LP row was yet created;
5930 * the user must not modify the row!
5931 */
5933 SCIP* scip, /**< SCIP data structure */
5934 SCIP_CONS* cons /**< constraint data */
5935 )
5936{
5937 SCIP_CONSDATA* consdata;
5938
5939 assert(scip != NULL);
5940
5941 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5942 {
5943 SCIPerrorMessage("constraint is not a variable bound constraint\n");
5944 SCIPABORT();
5945 return NULL; /*lint !e527*/
5946 }
5947
5948 consdata = SCIPconsGetData(cons);
5949 assert(consdata != NULL);
5950
5951 return consdata->row;
5952}
5953
5954/** cleans up (multi-)aggregations and fixings from varbound constraints */
5956 SCIP* scip, /**< SCIP data structure */
5957 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
5958 SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
5959 int* naddconss, /**< pointer to count number of added (linear) constraints */
5960 int* ndelconss, /**< pointer to count number of deleted (varbound) constraints */
5961 int* nchgbds /**< pointer to count number of bound changes */
5962 )
5963{
5964 SCIP_CONSHDLR* conshdlr;
5965 SCIP_CONSHDLRDATA* conshdlrdata;
5966 SCIP_EVENTHDLR* eventhdlr;
5967 SCIP_CONS** conss;
5968 int nconss;
5969 int i;
5970
5971 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5972 if( conshdlr == NULL )
5973 return SCIP_OKAY;
5974
5975 assert(infeasible != NULL);
5976 *infeasible = FALSE;
5977
5978 assert(naddconss != NULL);
5979 assert(ndelconss != NULL);
5980 assert(nchgbds != NULL);
5981
5982 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5983 assert(conshdlrdata != NULL);
5984
5985 eventhdlr = conshdlrdata->eventhdlr;
5986 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
5987 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
5988
5989 /* loop backwards since then deleted constraints do not interfere with the loop */
5990 for( i = nconss - 1; i >= 0; --i )
5991 {
5992 SCIP_CALL( applyFixings(scip, conss[i], eventhdlr, infeasible, nchgbds, ndelconss, naddconss) );
5993
5994 if( *infeasible )
5995 break;
5996 }
5997
5998 return SCIP_OKAY;
5999}
enum Proprule PROPRULE
Definition: cons_and.c:179
Proprule
Definition: cons_and.c:172
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:266
#define SCIP_Longint
Definition: def.h:157
#define SCIP_VARTYPE_INTEGER_CHAR
Definition: def.h:144
#define SCIP_VARTYPE_IMPLINT_CHAR
Definition: def.h:145
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define SCIP_Real
Definition: def.h:172
#define SCIP_UNKNOWN
Definition: def.h:193
#define ABS(x)
Definition: def.h:234
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_VARTYPE_BINARY_CHAR
Definition: def.h:143
#define SCIP_VARTYPE_CONTINUOUS_CHAR
Definition: def.h:146
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:373
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:9446
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 SCIPincludeConshdlrVarbound(SCIP *scip)
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:606
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2082
int SCIPgetNImplVars(SCIP *scip)
Definition: scip_prob.c:2127
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2770
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3475
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:9397
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11215
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:4664
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:4235
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4621
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:4205
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:4225
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:4678
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:4601
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:8252
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8481
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8242
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8391
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8431
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8421
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8351
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8531
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8411
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8283
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:8441
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8461
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8222
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:8471
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:8501
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8401
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8491
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
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:1030
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:361
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:407
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:132
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_RETCODE 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:1956
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:97
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1422
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1701
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2212
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip_lp.c:2167
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17358
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17556
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17345
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1213
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:137
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:5326
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4474
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17607
SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6453
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4799
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17546
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3353
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18152
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:8494
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:5729
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4889
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17934
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:12226
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5443
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17592
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip_var.c:1794
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18096
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:6825
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17766
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4382
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:6766
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4560
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17427
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1248
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4768
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip_var.c:704
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4736
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17618
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:1527
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18142
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18086
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:8381
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:5624
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3295
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1439
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1214
SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6333
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10869
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)
memory allocation routines
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
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
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:60
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:173
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:123
@ SCIP_EXPRCURV_LINEAR
Definition: type_expr.h:65
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ 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
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
@ SCIP_VARTYPE_INTEGER
Definition: type_var.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_IMPLINT
Definition: type_var.h:64
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:62
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:52
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:54
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:97