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