SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file cons_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
80
81/**@name Constraint handler properties
82 *
83 * @{
84 */
85
86/* constraint handler properties */
87#define CONSHDLR_NAME "varbound"
88#define CONSHDLR_DESC "variable bounds lhs <= x + c*y <= rhs, x non-binary, y non-continuous"
89#define CONSHDLR_SEPAPRIORITY +900000 /**< priority of the constraint handler for separation */
90#define CONSHDLR_ENFOPRIORITY -500000 /**< priority of the constraint handler for constraint enforcing */
91#define CONSHDLR_CHECKPRIORITY -500000 /**< priority of the constraint handler for checking feasibility */
92#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
93#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
94#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
95 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
96#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
97#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
98#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
99#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
100
101#define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_MEDIUM)
102#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
103
104#define EVENTHDLR_NAME "varbound"
105#define EVENTHDLR_DESC "bound change event handler for variable bound constraints"
106
107#define LINCONSUPGD_PRIORITY +50000 /**< priority of the constraint handler for upgrading of linear constraints */
108
109/**@} */
110
111/**@name Default parameter values
112 *
113 * @{
114 */
115
116#define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
117#define DEFAULT_MAXLPCOEF 1e+09 /**< maximum coefficient in varbound constraint to be added as a row into LP */
118#define DEFAULT_USEBDWIDENING TRUE /**< should bound widening be used to initialize conflict analysis? */
119#define DEFAULT_COPYTYPEDCONS FALSE /**< should varbound constraints be copied as varbound instead of linear? */
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 SCIP_Bool copytypedcons; /**< should varbound constraints be copied as varbound instead of linear? */
150};
151
152/** Propagation rules */
154{
155 PROPRULE_1, /**< left hand side and bounds on y -> lower bound on x */
156 PROPRULE_2, /**< left hand side and upper bound on x -> bound on y */
157 PROPRULE_3, /**< right hand side and bounds on y -> upper bound on x */
158 PROPRULE_4 /**< right hand side and lower bound on x -> bound on y */
159};
160typedef enum Proprule PROPRULE;
161
162
163/**@name Local methods
164 *
165 * @{
166 */
167
168/** 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$
169 * w.r.t. the indices of the contained variables
170 *
171 * returns -1 if:
172 * - the index of x1 is smaller than the index of x2 or
173 * - x1 = x2 and the index of y1 is smaller than the index of y2 or
174 * - x1 = x2 and y1 = y2 and cons2 was recently changed, but cons1 not
175 *
176 * returns 0 if x1 = x2, y1 = y2, and the changed status of both constraints is the same
177 *
178 * and returns +1 otherwise
179 */
180static
181SCIP_DECL_SORTPTRCOMP(consVarboundComp)
182{
183 SCIP_CONSDATA* consdata1;
184 SCIP_CONSDATA* consdata2;
185
186 assert(elem1 != NULL);
187 assert(elem2 != NULL);
188
189 consdata1 = SCIPconsGetData((SCIP_CONS*) elem1);
190 consdata2 = SCIPconsGetData((SCIP_CONS*) elem2);
191
192 assert(consdata1 != NULL);
193 assert(consdata2 != NULL);
194
195 /* comparison is done over 3 ordered criteria:
196 * (i) variable index of variable 1
197 * (ii) variable index of variable 2.
198 * (iii) changed status
199 */
200 if( SCIPvarGetIndex(consdata1->var) < SCIPvarGetIndex(consdata2->var)
201 || (SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
202 && SCIPvarGetIndex(consdata1->vbdvar) < SCIPvarGetIndex(consdata2->vbdvar))
203 || (SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
204 && SCIPvarGetIndex(consdata1->vbdvar) == SCIPvarGetIndex(consdata2->vbdvar)
205 && !consdata1->changed && consdata2->changed) )
206 return -1;
207 else if( SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
208 && SCIPvarGetIndex(consdata1->vbdvar) == SCIPvarGetIndex(consdata2->vbdvar)
209 && (consdata1->changed == consdata2->changed) )
210 return 0;
211 else
212 return +1;
213}
214
215/** creates constraint handler data for varbound constraint handler */
216static
218 SCIP* scip, /**< SCIP data structure */
219 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
220 SCIP_EVENTHDLR* eventhdlr /**< event handler */
221 )
222{
223 assert(scip != NULL);
224 assert(conshdlrdata != NULL);
225
226 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
227
228 /* set event handler for bound change events */
229 (*conshdlrdata)->eventhdlr = eventhdlr;
230
231 return SCIP_OKAY;
232}
233
234/** frees constraint handler data for varbound constraint handler */
235static
237 SCIP* scip, /**< SCIP data structure */
238 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
239 )
240{
241 assert(scip != NULL);
242 assert(conshdlrdata != NULL);
243 assert(*conshdlrdata != NULL);
244
245 SCIPfreeBlockMemory(scip, conshdlrdata);
246}
247
248/** catches events for variables
249 *
250 * @todo if lhs or rhs is infinite, catch only changes of the bound that could lead to propagation
251 */
252static
254 SCIP* scip, /**< SCIP data structure */
255 SCIP_CONS* cons, /**< variable bound constraint */
256 SCIP_EVENTHDLR* eventhdlr /**< event handler */
257 )
258{
259 SCIP_CONSDATA* consdata;
260 assert(cons != NULL);
261 assert(eventhdlr != NULL);
262 consdata = SCIPconsGetData(cons);
263 assert(consdata != NULL);
264
267
268 return SCIP_OKAY;
269}
270
271/** drops events for variables */
272static
274 SCIP* scip, /**< SCIP data structure */
275 SCIP_CONS* cons, /**< variable bound constraint */
276 SCIP_EVENTHDLR* eventhdlr /**< event handler */
277 )
278{
279 SCIP_CONSDATA* consdata;
280 assert(cons != NULL);
281 assert(eventhdlr != NULL);
282 consdata = SCIPconsGetData(cons);
283 assert(consdata != NULL);
284
287
288 return SCIP_OKAY;
289}
290
291/** creates a variable bound constraint data object */
292static
294 SCIP* scip, /**< SCIP data structure */
295 SCIP_CONSDATA** consdata, /**< pointer to store the variable bound constraint data */
296 SCIP_VAR* var, /**< variable x that has variable bound */
297 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
298 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
299 SCIP_Real lhs, /**< left hand side of variable bound inequality */
300 SCIP_Real rhs /**< right hand side of variable bound inequality */
301 )
302{
303 assert(consdata != NULL);
304 assert(SCIPvarIsIntegral(vbdvar));
305
306 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
307
308 if( SCIPisInfinity(scip, rhs) )
309 rhs = SCIPinfinity(scip);
310 else if( SCIPisInfinity(scip, -rhs) )
311 rhs = -SCIPinfinity(scip);
312
313 if( SCIPisInfinity(scip, -lhs) )
314 lhs = -SCIPinfinity(scip);
315 else if( SCIPisInfinity(scip, lhs) )
316 lhs = SCIPinfinity(scip);
317
318 if( SCIPisGT(scip, lhs, rhs) )
319 {
320 SCIPerrorMessage("left hand side of varbound constraint greater than right hand side\n");
321 SCIPerrorMessage(" -> lhs=%g, rhs=%g\n", lhs, rhs);
322 return SCIP_INVALIDDATA;
323 }
324
325 if( SCIPisZero(scip, vbdcoef) )
326 {
327 SCIPerrorMessage("varbound coefficient must be different to zero.\n");
328 return SCIP_INVALIDDATA;
329 }
330
331 if( SCIPisInfinity(scip, vbdcoef) )
332 vbdcoef = SCIPinfinity(scip);
333 else if( SCIPisInfinity(scip, -vbdcoef) )
334 vbdcoef = -SCIPinfinity(scip);
335
336 (*consdata)->var = var;
337 (*consdata)->vbdvar = vbdvar;
338 (*consdata)->vbdcoef = vbdcoef;
339 (*consdata)->lhs = lhs;
340 (*consdata)->rhs = rhs;
341 (*consdata)->row = NULL;
342 (*consdata)->nlrow = NULL;
343 (*consdata)->presolved = FALSE;
344 (*consdata)->varboundsadded = FALSE;
345 (*consdata)->changed = TRUE;
346 (*consdata)->tightened = FALSE;
347
348 /* if we are in the transformed problem, get transformed variables, add variable bound information, and catch events */
350 {
351 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->var, &(*consdata)->var) );
352 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vbdvar, &(*consdata)->vbdvar) );
353
354#ifndef NDEBUG
357#endif
358 }
359
360 /* capture variables */
361 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->var) );
362 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vbdvar) );
363
364 return SCIP_OKAY;
365}
366
367/** frees a variable bound constraint data */
368static
370 SCIP* scip, /**< SCIP data structure */
371 SCIP_CONSDATA** consdata /**< pointer to the variable bound constraint */
372 )
373{
374 assert(consdata != NULL);
375 assert(*consdata != NULL);
376
377 /* release the row */
378 if( (*consdata)->row != NULL )
379 {
380 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
381 }
382
383 /* release the nlrow */
384 if( (*consdata)->nlrow != NULL )
385 {
386 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
387 }
388
389 /* release variables */
390 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->var) );
391 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->vbdvar) );
392
393 SCIPfreeBlockMemory(scip, consdata);
394
395 return SCIP_OKAY;
396}
397
398/** creates LP row corresponding to variable bound constraint */
399static
401 SCIP* scip, /**< SCIP data structure */
402 SCIP_CONS* cons /**< variable bound constraint */
403 )
404{
405 SCIP_CONSDATA* consdata;
406
407 consdata = SCIPconsGetData(cons);
408 assert(consdata != NULL);
409 assert(consdata->row == NULL);
410
411 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
413 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->var, 1.0) );
414 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->vbdvar, consdata->vbdcoef) );
415
416 return SCIP_OKAY;
417}
418
419/** adds linear relaxation of variable bound constraint to the LP */
420static
422 SCIP* scip, /**< SCIP data structure */
423 SCIP_CONS* cons, /**< variable bound constraint */
424 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
425 )
426{
427 SCIP_CONSHDLR* conshdlr;
428 SCIP_CONSHDLRDATA* conshdlrdata;
429 SCIP_CONSDATA* consdata;
430
431 consdata = SCIPconsGetData(cons);
432 assert(consdata != NULL);
433
434 /* find the variable bound constraint handler */
436 if( conshdlr == NULL )
437 {
438 SCIPerrorMessage("variable bound constraint handler not found\n");
439 return SCIP_PLUGINNOTFOUND;
440 }
441
442 conshdlrdata = SCIPconshdlrGetData(conshdlr);
443 assert(conshdlrdata != NULL);
444
445 assert(SCIPvarIsIntegral(consdata->vbdvar));
446
447 /* check whether the coefficient is too large to put the row into the LP */
448 if( SCIPisGT(scip, REALABS(consdata->vbdcoef), conshdlrdata->maxlpcoef) )
449 return SCIP_OKAY;
450
451 if( consdata->row == NULL )
452 {
454 }
455 assert(consdata->row != NULL);
456
457 if( !SCIProwIsInLP(consdata->row) )
458 {
459 SCIPdebugMsg(scip, "adding relaxation of variable bound constraint <%s>: ", SCIPconsGetName(cons));
460 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
461 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, infeasible) );
462 }
463
464 return SCIP_OKAY;
465}
466
467/** adds varbound constraint as row to the NLP, if not added yet */
468static
470 SCIP* scip, /**< SCIP data structure */
471 SCIP_CONS* cons /**< varbound constraint */
472 )
473{
474 SCIP_CONSDATA* consdata;
475
477
478 /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
479 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
480 return SCIP_OKAY;
481
482 consdata = SCIPconsGetData(cons);
483 assert(consdata != NULL);
484
485 if( consdata->nlrow == NULL )
486 {
487 SCIP_VAR* vars[2];
488 SCIP_Real coefs[2];
489
490 assert(consdata->lhs <= consdata->rhs);
491
492 vars[0] = consdata->var;
493 vars[1] = consdata->vbdvar;
494
495 coefs[0] = 1.0;
496 coefs[1] = consdata->vbdcoef;
497
498 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
499 0.0, 2, vars, coefs, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) );
500
501 assert(consdata->nlrow != NULL);
502 }
503
504 if( !SCIPnlrowIsInNLP(consdata->nlrow) )
505 {
506 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
507 }
508
509 return SCIP_OKAY;
510}
511
512/** returns whether the given solution is feasible for the given variable bound constraint */
513static
515 SCIP* scip, /**< SCIP data structure */
516 SCIP_CONS* cons, /**< variable bound constraint */
517 SCIP_SOL* sol, /**< solution to check, NULL for current solution */
518 SCIP_Bool checklprows /**< Do constraints represented by rows in the current LP have to be checked? */
519 )
520{
521 SCIP_CONSDATA* consdata;
522 SCIP_Real absviol;
523 SCIP_Real relviol;
524
525 consdata = SCIPconsGetData(cons);
526 assert(consdata != NULL);
527
528 SCIPdebugMsg(scip, "checking variable bound constraint <%s> for feasibility of solution %p (lprows=%u)\n",
529 SCIPconsGetName(cons), (void*)sol, checklprows);
530
531 if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
532 {
533 SCIP_Real sum;
534 SCIP_Real lhsrelviol;
535 SCIP_Real rhsrelviol;
536
537 sum = SCIPgetSolVal(scip, sol, consdata->var) + consdata->vbdcoef * SCIPgetSolVal(scip, sol, consdata->vbdvar);
538
539 /* calculate constraint violation and update it in solution */
540 absviol = MAX(consdata->lhs - sum, sum - consdata->rhs);
541 lhsrelviol = SCIPrelDiff(consdata->lhs, sum);
542 rhsrelviol = SCIPrelDiff(sum, consdata->rhs);
543 relviol = MAX(lhsrelviol, rhsrelviol);
544 if( sol != NULL )
545 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
546
547 return (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, sum, consdata->lhs))
548 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, sum, consdata->rhs));
549 }
550 else
551 return TRUE;
552}
553
554
555/** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
556 * propagation rule (see propagateCons()):
557 * (1) left hand side and bounds on y -> lower bound on x
558 * (2) left hand side and upper bound on x -> bound on y
559 * (3) right hand side and bounds on y -> upper bound on x
560 * (4) right hand side and lower bound on x -> bound on y
561 */
562static
564 SCIP* scip, /**< SCIP data structure */
565 SCIP_CONS* cons, /**< constraint that inferred the bound change */
566 SCIP_VAR* infervar, /**< variable that was deduced */
567 PROPRULE proprule, /**< propagation rule that deduced the bound change */
568 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
569 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
570 SCIP_Real inferbd, /**< inference bound which needs to be explained */
571 SCIP_Bool usebdwidening /**< should bound widening be used to in conflict analysis? */
572 )
573{
574 SCIP_CONSDATA* consdata;
575 SCIP_VAR* vbdvar;
576 SCIP_VAR* var;
577 SCIP_Real vbdcoef;
578
579 consdata = SCIPconsGetData(cons);
580 assert(consdata != NULL);
581 assert(!SCIPisZero(scip, consdata->vbdcoef));
582
583 var = consdata->var;
584 assert(var != NULL);
585
586 vbdvar = consdata->vbdvar;
587 assert(vbdvar != NULL);
588
589 vbdcoef = consdata->vbdcoef;
590 assert(!SCIPisZero(scip, vbdcoef));
591
592 switch( proprule )
593 {
594 case PROPRULE_1:
595 /* lhs <= x + c*y: left hand side and bounds on y -> lower bound on x */
596 assert(infervar == var);
597 assert(boundtype == SCIP_BOUNDTYPE_LOWER);
598 assert(!SCIPisInfinity(scip, -consdata->lhs));
599
600 if( usebdwidening )
601 {
602 SCIP_Real QUAD(relaxedbd);
603
604 /* For integer variables, we can reduce the inferbound by 1 - z * eps, because this will be adjusted
605 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
606 * too small and too large vbdcoef values.
607 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
608 * arithmetics, so we explicitly check this here.
609 */
611 && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
612 {
613 SCIP_Real QUAD(tmp);
614
615 QUAD_ASSIGN(tmp, 2.0);
617
618 SCIPquadprecSumDD(relaxedbd, inferbd, -1.0);
619
620 SCIPquadprecSumQQ(relaxedbd, relaxedbd, tmp);
621 SCIPquadprecSumQD(relaxedbd, -relaxedbd, consdata->lhs);
622
623 SCIPquadprecDivQD(relaxedbd, relaxedbd, vbdcoef);
624 }
625 else
626 {
627 SCIPquadprecSumDD(relaxedbd, consdata->lhs, -inferbd);
628 SCIPquadprecDivQD(relaxedbd, relaxedbd, vbdcoef);
629 }
630
631#ifndef NDEBUG
632 {
633 /* check the computed relaxed lower/upper bound is a proper reason for the inference bound which has to be explained */
634 SCIP_Real QUAD(tmp);
635
636 SCIPquadprecProdQD(tmp, relaxedbd, vbdcoef);
637 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
638
640 }
641#endif
642 if( vbdcoef > 0.0 )
643 {
644 /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual
645 * inference bound due to the integrality condition of the variable bound variable
646 */
647 SCIPquadprecSumQD(relaxedbd, relaxedbd, -SCIPfeastol(scip));
648 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
649 }
650 else
651 {
652 /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference
653 * bound due to the integrality condition of the variable bound variable
654 */
655 SCIPquadprecSumQD(relaxedbd, relaxedbd, SCIPfeastol(scip));
656 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
657 }
658 }
659 else
660 {
661 if( vbdcoef > 0.0 )
662 {
663 SCIP_CALL( SCIPaddConflictUb(scip, vbdvar, bdchgidx) );
664 }
665 else
666 {
667 SCIP_CALL( SCIPaddConflictLb(scip, vbdvar, bdchgidx) );
668 }
669 }
670
671 break;
672
673 case PROPRULE_2:
674 /* lhs <= x + c*y: left hand side and upper bound on x -> bound on y */
675 assert(infervar == vbdvar);
676 assert(SCIPvarIsIntegral(vbdvar));
677 assert(!SCIPisInfinity(scip, -consdata->lhs));
678
679 if( usebdwidening )
680 {
681 SCIP_Real QUAD(relaxedub);
682
683 /* compute the relaxed upper bound of the variable which would be sufficient to reach one less (greater) than the
684 * inference bound
685 */
686 if( vbdcoef > 0.0 )
687 {
688 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
689 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
690 * too small and too large vbdcoef values.
691 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
692 * arithmetics, so we explicitly check this here.
693 */
695 && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
696 {
697 SCIP_Real QUAD(tmp);
698
699 QUAD_ASSIGN(tmp, 2.0);
701
702 SCIPquadprecSumDD(relaxedub, inferbd, -1.0);
703
704 SCIPquadprecSumQQ(relaxedub, relaxedub, tmp);
705 SCIPquadprecProdQD(relaxedub, relaxedub, vbdcoef);
706
707 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
708 }
709 else
710 {
711 SCIPquadprecProdDD(relaxedub, inferbd, vbdcoef);
712 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
713 }
714
715#ifndef NDEBUG
716 {
717 /* check the computed relaxed upper bound is a proper reason for the inference bound which has to be explained */
718 SCIP_Real QUAD(tmp);
719
720 SCIPquadprecSumQD(tmp, -relaxedub, consdata->lhs);
721 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
722
723 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, vbdvar, QUAD_TO_DBL(tmp))));
724 }
725#endif
726 }
727 else
728 {
729 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
730 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
731 * too small and too large vbdcoef values.
732 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
733 * arithmetics, so we explicitly check this here.
734 */
736 && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
737 {
738 SCIP_Real QUAD(tmp);
739
740 QUAD_ASSIGN(tmp, 2.0);
742
743 SCIPquadprecSumDD(relaxedub, inferbd, 1.0);
744
745 SCIPquadprecSumQQ(relaxedub, relaxedub, -tmp);
746 SCIPquadprecProdQD(relaxedub, relaxedub, vbdcoef);
747
748 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
749 }
750 else
751 {
752 SCIPquadprecProdDD(relaxedub, inferbd, vbdcoef);
753 SCIPquadprecSumQD(relaxedub, -relaxedub, consdata->lhs);
754 }
755
756#ifndef NDEBUG
757 {
758 /* check the computed relaxed upper bound is a proper reason for the inference bound which has to be explained */
759 SCIP_Real QUAD(tmp);
760
761 SCIPquadprecSumQD(tmp, -relaxedub, consdata->lhs);
762 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
763
764 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, vbdvar, QUAD_TO_DBL(tmp))));
765 }
766#endif
767 }
768
769 /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual inference bound due
770 * to the integrality condition of the variable bound variable
771 */
772 SCIPquadprecSumQD(relaxedub, relaxedub, -SCIPfeastol(scip));
773 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, var, bdchgidx, QUAD_TO_DBL(relaxedub)) );
774 }
775 else
776 {
777 SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
778 }
779
780 break;
781
782 case PROPRULE_3:
783 /* x + c*y <= rhs: right hand side and bounds on y -> upper bound on x */
784 assert(infervar == var);
785 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
786 assert(!SCIPisInfinity(scip, consdata->rhs));
787
788 if( usebdwidening )
789 {
790 SCIP_Real QUAD(relaxedbd);
791
792 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
793 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
794 * too small and too large vbdcoef values.
795 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
796 * arithmetics, so we explicitly check this here.
797 */
799 && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
800 {
801 SCIP_Real QUAD(tmp);
802
803 QUAD_ASSIGN(tmp, 2.0);
804
806 SCIPquadprecSumDD(relaxedbd, inferbd, 1.0);
807
808 SCIPquadprecSumQQ(relaxedbd, relaxedbd, -tmp);
809 SCIPquadprecSumQD(relaxedbd, relaxedbd, -consdata->rhs);
810
811 SCIPquadprecDivQD(relaxedbd, relaxedbd, -vbdcoef);
812 }
813 else
814 {
815 SCIPquadprecSumDD(relaxedbd, consdata->rhs, -inferbd);
816 SCIPquadprecDivQD(relaxedbd, relaxedbd, vbdcoef);
817 }
818#ifndef NDEBUG
819 {
820 /* check the computed relaxed lower/upper bound is a proper reason for the inference bound which has to be explained */
821 SCIP_Real QUAD(tmp);
822
823 SCIPquadprecProdQD(tmp, relaxedbd, -vbdcoef);
824 SCIPquadprecSumQD(tmp, tmp, consdata->rhs);
825
827 }
828#endif
829 if( vbdcoef > 0.0 )
830 {
831 /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference bound due
832 * to the integrality condition of the variable bound variable
833 */
834 SCIPquadprecSumQD(relaxedbd, relaxedbd, SCIPfeastol(scip));
835 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
836 }
837 else
838 {
839 /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual inference bound due
840 * to the integrality condition of the variable bound variable
841 */
842 SCIPquadprecSumQD(relaxedbd, relaxedbd, -SCIPfeastol(scip));
843 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, vbdvar, bdchgidx, QUAD_TO_DBL(relaxedbd)) );
844 }
845 }
846 else
847 {
848 if( vbdcoef > 0.0 )
849 {
850 SCIP_CALL( SCIPaddConflictLb(scip, vbdvar, bdchgidx) );
851 }
852 else
853 {
854 SCIP_CALL( SCIPaddConflictUb(scip, vbdvar, bdchgidx) );
855 }
856 }
857
858 break;
859
860 case PROPRULE_4:
861 /* x + c*y <= rhs: right hand side and lower bound on x -> bound on y */
862 assert(infervar == vbdvar);
863 assert(SCIPvarIsIntegral(vbdvar));
864 assert(!SCIPisInfinity(scip, consdata->rhs));
865
866 if( usebdwidening )
867 {
868 SCIP_Real QUAD(relaxedlb);
869
870 /* compute the relaxed lower bound of the variable which would be sufficient to reach one greater (less) than the
871 * inference bound
872 */
873 if( vbdcoef > 0.0 )
874 {
875 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
876 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
877 * too small and too large vbdcoef values.
878 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
879 * arithmetics, so we explicitly check this here.
880 */
882 && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
883 {
884 SCIP_Real QUAD(tmp);
885
886 QUAD_ASSIGN(tmp, 2.0);
888
889 SCIPquadprecSumDD(relaxedlb, inferbd, 1.0);
890 SCIPquadprecSumQQ(relaxedlb, relaxedlb, -tmp);
891
892 SCIPquadprecProdQD(relaxedlb, relaxedlb, vbdcoef);
893
894 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
895 }
896 else
897 {
898 SCIPquadprecProdDD(relaxedlb, inferbd, vbdcoef);
899 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
900 }
901#ifndef NDEBUG
902 {
903 /* check the computed relaxed lower bound is a proper reason for the inference bound which has to be explained */
904
905 SCIP_Real QUAD(tmp);
906
907 QUAD_ASSIGN(tmp, consdata->rhs);
908 SCIPquadprecSumQQ(tmp, tmp, -relaxedlb);
909 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
910
911 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, vbdvar, QUAD_TO_DBL(tmp))));
912 }
913#endif
914 }
915 else
916 {
917 /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
918 * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
919 * too small and too large vbdcoef values.
920 * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
921 * arithmetics, so we explicitly check this here.
922 */
924 && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
925 {
926 SCIP_Real QUAD(tmp);
927
928 QUAD_ASSIGN(tmp, 2.0);
930
931 SCIPquadprecSumDD(relaxedlb, inferbd, -1.0);
932 SCIPquadprecSumQQ(relaxedlb, relaxedlb, tmp);
933
934 SCIPquadprecProdQD(relaxedlb, relaxedlb, vbdcoef);
935
936 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
937 }
938 else
939 {
940 SCIPquadprecProdDD(relaxedlb, inferbd, vbdcoef);
941 SCIPquadprecSumQD(relaxedlb, -relaxedlb, consdata->rhs);
942 }
943
944#ifndef NDEBUG
945 {
946 /* check the computed relaxed lower bound is a proper reason for the inference bound which has to be explained */
947
948 SCIP_Real QUAD(tmp);
949
950 QUAD_ASSIGN(tmp, consdata->rhs);
951 SCIPquadprecSumQQ(tmp, tmp, -relaxedlb);
952 SCIPquadprecDivQD(tmp, tmp, vbdcoef);
953
954 assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, vbdvar, QUAD_TO_DBL(tmp))));
955 }
956#endif
957 }
958
959 /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference bound due
960 * to the integrality condition of the variable bound variable
961 */
962 SCIPquadprecSumQD(relaxedlb, relaxedlb, SCIPfeastol(scip));
963 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, var, bdchgidx, QUAD_TO_DBL(relaxedlb)) );
964 }
965 else
966 {
967 SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
968 }
969
970 break;
971
972 default:
973 SCIPerrorMessage("invalid inference information %d in variable bound constraint <%s>\n", proprule, SCIPconsGetName(cons));
974 return SCIP_INVALIDDATA;
975 }
976
977 return SCIP_OKAY;
978}
979
980/** analyze infeasibility */
981static
983 SCIP* scip, /**< SCIP data structure */
984 SCIP_CONS* cons, /**< variable bound constraint */
985 SCIP_VAR* infervar, /**< variable that was deduced */
986 SCIP_Real inferbd, /**< bound which led to infeasibility */
987 PROPRULE proprule, /**< propagation rule that deduced the bound change */
988 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
989 SCIP_Bool usebdwidening /**< should bound widening be used to in conflict analysis? */
990 )
991{
992 /* conflict analysis can only be applied in solving stage and if it is applicable */
994 return SCIP_OKAY;
995
996 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
998
999 /* add the bound which got violated */
1000 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1001 {
1002 if( usebdwidening )
1003 {
1004 SCIP_Real relaxedub;
1005
1006 /* adjust lower bound */
1007 inferbd = SCIPadjustedVarLb(scip, infervar, inferbd);
1008
1009 /* compute a relaxed upper bound which would be sufficient to be still infeasible */
1010 if( SCIPvarIsIntegral(infervar) )
1011 relaxedub = inferbd - 1.0;
1012 else
1013 {
1014 SCIP_CONSDATA* consdata;
1015 SCIP_Real abscoef;
1016
1017 consdata = SCIPconsGetData(cons);
1018 assert(consdata != NULL);
1019
1020 /* vbdvar can never be of non-integral type */
1021 assert(infervar == consdata->var);
1022
1023 abscoef = REALABS(consdata->vbdcoef);
1024
1025 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1026 * is big enough, therefore we multiply here with the vbdcoef
1027 *
1028 * @note it does not matter if we deceed the current local upper bound, because SCIPaddConflictRelaxedUb()
1029 * is correcting the bound afterwards
1030 */
1031 /* coverity[copy_paste_error] */
1032 relaxedub = inferbd - 2*SCIPfeastol(scip) * MAX(1, abscoef);
1033 }
1034
1035 /* try to relax inference variable upper bound such that the infeasibility is still given */
1036 SCIP_CALL( SCIPaddConflictRelaxedUb(scip, infervar, NULL, relaxedub) );
1037
1038 /* collect the upper bound which is reported to the conflict analysis */
1039 inferbd = SCIPgetConflictVarUb(scip, infervar);
1040
1041 /* adjust inference bound with respect to the upper bound reported to the conflict analysis */
1042 if( SCIPvarIsIntegral(infervar) )
1043 inferbd = inferbd + 1.0;
1044 else
1045 {
1046 SCIP_CONSDATA* consdata;
1047 SCIP_Real abscoef;
1048
1049 consdata = SCIPconsGetData(cons);
1050 assert(consdata != NULL);
1051
1052 /* vbdvar can never be of non-integral type */
1053 assert(infervar == consdata->var);
1054
1055 abscoef = REALABS(consdata->vbdcoef);
1056
1057 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1058 * is big enough, therefore we multiply here with the vbdcoef
1059 */
1060 inferbd = inferbd + 2*SCIPfeastol(scip) * MAX(1, abscoef);
1061 }
1062 }
1063 else
1064 {
1065 SCIP_CALL( SCIPaddConflictUb(scip, infervar, NULL) );
1066 }
1067 }
1068 else
1069 {
1070 if( usebdwidening )
1071 {
1072 SCIP_Real relaxedlb;
1073
1074 assert(boundtype == SCIP_BOUNDTYPE_UPPER);
1075
1076 /* adjust upper bound */
1077 inferbd = SCIPadjustedVarUb(scip, infervar, inferbd);
1078
1079 /* compute a relaxed lower bound which would be sufficient to be still infeasible */
1080 if( SCIPvarIsIntegral(infervar) )
1081 relaxedlb = inferbd + 1.0;
1082 else
1083 {
1084 SCIP_CONSDATA* consdata;
1085 SCIP_Real abscoef;
1086
1087 consdata = SCIPconsGetData(cons);
1088 assert(consdata != NULL);
1089
1090 /* vbdvar can never be of non-integral type */
1091 assert(infervar == consdata->var);
1092
1093 abscoef = REALABS(consdata->vbdcoef);
1094
1095 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1096 * is big enough, therefore we multiply here with the vbdcoef
1097 *
1098 * @note it does not matter if we exceed the current local lower bound, because SCIPaddConflictRelaxedLb()
1099 * is correcting the bound afterwards
1100 */
1101 /* coverity[copy_paste_error] */
1102 relaxedlb = inferbd + 2*SCIPfeastol(scip) * MAX(1, abscoef);
1103 }
1104
1105 /* try to relax inference variable upper bound such that the infeasibility is still given */
1106 SCIP_CALL( SCIPaddConflictRelaxedLb(scip, infervar, NULL, relaxedlb) );
1107
1108 /* collect the lower bound which is reported to the conflict analysis */
1109 inferbd = SCIPgetConflictVarLb(scip, infervar);
1110
1111 /* adjust inference bound with respect to the lower bound reported to the conflict analysis */
1112 if( SCIPvarIsIntegral(infervar) )
1113 inferbd = inferbd - 1.0;
1114 else
1115 {
1116 SCIP_CONSDATA* consdata;
1117 SCIP_Real abscoef;
1118
1119 consdata = SCIPconsGetData(cons);
1120 assert(consdata != NULL);
1121
1122 /* vbdvar can never be of non-integral type */
1123 assert(infervar == consdata->var);
1124
1125 abscoef = REALABS(consdata->vbdcoef);
1126
1127 /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
1128 * is big enough, therefore we multiply here with the vbdcoef
1129 */
1130 inferbd = inferbd - 2*SCIPfeastol(scip) * MAX(1, abscoef);
1131 }
1132 }
1133 else
1134 {
1135 SCIP_CALL( SCIPaddConflictLb(scip, infervar, NULL) );
1136 }
1137 }
1138
1139 /* add the reason for the violated of the bound */
1140 SCIP_CALL( resolvePropagation(scip, cons, infervar, proprule, boundtype, NULL, inferbd, usebdwidening) );
1141
1142 /* analyze the conflict */
1144
1145 return SCIP_OKAY;
1146}
1147
1148/** separates the given variable bound constraint */
1149static
1151 SCIP* scip, /**< SCIP data structure */
1152 SCIP_CONS* cons, /**< variable bound constraint */
1153 SCIP_Bool usebdwidening, /**< should bound widening be used to in conflict analysis? */
1154 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1155 SCIP_RESULT* result /**< pointer to store the result of the separation call */
1156 )
1157{
1158 SCIP_CONSHDLR* conshdlr;
1159 SCIP_CONSDATA* consdata;
1160 SCIP_VAR* vbdvar;
1161 SCIP_VAR* var;
1162 SCIP_Real vbdcoef;
1163 SCIP_Real feasibility;
1164
1165 assert(cons != NULL);
1166 assert(result != NULL);
1167
1168 consdata = SCIPconsGetData(cons);
1169 assert(consdata != NULL);
1170
1171 /* find the variable bound constraint handler */
1172 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
1173 if( conshdlr == NULL )
1174 {
1175 SCIPerrorMessage("variable bound constraint handler not found\n");
1176 return SCIP_PLUGINNOTFOUND;
1177 }
1178
1179 SCIPdebugMsg(scip, "separating variable bound constraint <%s>\n", SCIPconsGetName(cons));
1180
1181 var = consdata->var;
1182 vbdvar = consdata->vbdvar;
1183 vbdcoef = consdata->vbdcoef;
1184 assert(SCIPvarIsIntegral(vbdvar));
1185
1186 /* if x is not multiaggregated and y is fixed, propagate bounds on x */
1188 {
1190
1191 if( !SCIPisInfinity(scip, -consdata->lhs) )
1192 {
1193 SCIP_Real newlb;
1194 SCIP_Real QUAD(tmp);
1196 SCIP_Bool tightened;
1197
1198 SCIPquadprecProdDD(tmp, vbdcoef, SCIPvarGetLbLocal(vbdvar)); /*lint !e666*/
1199 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1200
1201 newlb = QUAD_TO_DBL(tmp);
1202
1203 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, (int)PROPRULE_1, TRUE,
1204 &cutoff, &tightened) );
1205
1206 if( cutoff )
1207 {
1209
1210 /* analyze infeasibility */
1211 SCIP_CALL( analyzeConflict(scip, cons, var, newlb, PROPRULE_1, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1213
1214 return SCIP_OKAY;
1215 }
1216 else if( tightened )
1217 {
1219 }
1220 }
1221
1222 if( !SCIPisInfinity(scip, consdata->rhs) )
1223 {
1224 SCIP_Real newub;
1225 SCIP_Real QUAD(tmp);
1227 SCIP_Bool tightened;
1228
1229 SCIPquadprecProdDD(tmp, vbdcoef, SCIPvarGetLbLocal(vbdvar)); /*lint !e666*/
1230 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1231
1232 newub = QUAD_TO_DBL(tmp);
1233
1234 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, (int)PROPRULE_3, TRUE,
1235 &cutoff, &tightened) );
1236
1237 if( cutoff )
1238 {
1240
1241 /* analyze infeasibility */
1242 SCIP_CALL( analyzeConflict(scip, cons, var, newub, PROPRULE_3, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1244
1245 return SCIP_OKAY;
1246 }
1247 else if( tightened )
1248 {
1250 }
1251 }
1252 }
1253
1254 /* if we already changed a bound or the coefficient is too large to put the row into the LP, stop here */
1255 if( *result == SCIP_REDUCEDDOM )
1256 return SCIP_OKAY;
1257
1258 /* check constraint for feasibility and create row if constraint is violated */
1259 if( !checkCons(scip, cons, sol, (sol != NULL)) )
1260 {
1261 /* create LP relaxation if not yet existing */
1262 if( consdata->row == NULL )
1263 {
1265 }
1266 assert(consdata->row != NULL);
1267
1268 /* check non-LP rows for feasibility and add them as cut, if violated */
1269 if( !SCIProwIsInLP(consdata->row) )
1270 {
1271 feasibility = SCIPgetRowSolFeasibility(scip, consdata->row, sol);
1272 if( SCIPisFeasNegative(scip, feasibility) )
1273 {
1274 SCIP_Bool infeasible;
1275
1276 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, &infeasible) );
1277 if ( infeasible )
1279 else
1281 }
1282 }
1283 }
1284
1285 return SCIP_OKAY;
1286}
1287
1288/** sets left hand side of varbound constraint */
1289static
1291 SCIP* scip, /**< SCIP data structure */
1292 SCIP_CONS* cons, /**< linear constraint */
1293 SCIP_Real lhs /**< new left hand side */
1294 )
1295{
1296 SCIP_CONSDATA* consdata;
1297
1298 assert(scip != NULL);
1299 assert(cons != NULL);
1300 assert(!SCIPisInfinity(scip, lhs));
1301
1302 /* adjust value to not be smaller than -inf */
1303 if( SCIPisInfinity(scip, -lhs) )
1304 lhs = -SCIPinfinity(scip);
1305
1306 consdata = SCIPconsGetData(cons);
1307 assert(consdata != NULL);
1308 assert(consdata->var != NULL && consdata->vbdvar != NULL);
1309 assert(!SCIPisInfinity(scip, consdata->lhs));
1310
1311 /* check whether the side is not changed */
1312 if( SCIPisEQ(scip, consdata->lhs, lhs) )
1313 return SCIP_OKAY;
1314
1315 assert(consdata->row == NULL);
1316
1317 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
1318 if( SCIPisEQ(scip, lhs, consdata->rhs) )
1319 consdata->rhs = lhs;
1320
1321 /* update the rounding locks of variables */
1322
1323 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
1324 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
1325 {
1326 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, TRUE, FALSE) );
1327
1328 if( consdata->vbdcoef > 0.0 )
1329 {
1330 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1331 }
1332 else
1333 {
1334 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1335 }
1336 }
1337 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
1338 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
1339 {
1340 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, TRUE, FALSE) );
1341
1342 if( consdata->vbdcoef > 0.0 )
1343 {
1344 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1345 }
1346 else
1347 {
1348 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1349 }
1350 }
1351
1352 /* if left hand side got tighter, we want to do additional presolving on this constraint */
1353 if( SCIPisLT(scip, consdata->lhs, lhs) )
1354 {
1355 consdata->varboundsadded = FALSE;
1356 consdata->tightened = FALSE;
1357
1359 }
1360
1361 consdata->presolved = FALSE;
1362 consdata->lhs = lhs;
1363 consdata->changed = TRUE;
1364
1365 return SCIP_OKAY;
1366}
1367
1368/** sets right hand side of varbound constraint */
1369static
1371 SCIP* scip, /**< SCIP data structure */
1372 SCIP_CONS* cons, /**< linear constraint */
1373 SCIP_Real rhs /**< new right hand side */
1374 )
1375{
1376 SCIP_CONSDATA* consdata;
1377
1378 assert(scip != NULL);
1379 assert(cons != NULL);
1380 assert(!SCIPisInfinity(scip, -rhs));
1381
1382 /* adjust value to not be larger than inf */
1383 if( SCIPisInfinity(scip, rhs) )
1384 rhs = SCIPinfinity(scip);
1385
1386 consdata = SCIPconsGetData(cons);
1387 assert(consdata != NULL);
1388 assert(consdata->var != NULL && consdata->vbdvar != NULL);
1389 assert(!SCIPisInfinity(scip, -consdata->rhs));
1390
1391 /* check whether the side is not changed */
1392 if( SCIPisEQ(scip, consdata->rhs, rhs) )
1393 return SCIP_OKAY;
1394
1395 assert(consdata->row == NULL);
1396
1397 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
1398 if( SCIPisEQ(scip, rhs, consdata->lhs) )
1399 consdata->lhs = rhs;
1400
1401 /* update the locks of variables */
1403
1404 /* the right hand side switched from infinity to a non-infinite value -> install locks */
1405 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
1406 {
1407 SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, FALSE, TRUE) );
1408
1409 if( consdata->vbdcoef > 0.0 )
1410 {
1411 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1412 }
1413 else
1414 {
1415 SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1416 }
1417 }
1418 /* the right hand side switched from a non-infinite value to infinity -> remove locks */
1419 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
1420 {
1421 SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, FALSE, TRUE) );
1422
1423 if( consdata->vbdcoef > 0.0 )
1424 {
1425 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1426 }
1427 else
1428 {
1429 SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1430 }
1431 }
1432
1433 /* if right hand side got tighter, we want to do additional presolving on this constraint */
1434 if( SCIPisGT(scip, consdata->rhs, rhs) )
1435 {
1436 consdata->varboundsadded = FALSE;
1437 consdata->tightened = FALSE;
1438
1440 }
1441
1442 consdata->presolved = FALSE;
1443 consdata->rhs = rhs;
1444 consdata->changed = TRUE;
1445
1446 return SCIP_OKAY;
1447}
1448
1449/** propagation method for variable bound constraint */
1450static
1452 SCIP* scip, /**< SCIP data structure */
1453 SCIP_CONS* cons, /**< variable bound constraint */
1454 SCIP_Bool usebdwidening, /**< should bound widening be used to in conflict analysis? */
1455 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1456 int* nchgbds, /**< pointer to count number of bound changes */
1457 int* nchgsides, /**< pointer to count number of side changes */
1458 int* ndelconss /**< pointer to count number of deleted constraints, or NULL */
1459 )
1460{
1461 SCIP_VAR** vars;
1462 SCIP_CONSDATA* consdata;
1464 SCIP_Real xlb;
1465 SCIP_Real xub;
1466 SCIP_Real ylb;
1467 SCIP_Real yub;
1468 SCIP_Real newlb;
1469 SCIP_Real newub;
1470 SCIP_Real constant;
1472 SCIP_Real QUAD(activity);
1473 SCIP_Bool tightened;
1474 SCIP_Bool tightenedround;
1475 SCIP_Bool islhsredundant;
1476 SCIP_Bool isrhsredundant;
1477 int nvars;
1478 int requiredsize;
1479 int i;
1480
1481 assert(cutoff != NULL);
1482 assert(nchgbds != NULL);
1483
1484 consdata = SCIPconsGetData(cons);
1485 assert(consdata != NULL);
1486 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
1487
1488 SCIPdebugMsg(scip, "propagating variable bound constraint <%s>: %.15g <= <%s>[%.9g, %.9g] + %.15g<%s>[%.9g, %.9g] <= %.15g\n",
1489 SCIPconsGetName(cons), consdata->lhs, SCIPvarGetName(consdata->var), SCIPvarGetLbLocal(consdata->var),
1490 SCIPvarGetUbLocal(consdata->var), consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
1491 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), consdata->rhs);
1492
1493 *cutoff = FALSE;
1494
1495 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1497 {
1498 SCIP_CALL( SCIPincConsAge(scip, cons) );
1499 }
1500
1501 /* get current bounds of variables */
1502 xlb = SCIPvarGetLbLocal(consdata->var);
1503 xub = SCIPvarGetUbLocal(consdata->var);
1504 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1505 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1506
1507 /* it can happen that constraint is of form lhs <= x <= rhs */
1508 if( SCIPisZero(scip, consdata->vbdcoef) && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1509 {
1510 SCIP_Bool infeasible;
1511 SCIP_Bool fixed;
1512
1513 SCIP_CALL( SCIPfixVar(scip, consdata->var, consdata->lhs, &infeasible, &fixed) );
1514
1515 if( infeasible )
1516 {
1517 SCIPdebugMsg(scip, "> constraint <%s> is infeasible.\n", SCIPconsGetName(cons));
1518 *cutoff = TRUE;
1519 return SCIP_OKAY;
1520 }
1521 }
1522
1523 /* tighten bounds of variables as long as possible */
1524 do
1525 {
1526 tightenedround = FALSE;
1527
1528 /* propagate left hand side inequality: lhs <= x + c*y */
1529 if( !SCIPisInfinity(scip, -consdata->lhs) )
1530 {
1531 assert(!(*cutoff));
1532
1533 /* propagate bounds on x:
1534 * (1) left hand side and bounds on y -> lower bound on x
1535 */
1536 if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1537 {
1538 if( consdata->vbdcoef > 0.0 )
1539 {
1540 if( !SCIPisInfinity(scip, yub) )
1541 {
1542 SCIP_Real QUAD(tmp);
1543
1544 SCIPquadprecProdDD(tmp, consdata->vbdcoef, yub);
1545 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1546
1547 newlb = SCIPadjustedVarLb(scip, consdata->var, QUAD_TO_DBL(tmp));
1548 }
1549 else
1550 {
1551 newlb = -SCIPinfinity(scip);
1552 }
1553 }
1554 else
1555 {
1556 if( !SCIPisInfinity(scip, -ylb) )
1557 {
1558 SCIP_Real QUAD(tmp);
1559
1560 SCIPquadprecProdDD(tmp, consdata->vbdcoef, ylb);
1561 SCIPquadprecSumQD(tmp, -tmp, consdata->lhs);
1562
1563 newlb = SCIPadjustedVarLb(scip, consdata->var, QUAD_TO_DBL(tmp));
1564 }
1565 else
1566 {
1567 newlb = -SCIPinfinity(scip);
1568 }
1569 }
1570
1571 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->var, newlb, cons, (int)PROPRULE_1, yub < ylb + 0.5, cutoff, &tightened) );
1572
1573 if( *cutoff )
1574 {
1575 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1576 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->var)));
1577
1579
1580 /* analyze infeasibility */
1581 SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newlb, PROPRULE_1, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1582 break;
1583 }
1584
1585 if( tightened )
1586 {
1587 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1588 tightenedround = TRUE;
1589 (*nchgbds)++;
1591 }
1592 xlb = SCIPvarGetLbLocal(consdata->var);
1593 }
1594
1595 assert(!*cutoff);
1596
1597 /* propagate bounds on y:
1598 * (2) left hand side and upper bound on x -> bound on y
1599 */
1600 if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, xub) ) /* cannot change bounds of multaggr vars */
1601 {
1602 if( consdata->vbdcoef > 0.0 )
1603 {
1604 SCIP_Real QUAD(tmp);
1605
1606 SCIPquadprecSumDD(tmp, consdata->lhs, -xub);
1607 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1608
1609 newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1610 if( newlb > ylb + 0.5 )
1611 {
1612 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1613
1614 if( *cutoff )
1615 {
1616 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1617 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)));
1618
1619 /* analyze infeasibility */
1620 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_2, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1621 break;
1622 }
1623
1624 if( tightened )
1625 {
1626 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1627 tightenedround = TRUE;
1628 (*nchgbds)++;
1629 }
1630 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1631 }
1632 }
1633 else
1634 {
1635 SCIP_Real QUAD(tmp);
1636
1637 SCIPquadprecSumDD(tmp, consdata->lhs, -xub);
1638 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1639
1640 newub = SCIPadjustedVarUb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1641
1642 if( newub < yub - 0.5 )
1643 {
1644 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1645
1646 if( *cutoff )
1647 {
1648 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1649 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)));
1650
1652
1653 /* analyze infeasibility */
1654 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_2, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1655 break;
1656 }
1657
1658 if( tightened )
1659 {
1660 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1661 tightenedround = TRUE;
1662 (*nchgbds)++;
1664 }
1665 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1666 }
1667 }
1668 }
1669 }
1670
1671 assert(!*cutoff);
1672
1673 /* propagate right hand side inequality: x + c*y <= rhs */
1674 if( !SCIPisInfinity(scip, consdata->rhs) )
1675 {
1676 /* propagate bounds on x:
1677 * (3) right hand side and bounds on y -> upper bound on x
1678 */
1679 if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1680 {
1681 if( consdata->vbdcoef > 0.0 )
1682 {
1683 if( !SCIPisInfinity(scip, -ylb) )
1684 {
1685 SCIP_Real QUAD(tmp);
1686
1687 SCIPquadprecProdDD(tmp, consdata->vbdcoef, ylb);
1688 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1689
1690 newub = SCIPadjustedVarUb(scip, consdata->var, QUAD_TO_DBL(tmp));
1691 }
1692 else
1693 {
1694 newub = SCIPinfinity(scip);
1695 }
1696 }
1697 else
1698 {
1699 if( !SCIPisInfinity(scip, yub) )
1700 {
1701 SCIP_Real QUAD(tmp);
1702
1703 SCIPquadprecProdDD(tmp, consdata->vbdcoef, yub);
1704 SCIPquadprecSumQD(tmp, -tmp, consdata->rhs);
1705
1706 newub = SCIPadjustedVarUb(scip, consdata->var, QUAD_TO_DBL(tmp));
1707 }
1708 else
1709 {
1710 newub = SCIPinfinity(scip);
1711 }
1712 }
1713
1714 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->var, newub, cons, (int)PROPRULE_3, yub < ylb + 0.5, cutoff, &tightened) );
1715
1716 if( *cutoff )
1717 {
1718 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1719 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->var)));
1720
1722
1723 /* analyze infeasibility */
1724 SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newub, PROPRULE_3, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1725 break;
1726 }
1727
1728 if( tightened )
1729 {
1730 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1731 tightenedround = TRUE;
1732 (*nchgbds)++;
1734 }
1735 xub = SCIPvarGetUbLocal(consdata->var);
1736 }
1737
1738 assert(!*cutoff);
1739
1740 /* propagate bounds on y:
1741 * (4) right hand side and lower bound on x -> bound on y
1742 */
1743 if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, -xlb) ) /* cannot change bounds of multaggr vars */
1744 {
1745 if( consdata->vbdcoef > 0.0 )
1746 {
1747 SCIP_Real QUAD(tmp);
1748
1749 SCIPquadprecSumDD(tmp, consdata->rhs, -xlb);
1750 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1751
1752 newub = SCIPadjustedVarUb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1753 if( newub < yub - 0.5 )
1754 {
1755 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1756
1757 if( *cutoff )
1758 {
1759 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1760 assert(SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)));
1761
1763
1764 /* analyze infeasibility */
1765 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_4, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1766 break;
1767 }
1768
1769 if( tightened )
1770 {
1771 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1772 tightenedround = TRUE;
1773 (*nchgbds)++;
1775 }
1776 yub = SCIPvarGetUbLocal(consdata->vbdvar);
1777 }
1778 }
1779 else
1780 {
1781 SCIP_Real QUAD(tmp);
1782
1783 SCIPquadprecSumDD(tmp, consdata->rhs, -xlb);
1784 SCIPquadprecDivQD(tmp, tmp, consdata->vbdcoef);
1785
1786 newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, QUAD_TO_DBL(tmp));
1787 if( newlb > ylb + 0.5 )
1788 {
1789 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1790
1791 if( *cutoff )
1792 {
1793 SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1794 assert(SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)));
1795
1797
1798 /* analyze infeasibility */
1799 SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_4, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1800 break;
1801 }
1802
1803 if( tightened )
1804 {
1805 SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1806 tightenedround = TRUE;
1807 (*nchgbds)++;
1809 }
1810 ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1811 }
1812 }
1813 }
1814 }
1815 assert(!(*cutoff));
1816 }
1817 while( tightenedround );
1818
1819 /* check for redundant sides */
1820 if( !(*cutoff) )
1821 {
1822 islhsredundant = TRUE;
1823 isrhsredundant = TRUE;
1824 nvars = 2;
1825
1828
1829 constant = 0.0;
1830 vars[0] = consdata->var;
1831 vars[1] = consdata->vbdvar;
1832 scalars[0] = 1.0;
1833 scalars[1] = consdata->vbdcoef;
1834 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, &nvars, nvars, &constant, &requiredsize) );
1835
1836 if( requiredsize > nvars )
1837 {
1838 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
1839 SCIP_CALL( SCIPreallocBufferArray(scip, &scalars, requiredsize) );
1840
1841 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, scalars, &nvars, requiredsize, &constant, &requiredsize) );
1842 assert(requiredsize <= nvars);
1843 }
1844
1845 if( !SCIPisInfinity(scip, -consdata->lhs) )
1846 {
1847 QUAD_ASSIGN(activity, constant);
1848
1849 for( i = 0; i < nvars; ++i )
1850 {
1851 assert(scalars[i] != 0.0);
1852 if( scalars[i] > 0.0 )
1853 {
1855
1856 if( SCIPisInfinity(scip, -bound) )
1857 {
1858 islhsredundant = FALSE;
1859 break;
1860 }
1861 }
1862 else
1863 {
1865
1866 if( SCIPisInfinity(scip, bound) )
1867 {
1868 islhsredundant = FALSE;
1869 break;
1870 }
1871 }
1872
1873 SCIPquadprecSumQD(activity, activity, scalars[i] * bound);
1874 }
1875
1876 if( islhsredundant && SCIPisLT(scip, QUAD_TO_DBL(activity), consdata->lhs) )
1877 islhsredundant = FALSE;
1878 }
1879
1880 if( !SCIPisInfinity(scip, consdata->rhs) )
1881 {
1882 QUAD_ASSIGN(activity, constant);
1883
1884 for( i = 0; i < nvars; ++i )
1885 {
1886 assert(scalars[i] != 0.0);
1887 if( scalars[i] > 0.0 )
1888 {
1890
1891 if( SCIPisInfinity(scip, bound) )
1892 {
1893 isrhsredundant = FALSE;
1894 break;
1895 }
1896 }
1897 else
1898 {
1900
1901 if( SCIPisInfinity(scip, -bound) )
1902 {
1903 isrhsredundant = FALSE;
1904 break;
1905 }
1906 }
1907
1908 SCIPquadprecSumQD(activity, activity, scalars[i] * bound);
1909 }
1910
1911 if( isrhsredundant && SCIPisGT(scip, QUAD_TO_DBL(activity), consdata->rhs) )
1912 isrhsredundant = FALSE;
1913 }
1914
1917
1918 /* check varbound constraint for redundancy */
1919 if( islhsredundant && isrhsredundant )
1920 {
1921 SCIPdebugMsg(scip, "variable bound constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
1922 SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
1923
1924 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
1925 if( nvars > 0 )
1927 else
1928 SCIP_CALL( SCIPdelCons(scip, cons) );
1929
1930 /* this did not seem to help but should be tested again, there might also still be a bug in there */
1931#ifdef SCIP_DISABLED_CODE
1932 /* local duality fixing of variables in the constraint */
1933 if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->vbdvar))
1934 && SCIPvarGetNLocksDownType(consdata->vbdvar, SCIP_LOCKTYPE_MODEL) == 1
1935 && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->vbdvar))
1936 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1937 && ((consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1938 || (consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1939 {
1940 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1941 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetLbLocal(consdata->vbdvar));
1942 SCIP_CALL( SCIPchgVarUb(scip, consdata->vbdvar, SCIPvarGetLbLocal(consdata->vbdvar)) );
1943 }
1944 else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->vbdvar))
1945 && SCIPvarGetNLocksUpType(consdata->vbdvar, SCIP_LOCKTYPE_MODEL) == 1
1946 && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->vbdvar))
1947 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1948 && ((consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1949 || (consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1950 {
1951 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1952 SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar));
1953 SCIP_CALL( SCIPchgVarLb(scip, consdata->vbdvar, SCIPvarGetUbLocal(consdata->vbdvar)) );
1954 }
1955 if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->var))
1956 && SCIPvarGetNLocksDownType(consdata->var, SCIP_LOCKTYPE_MODEL) == 1
1957 && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->var))
1958 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1959 && !SCIPisInfinity(scip, -consdata->lhs) )
1960 {
1961 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1962 SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetLbLocal(consdata->var));
1963 SCIP_CALL( SCIPchgVarUb(scip, consdata->var, SCIPvarGetLbLocal(consdata->var)) );
1964 }
1965 else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->var))
1966 && SCIPvarGetNLocksUpType(consdata->var, SCIP_LOCKTYPE_MODEL) == 1
1967 && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->var))
1968 && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1969 && !SCIPisInfinity(scip, consdata->rhs) )
1970 {
1971 SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1972 SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var));
1973 SCIP_CALL( SCIPchgVarLb(scip, consdata->var, SCIPvarGetUbLocal(consdata->var)) );
1974 }
1975#endif
1976 if( ndelconss != NULL )
1977 ++(*ndelconss);
1978 }
1980 {
1981 /* check left hand side for redundancy */
1982 if( islhsredundant )
1983 {
1984 assert(!isrhsredundant);
1985
1986 if( !SCIPisInfinity(scip, -consdata->lhs) )
1987 {
1988 SCIPdebugMsg(scip, "left hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
1989
1990 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
1991
1992 if( nchgsides != NULL )
1993 ++(*nchgsides);
1994 }
1995 }
1996 /* check right hand side for redundancy */
1997 else if( isrhsredundant )
1998 {
1999 assert(!islhsredundant);
2000
2001 if( !SCIPisInfinity(scip, consdata->rhs) )
2002 {
2003 SCIPdebugMsg(scip, "right hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
2004
2006
2007 if( nchgsides != NULL )
2008 ++(*nchgsides);
2009 }
2010 }
2011 }
2012 }
2013
2015
2016 return SCIP_OKAY;
2017}
2018
2019/* check whether one constraint side is redundant to another constraint side by calculating extreme values for
2020 * variables
2021 */
2022static
2024 SCIP* scip, /**< SCIP data structure */
2025 SCIP_VAR* var, /**< variable x that has variable bound */
2026 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
2027 SCIP_Real coef0, /**< coefficient c0 of bounding variable y for constraint 0 */
2028 SCIP_Real coef1, /**< coefficient c1 of bounding variable y for constraint 1 */
2029 SCIP_Real side0, /**< one side of variable bound inequality for constraint 0 */
2030 SCIP_Real side1, /**< one side of variable bound inequality for constraint 1 */
2031 SCIP_Bool* sideequal, /**< pointer to store if both constraints have the same redundancy on the
2032 * given side */
2033 SCIP_Bool* cons0sidered, /**< pointer to store if side of constraint 0 is redundant */
2034 SCIP_Bool* cons1sidered, /**< pointer to store if side of constraint 1 is redundant */
2035 SCIP_Bool islhs /**< do we check the left or the right hand side */
2036 )
2037{
2038 SCIP_Real lbvar;
2039 SCIP_Real ubvar;
2040 SCIP_Real lbvbdvar;
2041 SCIP_Real ubvbdvar;
2042 SCIP_Real boundxlb1;
2043 SCIP_Real boundxlb2;
2044 SCIP_Real boundylb1;
2045 SCIP_Real boundylb2;
2046 SCIP_Real boundxub1;
2047 SCIP_Real boundxub2;
2048 SCIP_Real boundyub1;
2049 SCIP_Real boundyub2;
2050 SCIP_Real boundvaluex1;
2051 SCIP_Real boundvaluex2;
2052 SCIP_Real boundvaluey1;
2053 SCIP_Real boundvaluey2;
2054 SCIP_Real valuex1;
2055 SCIP_Real valuex2;
2056 SCIP_Real valuey1;
2057 SCIP_Real valuey2;
2058 SCIP_Bool* redundant0;
2059 SCIP_Bool* redundant1;
2060
2061 assert(scip != NULL);
2062 assert(var != NULL);
2063 assert(vbdvar != NULL);
2064 assert(sideequal != NULL);
2065 assert(cons0sidered != NULL);
2066 assert(cons1sidered != NULL);
2067 assert(coef0 * coef1 > 0.0);
2068
2069 *cons0sidered = SCIPisInfinity(scip, islhs ? -side0 : side0);
2070 *cons1sidered = SCIPisInfinity(scip, islhs ? -side1 : side1);
2071 *sideequal = FALSE;
2072
2073 if( islhs )
2074 {
2075 redundant0 = cons1sidered;
2076 redundant1 = cons0sidered;
2077 }
2078 else
2079 {
2080 redundant0 = cons0sidered;
2081 redundant1 = cons1sidered;
2082 }
2083
2084 lbvar = SCIPvarGetLbGlobal(var);
2085 assert(!SCIPisInfinity(scip, lbvar));
2086 ubvar = SCIPvarGetUbGlobal(var);
2087 assert(!SCIPisInfinity(scip, -ubvar));
2088 lbvbdvar = SCIPvarGetLbGlobal(vbdvar);
2089 assert(!SCIPisInfinity(scip, lbvbdvar));
2090 ubvbdvar = SCIPvarGetUbGlobal(vbdvar);
2091 assert(!SCIPisInfinity(scip, -ubvbdvar));
2092
2093 /* if both constraints have this side */
2094 if( !*redundant0 && !*redundant1 )
2095 {
2096 /* calculate extreme values, which are reached by setting the other variable to their lower/upper bound */
2097 if( SCIPisInfinity(scip, -lbvbdvar) )
2098 {
2099 if( coef0 > 0.0 )
2100 {
2101 boundxlb1 = SCIPinfinity(scip);
2102 boundxlb2 = SCIPinfinity(scip);
2103 }
2104 else
2105 {
2106 boundxlb1 = -SCIPinfinity(scip);
2107 boundxlb2 = -SCIPinfinity(scip);
2108 }
2109 }
2110 else
2111 {
2112 boundxlb1 = side0 - lbvbdvar * coef0;
2113 boundxlb2 = side1 - lbvbdvar * coef1;
2114 }
2115 if( SCIPisInfinity(scip, -lbvar) )
2116 {
2117 if( coef0 > 0.0 )
2118 {
2119 boundylb1 = SCIPinfinity(scip);
2120 boundylb2 = SCIPinfinity(scip);
2121 }
2122 else
2123 {
2124 boundylb1 = -SCIPinfinity(scip);
2125 boundylb2 = -SCIPinfinity(scip);
2126 }
2127 }
2128 else
2129 {
2130 boundylb1 = (side0 - lbvar) / coef0;
2131 boundylb2 = (side1 - lbvar) / coef1;
2132 }
2133 if( SCIPisInfinity(scip, ubvbdvar) )
2134 {
2135 if( coef0 > 0.0 )
2136 {
2137 boundxub1 = -SCIPinfinity(scip);
2138 boundxub2 = -SCIPinfinity(scip);
2139 }
2140 else
2141 {
2142 boundxub1 = SCIPinfinity(scip);
2143 boundxub2 = SCIPinfinity(scip);
2144 }
2145 }
2146 else
2147 {
2148 boundxub1 = side0 - ubvbdvar * coef0;
2149 boundxub2 = side1 - ubvbdvar * coef1;
2150 }
2151 if( SCIPisInfinity(scip, ubvar) )
2152 {
2153 if( coef0 > 0.0 )
2154 {
2155 boundyub1 = -SCIPinfinity(scip);
2156 boundyub2 = -SCIPinfinity(scip);
2157 }
2158 else
2159 {
2160 boundyub1 = SCIPinfinity(scip);
2161 boundyub2 = SCIPinfinity(scip);
2162 }
2163 }
2164 else
2165 {
2166 boundyub1 = (side0 - ubvar) / coef0;
2167 boundyub2 = (side1 - ubvar) / coef1;
2168 }
2169
2170 if( islhs )
2171 {
2172 boundvaluex1 = MAX(boundxlb1, boundxlb2);
2173 boundvaluex2 = MAX(boundxub1, boundxub2);
2174 }
2175 else
2176 {
2177 boundvaluex1 = MIN(boundxlb1, boundxlb2);
2178 boundvaluex2 = MIN(boundxub1, boundxub2);
2179 }
2180
2181 /* calculate important values for variables */
2182 if( coef0 > 0.0 )
2183 {
2184 valuex1 = MIN(boundvaluex1, ubvar);
2185 valuex1 = MAX(valuex1, lbvar);
2186 valuex2 = MAX(boundvaluex2, lbvar);
2187 valuex2 = MIN(valuex2, ubvar);
2188
2189 /* if variable is of integral type make values integral too */
2190 if( SCIPvarIsIntegral(var) )
2191 {
2192 valuex1 = SCIPfeasFloor(scip, valuex1);
2193 valuex2 = SCIPfeasCeil(scip, valuex2);
2194 }
2195 }
2196 else
2197 {
2198 valuex1 = MAX(boundvaluex1, lbvar);
2199 valuex1 = MIN(valuex1, ubvar);
2200 valuex2 = MIN(boundvaluex2, ubvar);
2201 valuex2 = MAX(valuex2, lbvar);
2202
2203 /* if variable is of integral type make values integral too */
2204 if( SCIPvarIsIntegral(var) )
2205 {
2206 valuex1 = SCIPfeasCeil(scip, valuex1);
2207 valuex2 = SCIPfeasFloor(scip, valuex2);
2208 }
2209 }
2210
2211 /* calculate resulting values of variable y by setting x to valuex1 */
2212 if( SCIPisInfinity(scip, ABS(valuex1)) )
2213 {
2214 /* only consider sides if coefficients are equal */
2215 if( SCIPisEQ(scip, coef0, coef1) )
2216 {
2217 valuey1 = side0 / coef0;
2218 valuey2 = side1 / coef1;
2219 }
2220 /* only consider original coefficients if otherwise x approaches plus infinity */
2221 else if( valuex1 > 0.0 )
2222 {
2223 valuey1 = coef0;
2224 valuey2 = coef1;
2225 }
2226 /* only consider swapped coefficients if otherwise x approaches minus infinity */
2227 else
2228 {
2229 valuey1 = coef1;
2230 valuey2 = coef0;
2231 }
2232 }
2233 else
2234 {
2235 valuey1 = (side0 - valuex1) / coef0;
2236 valuey2 = (side1 - valuex1) / coef1;
2237 }
2238
2239 /* determine redundancy of one constraints side */
2240 if( SCIPisEQ(scip, valuey1, valuey2) )
2241 *sideequal = TRUE;
2242 else if( coef0 > 0.0 )
2243 {
2244 if( valuey1 < valuey2 )
2245 *redundant1 = TRUE;
2246 else
2247 *redundant0 = TRUE;
2248 }
2249 else
2250 {
2251 if( valuey1 < valuey2 )
2252 *redundant0 = TRUE;
2253 else
2254 *redundant1 = TRUE;
2255 }
2256
2257 /* calculate resulting values of variable y by setting x to valuex2 */
2258 if( SCIPisInfinity(scip, ABS(valuex2)) )
2259 {
2260 /* only consider sides if coefficients are equal */
2261 if( SCIPisEQ(scip, coef0, coef1) )
2262 {
2263 valuey1 = side0 / coef0;
2264 valuey2 = side1 / coef1;
2265 }
2266 /* only consider original coefficients if otherwise x approaches plus infinity */
2267 else if( valuex2 > 0.0 )
2268 {
2269 valuey1 = coef0;
2270 valuey2 = coef1;
2271 }
2272 /* only consider swapped coefficients if otherwise x approaches minus infinity */
2273 else
2274 {
2275 valuey1 = coef1;
2276 valuey2 = coef0;
2277 }
2278 }
2279 else
2280 {
2281 valuey1 = (side0 - valuex2) / coef0;
2282 valuey2 = (side1 - valuex2) / coef1;
2283 }
2284
2285 /* determine redundancy of one constraints side by checking for the first valuex2 */
2286 if( coef0 > 0.0 )
2287 {
2288 /* if both constraints are equal on one value, only consider the other value */
2289 if( *sideequal )
2290 {
2291 assert(!(*redundant0));
2292 assert(!(*redundant1));
2293
2294 if( SCIPisLT(scip, valuey1, valuey2) )
2295 {
2296 *sideequal = FALSE;
2297 *redundant1 = TRUE;
2298 }
2299 else if( SCIPisGT(scip, valuey1, valuey2) )
2300 {
2301 *sideequal = FALSE;
2302 *redundant0 = TRUE;
2303 }
2304 }
2305 /* if both constraints are weaker than the other on one value, we have no redundancy */
2306 else if( ( *redundant1 && SCIPisGT(scip, valuey1, valuey2) )
2307 || ( *redundant0 && SCIPisLT(scip, valuey1, valuey2) ) )
2308 {
2309 *redundant0 = FALSE;
2310 *redundant1 = FALSE;
2311 return;
2312 }
2313 }
2314 else
2315 {
2316 /* if both constraints are equal on one value, only consider the other value */
2317 if( *sideequal )
2318 {
2319 assert(!(*redundant0));
2320 assert(!(*redundant1));
2321
2322 if( SCIPisLT(scip, valuey1, valuey2) )
2323 {
2324 *sideequal = FALSE;
2325 *redundant0 = TRUE;
2326 }
2327 else if( SCIPisGT(scip, valuey1, valuey2) )
2328 {
2329 *sideequal = FALSE;
2330 *redundant1 = TRUE;
2331 }
2332 }
2333 /* if both constraints are weaker than the other one on one value, we have no redundancy */
2334 else if( ( *redundant0 && SCIPisGT(scip, valuey1, valuey2) )
2335 || ( *redundant1 && SCIPisLT(scip, valuey1, valuey2) ) )
2336 {
2337 *redundant0 = FALSE;
2338 *redundant1 = FALSE;
2339 return;
2340 }
2341 }
2342 assert(*sideequal || *redundant0 || *redundant1);
2343
2344 /* calculate feasibility domain values for variable y concerning these both constraints */
2345 if( coef0 > 0.0 )
2346 {
2347 if( islhs )
2348 {
2349 boundvaluey1 = MAX(boundylb1, boundylb2);
2350 boundvaluey2 = MAX(boundyub1, boundyub2);
2351 }
2352 else
2353 {
2354 boundvaluey1 = MIN(boundylb1, boundylb2);
2355 boundvaluey2 = MIN(boundyub1, boundyub2);
2356 }
2357
2358 valuey1 = MIN(boundvaluey1, ubvbdvar);
2359 valuey1 = MAX(valuey1, lbvbdvar);
2360 valuey2 = MAX(boundvaluey2, lbvbdvar);
2361 valuey2 = MIN(valuey2, ubvbdvar);
2362
2363 valuey1 = SCIPfeasFloor(scip, valuey1);
2364 valuey2 = SCIPfeasCeil(scip, valuey2);
2365 }
2366 else
2367 {
2368 if( islhs )
2369 {
2370 boundvaluey1 = MIN(boundylb1, boundylb2);
2371 boundvaluey2 = MIN(boundyub1, boundyub2);
2372 }
2373 else
2374 {
2375 boundvaluey1 = MAX(boundylb1, boundylb2);
2376 boundvaluey2 = MAX(boundyub1, boundyub2);
2377 }
2378
2379 valuey1 = MAX(boundvaluey1, lbvbdvar);
2380 valuey1 = MIN(valuey1, ubvbdvar);
2381 valuey2 = MIN(boundvaluey2, ubvbdvar);
2382 valuey2 = MAX(valuey2, lbvbdvar);
2383
2384 valuey1 = SCIPfeasCeil(scip, valuey1);
2385 valuey2 = SCIPfeasFloor(scip, valuey2);
2386 }
2387
2388 /* calculate resulting values of variable x by setting y to valuey1 */
2389 if( SCIPisInfinity(scip, ABS(valuey1)) )
2390 {
2391 /* only consider sides if coefficients are equal */
2392 if( SCIPisEQ(scip, coef0, coef1) )
2393 {
2394 valuex1 = side0;
2395 valuex2 = side1;
2396 }
2397 /* only consider swapped coefficients if otherwise y approaches plus infinity */
2398 else if( valuey1 > 0.0 )
2399 {
2400 valuex1 = coef1;
2401 valuex2 = coef0;
2402 }
2403 /* only consider original coefficients if otherwise y approaches minus infinity */
2404 else
2405 {
2406 valuex1 = coef0;
2407 valuex2 = coef1;
2408 }
2409 }
2410 else
2411 {
2412 valuex1 = side0 - valuey1 * coef0;
2413 valuex2 = side1 - valuey1 * coef1;
2414 }
2415
2416 /* determine redundancy of one constraints side by checking for the first valuey1 */
2417 if( *sideequal )
2418 {
2419 assert(!(*redundant0));
2420 assert(!(*redundant1));
2421
2422 if( SCIPisLT(scip, valuex1, valuex2) )
2423 {
2424 *sideequal = FALSE;
2425 *redundant1 = TRUE;
2426 }
2427 else if( SCIPisGT(scip, valuex1, valuex2) )
2428 {
2429 *sideequal = FALSE;
2430 *redundant0 = TRUE;
2431 }
2432 }
2433 else if( ( *redundant1 && SCIPisGT(scip, valuex1, valuex2) )
2434 || ( *redundant0 && SCIPisLT(scip, valuex1, valuex2) ) )
2435 {
2436 *redundant0 = FALSE;
2437 *redundant1 = FALSE;
2438 return;
2439 }
2440
2441 /* calculate resulting values of variable x by setting y to valuey2 */
2442 if( SCIPisInfinity(scip, ABS(valuey2)) )
2443 {
2444 /* only consider sides if coefficients are equal */
2445 if( SCIPisEQ(scip, coef0, coef1) )
2446 {
2447 valuex1 = side0;
2448 valuex2 = side1;
2449 }
2450 /* only consider swapped coefficients if otherwise y approaches plus infinity */
2451 else if( valuey2 > 0.0 )
2452 {
2453 valuex1 = coef1;
2454 valuex2 = coef0;
2455 }
2456 /* only consider original coefficients if otherwise y approaches minus infinity */
2457 else
2458 {
2459 valuex1 = coef0;
2460 valuex2 = coef1;
2461 }
2462 }
2463 else
2464 {
2465 valuex1 = side0 - valuey2 * coef0;
2466 valuex2 = side1 - valuey2 * coef1;
2467 }
2468
2469 /* determine redundancy of one constraints side by checking for the second valuey2 */
2470 if( *sideequal )
2471 {
2472 assert(!(*redundant0));
2473 assert(!(*redundant1));
2474
2475 if( SCIPisLT(scip, valuex1, valuex2) )
2476 {
2477 *sideequal = FALSE;
2478 *redundant1 = TRUE;
2479 }
2480 else if( SCIPisGT(scip, valuex1, valuex2) )
2481 {
2482 *sideequal = FALSE;
2483 *redundant0 = TRUE;
2484 }
2485 }
2486 else if( ( *redundant1 && SCIPisGT(scip, valuex1, valuex2) )
2487 || ( *redundant0 && SCIPisLT(scip, valuex1, valuex2) ) )
2488 {
2489 *redundant0 = FALSE;
2490 *redundant1 = FALSE;
2491 return;
2492 }
2493 assert(*redundant0 || *redundant1 || *sideequal);
2494 }
2495}
2496
2497/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
2498 *
2499 * we will order all constraint to have constraints with same variables next to each other to speed up presolving
2500 *
2501 * consider two constraints like lhs1 <= x + b1*y <= rhs1 and lhs2 <= x + b2*y <= rhs2
2502 * we are doing the following presolving steps:
2503 *
2504 * if( b1 == b2 )
2505 * newlhs = MAX(lhs1, lhs2)
2506 * newrhs = MIN(rhs1, rhs2)
2507 * updateSides
2508 * delete one constraint
2509 * else if( ((b1 > 0) == (b2 > 0)) && (lhs1 != -inf && lhs2 != -inf) || (rhs1 != inf && rhs2 != inf) )
2510 *
2511 * (i.e. both constraint have either a valid lhs or a valid rhs and infinity is on the same side and the
2512 * coeffcients have the same size )
2513 *
2514 * if( y is binary )
2515 * if( lhs1 != -inf )
2516 * newlhs = MAX(lhs1, lhs2)
2517 * newb = newlhs - MAX(lhs1 - b1, lhs2 - b2)
2518 * else
2519 * newrhs = MIN(lhs1, lhs2)
2520 * newb = newrhs - MIN(rhs1 - b1, rhs2 - b2)
2521 * updateSidesAndCoef
2522 * delete one constraint
2523 * else
2524 * we calculate possible values for both variables and check which constraint is tighter
2525 * else
2526 * nothing possible
2527 *
2528 * We also try to tighten bounds in the case of two constraints lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2.
2529 * Eliminiating one variable and inserting into the second yields the following bounds:
2530 * If b2 > 0:
2531 * (1 - b1 * b2) * y >= lhs2 - b2 * rhs1
2532 * (1 - b1 * b2) * y <= rhs2 - b2 * lhs1
2533 * If b2 < 0:
2534 * (1 - b1 * b2) * y >= lhs2 - b2 * lhs1
2535 * (1 - b1 * b2) * y <= rhs2 - b2 * rhs1
2536 * The case of x is similar.
2537 */
2538static
2540 SCIP* scip, /**< SCIP data structure */
2541 SCIP_CONS** conss, /**< constraint set */
2542 int nconss, /**< number of constraints in constraint set */
2543 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
2544 int* nchgbds, /**< pointer to count number of bound changes */
2545 int* ndelconss, /**< pointer to count number of deleted constraints */
2546 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
2547 int* nchgsides /**< pointer to count number of changed left/right hand sides */
2548 )
2549{
2550 SCIP_CONS** sortedconss;
2551 int c;
2552 int s;
2553
2554 assert(scip != NULL);
2555 assert(conss != NULL);
2556 assert(cutoff != NULL);
2557 assert(nchgbds != NULL);
2558 assert(ndelconss != NULL);
2559 assert(nchgcoefs != NULL);
2560 assert(nchgsides != NULL);
2561
2562 /* create our temporary working array */
2563 SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedconss, conss, nconss) );
2564
2565 /* sort all constraints, so that all constraints with same variables stand next to each other */
2566 SCIPsortPtr((void**)sortedconss, consVarboundComp, nconss);
2567
2568 /* check all constraints for redundancy */
2569 for( c = nconss - 1; c > 0 && !(*cutoff); --c )
2570 {
2571 SCIP_CONS* cons0;
2572 SCIP_CONSDATA* consdata0;
2573
2574 cons0 = sortedconss[c];
2575
2576 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
2577 continue;
2578
2579 consdata0 = SCIPconsGetData(cons0);
2580 assert(consdata0 != NULL);
2581 assert(consdata0->var != NULL);
2582 assert(consdata0->vbdvar != NULL);
2583
2584 /* do not check for already redundant constraints */
2585 assert(!SCIPisZero(scip, consdata0->vbdcoef));
2586 assert(!SCIPisInfinity(scip, -consdata0->lhs) || !SCIPisInfinity(scip, consdata0->rhs));
2587
2588 if( !consdata0->changed )
2589 continue;
2590
2591 consdata0->changed = FALSE;
2592
2593 for( s = c - 1; s >= 0; --s )
2594 {
2595 SCIP_CONS* cons1;
2596 SCIP_CONSDATA* consdata1;
2597 SCIP_Real lhs;
2598 SCIP_Real rhs;
2599 SCIP_Real coef;
2600 SCIP_Bool deletecons1;
2601
2602 cons1 = sortedconss[s];
2603
2604 if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
2605 continue;
2606
2607 consdata1 = SCIPconsGetData(cons1);
2608 assert(consdata1 != NULL);
2609 assert(consdata1->var != NULL);
2610 assert(consdata1->vbdvar != NULL);
2611
2612 /* do not check for already redundant constraints */
2613 assert(!SCIPisZero(scip, consdata1->vbdcoef));
2614 assert(!SCIPisInfinity(scip, -consdata1->lhs) || !SCIPisInfinity(scip, consdata1->rhs));
2615
2616 lhs = consdata0->lhs;
2617 rhs = consdata0->rhs;
2618 coef = consdata0->vbdcoef;
2619
2620 /* check for propagation in the case: lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2. */
2621 if ( consdata0->var == consdata1->vbdvar && consdata0->vbdvar == consdata1->var &&
2622 !SCIPisFeasZero(scip, 1.0 - coef * consdata1->vbdcoef) )
2623 {
2624 SCIP_Bool tightened = FALSE;
2625 SCIP_Real bnd = SCIP_UNKNOWN;
2626 SCIP_Real scalar;
2627 SCIP_Real newbnd;
2628
2629 scalar = (1.0 - coef * consdata1->vbdcoef);
2630
2631 assert( ! SCIPisInfinity(scip, REALABS(scalar)) );
2632 assert( ! SCIPisZero(scip, consdata0->vbdcoef) );
2633 assert( ! SCIPisZero(scip, consdata1->vbdcoef) );
2634
2635 /* lower bounds for consdata0->var */
2636 if ( ! SCIPisInfinity(scip, -lhs) )
2637 {
2638 if ( SCIPisPositive(scip, coef) )
2639 {
2640 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2641 bnd = (lhs - coef * consdata1->rhs)/scalar;
2642 }
2643 else
2644 {
2645 assert( SCIPisNegative(scip, coef) );
2646 if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2647 bnd = (lhs - coef * consdata1->lhs)/scalar;
2648 }
2649
2650 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2651 {
2652 if ( SCIPisFeasPositive(scip, scalar) )
2653 {
2654 newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2655 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2656 if ( *cutoff )
2657 {
2658 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2659 SCIPvarGetName(consdata0->var), newbnd);
2660 break;
2661 }
2662 if ( tightened )
2663 {
2664 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2665 SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2666 (*nchgbds)++;
2667 }
2668 }
2669 else if ( SCIPisFeasNegative(scip, scalar) )
2670 {
2671 newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2672 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2673 if ( *cutoff )
2674 {
2675 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2676 SCIPvarGetName(consdata0->var), newbnd);
2677 break;
2678 }
2679 if ( tightened )
2680 {
2681 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2682 SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2683 (*nchgbds)++;
2684 }
2685 }
2686 }
2687 }
2688
2689 /* upper bound for consdata0>var */
2690 if ( ! SCIPisInfinity(scip, rhs) )
2691 {
2692 bnd = SCIP_UNKNOWN;
2693 if ( SCIPisPositive(scip, coef) )
2694 {
2695 if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2696 bnd = (rhs - coef * consdata1->lhs)/scalar;
2697 }
2698 else
2699 {
2700 assert( SCIPisNegative(scip, coef) );
2701 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2702 bnd = (rhs - coef * consdata1->rhs)/scalar;
2703 }
2704
2705 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2706 {
2707 if ( SCIPisFeasPositive(scip, scalar) )
2708 {
2709 newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2710 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2711 if ( *cutoff )
2712 {
2713 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2714 SCIPvarGetName(consdata0->var), newbnd);
2715 break;
2716 }
2717 if ( tightened )
2718 {
2719 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2720 SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2721 (*nchgbds)++;
2722 }
2723 }
2724 else if ( SCIPisFeasNegative(scip, scalar) )
2725 {
2726 newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2727 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2728 if ( *cutoff )
2729 {
2730 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2731 SCIPvarGetName(consdata0->var), newbnd);
2732 break;
2733 }
2734 if ( tightened )
2735 {
2736 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2737 SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2738 (*nchgbds)++;
2739 }
2740 }
2741 }
2742 }
2743
2744 /* lower bounds for consdata1->var */
2745 if ( ! SCIPisInfinity(scip, -consdata1->lhs) )
2746 {
2747 bnd = SCIP_UNKNOWN;
2748 if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2749 {
2750 if ( ! SCIPisInfinity(scip, rhs) )
2751 bnd = (consdata1->lhs - consdata1->vbdcoef * rhs)/scalar;
2752 }
2753 else
2754 {
2755 assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2756 if ( ! SCIPisInfinity(scip, lhs) )
2757 bnd = (consdata1->lhs - consdata1->vbdcoef * lhs)/scalar;
2758 }
2759
2760 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2761 {
2762 if ( SCIPisFeasPositive(scip, scalar) )
2763 {
2764 newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2765 SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2766 if ( *cutoff )
2767 {
2768 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2769 SCIPvarGetName(consdata1->var), newbnd);
2770 break;
2771 }
2772 if ( tightened )
2773 {
2774 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2775 SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2776 (*nchgbds)++;
2777 }
2778 }
2779 else if ( SCIPisFeasNegative(scip, scalar) )
2780 {
2781 newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2782 SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2783 if ( *cutoff )
2784 {
2785 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2786 SCIPvarGetName(consdata1->var), newbnd);
2787 break;
2788 }
2789 if ( tightened )
2790 {
2791 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2792 SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2793 (*nchgbds)++;
2794 }
2795 }
2796 }
2797 }
2798
2799 /* upper bound for consdata1->var */
2800 if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2801 {
2802 bnd = SCIP_UNKNOWN;
2803 if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2804 {
2805 if ( ! SCIPisInfinity(scip, lhs) )
2806 bnd = (consdata1->rhs - consdata1->vbdcoef * lhs)/scalar;
2807 }
2808 else
2809 {
2810 assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2811 if ( ! SCIPisInfinity(scip, rhs) )
2812 bnd = (consdata1->rhs - consdata1->vbdcoef * rhs)/scalar;
2813 }
2814
2815 if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2816 {
2817 if ( SCIPisFeasPositive(scip, scalar) )
2818 {
2819 newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2820 SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2821 if ( *cutoff )
2822 {
2823 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> <= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2824 SCIPvarGetName(consdata1->var), newbnd);
2825 break;
2826 }
2827 if ( tightened )
2828 {
2829 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> <= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2830 SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2831 (*nchgbds)++;
2832 }
2833 }
2834 else if ( SCIPisFeasNegative(scip, scalar) )
2835 {
2836 newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2837 SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2838 if ( *cutoff )
2839 {
2840 SCIPdebugMsg(scip, "<%s>, <%s> -> tightening <%s> >= %.15g infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2841 SCIPvarGetName(consdata1->var), newbnd);
2842 break;
2843 }
2844 if ( tightened )
2845 {
2846 SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2847 SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2848 (*nchgbds)++;
2849 }
2850 }
2851 }
2852 }
2853 }
2854
2855 /* check for equal variables */
2856 if( consdata0->var != consdata1->var || consdata0->vbdvar != consdata1->vbdvar )
2857 break;
2858
2859 /* mark constraint1 for deletion if possible */
2860 deletecons1 = TRUE;
2861
2862 /* the coefficients of both constraints are equal */
2863 if( SCIPisEQ(scip, coef, consdata1->vbdcoef) )
2864 {
2865 lhs = MAX(consdata1->lhs, lhs);
2866 rhs = MIN(consdata1->rhs, rhs);
2867 }
2868 /* now only one side and in both constraints the same side should be infinity and the vbdvar should be binary
2869 * then we neither do not need to have the same side nor the same coefficient
2870 */
2871 else if( SCIPvarIsBinary(consdata0->vbdvar)
2872 && (SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs))
2873 && (SCIPisInfinity(scip, -consdata1->lhs) || SCIPisInfinity(scip, consdata1->rhs))
2874 && (SCIPisInfinity(scip, -lhs) == SCIPisInfinity(scip, -consdata1->lhs)) )
2875 {
2876 /* lhs <= x + b*y <= +inf */
2877 if( !SCIPisInfinity(scip, -lhs) )
2878 {
2879 lhs = MAX(consdata1->lhs, lhs);
2880 coef = lhs - MAX(consdata1->lhs - consdata1->vbdcoef, consdata0->lhs - coef);
2881 }
2882 /* -inf <= x + b*y <= rhs */
2883 else
2884 {
2885 rhs = MIN(consdata1->rhs, rhs);
2886 coef = rhs - MIN(consdata1->rhs - consdata1->vbdcoef, consdata0->rhs - coef);
2887 }
2888
2890 }
2891 else if( SCIPisPositive(scip, coef) == SCIPisPositive(scip, consdata1->vbdcoef)
2892 && ((!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, -consdata1->lhs))
2893 || (!SCIPisInfinity(scip, rhs) && !SCIPisInfinity(scip, consdata1->rhs))) )
2894 {
2895 SCIP_Bool cons0lhsred;
2896 SCIP_Bool cons0rhsred;
2897 SCIP_Bool cons1lhsred;
2898 SCIP_Bool cons1rhsred;
2899 SCIP_Bool lhsequal;
2900 SCIP_Bool rhsequal;
2901
2902 assert(!SCIPisInfinity(scip, lhs));
2903 assert(!SCIPisInfinity(scip, consdata1->lhs));
2904 assert(!SCIPisInfinity(scip, -rhs));
2905 assert(!SCIPisInfinity(scip, -consdata1->rhs));
2906
2907 /* check if a left hand side of one constraints is redundant */
2908 checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, lhs, consdata1->lhs, &lhsequal, &cons0lhsred, &cons1lhsred, TRUE);
2909
2910 /* check if a right hand side of one constraints is redundant */
2911 checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, rhs, consdata1->rhs, &rhsequal, &cons0rhsred, &cons1rhsred, FALSE);
2912
2913 /* if cons0 is redundant, update cons1 and delete cons0 */
2914 if( (lhsequal || cons0lhsred) && (rhsequal || cons0rhsred) )
2915 {
2916 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2917 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2918
2919 SCIPdebugMsg(scip, "constraint: ");
2920 SCIPdebugPrintCons(scip, cons0, NULL);
2921 SCIPdebugMsg(scip, "is redundant to constraint: ");
2922 SCIPdebugPrintCons(scip, cons1, NULL);
2923
2924 SCIP_CALL( SCIPdelCons(scip, cons0) );
2925 ++(*ndelconss);
2926
2927 /* get next cons0 */
2928 break;
2929 }
2930 /* if cons1 is redundant, update cons0 and delete cons1 */
2931 else if( cons1lhsred && cons1rhsred )
2932 {
2933 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2934 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2935
2936 SCIPdebugMsg(scip, "constraint: ");
2937 SCIPdebugPrintCons(scip, cons1, NULL);
2938 SCIPdebugMsg(scip, "is redundant to constraint: ");
2939 SCIPdebugPrintCons(scip, cons0, NULL);
2940
2941 SCIP_CALL( SCIPdelCons(scip, cons1) );
2942 ++(*ndelconss);
2943
2944 /* get next cons1 */
2945 continue;
2946 }
2947 /* if left hand side of cons0 is redundant set it to -infinity */
2948 else if( (lhsequal || cons0lhsred) && !SCIPisInfinity(scip, -lhs) )
2949 {
2950 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2951 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2952
2953 lhs = -SCIPinfinity(scip);
2954
2955 /* if right hand side of cons1 is redundant too, set it to infinity */
2956 if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
2957 {
2958 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2959 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2960
2961 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
2962 ++(*nchgsides);
2963
2964 SCIPdebugMsg(scip, "deleted rhs of constraint: ");
2965 SCIPdebugPrintCons(scip, cons1, NULL);
2966 SCIPdebugMsg(scip, "due to constraint: ");
2967 SCIPdebugPrintCons(scip, cons0, NULL);
2968 }
2969
2970 /* later on we do not want to delete cons1 */
2971 deletecons1 = FALSE;
2972 }
2973 /* if right hand side of cons0 is redundant set it to infinity */
2974 else if( (rhsequal || cons0rhsred) && !SCIPisInfinity(scip, rhs) )
2975 {
2976 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2977 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2978
2979 rhs = SCIPinfinity(scip);
2980
2981 /* if left hand side of cons1 is redundant too, set it to -infinity */
2982 if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
2983 {
2984 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2985 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2986
2987 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
2988 ++(*nchgsides);
2989
2990 SCIPdebugMsg(scip, "deleted lhs of constraint: ");
2991 SCIPdebugPrintCons(scip, cons1, NULL);
2992 SCIPdebugMsg(scip, "due to constraint: ");
2993 SCIPdebugPrintCons(scip, cons0, NULL);
2994 }
2995
2996 /* later on we do not want to delete cons1 */
2997 deletecons1 = FALSE;
2998 }
2999 /* if left hand side of cons1 is redundant set it to -infinity */
3000 else if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
3001 {
3002 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3003 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3004
3005 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
3006 ++(*nchgsides);
3007
3008 SCIPdebugMsg(scip, "deleted lhs of constraint: ");
3009 SCIPdebugPrintCons(scip, cons1, NULL);
3010 SCIPdebugMsg(scip, "due to constraint: ");
3011 SCIPdebugPrintCons(scip, cons0, NULL);
3012
3013 continue;
3014 }
3015 /* if right hand side of cons1 is redundant set it to infinity */
3016 else if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
3017 {
3018 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3019 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3020
3021 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
3022 ++(*nchgsides);
3023
3024 SCIPdebugMsg(scip, "deleted rhs of constraint: ");
3025 SCIPdebugPrintCons(scip, cons1, NULL);
3026 SCIPdebugMsg(scip, "due to constraint: ");
3027 SCIPdebugPrintCons(scip, cons0, NULL);
3028
3029 continue;
3030 }
3031 else /* nothing was redundant */
3032 continue;
3033 }
3034 else
3035 {
3036 /* there is no redundancy in both constraints with same variables */
3037 continue;
3038 }
3039
3040 if( SCIPisFeasLT(scip, rhs, lhs) )
3041 {
3042 SCIPdebugMsg(scip, "constraint <%s> and <%s> lead to infeasibility due to their sides\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
3043 *cutoff = TRUE;
3044 break;
3045 }
3046
3047 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
3048 if( lhs > rhs )
3049 {
3050 rhs = (lhs + rhs)/2;
3051 lhs = rhs;
3052 }
3053
3054 /* we decide to let constraint cons0 stay, so update data structure consdata0 */
3055
3056 /* update coefficient of cons0 */
3057
3058 /* special case if new coefficient becomes zero, both constraints are redundant but we may tighten the bounds */
3059 if( SCIPisZero(scip, coef) )
3060 {
3061 SCIP_Bool tightened;
3062
3063 SCIPdebugMsg(scip, "constraint: ");
3064 SCIPdebugPrintCons(scip, cons1, NULL);
3065 SCIPdebugMsg(scip, "and constraint: ");
3066 SCIPdebugPrintCons(scip, cons0, NULL);
3067 SCIPdebugMsg(scip, "are both redundant and lead to bounding of <%s> in [%g, %g]\n", SCIPvarGetName(consdata0->var), lhs, rhs);
3068
3069 /* delete cons1 */
3070 SCIP_CALL( SCIPdelCons(scip, cons1) );
3071 ++(*ndelconss);
3072
3073 /* update upper bound if possible
3074 *
3075 * @note we need to force the bound change since we are deleting the constraint afterwards
3076 */
3077 SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, rhs, TRUE, cutoff, &tightened) );
3078 if( *cutoff )
3079 break;
3080 if( tightened )
3081 ++(*nchgbds);
3082
3083 /* update lower bound if possible
3084 *
3085 * @note we need to force the bound change since we are deleting the constraint afterwards
3086 */
3087 SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, lhs, TRUE, cutoff, &tightened) );
3088 if( *cutoff )
3089 break;
3090 if( tightened )
3091 ++(*nchgbds);
3092
3093 /* delete cons0 */
3094 SCIP_CALL( SCIPdelCons(scip, cons0) );
3095 ++(*ndelconss);
3096
3097 /* get next cons0 */
3098 break;
3099 }
3100
3101 SCIPdebugMsg(scip, "constraint: ");
3102 SCIPdebugPrintCons(scip, cons1, NULL);
3103 SCIPdebugMsg(scip, "and constraint: ");
3104 SCIPdebugPrintCons(scip, cons0, NULL);
3105
3106 /* if sign of coefficient switches, update the locks of the variable */
3107 if( consdata0->vbdcoef * coef < 0.0 )
3108 {
3110
3111 /* remove locks for variable with old coefficient and install locks for variable with new
3112 * coefficient
3113 */
3114 if( consdata0->vbdcoef > 0.0 )
3115 {
3116 SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, -consdata0->lhs),
3117 !SCIPisInfinity(scip, consdata0->rhs)) );
3118 SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, consdata0->rhs),
3119 !SCIPisInfinity(scip, -consdata0->lhs)) );
3120 }
3121 else
3122 {
3123 SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, consdata0->rhs),
3124 !SCIPisInfinity(scip, -consdata0->lhs)) );
3125 SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0, !SCIPisInfinity(scip, -consdata0->lhs),
3126 !SCIPisInfinity(scip, consdata0->rhs)) );
3127 }
3128 }
3129
3130 /* now change the coefficient */
3131 if( !SCIPisEQ(scip, consdata0->vbdcoef, coef) )
3132 {
3133 ++(*nchgcoefs);
3134
3135 /* mark to add new varbound information */
3136 consdata0->varboundsadded = FALSE;
3137 consdata0->tightened = FALSE;
3138 consdata0->presolved = FALSE;
3139 consdata0->changed = FALSE;
3140
3141 consdata0->vbdcoef = coef;
3142
3144 }
3145
3146 /* update lhs and rhs of cons0 */
3147 if( !SCIPisEQ(scip, consdata0->lhs, lhs) )
3148 {
3149 SCIP_CALL( chgLhs(scip, cons0, lhs) );
3150 ++(*nchgsides);
3151 }
3152 if( !SCIPisEQ(scip, consdata0->rhs, rhs) )
3153 {
3154 SCIP_CALL( chgRhs(scip, cons0, rhs) );
3155 ++(*nchgsides);
3156 }
3157
3158 SCIPdebugMsg(scip, "lead to new constraint: ");
3159 SCIPdebugPrintCons(scip, cons0, NULL);
3160
3161 /* if cons1 is still marked for deletion, delete it */
3162 if( deletecons1 )
3163 {
3164 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3165 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3166
3167 /* delete cons1 */
3168 SCIP_CALL( SCIPdelCons(scip, cons1) );
3169 ++(*ndelconss);
3170 }
3171
3172 assert(SCIPconsIsActive(cons0));
3173 }
3174 }
3175
3176 /* free temporary memory */
3177 SCIPfreeBufferArray(scip, &sortedconss);
3178
3179 return SCIP_OKAY;
3180}
3181
3182/** for all varbound constraints with two integer variables make the coefficients integral */
3183static
3185 SCIP* scip, /**< SCIP data structure */
3186 SCIP_CONS** conss, /**< constraint set */
3187 int nconss, /**< number of constraints in constraint set */
3188 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3189 int* nchgsides /**< pointer to count number of changed left/right hand sides */
3190 )
3191{
3192 SCIP_CONSDATA* consdata;
3193 int c;
3194
3195 assert(scip != NULL);
3196 assert(conss != NULL || nconss == 0);
3197 assert(nchgcoefs != NULL);
3198 assert(nchgsides != NULL);
3199
3200 /* if we cannot find any constraint for prettifying, stop */
3202 return;
3203
3204 for( c = nconss - 1; c >= 0; --c )
3205 {
3206 assert(conss != NULL);
3207
3208 if( SCIPconsIsDeleted(conss[c]) )
3209 continue;
3210
3211 consdata = SCIPconsGetData(conss[c]);
3212 assert(consdata != NULL);
3213
3214 /* check for integer variables and one coefficient with an absolute value smaller than 1 */
3215 /* @note: we allow that the variable type of the bounded variable can be smaller than the variable type of the
3216 * bounding variable
3217 */
3218 if( SCIPvarIsIntegral(consdata->var) && SCIPvarIsIntegral(consdata->vbdvar)
3219 && SCIPvarGetType(consdata->vbdvar) != SCIP_VARTYPE_BINARY
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",
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 {
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 */
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 {
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 SCIPdebugMsg(scip, "resolved multi aggregation in varbound constraint <%s> by creating a new linear constraint\n", SCIPconsGetName(cons));
3867 SCIPdebugPrintCons(scip, newcons, NULL);
3868
3869 SCIP_CALL( SCIPaddCons(scip, newcons) );
3870 SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3871
3872 redundant = TRUE;
3873 ++(*naddconss);
3874 }
3875
3876 /* delete a redundant constraint */
3877 if( redundant )
3878 {
3879 SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
3880 SCIP_CALL( SCIPdelCons(scip, cons) );
3881 (*ndelconss)++;
3882 }
3883
3884 return SCIP_OKAY;
3885}
3886
3887/** tightens variable bound coefficient by inspecting the global bounds of the involved variables; note: this is also
3888 * performed by the linear constraint handler - only necessary if the user directly creates variable bound constraints
3889 */
3890static
3892 SCIP* scip, /**< SCIP data structure */
3893 SCIP_CONS* cons, /**< variable bound constraint */
3894 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3895 int* nchgsides, /**< pointer to count the number of left and right hand sides */
3896 int* ndelconss, /**< pointer to count number of deleted constraints */
3897 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3898 int* nchgbds /**< pointer to count number of bound changes */
3899 )
3900{
3901 SCIP_CONSDATA* consdata;
3902 SCIP_Real xlb;
3903 SCIP_Real xub;
3904 SCIP_Real oldcoef;
3905 int oldnchgcoefs;
3906 int oldnchgsides;
3907
3908 assert(nchgcoefs != NULL);
3909 assert(nchgsides != NULL);
3910 assert(ndelconss != NULL);
3911
3912 consdata = SCIPconsGetData(cons);
3913 assert(consdata != NULL);
3914
3915 /* tightening already done */
3916 if( consdata->tightened )
3917 return SCIP_OKAY;
3918
3919 SCIPdebugMsg(scip, "tightening coefficients on variable bound constraint <%s>\n", SCIPconsGetName(cons));
3920
3921 consdata->tightened = TRUE;
3922
3923 /* if values and variable are integral the sides should it be too */
3924 if( SCIPvarIsIntegral(consdata->var) && SCIPvarIsIntegral(consdata->vbdvar)
3925 && SCIPisIntegral(scip, consdata->vbdcoef) )
3926 {
3927 if( !SCIPisIntegral(scip, consdata->lhs) )
3928 {
3929 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3930 ++(*nchgsides);
3931 consdata->changed = TRUE;
3932 }
3933 if( !SCIPisIntegral(scip, consdata->rhs) )
3934 {
3935 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3936 ++(*nchgsides);
3937 consdata->changed = TRUE;
3938 }
3939 }
3940
3941 /* coefficient tightening only works for binary bound variable */
3942 if( !SCIPvarIsBinary(consdata->vbdvar) )
3943 return SCIP_OKAY;
3944
3945 oldnchgcoefs = *nchgcoefs;
3946 oldnchgsides = *nchgsides;
3947 oldcoef = consdata->vbdcoef;
3948
3949 /* coefficients tightening when all variables are integer */
3950 /* we consider the following varbound constraint: lhs <= x + b*y <= rhs (sides are possibly infinity)
3951 * y should always be binary and x of integral type and b not integral, we also need at least one side with infinity
3952 * or not integral value.
3953 *
3954 * 1. if( (lhs is integral and not -infinity) and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3955 *
3956 * lhs <= x + b*y <= rhs => lhs <= x + floor(b)*y <= floor(rhs)
3957 *
3958 * 2. if( (rhs is integral and not infinity) and ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs))) ):
3959 *
3960 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= rhs
3961 *
3962 * 3. if( ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs)))
3963 * and ((rhs is infinity) or (b - floor(b) > rhs - floor(rhs))) ):
3964 *
3965 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= floor(rhs)
3966 *
3967 * 4. if( ((lhs is -infinity) or (b - floor(b) < lhs - floor(lhs)))
3968 * and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3969 *
3970 * lhs <= x + b*y <= rhs => ceil(lhs) <= x + floor(b)*y <= floor(rhs)
3971 *
3972 * 5. if( (lhs is not integral) or (rhs is not integral) )
3973 *
3974 * if (lhs is not -infinity)
3975 * if (b - floor(b) < lhs - floor(lhs)):
3976 *
3977 * lhs <= x + b*y => ceil(lhs) <= x + b*y
3978 *
3979 * else if (b - floor(b) > lhs - floor(lhs)):
3980 *
3981 * lhs <= x + b*y => floor(lhs) + b - floor(b) <= x + b*y
3982 *
3983 * if (rhs is not infinity)
3984 * if (b - floor(b) < rhs - floor(rhs)):
3985 *
3986 * x + b*y <= rhs => x + b*y <= floor(rhs) + b - floor(b)
3987 *
3988 * else if (b - floor(b) > rhs - floor(rhs)):
3989 *
3990 * x + b*y <= rhs => x + b*y <= floor(rhs)
3991 */
3992 if( SCIPvarIsIntegral(consdata->var) && !SCIPisIntegral(scip, consdata->vbdcoef)
3993 && ( !SCIPisIntegral(scip, consdata->lhs) || SCIPisInfinity(scip, -consdata->lhs)
3994 || !SCIPisIntegral(scip, consdata->rhs) || SCIPisInfinity(scip, consdata->rhs) ) )
3995 {
3996 /* infinity should be an integral value */
3997 assert(!SCIPisInfinity(scip, -consdata->lhs) || SCIPisIntegral(scip, consdata->lhs));
3998 assert(!SCIPisInfinity(scip, consdata->rhs) || SCIPisIntegral(scip, consdata->rhs));
3999
4000 /* should not be a redundant constraint */
4001 assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
4002
4003 /* case 1 */
4004 if( SCIPisIntegral(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs) &&
4005 (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
4006 {
4007 consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
4008 ++(*nchgcoefs);
4009
4010 if( !SCIPisInfinity(scip, consdata->rhs) )
4011 {
4012 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4013 ++(*nchgsides);
4014 }
4015 }
4016 /* case 2 */
4017 else if( SCIPisIntegral(scip, consdata->rhs) && !SCIPisInfinity(scip, consdata->rhs) &&
4018 (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) )
4019 {
4020 consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
4021 ++(*nchgcoefs);
4022
4023 if( !SCIPisInfinity(scip, -consdata->lhs) )
4024 {
4025 if( !SCIPisIntegral(scip, consdata->lhs) )
4026 ++(*nchgsides);
4027
4028 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4029 }
4030 }
4031 /* case 3 */
4032 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))) )
4033 {
4034 consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
4035 ++(*nchgcoefs);
4036
4037 if( !SCIPisInfinity(scip, -consdata->lhs) )
4038 {
4039 if( !SCIPisIntegral(scip, consdata->lhs) )
4040 ++(*nchgsides);
4041
4042 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4043 }
4044 if( !SCIPisInfinity(scip, consdata->rhs) )
4045 {
4046 if( !SCIPisIntegral(scip, consdata->rhs) )
4047 ++(*nchgsides);
4048
4049 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4050 }
4051 }
4052 /* case 4 */
4053 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))) )
4054 {
4055 consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
4056 ++(*nchgcoefs);
4057
4058 if( !SCIPisInfinity(scip, -consdata->lhs) )
4059 {
4060 if( !SCIPisIntegral(scip, consdata->lhs) )
4061 ++(*nchgsides);
4062
4063 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4064 }
4065 if( !SCIPisInfinity(scip, consdata->rhs) )
4066 {
4067 if( !SCIPisIntegral(scip, consdata->rhs) )
4068 ++(*nchgsides);
4069
4070 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4071 }
4072 }
4073 /* case 5 */
4074 if( !SCIPisFeasIntegral(scip, consdata->lhs) || !SCIPisFeasIntegral(scip, consdata->rhs) )
4075 {
4076 if( !SCIPisInfinity(scip, -consdata->lhs) )
4077 {
4078 if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
4079 {
4080 consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
4081 ++(*nchgsides);
4082 }
4083 else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
4084 {
4085 consdata->lhs = SCIPfeasFloor(scip, consdata->lhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
4086 ++(*nchgsides);
4087 }
4088 }
4089 if( !SCIPisInfinity(scip, consdata->rhs) )
4090 {
4091 if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
4092 {
4093 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
4094 ++(*nchgsides);
4095 }
4096 else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
4097 {
4098 consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
4099 ++(*nchgsides);
4100 }
4101 }
4102 }
4103 }
4104
4105 /* check if due to tightening the constraint got redundant */
4106 if( SCIPisZero(scip, consdata->vbdcoef) )
4107 {
4108 /* we have to make sure that the induced bound(s) is (are) actually applied;
4109 * if the relative change is too small, this may have been skipped in propagation
4110 */
4111 if( SCIPisLT(scip, SCIPvarGetLbGlobal(consdata->var), consdata->lhs) )
4112 {
4113 SCIP_Bool tightened;
4114
4115 SCIP_CALL( SCIPtightenVarLbGlobal(scip, consdata->var, consdata->lhs, TRUE, cutoff, &tightened) );
4116 if( *cutoff )
4117 {
4118 SCIPdebugMsg(scip, " -> tightening lower bound of <%s> to %.15g infeasible\n", SCIPvarGetName(consdata->var),
4119 consdata->lhs);
4120 return SCIP_OKAY;
4121 }
4122 if( tightened )
4123 {
4124 SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
4125 SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
4126 (*nchgbds)++;
4127 }
4128 }
4129 if( SCIPisGT(scip, SCIPvarGetUbGlobal(consdata->var), consdata->rhs) )
4130 {
4131 SCIP_Bool tightened;
4132
4133 SCIP_CALL( SCIPtightenVarUbGlobal(scip, consdata->var, consdata->rhs, TRUE, cutoff, &tightened) );
4134 if( *cutoff )
4135 {
4136 SCIPdebugMsg(scip, " -> tightening upper bound of <%s> to %.15g infeasible\n", SCIPvarGetName(consdata->var),
4137 consdata->rhs);
4138 return SCIP_OKAY;
4139 }
4140 if( tightened )
4141 {
4142 SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
4143 SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
4144 (*nchgbds)++;
4145 }
4146 }
4147
4148 SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
4149
4150 /* in order to correctly update the rounding locks, we need the coefficient to have the same sign as before the
4151 * coefficient tightening
4152 */
4153 consdata->vbdcoef = oldcoef;
4154
4155 SCIP_CALL( SCIPdelCons(scip, cons) );
4156 ++(*ndelconss);
4157
4158 return SCIP_OKAY;
4159 }
4160
4161 /* get bounds of variable x */
4162 xlb = SCIPvarGetLbGlobal(consdata->var);
4163 xub = SCIPvarGetUbGlobal(consdata->var);
4164
4165 /* it can happen that var is not of varstatus SCIP_VARSTATUS_FIXED but the bounds are equal, in this case we need to
4166 * stop
4167 */
4168 if( SCIPisEQ(scip, xlb, xub) )
4169 return SCIP_OKAY;
4170
4171 /* modification of coefficient checking for slack in constraints */
4172 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
4173 {
4174 /* lhs <= x + c*y <= rhs => lhs - c*y <= x <= rhs - c*y */
4175 if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) && SCIPisFeasLT(scip, xub, consdata->rhs) )
4176 {
4177 SCIP_Real newcoef;
4178 SCIP_Real newrhs;
4179 SCIP_Real oldrhs;
4180
4181 oldrhs = consdata->rhs;
4182
4183 /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
4184 * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
4185 * -> c' = MAX(c - rhs + xub, lhs - xlb), rhs' = rhs - c + c'
4186 */
4187 newcoef = MAX(consdata->vbdcoef - consdata->rhs + xub, consdata->lhs - xlb);
4188
4189 /* in this case both sides are redundant and the constraint can be removed */
4190 if( SCIPisLE(scip, newcoef, 0.0) )
4191 {
4192 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4193 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4194
4195 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4196 SCIP_CALL( SCIPdelCons(scip, cons) );
4197 ++(*ndelconss);
4198 }
4199 else
4200 {
4201 newrhs = consdata->rhs - consdata->vbdcoef + newcoef;
4202
4204 "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
4205 consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef,
4206 SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4207 consdata->lhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar),
4208 newrhs);
4209
4210 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4211 assert(consdata->vbdcoef * newcoef > 0);
4212
4213 consdata->vbdcoef = newcoef;
4214 consdata->rhs = MAX(newrhs, consdata->lhs);
4215 (*nchgcoefs)++;
4216 (*nchgsides)++;
4217
4218 /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
4219 * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
4220 * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
4221 */
4222 if( !SCIPisFeasIntegral(scip, oldrhs) && SCIPisFeasIntegral(scip, newrhs))
4223 {
4224 consdata->tightened = FALSE;
4225 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4226 assert(consdata->tightened);
4227 assert(!(*cutoff));
4228 }
4229 else
4230 consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->rhs));
4231 }
4232 }
4233 else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
4234 {
4235 SCIP_Real newcoef;
4236 SCIP_Real newlhs;
4237 SCIP_Real oldlhs;
4238
4239 oldlhs = consdata->lhs;
4240
4241 /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
4242 * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
4243 * -> c' = MIN(c - lhs + xlb, rhs - xub), lhs' = lhs - c + c'
4244 */
4245 newcoef = MIN(consdata->vbdcoef - consdata->lhs + xlb, consdata->rhs - xub);
4246
4247 /* in this case both sides are redundant and the constraint can be removed */
4248 if( SCIPisGE(scip, newcoef, 0.0) )
4249 {
4250 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4251 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4252
4253 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4254 SCIP_CALL( SCIPdelCons(scip, cons) );
4255 ++(*ndelconss);
4256 }
4257 else
4258 {
4259 newlhs = consdata->lhs - consdata->vbdcoef + newcoef;
4260
4262 "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
4263 consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef,
4264 SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4265 newlhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar),
4266 consdata->rhs);
4267
4268 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4269 assert(consdata->vbdcoef * newcoef > 0);
4270
4271 consdata->vbdcoef = newcoef;
4272 consdata->lhs = MIN(newlhs, consdata->rhs);
4273 (*nchgcoefs)++;
4274 (*nchgsides)++;
4275
4276 /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
4277 * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
4278 * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
4279 */
4280 if( !SCIPisFeasIntegral(scip, oldlhs) && SCIPisFeasIntegral(scip, newlhs))
4281 {
4282 consdata->tightened = FALSE;
4283 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4284 assert(consdata->tightened);
4285 assert(!(*cutoff));
4286 }
4287 else
4288 consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->lhs));
4289 }
4290 }
4291 }
4292 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, consdata->rhs) )
4293 {
4294 /* lhs <= x + c*y => x >= lhs - c*y */
4295 if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) )
4296 {
4297 SCIP_Real newcoef;
4298
4299 /* constraint has positive slack for the non-restricting case y = 1
4300 * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
4301 * -> c' = lhs - xlb
4302 */
4303 newcoef = consdata->lhs - xlb;
4304
4305 /* in this case the constraint is redundant and can be removed */
4306 if( SCIPisLE(scip, newcoef, 0.0) )
4307 {
4308 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4309
4310 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4311 SCIP_CALL( SCIPdelCons(scip, cons) );
4312 ++(*ndelconss);
4313 }
4314 else
4315 {
4316 SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
4317 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4318 consdata->lhs,
4319 SCIPvarGetName(consdata->var), consdata->lhs - xlb, SCIPvarGetName(consdata->vbdvar),
4320 consdata->lhs);
4321
4322 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4323 assert(consdata->vbdcoef * newcoef > 0);
4324
4325 consdata->vbdcoef = newcoef;
4326 (*nchgcoefs)++;
4327 }
4328 }
4329 else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) )
4330 {
4331 SCIP_Real newcoef;
4332
4333 /* constraint has positive slack for the non-restricting case y = 0
4334 * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
4335 * -> c' = c - lhs + xlb, lhs' = xlb
4336 */
4337 newcoef = consdata->vbdcoef - consdata->lhs + xlb;
4338
4339 /* in this case the constraint is redundant and can be removed */
4340 if( SCIPisGE(scip, newcoef, 0.0) )
4341 {
4342 assert(SCIPisFeasGE(scip, xlb, consdata->lhs) && SCIPisFeasGE(scip, xlb + consdata->vbdcoef, consdata->lhs));
4343
4344 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4345 SCIP_CALL( SCIPdelCons(scip, cons) );
4346 ++(*ndelconss);
4347 }
4348 else
4349 {
4350 SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
4351 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4352 consdata->lhs,
4353 SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->lhs + xlb,
4354 SCIPvarGetName(consdata->vbdvar), xlb);
4355
4356 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4357 assert(consdata->vbdcoef * newcoef > 0);
4358
4359 consdata->vbdcoef = newcoef;
4360 consdata->lhs = xlb;
4361 (*nchgcoefs)++;
4362 (*nchgsides)++;
4363 }
4364 }
4365 }
4366 else if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
4367 {
4368 /* x + c*y <= rhs => x <= rhs - c*y */
4369 if( consdata->vbdcoef > 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs) )
4370 {
4371 SCIP_Real newcoef;
4372
4373 /* constraint has positive slack for the non-restricting case y = 0
4374 * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
4375 * -> c' = c - rhs + xub, rhs' = xub
4376 */
4377 newcoef = consdata->vbdcoef - consdata->rhs + xub;
4378
4379 /* in this case the constraint is redundant and can be removed */
4380 if( SCIPisLE(scip, newcoef, 0.0) )
4381 {
4382 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4383
4384 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4385 SCIP_CALL( SCIPdelCons(scip, cons) );
4386 ++(*ndelconss);
4387 }
4388 else
4389 {
4390 SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
4391 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4392 consdata->rhs,
4393 SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->rhs + xub,
4394 SCIPvarGetName(consdata->vbdvar), xub);
4395
4396 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4397 assert(consdata->vbdcoef * newcoef > 0);
4398
4399 consdata->vbdcoef = newcoef;
4400 consdata->rhs = xub;
4401 (*nchgcoefs)++;
4402 (*nchgsides)++;
4403 }
4404 }
4405 else if( consdata->vbdcoef < 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
4406 {
4407 SCIP_Real newcoef;
4408
4409 /* constraint has positive slack for the non-restricting case y = 1
4410 * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
4411 * -> c' = rhs - xub
4412 */
4413 newcoef = consdata->rhs - xub;
4414
4415 /* in this case the constraint is redundant and can be removed */
4416 if( SCIPisGE(scip, newcoef, 0.0) )
4417 {
4418 assert(SCIPisFeasLE(scip, xub, consdata->rhs) && SCIPisFeasLE(scip, xub + consdata->vbdcoef, consdata->rhs));
4419
4420 SCIPdebugMsg(scip, "delete cons <%s>\n", SCIPconsGetName(cons));
4421 SCIP_CALL( SCIPdelCons(scip, cons) );
4422 ++(*ndelconss);
4423 }
4424 else
4425 {
4426 SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
4427 SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4428 SCIPvarGetName(consdata->var), consdata->rhs - xub, SCIPvarGetName(consdata->vbdvar), consdata->rhs);
4429
4430 /* we cannot allow that the coefficient changes the sign because of the rounding locks */
4431 assert(consdata->vbdcoef * newcoef > 0);
4432
4433 consdata->vbdcoef = newcoef;
4434 (*nchgcoefs)++;
4435 }
4436 }
4437 }
4438
4439 /* if something a coefficient or side of the varbound constraint was changed, ensure that the variable lower or
4440 * upper bounds of the variables are informed
4441 */
4442 if( *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
4443 {
4444 consdata->varboundsadded = FALSE;
4445 consdata->changed = TRUE;
4446
4448 }
4449
4450 return SCIP_OKAY;
4451}
4452
4453/** check if we can upgrade to a set-packing constraint */
4454static
4456 SCIP* scip, /**< SCIP data structure */
4457 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
4458 SCIP_CONS** conss, /**< constraint set */
4459 int nconss, /**< number of constraints in constraint set */
4460 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4461 int* naggrvars, /**< pointer to count the number of aggregated variables */
4462 int* nchgbds, /**< pointer to count number of bound changes */
4463 int* nchgcoefs, /**< pointer to count the number of changed coefficients */
4464 int* nchgsides, /**< pointer to count the number of left and right hand sides */
4465 int* ndelconss, /**< pointer to count the number of deleted constraints */
4466 int* naddconss /**< pointer to count the number of added constraints */
4467 )
4468{
4469 SCIP_VAR* vars[2];
4470 SCIP_CONS* newcons;
4471 SCIP_CONS* cons;
4472 SCIP_CONSDATA* consdata;
4473 int c;
4474
4475 assert(scip != NULL);
4476 assert(conshdlrdata != NULL);
4477 assert(conss != NULL || nconss == 0);
4478 assert(cutoff != NULL);
4479 assert(naggrvars != NULL);
4480 assert(nchgbds != NULL);
4481 assert(nchgcoefs != NULL);
4482 assert(nchgsides != NULL);
4483 assert(ndelconss != NULL);
4484 assert(naddconss != NULL);
4485
4486 /* if we cannot find any constraint for upgrading, stop */
4488 return SCIP_OKAY;
4489
4490 if( nconss == 0 )
4491 return SCIP_OKAY;
4492
4493 assert(conss != NULL);
4494
4495 for( c = nconss - 1; c >= 0; --c )
4496 {
4497 cons = conss[c];
4498 assert(cons != NULL);
4499
4500 if( !SCIPconsIsActive(cons) || SCIPconsGetNUpgradeLocks(cons) >= 1 )
4501 continue;
4502
4503 consdata = SCIPconsGetData(cons);
4504 assert(consdata != NULL);
4505 assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
4506
4507 if( !consdata->presolved )
4508 {
4509 /* incorporate fixings and aggregations in constraint */
4510 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, cutoff, nchgbds, ndelconss, naddconss) );
4511
4512 if( *cutoff )
4513 return SCIP_OKAY;
4514 if( !SCIPconsIsActive(cons) )
4515 continue;
4516 }
4517
4518 if( SCIPconsIsMarkedPropagate(cons) )
4519 {
4520 /* propagate constraint */
4521 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, cutoff, nchgbds, nchgsides, ndelconss) );
4522
4523 if( *cutoff )
4524 return SCIP_OKAY;
4525 if( !SCIPconsIsActive(cons) )
4526 continue;
4527 }
4528
4529 if( !consdata->tightened )
4530 {
4531 /* tighten variable bound coefficient */
4532 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
4533
4534 if( *cutoff )
4535 return SCIP_OKAY;
4536 if( !SCIPconsIsActive(cons) )
4537 continue;
4538
4539 assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
4540 }
4541
4542 /* check if both variables are of binary type */
4543 if( SCIPvarIsBinary(consdata->vbdvar) && SCIPvarIsBinary(consdata->var) )
4544 {
4545 /* coefficient and sides should be tightened and we assume that the constraint is not redundant */
4546 assert(SCIPisEQ(scip, REALABS(consdata->vbdcoef), 1.0));
4547 assert(SCIPisZero(scip, consdata->rhs) || SCIPisEQ(scip, consdata->rhs, 1.0) || SCIPisInfinity(scip, consdata->rhs));
4548 assert(SCIPisZero(scip, consdata->lhs) || SCIPisEQ(scip, consdata->lhs, 1.0) || SCIPisInfinity(scip, -consdata->lhs));
4549 assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
4550
4551 /* the case x + y <= 1 or x + y >= 1 */
4552 if( consdata->vbdcoef > 0.0 )
4553 {
4554 if( SCIPisEQ(scip, consdata->rhs, 1.0) )
4555 {
4556 /* check for aggregations like x + y == 1 */
4557 if( SCIPisEQ(scip, consdata->lhs, 1.0) )
4558 {
4559 SCIP_Bool infeasible;
4560 SCIP_Bool redundant;
4561 SCIP_Bool aggregated;
4562
4563 SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> + <%s> == 1\n",
4564 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
4565
4566 /* aggregate both variables */
4567 SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
4568 assert(!infeasible);
4569 ++(*naggrvars);
4570
4571 SCIP_CALL( SCIPdelCons(scip, cons) );
4572 ++(*ndelconss);
4573
4574 continue;
4575 }
4576 assert(consdata->lhs < 0.5);
4577
4578 vars[0] = consdata->var;
4579 vars[1] = consdata->vbdvar;
4580 }
4581 else
4582 {
4583 assert(SCIPisEQ(scip, consdata->lhs, 1.0));
4584
4585 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
4586 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
4587 }
4588 }
4589 /* the case x - y <= 0 or x - y >= 0 */
4590 else
4591 {
4592 /* the case x - y <= 0 */
4593 if( SCIPisZero(scip, consdata->rhs) )
4594 {
4595 /* check for aggregations like x - y == 0 */
4596 if( SCIPisZero(scip, consdata->lhs) )
4597 {
4598 SCIP_Bool infeasible;
4599 SCIP_Bool redundant;
4600 SCIP_Bool aggregated;
4601
4602 SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> - <%s> == 0\n",
4603 SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
4604
4605 /* aggregate both variables */
4606 SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
4607 assert(!infeasible);
4608 ++(*naggrvars);
4609
4610 SCIP_CALL( SCIPdelCons(scip, cons) );
4611 ++(*ndelconss);
4612
4613 continue;
4614 }
4615 assert(consdata->lhs < -0.5);
4616
4617 vars[0] = consdata->var;
4618 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
4619 }
4620 /* the case x - y >= 0 */
4621 else
4622 {
4623 assert(SCIPisZero(scip, consdata->lhs));
4624
4625 SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
4626 vars[1] = consdata->vbdvar;
4627 }
4628 }
4629
4635
4636 SCIPdebugMsg(scip, "upgraded varbound constraint <%s> to a set-packing constraint\n", SCIPconsGetName(cons));
4637 SCIPdebugPrintCons(scip, newcons, NULL);
4638
4639 SCIP_CALL( SCIPaddConsUpgrade(scip, cons, &newcons) );
4640 ++(*naddconss);
4641
4642 SCIP_CALL( SCIPdelCons(scip, cons) );
4643 ++(*ndelconss);
4644 }
4645 }
4646
4647 return SCIP_OKAY;
4648}
4649
4650/**@} */
4651
4652
4653/**@name Linear constraint upgrading
4654 *
4655 * @{
4656 */
4657
4658/** tries to upgrade a linear constraint into a variable bound constraint */
4659static
4660SCIP_DECL_LINCONSUPGD(linconsUpgdVarbound)
4661{ /*lint --e{715}*/
4662 SCIP_Bool upgrade;
4663
4664 assert(upgdcons != NULL);
4665
4666 /* check, if linear constraint can be upgraded to a variable bound constraint lhs <= x + a*y <= rhs
4667 * - there are exactly two variables
4668 * - one of the variables is non-binary (called the bounded variable x)
4669 * - one of the variables is non-continuous (called the bounding variable y)
4670 */
4671 upgrade = (nvars == 2) && (nposbin + nnegbin <= 1) && (nposcont + nnegcont <= 1);
4672
4673 if( upgrade )
4674 {
4675 SCIP_VAR* var;
4676 SCIP_VAR* vbdvar;
4677 SCIP_Real vbdcoef;
4678 SCIP_Real vbdlhs;
4679 SCIP_Real vbdrhs;
4682 int vbdind;
4683
4684 /* decide which variable we want to use as bounding variable y */
4685 if( zerotype < onetype )
4686 vbdind = 0;
4687 else if( zerotype > onetype )
4688 vbdind = 1;
4689 else if( SCIPisIntegral(scip, vals[0]) && !SCIPisIntegral(scip, vals[1]) )
4690 vbdind = 0;
4691 else if( !SCIPisIntegral(scip, vals[0]) && SCIPisIntegral(scip, vals[1]) )
4692 vbdind = 1;
4693 else if( REALABS(REALABS(vals[0]) - 1.0) < REALABS(REALABS(vals[1]) - 1.0) )
4694 vbdind = 1;
4695 else
4696 vbdind = 0;
4697
4698 /* do not upgrade when it is numerical unstable */
4699 if( SCIPisZero(scip, vals[vbdind]/vals[1-vbdind]) )
4700 return SCIP_OKAY;
4701
4702 SCIPdebugMsg(scip, "upgrading constraint <%s> to variable bound constraint\n", SCIPconsGetName(cons));
4703
4704 var = vars[1-vbdind];
4705 vbdvar = vars[vbdind];
4706
4707 assert(!SCIPisZero(scip, vals[1-vbdind]));
4708 vbdcoef = vals[vbdind]/vals[1-vbdind];
4709
4710 if( vals[1-vbdind] > 0.0 )
4711 {
4712 vbdlhs = SCIPisInfinity(scip, -lhs) ? -SCIPinfinity(scip) : lhs/vals[1-vbdind];
4713 vbdrhs = SCIPisInfinity(scip, rhs) ? SCIPinfinity(scip) : rhs/vals[1-vbdind];
4714 }
4715 else
4716 {
4717 vbdlhs = SCIPisInfinity(scip, rhs) ? -SCIPinfinity(scip) : rhs/vals[1-vbdind];
4718 vbdrhs = SCIPisInfinity(scip, -lhs) ? SCIPinfinity(scip) : lhs/vals[1-vbdind];
4719 }
4720
4721 /* create the bin variable bound constraint (an automatically upgraded constraint is always unmodifiable) */
4723 SCIP_CALL( SCIPcreateConsVarbound(scip, upgdcons, SCIPconsGetName(cons), var, vbdvar, vbdcoef, vbdlhs, vbdrhs,
4728 }
4729
4730 return SCIP_OKAY;
4731}
4732
4733/** adds symmetry information of constraint to a symmetry detection graph */
4734static
4736 SCIP* scip, /**< SCIP pointer */
4737 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */
4738 SCIP_CONS* cons, /**< constraint */
4739 SYM_GRAPH* graph, /**< symmetry detection graph */
4740 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */
4741 )
4742{
4743 SCIP_VAR** vars;
4744 SCIP_Real* vals;
4745 SCIP_Real constant = 0.0;
4746 SCIP_Real lhs;
4747 SCIP_Real rhs;
4748 int nlocvars;
4749 int nvars;
4750
4751 assert(scip != NULL);
4752 assert(cons != NULL);
4753 assert(graph != NULL);
4754 assert(success != NULL);
4755
4756 /* get active variables of the constraint */
4758 nlocvars = 2;
4759
4762
4763 vars[0] = SCIPgetVarVarbound(scip, cons);
4764 vars[1] = SCIPgetVbdvarVarbound(scip, cons);
4765 vals[0] = 1.0;
4766 vals[1] = SCIPgetVbdcoefVarbound(scip, cons);
4767
4768 SCIP_CALL( SCIPgetSymActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
4769 lhs = SCIPgetLhsVarbound(scip, cons) - constant;
4770 rhs = SCIPgetRhsVarbound(scip, cons) - constant;
4771
4773 cons, lhs, rhs, success) );
4774
4775 SCIPfreeBufferArray(scip, &vals);
4777
4778 return SCIP_OKAY;
4779}
4780
4781/**@} */
4782
4783
4784/**@name Callback methods
4785 *
4786 * @{
4787 */
4788
4789/** copy method for constraint handler plugins (called when SCIP copies plugins) */
4790static
4791SCIP_DECL_CONSHDLRCOPY(conshdlrCopyVarbound)
4792{ /*lint --e{715}*/
4793 assert(scip != NULL);
4794 assert(conshdlr != NULL);
4795
4797
4798 /* call inclusion method of constraint handler */
4800
4801 *valid = TRUE;
4802
4803 return SCIP_OKAY;
4804}
4805
4806/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
4807static
4808SCIP_DECL_CONSFREE(consFreeVarbound)
4809{ /*lint --e{715}*/
4810 SCIP_CONSHDLRDATA* conshdlrdata;
4811
4812 assert(scip != NULL);
4813 assert(conshdlr != NULL);
4814
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
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
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
5019
5020 for( i = 0; i < nconss; i++ )
5021 {
5022 if( !checkCons(scip, conss[i], NULL, FALSE) )
5023 {
5025 (*result) = SCIP_INFEASIBLE;
5026
5027 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
5028
5029 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
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
5059
5060 for( i = 0; i < nconss; i++ )
5061 {
5062 if( !checkCons(scip, conss[i], sol, FALSE) )
5063 {
5065 (*result) = SCIP_INFEASIBLE;
5066
5067 SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
5068
5069 SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
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
5099 return SCIP_OKAY;
5100 }
5101 else
5102 {
5103 /* increase age of constraint */
5104 SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
5105 }
5106 }
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
5120
5121 for( i = 0; i < nconss && (*result == SCIP_FEASIBLE || completely); i++ )
5122 {
5123 if( !checkCons(scip, conss[i], sol, checklprows) )
5124 {
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;
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 )
5183 else if( nchgbds > 0 )
5185 else
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;
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(result != NULL);
5211
5213
5214 /* get constraint handler data */
5215 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5216 assert(conshdlrdata != NULL);
5217
5218 cutoff = FALSE;
5219 oldnchgbds = *nchgbds;
5220 oldndelconss = *ndelconss;
5221 oldnaddconss = *naddconss;
5222 oldnchgcoefs = *nchgcoefs;
5223 oldnchgsides = *nchgsides;
5224 oldnaggrvars = *naggrvars;
5225
5226 for( i = 0; i < nconss; i++ )
5227 {
5228 cons = conss[i];
5229 assert(cons != NULL);
5230
5232
5233 consdata = SCIPconsGetData(cons);
5234 assert(consdata != NULL);
5235
5236 if( i % 1000 == 0 && SCIPisStopped(scip) )
5237 break;
5238
5239 /* force presolving the constraint in the initial round */
5240 if( nrounds == 0 )
5241 consdata->presolved = FALSE;
5242
5243 if( consdata->presolved )
5244 continue;
5245 consdata->presolved = TRUE;
5246
5247 /* incorporate fixings and aggregations in constraint */
5248 SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &cutoff, nchgbds, ndelconss, naddconss) );
5249
5250 if( cutoff )
5251 break;
5252 if( !SCIPconsIsActive(cons) )
5253 continue;
5254
5255 /* propagate constraint */
5256 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, &cutoff, nchgbds, nchgsides, ndelconss) );
5257
5258 if( cutoff )
5259 break;
5260 if( !SCIPconsIsActive(cons) )
5261 continue;
5262
5263 /* tighten variable bound coefficient */
5264 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
5265 if( cutoff )
5266 break;
5267 if( !SCIPconsIsActive(cons) )
5268 continue;
5269
5270 /* informs once variable x about a globally valid variable lower or upper bound */
5271 if( !consdata->varboundsadded )
5272 {
5273 SCIP_Bool infeasible;
5274 int nlocalchgbds;
5275 int localoldnchgbds;
5276
5277 localoldnchgbds = *nchgbds;
5278
5279 /* if lhs is finite, we have a variable lower bound: lhs <= x + c*y => x >= -c*y + lhs */
5280 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, REALABS(consdata->vbdcoef)) )
5281 {
5282 SCIPdebugMsg(scip, "adding variable lower bound <%s> >= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
5283 SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->lhs,
5284 SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? ">=" : "<="), 1.0/-consdata->vbdcoef,
5285 SCIPvarGetName(consdata->var), consdata->lhs/consdata->vbdcoef);
5286
5287 SCIP_CALL( SCIPaddVarVlb(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->lhs,
5288 &infeasible, &nlocalchgbds) );
5289 assert(!infeasible);
5290
5291 *nchgbds += nlocalchgbds;
5292 }
5293
5294 /* if rhs is finite, we have a variable upper bound: x + c*y <= rhs => x <= -c*y + rhs */
5295 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, REALABS(consdata->vbdcoef)) )
5296 {
5297 SCIPdebugMsg(scip, "adding variable upper bound <%s> <= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
5298 SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
5299 SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? "<=" : ">="), 1.0/-consdata->vbdcoef,
5300 SCIPvarGetName(consdata->var), consdata->rhs/consdata->vbdcoef);
5301
5302 SCIP_CALL( SCIPaddVarVub(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->rhs,
5303 &infeasible, &nlocalchgbds) );
5304 assert(!infeasible);
5305
5306 *nchgbds += nlocalchgbds;
5307 }
5308 consdata->varboundsadded = TRUE;
5309
5310 if( *nchgbds > localoldnchgbds )
5311 {
5312 /* tighten variable bound coefficient */
5313 SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
5314 if( cutoff )
5315 break;
5316 }
5317 }
5318 }
5319
5320 if( !cutoff )
5321 {
5322 /* for varbound constraint with two integer variables make coefficients integral */
5323 prettifyConss(scip, conss, nconss, nchgcoefs, nchgsides);
5324
5325 /* check if we can upgrade to a set-packing constraint */
5326 SCIP_CALL( upgradeConss(scip, conshdlrdata, conss, nconss, &cutoff, naggrvars, nchgbds, nchgcoefs, nchgsides, ndelconss, naddconss) );
5327
5328 if( !cutoff && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
5329 {
5330 /* preprocess pairs of variable bound constraints */
5331 SCIP_CALL( preprocessConstraintPairs(scip, conss, nconss, &cutoff, nchgbds, ndelconss, nchgcoefs, nchgsides) );
5332 }
5333 }
5334
5335 /* return the correct result code */
5336 if( cutoff )
5338 else if( *nchgbds > oldnchgbds || *ndelconss > oldndelconss || *naddconss > oldnaddconss
5339 || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides || *naggrvars > oldnaggrvars )
5341 else
5343
5344 return SCIP_OKAY;
5345}
5346
5347
5348/** propagation conflict resolving method of constraint handler */
5349static
5350SCIP_DECL_CONSRESPROP(consRespropVarbound)
5351{ /*lint --e{715}*/
5352 SCIP_CONSHDLRDATA* conshdlrdata;
5353
5354 assert(conshdlr != NULL);
5355
5356 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5357 assert(conshdlrdata != NULL);
5358
5359 SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, boundtype, bdchgidx, relaxedbd, conshdlrdata->usebdwidening) );
5360
5362
5363 return SCIP_OKAY;
5364}
5365
5366
5367/** variable rounding lock method of constraint handler */
5368static
5369SCIP_DECL_CONSLOCK(consLockVarbound)
5370{ /*lint --e{715}*/
5371 SCIP_CONSDATA* consdata;
5372
5373 consdata = SCIPconsGetData(cons);
5374 assert(consdata != NULL);
5375
5376 if( !SCIPisInfinity(scip, -consdata->lhs) )
5377 {
5378 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->var, locktype, nlockspos, nlocksneg) );
5379 if( consdata->vbdcoef > 0.0 )
5380 {
5381 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlockspos, nlocksneg) );
5382 }
5383 else
5384 {
5385 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlocksneg, nlockspos) );
5386 }
5387 }
5388
5389 if( !SCIPisInfinity(scip, consdata->rhs) )
5390 {
5391 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->var, locktype, nlocksneg, nlockspos) );
5392 if( consdata->vbdcoef > 0.0 )
5393 {
5394 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlocksneg, nlockspos) );
5395 }
5396 else
5397 {
5398 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vbdvar, locktype, nlockspos, nlocksneg) );
5399 }
5400 }
5401
5402 return SCIP_OKAY;
5403}
5404
5405/** constraint activation notification method of constraint handler */
5406static
5407SCIP_DECL_CONSACTIVE(consActiveVarbound)
5408{ /*lint --e{715}*/
5410 {
5411 SCIP_CALL( addNlrow(scip, cons) );
5412 }
5413
5414 return SCIP_OKAY;
5415}
5416
5417/** constraint deactivation notification method of constraint handler */
5418static
5419SCIP_DECL_CONSDEACTIVE(consDeactiveVarbound)
5420{ /*lint --e{715}*/
5421 SCIP_CONSDATA* consdata;
5422
5423 assert(cons != NULL);
5424
5425 consdata = SCIPconsGetData(cons);
5426 assert(consdata != NULL);
5427
5428 /* remove row from NLP, if still in solving
5429 * if we are in exitsolve, the whole NLP will be freed anyway
5430 */
5431 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
5432 {
5433 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
5434 }
5435
5436 return SCIP_OKAY;
5437}
5438
5439/** constraint display method of constraint handler */
5440static
5441SCIP_DECL_CONSPRINT(consPrintVarbound)
5442{ /*lint --e{715}*/
5443 SCIP_CONSDATA* consdata;
5444
5445 assert(scip != NULL);
5446 assert(conshdlr != NULL);
5447 assert(cons != NULL);
5448
5449 consdata = SCIPconsGetData(cons);
5450 assert(consdata != NULL);
5451
5452 /* print left hand side for ranged rows */
5453 if( !SCIPisInfinity(scip, -consdata->lhs)
5454 && !SCIPisInfinity(scip, consdata->rhs)
5455 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5456 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
5457
5458 /* print variables and coefficient */
5459 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->var, TRUE) );
5460 SCIPinfoMessage(scip, file, " %+.15g", consdata->vbdcoef);
5461 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vbdvar, TRUE) );
5462
5463 /* print right hand side */
5464 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5465 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
5466 else if( !SCIPisInfinity(scip, consdata->rhs) )
5467 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
5468 else if( !SCIPisInfinity(scip, -consdata->lhs) )
5469 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
5470 else
5471 SCIPinfoMessage(scip, file, " [free]");
5472
5473 return SCIP_OKAY;
5474}
5475
5476/** constraint copying method of constraint handler */
5477static
5478SCIP_DECL_CONSCOPY(consCopyVarbound)
5479{ /*lint --e{715}*/
5480 SCIP_CONSHDLRDATA* conshdlrdata;
5481 const char* consname;
5482
5483 assert(scip != NULL);
5484 assert(sourcescip != NULL);
5485 assert(sourcecons != NULL);
5486 assert(valid != NULL);
5487
5488 conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
5489 assert(conshdlrdata != NULL);
5490
5491 if( conshdlrdata->copytypedcons )
5492 {
5493 SCIP_VAR* sourcevar;
5494 SCIP_VAR* sourcevbdvar;
5495 SCIP_VAR* targetvar;
5496 SCIP_VAR* targetvbdvar = NULL;
5497
5498 *valid = TRUE;
5499
5500 /* get source variables */
5501 sourcevar = SCIPgetVarVarbound(sourcescip, sourcecons);
5502 sourcevbdvar = SCIPgetVbdvarVarbound(sourcescip, sourcecons);
5503
5504 /* map source variables to target variables */
5505 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevar, &targetvar, varmap, consmap, global, valid) );
5506 assert(!(*valid) || targetvar != NULL);
5507
5508 if( *valid )
5509 {
5510 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevbdvar, &targetvbdvar, varmap, consmap, global, valid) );
5511 assert(!(*valid) || targetvbdvar != NULL);
5512 }
5513
5514 /* only create the target constraint if both variables were successfully copied */
5515 if( *valid )
5516 {
5517 if( name != NULL )
5518 consname = name;
5519 else
5520 consname = SCIPconsGetName(sourcecons);
5521
5522 SCIP_CALL( SCIPcreateConsVarbound(scip, cons, consname, targetvar, targetvbdvar,
5523 SCIPgetVbdcoefVarbound(sourcescip, sourcecons),
5524 SCIPgetLhsVarbound(sourcescip, sourcecons),
5525 SCIPgetRhsVarbound(sourcescip, sourcecons),
5526 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
5527 }
5528 }
5529 else
5530 {
5531 SCIP_VAR* vars[2];
5532 SCIP_Real coefs[2];
5533
5534 vars[0] = SCIPgetVarVarbound(sourcescip, sourcecons);
5535 vars[1] = SCIPgetVbdvarVarbound(sourcescip, sourcecons);
5536
5537 coefs[0] = 1.0;
5538 coefs[1] = SCIPgetVbdcoefVarbound(sourcescip, sourcecons);
5539
5540 if( name != NULL )
5541 consname = name;
5542 else
5543 consname = SCIPconsGetName(sourcecons);
5544
5545 /* copy the varbound using the linear constraint copy method */
5546 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, 2, vars, coefs,
5547 SCIPgetLhsVarbound(sourcescip, sourcecons), SCIPgetRhsVarbound(sourcescip, sourcecons), varmap, consmap,
5548 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
5549
5550 }
5551
5552 return SCIP_OKAY;
5553}
5554
5555/** constraint parsing method of constraint handler */
5556static
5557SCIP_DECL_CONSPARSE(consParseVarbound)
5558{ /*lint --e{715}*/
5559 SCIP_VAR** vars;
5560 SCIP_Real* coefs;
5561 SCIP_Real lhs;
5562 SCIP_Real rhs;
5563 char* endstr;
5564 int requiredsize;
5565 int nvars;
5566
5567 assert(scip != NULL);
5568 assert(success != NULL);
5569 assert(str != NULL);
5570 assert(name != NULL);
5571 assert(cons != NULL);
5572
5573 /* set left and right hand side to their default values */
5574 lhs = -SCIPinfinity(scip);
5575 rhs = SCIPinfinity(scip);
5576
5577 (*success) = FALSE;
5578
5579 /* return of string empty */
5580 if( !*str )
5581 return SCIP_OKAY;
5582
5583 /* ignore whitespace */
5584 SCIP_CALL( SCIPskipSpace((char**)&str) );
5585
5586 if( isdigit((unsigned char)str[0]) || ((str[0] == '-' || str[0] == '+') && isdigit((unsigned char)str[1])) )
5587 {
5588 if( !SCIPparseReal(scip, str, &lhs, &endstr) )
5589 {
5590 SCIPerrorMessage("error parsing left hand side\n");
5591 return SCIP_OKAY;
5592 }
5593
5594 /* ignore whitespace */
5595 SCIP_CALL( SCIPskipSpace(&endstr) );
5596
5597 if( endstr[0] != '<' || endstr[1] != '=' )
5598 {
5599 SCIPerrorMessage("missing \"<=\" after left hand side(, found %c%c)\n", endstr[0], endstr[1]);
5600 return SCIP_OKAY;
5601 }
5602
5603 SCIPdebugMsg(scip, "found left hand side <%g>\n", lhs);
5604
5605 /* it was indeed a left-hand-side, so continue parsing after it */
5606 str = endstr + 2;
5607 }
5608
5609 /* pares x + c*y as linear sum */
5611 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, 2) );
5612
5613 /* parse linear sum to get variables and coefficients */
5614 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, 2, &requiredsize, &endstr, success) );
5615
5616 if( requiredsize == 2 && *success )
5617 {
5618 SCIP_Real value;
5619
5620 assert(nvars == 2);
5621 assert(SCIPisEQ(scip, coefs[0], 1.0));
5622
5623 SCIPdebugMsg(scip, "found linear sum <%s> + %g <%s>\n", SCIPvarGetName(vars[0]), coefs[1], SCIPvarGetName(vars[1]));
5624
5625 /* ignore whitespace */
5626 SCIP_CALL( SCIPskipSpace(&endstr) );
5627
5628 str = endstr;
5629
5630 if( *str != '\0' && *(str+1) != '\0' && SCIPparseReal(scip, str+2, &value, &endstr) )
5631 {
5632 /* search for end of linear sum: either '<=', '>=', '==', or '[free]' */
5633 switch( *str )
5634 {
5635 case '<':
5636 assert(str[1] == '=');
5637 rhs = value;
5638 break;
5639 case '=':
5640 assert(str[1] == '=');
5641 assert(SCIPisInfinity(scip, -lhs));
5642 lhs = value;
5643 rhs = value;
5644 break;
5645 case '>':
5646 assert(str[1] == '=');
5647 assert(SCIPisInfinity(scip, -lhs));
5648 lhs = value;
5649 break;
5650 default:
5651 SCIPerrorMessage("missing relation symbol after linear sum\n");
5652 *success = FALSE;
5653 }
5654 }
5655 else if( strncmp(str, "[free]", 6) != 0 )
5656 *success = FALSE;
5657 }
5658
5659 if( *success )
5660 {
5661 SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, vars[0], vars[1], coefs[1], lhs, rhs,
5662 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
5663 }
5664
5665 /* free buffer arrays */
5666 SCIPfreeBufferArray(scip, &coefs);
5668
5669 return SCIP_OKAY;
5670}
5671
5672/** constraint method of constraint handler which returns the variables (if possible) */
5673static
5674SCIP_DECL_CONSGETVARS(consGetVarsVarbound)
5675{ /*lint --e{715}*/
5676 assert( success != NULL );
5677
5678 if( varssize < 2 )
5679 (*success) = FALSE;
5680 else
5681 {
5682 SCIP_CONSDATA* consdata;
5683 assert(cons != NULL);
5684 assert(vars != NULL);
5685
5686 consdata = SCIPconsGetData(cons);
5687 assert(consdata != NULL);
5688
5689 vars[0] = consdata->var;
5690 vars[1] = consdata->vbdvar;
5691 (*success) = TRUE;
5692 }
5693
5694 return SCIP_OKAY;
5695}
5696
5697/** constraint method of constraint handler which returns the number of variables (if possible) */
5698static
5699SCIP_DECL_CONSGETNVARS(consGetNVarsVarbound)
5700{ /*lint --e{715}*/
5701 (*nvars) = 2;
5702 (*success) = TRUE;
5703
5704 return SCIP_OKAY;
5705}
5706
5707/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
5708static
5709SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphVarbound)
5710{ /*lint --e{715}*/
5711 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
5712
5713 return SCIP_OKAY;
5714}
5715
5716/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
5717static
5718SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphVarbound)
5719{ /*lint --e{715}*/
5720 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
5721
5722 return SCIP_OKAY;
5723}
5724
5725/*
5726 * Event Handler
5727 */
5728
5729/** execution method of bound change event handler */
5730static
5731SCIP_DECL_EVENTEXEC(eventExecVarbound)
5732{ /*lint --e{715}*/
5733 SCIP_CONS* cons;
5734 SCIP_CONSDATA* consdata;
5735
5736 assert(event != NULL);
5737 cons = (SCIP_CONS*)eventdata;
5738 assert(cons != NULL);
5739 consdata = SCIPconsGetData(cons);
5740 assert(consdata != NULL);
5741
5743 {
5744 consdata->presolved = FALSE;
5745 }
5746 else
5747 {
5749
5750 consdata->presolved = FALSE;
5751 consdata->tightened = FALSE;
5752
5754 }
5755
5756 return SCIP_OKAY;
5757}
5758
5759/**@} */
5760
5761
5762/** creates the handler for variable bound constraints and includes it in SCIP */
5764 SCIP* scip /**< SCIP data structure */
5765 )
5766{
5767 SCIP_CONSHDLRDATA* conshdlrdata;
5768 SCIP_EVENTHDLR* eventhdlr;
5769 SCIP_CONSHDLR* conshdlr;
5770
5771 /* include event handler for bound change events */
5773 eventExecVarbound, NULL) );
5774
5775 /* create variable bound constraint handler data */
5776 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
5777
5778 /* include constraint handler */
5781 consEnfolpVarbound, consEnfopsVarbound, consCheckVarbound, consLockVarbound,
5782 conshdlrdata) );
5783 assert(conshdlr != NULL);
5784
5785 /* set non-fundamental callbacks via specific setter functions */
5786 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyVarbound, consCopyVarbound) );
5787 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveVarbound) );
5788 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveVarbound) );
5789 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteVarbound) );
5790 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolVarbound) );
5791 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolVarbound) );
5792 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeVarbound) );
5793 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsVarbound) );
5794 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsVarbound) );
5795 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpVarbound) );
5796 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseVarbound) );
5798 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintVarbound) );
5801 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropVarbound) );
5802 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpVarbound, consSepasolVarbound, CONSHDLR_SEPAFREQ,
5804 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransVarbound) );
5805 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxVarbound) );
5806 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphVarbound) );
5807 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphVarbound) );
5808
5809 if( SCIPfindConshdlr(scip,"linear") != NULL )
5810 {
5811 /* include the linear constraint to varbound constraint upgrade in the linear constraint handler */
5813 }
5814
5815 /* add varbound constraint handler parameters */
5817 "constraints/" CONSHDLR_NAME "/presolpairwise",
5818 "should pairwise constraint comparison be performed in presolving?",
5819 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
5821 "constraints/" CONSHDLR_NAME "/maxlpcoef",
5822 "maximum coefficient in varbound constraint to be added as a row into LP",
5823 &conshdlrdata->maxlpcoef, TRUE, DEFAULT_MAXLPCOEF, 0.0, 1e+20, NULL, NULL) );
5825 "constraints/" CONSHDLR_NAME "/usebdwidening", "should bound widening be used in conflict analysis?",
5826 &conshdlrdata->usebdwidening, FALSE, DEFAULT_USEBDWIDENING, NULL, NULL) );
5828 "constraints/" CONSHDLR_NAME "/copytypedcons",
5829 "should varbound constraints be copied as varbound instead of as linear constraints?",
5830 &conshdlrdata->copytypedcons, TRUE, DEFAULT_COPYTYPEDCONS, NULL, NULL) );
5831
5832 return SCIP_OKAY;
5833}
5834
5835/** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
5836 *
5837 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5838 */
5840 SCIP* scip, /**< SCIP data structure */
5841 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5842 const char* name, /**< name of constraint */
5843 SCIP_VAR* var, /**< variable x that has variable bound */
5844 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
5845 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
5846 SCIP_Real lhs, /**< left hand side of variable bound inequality */
5847 SCIP_Real rhs, /**< right hand side of variable bound inequality */
5848 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
5849 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
5850 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
5851 * Usually set to TRUE. */
5852 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
5853 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5854 SCIP_Bool check, /**< should the constraint be checked for feasibility?
5855 * TRUE for model constraints, FALSE for additional, redundant constraints. */
5856 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
5857 * Usually set to TRUE. */
5858 SCIP_Bool local, /**< is constraint only valid locally?
5859 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
5860 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
5861 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
5862 * adds coefficients to this constraint. */
5863 SCIP_Bool dynamic, /**< is constraint subject to aging?
5864 * Usually set to FALSE. Set to TRUE for own cuts which
5865 * are separated as constraints. */
5866 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
5867 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
5868 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
5869 * if it may be moved to a more global node?
5870 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
5871 )
5872{
5873 SCIP_CONSHDLR* conshdlr;
5874 SCIP_CONSHDLRDATA* conshdlrdata;
5875 SCIP_CONSDATA* consdata;
5876
5877 /* check that the given parameters are sensible, i.e., not nan or inf */
5878 assert( SCIPisFinite(vbdcoef) );
5879 assert( SCIPisFinite(lhs) );
5880 assert( SCIPisFinite(rhs) );
5881
5882 /* find the variable bound constraint handler */
5883 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5884 if( conshdlr == NULL )
5885 {
5886 SCIPerrorMessage("variable bound constraint handler not found\n");
5887 return SCIP_PLUGINNOTFOUND;
5888 }
5889
5890 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5891 assert(conshdlrdata != NULL);
5892
5893 /* create constraint data */
5894 SCIP_CALL( consdataCreate(scip, &consdata, var, vbdvar, vbdcoef, lhs, rhs) );
5895
5896 /* create constraint */
5897 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5898 local, modifiable, dynamic, removable, stickingatnode) );
5899
5900 if( SCIPisTransformed(scip) )
5901 {
5902 /* catch events for variables */
5903 SCIP_CALL( catchEvents(scip, *cons, conshdlrdata->eventhdlr) );
5904 }
5905
5906 return SCIP_OKAY;
5907}
5908
5909/** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
5910 * with all constraint flags set to their default values
5911 *
5912 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5913 */
5915 SCIP* scip, /**< SCIP data structure */
5916 SCIP_CONS** cons, /**< pointer to hold the created constraint */
5917 const char* name, /**< name of constraint */
5918 SCIP_VAR* var, /**< variable x that has variable bound */
5919 SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
5920 SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
5921 SCIP_Real lhs, /**< left hand side of variable bound inequality */
5922 SCIP_Real rhs /**< right hand side of variable bound inequality */
5923 )
5924{
5925 SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, var, vbdvar,vbdcoef, lhs, rhs,
5927
5928 return SCIP_OKAY;
5929}
5930
5931/** gets left hand side of variable bound constraint lhs <= x + c*y <= rhs */
5933 SCIP* scip, /**< SCIP data structure */
5934 SCIP_CONS* cons /**< constraint data */
5935 )
5936{
5937 SCIP_CONSDATA* consdata;
5938
5939 assert(scip != NULL);
5940
5942
5943 consdata = SCIPconsGetData(cons);
5944 assert(consdata != NULL);
5945
5946 return consdata->lhs;
5947}
5948
5949/** gets right hand side 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
5960
5961 consdata = SCIPconsGetData(cons);
5962 assert(consdata != NULL);
5963
5964 return consdata->rhs;
5965}
5966
5967/** gets bounded variable x of variable bound constraint lhs <= x + c*y <= rhs */
5969 SCIP* scip, /**< SCIP data structure */
5970 SCIP_CONS* cons /**< constraint data */
5971 )
5972{
5973 SCIP_CONSDATA* consdata;
5974
5975 assert(scip != NULL);
5976
5978
5979 consdata = SCIPconsGetData(cons);
5980 assert(consdata != NULL);
5981
5982 return consdata->var;
5983}
5984
5985/** gets bounding variable y of variable bound constraint lhs <= x + c*y <= rhs */
5987 SCIP* scip, /**< SCIP data structure */
5988 SCIP_CONS* cons /**< constraint data */
5989 )
5990{
5991 SCIP_CONSDATA* consdata;
5992
5993 assert(scip != NULL);
5994
5996
5997 consdata = SCIPconsGetData(cons);
5998 assert(consdata != NULL);
5999
6000 return consdata->vbdvar;
6001}
6002
6003/** gets bound coefficient c of variable bound constraint lhs <= x + c*y <= rhs */
6005 SCIP* scip, /**< SCIP data structure */
6006 SCIP_CONS* cons /**< constraint data */
6007 )
6008{
6009 SCIP_CONSDATA* consdata;
6010
6011 assert(scip != NULL);
6012
6014
6015 consdata = SCIPconsGetData(cons);
6016 assert(consdata != NULL);
6017
6018 return consdata->vbdcoef;
6019}
6020
6021/** gets the dual solution of the variable bound constraint in the current 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
6032
6033 consdata = SCIPconsGetData(cons);
6034 assert(consdata != NULL);
6035
6036 if( consdata->row != NULL )
6037 return SCIProwGetDualsol(consdata->row);
6038 else
6039 return 0.0;
6040}
6041
6042/** gets the dual Farkas value of the variable bound constraint in the current infeasible LP */
6044 SCIP* scip, /**< SCIP data structure */
6045 SCIP_CONS* cons /**< constraint data */
6046 )
6047{
6048 SCIP_CONSDATA* consdata;
6049
6050 assert(scip != NULL);
6051
6053
6054 consdata = SCIPconsGetData(cons);
6055 assert(consdata != NULL);
6056
6057 if( consdata->row != NULL )
6058 return SCIProwGetDualfarkas(consdata->row);
6059 else
6060 return 0.0;
6061}
6062
6063/** returns the linear relaxation of the given variable bound constraint; may return NULL if no LP row was yet created;
6064 * the user must not modify the row!
6065 */
6067 SCIP* scip, /**< SCIP data structure */
6068 SCIP_CONS* cons /**< constraint data */
6069 )
6070{
6071 SCIP_CONSDATA* consdata;
6072
6073 assert(scip != NULL);
6074
6076
6077 consdata = SCIPconsGetData(cons);
6078 assert(consdata != NULL);
6079
6080 return consdata->row;
6081}
6082
6083/** creates and returns the row of the given varbound constraint */
6085 SCIP* scip, /**< SCIP data structure */
6086 SCIP_CONS* cons /**< constraint data */
6087 )
6088{
6089 SCIP_CONSDATA* consdata;
6090
6091 assert(scip != NULL);
6092
6094
6095 consdata = SCIPconsGetData(cons);
6096 assert(consdata != NULL);
6097 assert(consdata->row == NULL);
6098
6099 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
6101 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->var, 1.0) );
6102 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->vbdvar, consdata->vbdcoef) );
6103
6104 return SCIP_OKAY;
6105}
6106
6107/** cleans up (multi-)aggregations and fixings from varbound constraints */
6109 SCIP* scip, /**< SCIP data structure */
6110 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */
6111 SCIP_Bool* infeasible, /**< pointer to return whether the problem was detected to be infeasible */
6112 int* naddconss, /**< pointer to count number of added (linear) constraints */
6113 int* ndelconss, /**< pointer to count number of deleted (varbound) constraints */
6114 int* nchgbds /**< pointer to count number of bound changes */
6115 )
6116{
6117 SCIP_CONSHDLR* conshdlr;
6118 SCIP_CONSHDLRDATA* conshdlrdata;
6119 SCIP_EVENTHDLR* eventhdlr;
6120 SCIP_CONS** conss;
6121 int nconss;
6122 int i;
6123
6124 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
6125 if( conshdlr == NULL )
6126 return SCIP_OKAY;
6127
6128 assert(infeasible != NULL);
6129 *infeasible = FALSE;
6130
6131 assert(naddconss != NULL);
6132 assert(ndelconss != NULL);
6133 assert(nchgbds != NULL);
6134
6135 conshdlrdata = SCIPconshdlrGetData(conshdlr);
6136 assert(conshdlrdata != NULL);
6137
6138 eventhdlr = conshdlrdata->eventhdlr;
6139 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
6140 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
6141
6142 /* loop backwards since then deleted constraints do not interfere with the loop */
6143 for( i = nconss - 1; i >= 0; --i )
6144 {
6145 SCIP_CALL( applyFixings(scip, conss[i], eventhdlr, infeasible, nchgbds, ndelconss, naddconss) );
6146
6147 if( *infeasible )
6148 break;
6149 }
6150
6151 return SCIP_OKAY;
6152}
static long bound
#define EVENTHDLR_NAME
#define EVENTHDLR_DESC
enum Proprule PROPRULE
Definition cons_and.c:172
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:96
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:89
#define CONSHDLR_CHECKPRIORITY
Definition cons_and.c:88
#define CONSHDLR_DESC
Definition cons_and.c:85
#define CONSHDLR_PROP_TIMING
Definition cons_and.c:99
#define CONSHDLR_MAXPREROUNDS
Definition cons_and.c:93
#define DEFAULT_PRESOLPAIRWISE
Definition cons_and.c:104
#define CONSHDLR_SEPAPRIORITY
Definition cons_and.c:86
Proprule
Definition cons_and.c:165
@ PROPRULE_2
Definition cons_and.c:168
@ PROPRULE_1
Definition cons_and.c:167
@ PROPRULE_3
Definition cons_and.c:169
@ PROPRULE_4
Definition cons_and.c:170
#define CONSHDLR_PROPFREQ
Definition cons_and.c:90
#define CONSHDLR_PRESOLTIMING
Definition cons_and.c:98
#define CONSHDLR_EAGERFREQ
Definition cons_and.c:91
#define CONSHDLR_ENFOPRIORITY
Definition cons_and.c:87
#define CONSHDLR_DELAYSEPA
Definition cons_and.c:94
#define CONSHDLR_NAME
Definition cons_and.c:84
#define CONSHDLR_DELAYPROP
Definition cons_and.c:95
#define DEFAULT_USEBDWIDENING
#define LINCONSUPGD_PRIORITY
#define DEFAULT_COPYTYPEDCONS
#define MAXSCALEDCOEF
Constraint handler for linear constraints in their most general form, .
Constraint handler for the set partitioning / packing / covering constraints .
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static SCIP_RETCODE dropEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
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_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs)
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 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_Bool checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows)
#define DEFAULT_MAXLPCOEF
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_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_Real inferbd, PROPRULE proprule, SCIP_BOUNDTYPE boundtype, SCIP_Bool usebdwidening)
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
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_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool usebdwidening, SCIP_Bool *cutoff, int *nchgbds, int *nchgsides, int *ndelconss)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static SCIP_RETCODE addNlrow(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE catchEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool usebdwidening, SCIP_SOL *sol, SCIP_RESULT *result)
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:257
#define SCIP_Longint
Definition def.h:150
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define SCIP_UNKNOWN
Definition def.h:188
#define ABS(x)
Definition def.h:225
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
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)
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)
#define SCIP_DECL_LINCONSUPGD(x)
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetDualsolVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsVarbound(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_RETCODE SCIPcreateRowVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPincludeConshdlrVarbound(SCIP *scip)
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition scip_copy.c:713
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
int SCIPgetNIntVars(SCIP *scip)
Definition scip_prob.c:2340
SCIP_RETCODE SCIPaddConsUpgrade(SCIP *scip, SCIP_CONS *oldcons, SCIP_CONS **newcons)
Definition scip_prob.c:3368
int SCIPgetNImplVars(SCIP *scip)
Definition scip_prob.c:2387
int SCIPgetNVars(SCIP *scip)
Definition scip_prob.c:2246
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
int SCIPgetNBinVars(SCIP *scip)
Definition scip_prob.c:2293
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:4067
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
Definition misc.c:9470
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition misc.c:11162
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:139
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPaddConflictRelaxedLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedlb)
SCIP_RETCODE SCIPaddConflictRelaxedUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedub)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_Real SCIPgetConflictVarUb(SCIP *scip, SCIP_VAR *var)
SCIP_Real SCIPgetConflictVarLb(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
int SCIPconshdlrGetNCheckConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4802
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition cons.c:4350
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:670
SCIP_CONS ** SCIPconshdlrGetCheckConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4759
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition scip_cons.c:540
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition scip_cons.c:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition scip_cons.c:281
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:323
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition scip_cons.c:181
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:808
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:785
SCIP_RETCODE SCIPsetConshdlrGetSignedPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:924
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),)
Definition scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrGetPermsymGraph(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:900
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:444
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:693
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4340
int SCIPconshdlrGetNActiveConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4816
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:468
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4739
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:854
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition cons.c:8423
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition scip_cons.c:2536
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition cons.c:8845
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition cons.c:8602
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition cons.c:8522
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition cons.c:8702
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition scip_cons.c:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
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:8642
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:8672
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition scip_event.c:111
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition event.c:1194
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition scip_event.c:367
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition scip_event.c:413
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition scip_mem.h:132
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_RETCODE SCIPdelNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:424
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition scip_nlp.c:396
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition scip_nlp.c:110
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition scip_nlp.c:1058
SCIP_Bool SCIPnlrowIsInNLP(SCIP_NLROW *nlrow)
Definition nlp.c:1953
SCIP_RETCODE SCIPcreateNlRow(SCIP *scip, SCIP_NLROW **nlrow, const char *name, SCIP_Real constant, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, SCIP_EXPR *expr, SCIP_Real lhs, SCIP_Real rhs, SCIP_EXPRCURV curvature)
Definition scip_nlp.c:954
SCIP_Bool SCIPinProbing(SCIP *scip)
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1398
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition scip_lp.c:2131
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition lp.c:17719
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition lp.c:17917
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition lp.c:17706
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition scip_sol.c:467
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeastol(SCIP *scip)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition scip_tree.c:146
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6401
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5210
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:8257
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition scip_var.c:5697
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4380
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition scip_var.c:10550
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:7069
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition scip_var.c:5875
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition var.c:17595
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6651
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition scip_var.c:2499
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
SCIP_RETCODE SCIPaddVarVub(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition scip_var.c:8680
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition scip_var.c:5118
SCIP_RETCODE SCIPaddVarVlb(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition scip_var.c:8621
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5296
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition scip_var.c:5634
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition scip_var.c:899
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition scip_var.c:2378
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition scip_var.c:5570
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition scip_var.c:2166
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition scip_var.c:10318
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6964
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition scip_var.c:361
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition var.c:4322
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition scip_var.c:2078
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1853
SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:8026
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
SCIP_RETCODE SCIPgetSymActiveVariables(SCIP *scip, SYM_SYMTYPE symtype, SCIP_VAR ***vars, SCIP_Real **scalars, int *nvars, SCIP_Real *constant, SCIP_Bool transformed)
SCIP_RETCODE SCIPextendPermsymDetectionGraphLinear(SCIP *scip, SYM_GRAPH *graph, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_CONS *cons, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool *success)
return SCIP_OKAY
int c
SCIP_Bool cutoff
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_Bool propagate
static SCIP_VAR ** vars
static const SCIP_Real scalars[]
Definition lp.c:5959
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)
public data structures and miscellaneous methods
#define SCIPisFinite(x)
Definition pub_misc.h:82
methods for sorting joint arrays of various types
public methods for problem variables
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for the branch-and-bound tree
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
structs for symmetry computations
methods for dealing with symmetry detection graphs
@ SCIP_CONFTYPE_PROPAGATION
#define SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(x)
Definition type_cons.h:956
#define SCIP_DECL_CONSGETPERMSYMGRAPH(x)
Definition type_cons.h:938
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:363
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:867
#define SCIP_DECL_CONSINITSOL(x)
Definition type_cons.h:201
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:769
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
struct SYM_Graph SYM_GRAPH
Definition type_cons.h:68
#define SCIP_DECL_CONSENFORELAX(x)
Definition type_cons.h:388
#define SCIP_DECL_CONSPROP(x)
Definition type_cons.h:506
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:885
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:612
#define SCIP_DECL_CONSACTIVE(x)
Definition type_cons.h:691
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:845
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSDEACTIVE(x)
Definition type_cons.h:706
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:561
#define SCIP_DECL_CONSINITLP(x)
Definition type_cons.h:259
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:676
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:810
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:474
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:108
#define SCIP_DECL_CONSEXITSOL(x)
Definition type_cons.h:216
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:116
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:320
struct SCIP_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
#define SCIP_EVENTTYPE_VARFIXED
Definition type_event.h:72
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:259
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition type_event.h:125
@ SCIP_EXPRCURV_LINEAR
Definition type_expr.h:65
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_BOUNDTYPE_UPPER
Definition type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition type_lp.h:60
#define SCIP_DECL_SORTPTRCOMP(x)
Definition type_misc.h:189
struct SCIP_NlRow SCIP_NLROW
Definition type_nlp.h:41
@ 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
@ SCIP_PLUGINNOTFOUND
@ SCIP_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_PRESOLVING
Definition type_set.h:49
@ SCIP_STAGE_SOLVING
Definition type_set.h:53
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
enum SYM_Symtype SYM_SYMTYPE
@ SYM_SYMTYPE_SIGNPERM
@ SYM_SYMTYPE_PERM
#define SCIP_PRESOLTIMING_MEDIUM
Definition type_timing.h:53
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
#define SCIP_DEPRECATED_VARTYPE_IMPLINT
Definition type_var.h:79
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition type_var.h:73