Scippy

SCIP

Solving Constraint Integer Programs

cons_exactlinear.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file cons_exactlinear.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief Constraint handler for exact linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
28 * @author Leon Eifler
29 * @author Sander Borst
30 */
31
32/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33
34#include "scip/clock.h"
35#include "scip/def.h"
36#include "scip/struct_stat.h"
37#include "scip/type_retcode.h"
39#include "scip/cons_knapsack.h"
41#include "scip/cons_linear.h"
42#include "scip/cons_nonlinear.h"
43#include "scip/debug.h"
44#include "scip/intervalarith.h"
45#include "scip/pub_conflict.h"
46#include "scip/pub_cons.h"
47#include "scip/pub_event.h"
48#include "scip/pub_lp.h"
49#include "scip/pub_lpexact.h"
50#include "scip/pub_message.h"
51#include "scip/pub_misc.h"
52#include "scip/pub_misc_sort.h"
53#include "scip/pub_var.h"
54#include "scip/rational.h"
55#include "scip/scip_branch.h"
57#include "scip/scip_conflict.h"
58#include "scip/scip_cons.h"
59#include "scip/scip_copy.h"
60#include "scip/scip_cut.h"
61#include "scip/scip_event.h"
62#include "scip/scip_exact.h"
63#include "scip/scip_general.h"
64#include "scip/scip_lp.h"
65#include "scip/scip_lpexact.h"
66#include "scip/scip_mem.h"
67#include "scip/scip_message.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"
73#include "scip/scip_tree.h"
74#include "scip/scip_var.h"
75#include "scip/var.h"
76#include "scip/sepastoreexact.h"
77#include <ctype.h>
78#include <string.h>
79#ifndef _WIN32
80#include <strings.h> /*lint --e{766}*/
81#endif
82
83
84#define CONSHDLR_NAME "exactlinear"
85#define CONSHDLR_DESC "exact linear constraints of the form lhs <= a^T x <= rhs"
86#define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
87#define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
88#define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
89#define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
90#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
91#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
92 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
93#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
94#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
95#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
96
97#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
98
99#define EVENTHDLR_NAME "exactlinear"
100#define EVENTHDLR_DESC "bound change event handler for exact linear constraints"
101
102#define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
103#define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
104#define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
105#define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
106#define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
107#define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
108 * propagation? */
109#define DEFAULT_LIMITDENOM FALSE /**< should denominator sizes for continuous variables be controlled?*/
110#define DEFAULT_BOUNDMAXDENOM 256L /**< maximal denominator for rational bounds on continuous variables after propagation */
111
112
113/** constraint data for linear constraints */
114struct SCIP_ConsData
115{
116 SCIP_RATIONAL* lhs; /**< left hand side of row (for ranged rows) */
117 SCIP_RATIONAL* rhs; /**< right hand side of row */
118 SCIP_Real lhsreal; /**< real relaxation of lhs */
119 SCIP_Real rhsreal; /**< real relaxation of rhs */
120 SCIP_RATIONAL* violation; /**< used to store violation */
121 SCIP_RATIONAL* activity; /**< used to store activity */
122 SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
123 SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
124 SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
125 * activity, ignoring the coefficients contributing with infinite value */
126 SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
127 * activity, ignoring the coefficients contributing with infinite value */
128 SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
129 * over all contributing values */
130 SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
131 * over all contributing values */
132 SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
133 * activity, ignoring the coefficients contributing with infinite value */
134 SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
135 * activity, ignoring the coefficients contributing with infinite value */
136 SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
137 * over all contributing values */
138 SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
139 * over all contributing values */
140 SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
141 SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
142 SCIP_RATIONAL* maxabsvalexact; /**< exact maximum absolute value of all coefficients */
143 SCIP_RATIONAL* minabsvalexact; /**< exact minimal absolute value of all coefficients */
144 SCIP_ROW* rowlhs; /**< LP row, if constraint is already stored in LP row format; represents fp-relaxation of lhs-part of rowexact;
145 only this row will be added to the exact LP, rowrhs is used for safe aggregation of rows */
146 SCIP_ROW* rowrhs; /**< LP row, if constraint is already stored in LP row format; represents fp-relaxation of rhs-part of rowexact */
147 SCIP_ROWEXACT* rowexact; /**< Exact rational lp row */
148 SCIP_VAR** vars; /**< variables of constraint entries */
149 SCIP_RATIONAL** vals; /**< coefficients of constraint entries */
150 SCIP_INTERVAL* valsreal; /**< values of val rounded up/down to closest fp-representable numbers */
151 SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
152 int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
153 int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
154 int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
155 int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
156 int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
157 int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
158 int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
159 int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
160 int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
161 int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
162 int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
163 int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
164 int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
165 int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
166 int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
167 int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
168 int varssize; /**< size of the vars- and vals-arrays */
169 int nvars; /**< number of nonzeros in constraint */
170 int nbinvars; /**< the number of binary variables in the constraint, only valid after
171 * sorting in stage >= SCIP_STAGE_INITSOLVE
172 */
173 unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
174 unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
175 * (0: no, 1: yes, 2: with potentially adding artificial constraint */
176 unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
177 unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
178 unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
179 unsigned int validminact:1; /**< is the local minactivity valid? */
180 unsigned int validmaxact:1; /**< is the local maxactivity valid? */
181 unsigned int validglbminact:1; /**< is the global minactivity valid? */
182 unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
183 unsigned int presolved:1; /**< is constraint already presolved? */
184 unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
185 unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
186 unsigned int normalized:1; /**< is the constraint in normalized form? */
187 unsigned int coefsorted :1; /**< are the constraint's variables sorted? */
188 unsigned int merged:1; /**< are the constraint's equal variables already merged? */
189 unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
190 unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
191 unsigned int indexsorted:1; /**< are binary variables sorted w.r.t. the absolute value of their coefficient? */
192 unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
193 unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
194 unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
195 unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
196 unsigned int onerowrelax:1; /**< is one floating-point row enough for the fp-relaxation? if so only rowlhs is used */
197 unsigned int hasfprelax:1; /**< is the constraint possible to be represented as a fp relaxation (only false if var without bound is present) */
198};
199
200/** event data for bound change event */
201struct SCIP_EventData
202{
203 SCIP_CONS* cons; /**< linear constraint to process the bound change for */
204 int varpos; /**< position of variable in vars array */
205 bool rowvar; /**< is the event a row event? */
206 int filterpos; /**< position of event in variable's event filter */
207};
208
209/** constraint handler data */
210struct SCIP_ConshdlrData
211{
212 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
213 SCIP_RATIONAL* maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
214 * (0.0: disable constraint aggregation) */
215 SCIP_RATIONAL* maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
216 * to best node's dual bound for separating knapsack cardinality cuts */
217 SCIP_RATIONAL* mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
218 SCIP_RATIONAL* maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
219 * (faster, but numerically less stable) */
220 int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
221 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
222 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
223 int maxsepacuts; /**< maximal number of cuts separated per separation round */
224 int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
225 int naddconss; /**< number of added constraints */
226 SCIP_Longint ncheckserrorbound; /**< number of times running error analyis activity computation was called */
227 SCIP_Longint nsuccesserrorbound; /**< number of times running error analyis activity computation could determine feasibility */
228 SCIP_Longint nabotserrorbound; /**< number of times running error analysis activity computation not appliccable (e.g. row->len != fprow->len) */
229 SCIP_Longint nconsprop; /**< number of times a constraint was propagated */
230 SCIP_Longint nconspropnoninit; /**< number of times a non-initial (conflict) constraint was propagated */
231 SCIP_Longint propnonzeros; /**< number of nonzeros in propagated rows */
232 SCIP_Longint propnonzerosnoninit;/**< number of nonzeros in propagated rows in non-initial (conflict) propagations */
233 SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
234 SCIP_Bool propcont; /**< should bounds on continuous variables be tightened by propagation?*/
235 SCIP_Bool limitdenom; /**< should denominator sizes for continuous variables be controlled?*/
236 SCIP_Longint boundmaxdenom; /**< maximal denominator for rational bounds on continuous variables after propagation */
237};
238
239
240/*
241 * Propagation rules
242 */
243
244/*lint --e{749} */
246{
247 PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
248 * variable due to the right hand side of the inequality */
249 PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
250 * variable due to the left hand side of the inequality */
251 PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
252 * single variable in this reanged row */
253 PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
255typedef enum Proprule PROPRULE;
256
257/** inference information */
258struct InferInfo
259{
260 union
261 {
262 struct
263 {
264 unsigned int proprule:8; /**< propagation rule that was applied */
265 unsigned int pos:24; /**< variable position, the propagation rule was applied at */
266 } asbits;
267 int asint; /**< inference information as a single int value */
268 } val;
269};
270
271typedef struct InferInfo INFERINFO;
272
273
274/** converts an inference information into an int */
275static
277 INFERINFO inferinfo /**< inference information to convert */
278 )
279{
280 return inferinfo.val.asint;
281}
282
283
284/** constructs an inference information out of a propagation rule and a position number */
285static
287 PROPRULE proprule, /**< propagation rule that deduced the value */
288 int pos /**< variable position, the propagation rule was applied at */
289 )
290{
291 INFERINFO inferinfo;
292
293 assert(pos >= 0);
294 /* in the inferinfo struct only 24 bits for 'pos' are reserved */
295 assert(pos < (1<<24));
296
297 inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
298 inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
299
300 return inferinfo;
301}
302
303/** constructs an inference information out of a propagation rule and a position number, returns info as int */
304static
306 PROPRULE proprule, /**< propagation rule that deduced the value */
307 int pos /**< variable position, the propagation rule was applied at */
308 )
309{
310 return inferInfoToInt(getInferInfo(proprule, pos));
311}
312
313/** ensures, that vars and vals arrays can store at least num entries */
314static
316 SCIP* scip, /**< SCIP data structure */
317 SCIP_CONSDATA* consdata, /**< linear constraint data */
318 int num /**< minimum number of entries to store */
319 )
320{
321 int k;
322 assert(scip != NULL);
323 assert(consdata != NULL);
324 assert(consdata->nvars <= consdata->varssize);
325
326 if( num > consdata->varssize )
327 {
328 int newsize;
329
330 newsize = SCIPcalcMemGrowSize(scip, num);
331 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
332 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
333 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->valsreal, consdata->varssize, newsize) );
334 for( k = consdata->varssize; k < newsize; ++k )
335 SCIP_CALL( SCIPrationalCreateBlock(SCIPblkmem(scip), &consdata->vals[k]) );
336
337 if( consdata->eventdata != NULL )
338 {
339 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
340 }
341 consdata->varssize = newsize;
342 }
343 assert(num <= consdata->varssize);
344
345 return SCIP_OKAY;
346}
347
348
349/*
350 * local methods for managing linear constraint update methods
351 */
352
353
354/** creates constraint handler data for linear constraint handler */
355static
357 SCIP* scip, /**< SCIP data structure */
358 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
359 SCIP_EVENTHDLR* eventhdlr /**< event handler */
360 )
361{
362 assert(scip != NULL);
363 assert(conshdlrdata != NULL);
364 assert(eventhdlr != NULL);
365
366 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
367 (*conshdlrdata)->naddconss = 0;
368 (*conshdlrdata)->ncheckserrorbound = 0;
369 (*conshdlrdata)->nabotserrorbound = 0;
370 (*conshdlrdata)->nsuccesserrorbound = 0;
371 (*conshdlrdata)->nconsprop = 0;
372 (*conshdlrdata)->nconspropnoninit = 0;
373 (*conshdlrdata)->propnonzeros = 0;
374 (*conshdlrdata)->propnonzerosnoninit = 0;
375 SCIP_CALL( SCIPrationalCreateBlock(SCIPblkmem(scip), &(*conshdlrdata)->maxaggrnormscale) );
376 SCIP_CALL( SCIPrationalCreateBlock(SCIPblkmem(scip), &(*conshdlrdata)->maxcardbounddist) );
377 SCIP_CALL( SCIPrationalCreateBlock(SCIPblkmem(scip), &(*conshdlrdata)->maxeasyactivitydelta) );
378 SCIP_CALL( SCIPrationalCreateBlock(SCIPblkmem(scip), &(*conshdlrdata)->mingainpernmincomp) );
379
380 /* set event handler for updating linear constraint activity bounds */
381 (*conshdlrdata)->eventhdlr = eventhdlr;
382
383 return SCIP_OKAY;
384}
385
386/** frees constraint handler data for linear constraint handler */
387static
389 SCIP* scip, /**< SCIP data structure */
390 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
391 )
392{
393 assert(scip != NULL);
394 assert(conshdlrdata != NULL);
395 assert(*conshdlrdata != NULL);
396
397 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*conshdlrdata)->maxaggrnormscale);
398 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*conshdlrdata)->maxcardbounddist);
399 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*conshdlrdata)->maxeasyactivitydelta);
400 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*conshdlrdata)->mingainpernmincomp);
401
402 SCIPfreeBlockMemory(scip, conshdlrdata);
403}
404
405/*
406 * local methods
407 */
408
409/** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
410static
412 SCIP* scip, /**< SCIP data structure */
413 SCIP_CONS* cons, /**< linear constraint */
414 SCIP_VAR* var, /**< variable of constraint entry */
415 SCIP_RATIONAL* val /**< coefficient of constraint entry */
416 )
417{
418 SCIP_CONSDATA* consdata;
419
420 assert(scip != NULL);
421 assert(cons != NULL);
422 assert(var != NULL);
423
424 consdata = SCIPconsGetData(cons);
425 assert(consdata != NULL);
426 assert(!SCIPrationalIsZero(val));
427
428 if( SCIPrationalIsPositive(val) )
429 {
430 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
431 !SCIPrationalIsNegInfinity(consdata->lhs), !SCIPrationalIsInfinity(consdata->rhs)) );
432 }
433 else
434 {
435 SCIP_CALL( SCIPlockVarCons(scip, var, cons,
436 !SCIPrationalIsInfinity(consdata->rhs), !SCIPrationalIsNegInfinity(consdata->lhs)) );
437 }
438
439 return SCIP_OKAY;
440}
441
442/** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
443static
445 SCIP* scip, /**< SCIP data structure */
446 SCIP_CONS* cons, /**< linear constraint */
447 SCIP_VAR* var, /**< variable of constraint entry */
448 SCIP_RATIONAL* val /**< coefficient of constraint entry */
449 )
450{
451 SCIP_CONSDATA* consdata;
452
453 assert(scip != NULL);
454 assert(cons != NULL);
455 assert(var != NULL);
456
457 consdata = SCIPconsGetData(cons);
458 assert(consdata != NULL);
459 assert(!SCIPrationalIsZero(val));
460
461 if( SCIPrationalIsPositive(val) )
462 {
463 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPrationalIsNegInfinity(consdata->lhs),
464 !SCIPrationalIsInfinity(consdata->rhs)) );
465 }
466 else
467 {
468 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPrationalIsInfinity(consdata->rhs),
469 !SCIPrationalIsNegInfinity(consdata->lhs)) );
470 }
471
472 return SCIP_OKAY;
473}
474
475/** creates event data for variable at given position, and catches events */
476/**! [SnippetDebugAssertions] */
477static
479 SCIP* scip, /**< SCIP data structure */
480 SCIP_CONS* cons, /**< linear constraint */
481 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
482 int pos /**< array position of variable to catch bound change events for */
483 )
484{
485 SCIP_CONSDATA* consdata;
486 assert(scip != NULL);
487 assert(cons != NULL);
488 assert(eventhdlr != NULL);
489
490 consdata = SCIPconsGetData(cons);
491 assert(consdata != NULL);
492
493 assert(0 <= pos && pos < consdata->nvars);
494 assert(consdata->vars != NULL);
495 assert(consdata->vars[pos] != NULL);
496 assert(SCIPvarIsTransformed(consdata->vars[pos]));
497 assert(consdata->eventdata != NULL);
498 assert(consdata->eventdata[pos] == NULL);
499
500 SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
501 consdata->eventdata[pos]->cons = cons;
502 consdata->eventdata[pos]->varpos = pos;
503 consdata->eventdata[pos]->rowvar = false;
504
505 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
508 eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
509
510 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
511
512 return SCIP_OKAY;
513}
514
515/**! [SnippetDebugAssertions] */
516
517/** deletes event data for variable at given position, and drops events */
518static
520 SCIP* scip, /**< SCIP data structure */
521 SCIP_CONS* cons, /**< linear constraint */
522 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
523 int pos /**< array position of variable to catch bound change events for */
524 )
525{
526 SCIP_CONSDATA* consdata;
527 assert(scip != NULL);
528 assert(cons != NULL);
529 assert(eventhdlr != NULL);
530
531 consdata = SCIPconsGetData(cons);
532 assert(consdata != NULL);
533
534 assert(0 <= pos && pos < consdata->nvars);
535 assert(consdata->vars[pos] != NULL);
536 assert(consdata->eventdata != NULL);
537 assert(consdata->eventdata[pos] != NULL);
538 assert(consdata->eventdata[pos]->cons == cons);
539 assert(consdata->eventdata[pos]->varpos == pos);
540
541 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
544 eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
545
546 SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
547
548 return SCIP_OKAY;
549}
550
551/** catches bound change events for all variables in transformed linear constraint */
552static
554 SCIP* scip, /**< SCIP data structure */
555 SCIP_CONS* cons, /**< linear constraint */
556 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
557 )
558{
559 SCIP_CONSDATA* consdata;
560 int i;
561
562 assert(scip != NULL);
563 assert(cons != NULL);
564
565 consdata = SCIPconsGetData(cons);
566 assert(consdata != NULL);
567 assert(consdata->eventdata == NULL);
568
569 /* allocate eventdata array */
570 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
571 assert(consdata->eventdata != NULL);
572 BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
573
574 /* catch event for every single variable */
575 for( i = 0; i < consdata->nvars; ++i )
576 {
577 SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
578 }
579
580 return SCIP_OKAY;
581}
582
583/** drops bound change events for all variables in transformed linear constraint */
584static
586 SCIP* scip, /**< SCIP data structure */
587 SCIP_CONS* cons, /**< linear constraint */
588 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
589 )
590{
591 SCIP_CONSDATA* consdata;
592 int i;
593
594 assert(scip != NULL);
595 assert(cons != NULL);
596
597 consdata = SCIPconsGetData(cons);
598 assert(consdata != NULL);
599 assert(consdata->eventdata != NULL);
600
601 /* drop event of every single variable */
602 for( i = consdata->nvars - 1; i >= 0; --i )
603 {
604 SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
605 }
606
607 /* free eventdata array */
608 SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
609 assert(consdata->eventdata == NULL);
610
611 return SCIP_OKAY;
612}
613
614/** creates a linear constraint data */
615static
617 SCIP* scip, /**< SCIP data structure */
618 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
619 int nvars, /**< number of nonzeros in the constraint */
620 SCIP_VAR** vars, /**< array with variables of constraint entries */
621 SCIP_RATIONAL** vals, /**< array with coefficients of constraint entries */
622 SCIP_RATIONAL* lhs, /**< left hand side of row */
623 SCIP_RATIONAL* rhs /**< right hand side of row */
624 )
625{
626 int v;
627 SCIP_RATIONAL* constant;
628 SCIP_Real lhsrel;
629 SCIP_Real rhsrel;
630
631 assert(scip != NULL);
632 assert(consdata != NULL);
633 assert(nvars == 0 || vars != NULL);
634 assert(nvars == 0 || vals != NULL);
635
636 if( SCIPrationalIsGT(lhs, rhs) )
637 {
638 SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
639 SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", SCIPrationalGetReal(lhs), SCIPrationalGetReal(rhs));
640 }
641
642 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
643
644 (*consdata)->varssize = 0;
645 (*consdata)->nvars = nvars;
646 (*consdata)->hascontvar = FALSE;
647 (*consdata)->hasnonbinvar = FALSE;
648 (*consdata)->hasnonbinvalid = TRUE;
649 (*consdata)->vars = NULL;
650 (*consdata)->vals = NULL;
651 (*consdata)->valsreal = NULL;
652
654 if( nvars > 0 )
655 {
656 int k;
657
658 SCIP_VAR** varsbuffer;
659 SCIP_RATIONAL** valsbuffer;
660 SCIP_INTERVAL* valsrealbuffer;
661
662 /* copy variables into temporary buffer */
663 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
665 SCIP_CALL( SCIPallocBufferArray(scip, &valsrealbuffer, nvars) );
666 k = 0;
667
668 /* loop over variables and sort out fixed ones */
669 for( v = 0; v < nvars; ++v )
670 {
671 SCIP_VAR* var;
672
673 var = vars[v];
674 assert(var != NULL);
675 assert(!SCIPrationalIsAbsInfinity(vals[v]));
676
677 if( !SCIPrationalIsZero(vals[v]) )
678 {
679 /* treat fixed variable as a constant if problem compression is enabled */
681 {
682 SCIPrationalAddProd(constant, vals[v], SCIPvarGetLbGlobalExact(var));
683 }
684 else
685 {
686 varsbuffer[k] = var;
687 SCIPrationalSetRational(valsbuffer[k], vals[v]);
688 SCIPintervalSetRational(&(valsrealbuffer[k]), vals[v]);
689 k++;
690
691 /* update hascontvar and hasnonbinvar flags */
692 if( !(*consdata)->hascontvar )
693 {
694 SCIP_VARTYPE vartype = SCIPvarGetType(var);
695
696 if( vartype != SCIP_VARTYPE_BINARY )
697 {
698 (*consdata)->hasnonbinvar = TRUE;
699
700 if( vartype == SCIP_VARTYPE_CONTINUOUS )
701 (*consdata)->hascontvar = TRUE;
702 }
703 }
704 }
705 }
706 }
707 (*consdata)->nvars = k;
708
709 if( k > 0 )
710 {
711 /* copy the possibly reduced buffer arrays into block */
712 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
713 SCIP_CALL( SCIPrationalCopyBlockArray(SCIPblkmem(scip), &(*consdata)->vals, valsbuffer, k) );
714 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->valsreal, valsrealbuffer, k) );
715 (*consdata)->varssize = k;
716 }
717
718 SCIPfreeBufferArray(scip, &valsrealbuffer);
719 SCIPrationalFreeBufferArray(SCIPbuffer(scip), &valsbuffer, nvars);
720 SCIPfreeBufferArray(scip, &varsbuffer);
721 }
722
723 (*consdata)->eventdata = NULL;
724
727
728 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
729 if( !SCIPrationalIsZero(constant) )
730 {
731 if( !SCIPrationalIsAbsInfinity(lhs) )
732 SCIPrationalDiff(lhs, lhs, constant);
733
734 if( !SCIPrationalIsAbsInfinity(rhs) )
735 SCIPrationalDiff(rhs, rhs, constant);
736 }
737
738 (*consdata)->rowlhs = NULL;
739 (*consdata)->rowrhs = NULL;
740 (*consdata)->rowexact = NULL;
741 SCIP_CALL( SCIPrationalCopyBlock(SCIPblkmem(scip), &(*consdata)->lhs, lhs) );
742 SCIP_CALL( SCIPrationalCopyBlock(SCIPblkmem(scip), &(*consdata)->rhs, rhs) );
743 (*consdata)->lhsreal = lhsrel;
744 (*consdata)->rhsreal = rhsrel;
745 SCIP_CALL( SCIPrationalCreateString(SCIPblkmem(scip), &(*consdata)->maxabsvalexact, "inf") );
746 SCIP_CALL( SCIPrationalCreateString(SCIPblkmem(scip), &(*consdata)->minabsvalexact, "inf") );
747 (*consdata)->maxabsval = SCIP_INVALID;
748 (*consdata)->minabsval = SCIP_INVALID;
749 (*consdata)->minactivity = SCIP_INVALID;
750 (*consdata)->maxactivity = SCIP_INVALID;
751 (*consdata)->lastminactivity = SCIP_INVALID;
752 (*consdata)->lastmaxactivity = SCIP_INVALID;
753 (*consdata)->maxactdelta = SCIP_INVALID;
754 (*consdata)->maxactdeltavar = NULL;
755 (*consdata)->minactivityneginf = -1;
756 (*consdata)->minactivityposinf = -1;
757 (*consdata)->maxactivityneginf = -1;
758 (*consdata)->maxactivityposinf = -1;
759 (*consdata)->minactivityneghuge = -1;
760 (*consdata)->minactivityposhuge = -1;
761 (*consdata)->maxactivityneghuge = -1;
762 (*consdata)->maxactivityposhuge = -1;
763 (*consdata)->glbminactivity = SCIP_INVALID;
764 (*consdata)->glbmaxactivity = SCIP_INVALID;
765 (*consdata)->lastglbminactivity = SCIP_INVALID;
766 (*consdata)->lastglbmaxactivity = SCIP_INVALID;
767 (*consdata)->glbminactivityneginf = -1;
768 (*consdata)->glbminactivityposinf = -1;
769 (*consdata)->glbmaxactivityneginf = -1;
770 (*consdata)->glbmaxactivityposinf = -1;
771 (*consdata)->glbminactivityneghuge = -1;
772 (*consdata)->glbminactivityposhuge = -1;
773 (*consdata)->glbmaxactivityneghuge = -1;
774 (*consdata)->glbmaxactivityposhuge = -1;
775 (*consdata)->validmaxabsval = FALSE;
776 (*consdata)->validminabsval = FALSE;
777 (*consdata)->validactivities = FALSE;
778 (*consdata)->validminact = FALSE;
779 (*consdata)->validmaxact = FALSE;
780 (*consdata)->validglbminact = FALSE;
781 (*consdata)->validglbmaxact = FALSE;
782 (*consdata)->boundstightened = 0;
783 (*consdata)->presolved = FALSE;
784 (*consdata)->removedfixings = FALSE;
785 (*consdata)->changed = TRUE;
786 (*consdata)->normalized = FALSE;
787 (*consdata)->indexsorted = (nvars <= 1);
788 (*consdata)->merged = (nvars <= 1);
789 (*consdata)->cliquesadded = FALSE;
790 (*consdata)->implsadded = FALSE;
791 (*consdata)->coefsorted = FALSE;
792 (*consdata)->nbinvars = -1;
793 (*consdata)->varsdeleted = FALSE;
794 (*consdata)->rangedrowpropagated = 0;
795 (*consdata)->onerowrelax = FALSE;
796 (*consdata)->hasfprelax = FALSE;
797
798 SCIP_CALL( SCIPrationalCreateBlock(SCIPblkmem(scip), &(*consdata)->activity) );
799 SCIP_CALL( SCIPrationalCreateBlock(SCIPblkmem(scip), &(*consdata)->violation) );
800
802 {
803 /* get transformed variables */
804 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
805 }
806
807 /* capture variables */
808 for( v = 0; v < (*consdata)->nvars; v++ )
809 {
810 assert((*consdata)->vars[v] != NULL);
811 assert(!SCIPrationalIsZero((*consdata)->vals[v]));
812 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
813 }
814
816
817 return SCIP_OKAY;
818}
819
820/** frees a linear constraint data */
821static
823 SCIP* scip, /**< SCIP data structure */
824 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
825 )
826{
827 int v;
828
829 assert(scip != NULL);
830 assert(consdata != NULL);
831 assert(*consdata != NULL);
832 assert((*consdata)->varssize >= 0);
833
834 /* release the row */
835 if( (*consdata)->rowlhs != NULL )
836 {
837 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowlhs) );
838 }
839 if( (*consdata)->rowrhs != NULL && !(*consdata)->onerowrelax )
840 {
841 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowrhs) );
842 }
843
844 /* release variables */
845 for( v = 0; v < (*consdata)->nvars; v++ )
846 {
847 assert((*consdata)->vars[v] != NULL);
848 assert(!SCIPrationalIsZero((*consdata)->vals[v]));
849 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
850 }
851
852 SCIPrationalFreeBlockArray(SCIPblkmem(scip), &(*consdata)->vals, (*consdata)->varssize);
853
854 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
855 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
856 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->valsreal, (*consdata)->varssize);
857
858 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*consdata)->lhs);
859 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*consdata)->rhs);
860 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*consdata)->maxabsvalexact);
861 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*consdata)->minabsvalexact);
862 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*consdata)->violation);
863 SCIPrationalFreeBlock(SCIPblkmem(scip), &(*consdata)->activity);
864
865 SCIPfreeBlockMemory(scip, consdata);
866 return SCIP_OKAY;
867}
868/** prints linear constraint in CIP format to file stream */
869static
871 SCIP* scip, /**< SCIP data structure */
872 SCIP_CONSDATA* consdata, /**< linear constraint data */
873 FILE* file /**< output file (or NULL for standard output) */
874 )
875{
876 assert(scip != NULL);
877 assert(consdata != NULL);
878
879 /* print left hand side for ranged rows */
880 if( !SCIPrationalIsNegInfinity(consdata->lhs)
881 && !SCIPrationalIsInfinity(consdata->rhs)
882 && !SCIPrationalIsEQ(consdata->lhs, consdata->rhs) )
883 {
884 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->lhs);
885 SCIPinfoMessage(scip, file, " <= ");
886 }
887
888 /* print coefficients and variables */
889 if( consdata->nvars == 0 )
890 SCIPinfoMessage(scip, file, "0");
891 else
892 {
893 /* post linear sum of the linear constraint */
894 SCIP_CALL( SCIPwriteVarsLinearsumExact(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
895 }
896
897 /* print right hand side */
898 if( SCIPrationalIsEQ(consdata->lhs, consdata->rhs) )
899 {
900 SCIPinfoMessage(scip, file, " == ");
901 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->lhs);
902 }
903 else if( !SCIPrationalIsInfinity(consdata->rhs) )
904 {
905 SCIPinfoMessage(scip, file, " <= ");
906 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->rhs);
907 }
908 else if( !SCIPrationalIsNegInfinity(consdata->lhs) )
909 {
910 SCIPinfoMessage(scip, file, " >= ");
911 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->lhs);
912 }
913 else
914 SCIPinfoMessage(scip, file, " [free]");
915
916 return SCIP_OKAY;
917}
918
919/** prints linear constraint and contained solution values of variables to file stream */
920static
922 SCIP* scip, /**< SCIP data structure */
923 SCIP_CONS* cons, /**< linear constraint */
924 SCIP_SOL* sol, /**< solution to print */
925 SCIP_Bool useexactsol, /**< should the exact sol be used */
926 FILE* file /**< output file (or NULL for standard output) */
927 )
928{
929 SCIP_CONSDATA* consdata;
930
931 assert(scip != NULL);
932 assert(cons != NULL);
933
934 consdata = SCIPconsGetData(cons);
935 assert(consdata != NULL);
936
938
939 /* print left hand side for ranged rows */
940 /* print left hand side for ranged rows */
941 if( !SCIPrationalIsNegInfinity(consdata->lhs)
942 && !SCIPrationalIsInfinity(consdata->rhs)
943 && !SCIPrationalIsEQ(consdata->lhs, consdata->rhs) )
944 {
945 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->lhs);
946 SCIPinfoMessage(scip, file, " <= ");
947 }
948
949 /* print coefficients and variables */
950 if( consdata->nvars == 0 )
951 SCIPinfoMessage(scip, file, "0");
952 else
953 {
954 int v;
955
956 /* post linear sum of the linear constraint */
957 for( v = 0; v < consdata->nvars; ++v )
958 {
959 if( consdata->vals != NULL )
960 {
961 if( SCIPrationalIsEQReal(consdata->vals[v], 1.0) )
962 {
963 if( v > 0 )
964 SCIPinfoMessage(scip, file, " +");
965 }
966 else if( SCIPrationalIsEQReal(consdata->vals[v], -1.0) )
967 SCIPinfoMessage(scip, file, " -");
968 else
969 {
970 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->vals[v]);
971 }
972 }
973 else if( consdata->nvars > 0 )
974 SCIPinfoMessage(scip, file, " +");
975
976 /* print variable name */
977 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
978
979 if( sol != NULL )
980 {
981 SCIPinfoMessage(scip, file, " (");
982 if( useexactsol )
983 {
984 SCIP_RATIONAL* tmp;
986 SCIPgetSolValExact(scip, sol, consdata->vars[v], tmp);
989 }
990 else
991 SCIPinfoMessage(scip, file, "%+.9g", SCIPgetSolVal(scip, sol, consdata->vars[v]));
992 SCIPinfoMessage(scip, file, ")");
993 }
994 }
995 }
996
997 /* print right hand side */
998 if( SCIPrationalIsEQ(consdata->lhs, consdata->rhs) )
999 {
1000 SCIPinfoMessage(scip, file, " == ");
1001 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->lhs);
1002 }
1003 else if( !SCIPrationalIsInfinity(consdata->rhs) )
1004 {
1005 SCIPinfoMessage(scip, file, " <= ");
1006 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->rhs);
1007 }
1008 else if( !SCIPrationalIsNegInfinity(consdata->lhs) )
1009 {
1010 SCIPinfoMessage(scip, file, " >= ");
1011 SCIPrationalMessage(SCIPgetMessagehdlr(scip), file, consdata->lhs);
1012 }
1013 else
1014 SCIPinfoMessage(scip, file, " [free]");
1015
1016 SCIPinfoMessage(scip, file, ";\n");
1017
1018 return SCIP_OKAY;
1019}
1020
1021/** invalidates activity bounds, such that they are recalculated in next get */
1022static
1024 SCIP_CONSDATA* consdata /**< linear constraint */
1025 )
1026{
1027 assert(consdata != NULL);
1028
1029 consdata->validactivities = FALSE;
1030 consdata->validminact = FALSE;
1031 consdata->validmaxact = FALSE;
1032 consdata->validglbminact = FALSE;
1033 consdata->validglbmaxact = FALSE;
1034 consdata->validmaxabsval = FALSE;
1035 consdata->validminabsval = FALSE;
1036 consdata->hasnonbinvalid = FALSE;
1037 consdata->minactivity = SCIP_INVALID;
1038 consdata->maxactivity = SCIP_INVALID;
1039 consdata->lastminactivity = SCIP_INVALID;
1040 consdata->lastmaxactivity = SCIP_INVALID;
1041 consdata->maxabsval = SCIP_INVALID;
1042 consdata->minabsval = SCIP_INVALID;
1043 consdata->maxactdelta = SCIP_INVALID;
1044 SCIPrationalSetInfinity(consdata->maxabsvalexact);
1045 SCIPrationalSetInfinity(consdata->minabsvalexact);
1046 consdata->maxactdeltavar = NULL;
1047 consdata->minactivityneginf = -1;
1048 consdata->minactivityposinf = -1;
1049 consdata->maxactivityneginf = -1;
1050 consdata->maxactivityposinf = -1;
1051 consdata->minactivityneghuge = -1;
1052 consdata->minactivityposhuge = -1;
1053 consdata->maxactivityneghuge = -1;
1054 consdata->maxactivityposhuge = -1;
1055 consdata->glbminactivity = SCIP_INVALID;
1056 consdata->glbmaxactivity = SCIP_INVALID;
1057 consdata->lastglbminactivity = SCIP_INVALID;
1058 consdata->lastglbmaxactivity = SCIP_INVALID;
1059 consdata->glbminactivityneginf = -1;
1060 consdata->glbminactivityposinf = -1;
1061 consdata->glbmaxactivityneginf = -1;
1062 consdata->glbmaxactivityposinf = -1;
1063 consdata->glbminactivityneghuge = -1;
1064 consdata->glbminactivityposhuge = -1;
1065 consdata->glbmaxactivityneghuge = -1;
1066 consdata->glbmaxactivityposhuge = -1;
1067}
1068
1069/** computes the pseudo activity of a constraint */
1070static
1072 SCIP_CONSDATA* consdata, /**< linear constraint data */
1073 SCIP_RATIONAL* pseudoactivity /**< buffer to store pseudoactivity */
1074 )
1075{
1076 int i;
1077 int pseudoactivityposinf;
1078 int pseudoactivityneginf;
1080 SCIP_RATIONAL* val;
1081
1082 SCIPrationalSetFraction(pseudoactivity, 0LL, 1LL);
1083
1084 pseudoactivityposinf = 0;
1085 pseudoactivityneginf = 0;
1086
1087 for( i = consdata->nvars - 1; i >= 0; --i )
1088 {
1089 bound = SCIPvarGetBestBoundLocalExact(consdata->vars[i]);
1090 val = consdata->vals[i];
1091 assert(!SCIPrationalIsZero(val));
1092
1094 {
1095 if( SCIPrationalIsNegative(val) )
1096 ++pseudoactivityposinf;
1097 else
1098 ++pseudoactivityneginf;
1099 }
1100 else if( SCIPrationalIsInfinity(bound) )
1101 {
1102 if( SCIPrationalIsNegative(val) )
1103 ++pseudoactivityneginf;
1104 else
1105 ++pseudoactivityposinf;
1106 }
1107 else
1108 SCIPrationalAddProd(pseudoactivity, val, bound);
1109 }
1110
1111 /* set pseudo activity to infeasible infinity for contradicting contributions */
1112 if( pseudoactivityneginf > 0 && ( pseudoactivityposinf == 0 || !SCIPrationalIsNegInfinity(consdata->lhs) ) )
1113 SCIPrationalSetNegInfinity(pseudoactivity);
1114 else if( pseudoactivityposinf > 0 && ( pseudoactivityneginf == 0 || !SCIPrationalIsInfinity(consdata->rhs) ) )
1115 SCIPrationalSetInfinity(pseudoactivity);
1116}
1117
1118/** recompute the minactivity of a constraint */
1119static
1121 SCIP* scip, /**< SCIP data structure */
1122 SCIP_CONSDATA* consdata /**< linear constraint data */
1123 )
1124{
1125 SCIP_ROUNDMODE prevmode;
1126 SCIP_Real contribution;
1127 int i;
1128
1129 consdata->minactivity = 0.0;
1130 prevmode = SCIPintervalGetRoundingMode();
1132
1133 for( i = consdata->nvars - 1; i >= 0; --i )
1134 {
1135 if( consdata->valsreal[i].sup < 0.0 )
1136 {
1137 assert(consdata->valsreal[i].inf <= 0.0);
1138
1139 contribution = SCIPvarGetUbLocal(consdata->vars[i]);
1140
1141 if( SCIPisInfinity(scip, contribution) )
1142 continue;
1143 }
1144 else
1145 {
1146 assert(consdata->valsreal[i].inf >= 0.0);
1147
1148 contribution = SCIPvarGetLbLocal(consdata->vars[i]);
1149
1150 if( SCIPisInfinity(scip, -contribution) )
1151 continue;
1152 }
1153
1154 contribution *= contribution < 0.0 ? consdata->valsreal[i].sup : consdata->valsreal[i].inf;
1155
1156 if( SCIPisHugeValue(scip, REALABS(contribution)) )
1157 continue;
1158
1159 consdata->minactivity += contribution;
1160 }
1161
1162 /* the activity was just computed from scratch and is valid now */
1163 consdata->validminact = TRUE;
1164
1165 /* the activity was just computed from scratch, mark it to be reliable */
1166 consdata->lastminactivity = consdata->minactivity;
1168}
1169
1170/** recompute the maxactivity of a constraint */
1171static
1173 SCIP* scip, /**< SCIP data structure */
1174 SCIP_CONSDATA* consdata /**< linear constraint data */
1175 )
1176{
1177 SCIP_ROUNDMODE prevmode;
1178 SCIP_Real contribution;
1179 int i;
1180
1181 consdata->maxactivity = 0.0;
1182 prevmode = SCIPintervalGetRoundingMode();
1184
1185 for( i = consdata->nvars - 1; i >= 0; --i )
1186 {
1187 if( consdata->valsreal[i].sup < 0.0 )
1188 {
1189 assert(consdata->valsreal[i].inf <= 0.0);
1190
1191 contribution = SCIPvarGetLbLocal(consdata->vars[i]);
1192
1193 if( SCIPisInfinity(scip, -contribution) )
1194 continue;
1195 }
1196 else
1197 {
1198 assert(consdata->valsreal[i].inf >= 0.0);
1199
1200 contribution = SCIPvarGetUbLocal(consdata->vars[i]);
1201
1202 if( SCIPisInfinity(scip, contribution) )
1203 continue;
1204 }
1205
1206 contribution *= contribution < 0.0 ? consdata->valsreal[i].inf : consdata->valsreal[i].sup;
1207
1208 if( SCIPisHugeValue(scip, REALABS(contribution)) )
1209 continue;
1210
1211 consdata->maxactivity += contribution;
1212 }
1213
1214 /* the activity was just computed from scratch and is valid now */
1215 consdata->validmaxact = TRUE;
1216
1217 /* the activity was just computed from scratch, mark it to be reliable */
1218 consdata->lastmaxactivity = consdata->maxactivity;
1219
1221}
1222
1223/** recompute the global minactivity of a constraint */
1224static
1226 SCIP* scip, /**< SCIP data structure */
1227 SCIP_CONSDATA* consdata /**< linear constraint data */
1228 )
1229{
1230 SCIP_ROUNDMODE prevmode;
1231 SCIP_Real contribution;
1232 int i;
1233
1234 consdata->glbminactivity = 0.0;
1235 prevmode = SCIPintervalGetRoundingMode();
1237
1238 for( i = consdata->nvars - 1; i >= 0; --i )
1239 {
1240 if( consdata->valsreal[i].sup < 0.0 )
1241 {
1242 assert(consdata->valsreal[i].inf <= 0.0);
1243
1244 contribution = SCIPvarGetUbGlobal(consdata->vars[i]);
1245
1246 if( SCIPisInfinity(scip, contribution) )
1247 continue;
1248 }
1249 else
1250 {
1251 assert(consdata->valsreal[i].inf >= 0.0);
1252
1253 contribution = SCIPvarGetLbGlobal(consdata->vars[i]);
1254
1255 if( SCIPisInfinity(scip, -contribution) )
1256 continue;
1257 }
1258
1259 contribution *= contribution < 0.0 ? consdata->valsreal[i].sup : consdata->valsreal[i].inf;
1260
1261 if( SCIPisHugeValue(scip, REALABS(contribution)) )
1262 continue;
1263
1264 consdata->glbminactivity += contribution;
1265 }
1266
1267 /* the activity was just computed from scratch and is valid now */
1268 consdata->validglbminact = TRUE;
1269
1270 /* the activity was just computed from scratch, mark it to be reliable */
1271 consdata->lastglbminactivity = consdata->glbminactivity;
1272
1274}
1275
1276/** recompute the global maxactivity of a constraint */
1277static
1279 SCIP* scip, /**< SCIP data structure */
1280 SCIP_CONSDATA* consdata /**< linear constraint data */
1281 )
1282{
1283 SCIP_ROUNDMODE prevmode;
1284 SCIP_Real contribution;
1285 int i;
1286
1287 consdata->glbmaxactivity = 0.0;
1288 prevmode = SCIPintervalGetRoundingMode();
1290
1291 for( i = consdata->nvars - 1; i >= 0; --i )
1292 {
1293 if( consdata->valsreal[i].sup < 0.0 )
1294 {
1295 assert(consdata->valsreal[i].inf <= 0.0);
1296
1297 contribution = SCIPvarGetLbGlobal(consdata->vars[i]);
1298
1299 if( SCIPisInfinity(scip, -contribution) )
1300 continue;
1301 }
1302 else
1303 {
1304 assert(consdata->valsreal[i].inf >= 0.0);
1305
1306 contribution = SCIPvarGetUbGlobal(consdata->vars[i]);
1307
1308 if( SCIPisInfinity(scip, contribution) )
1309 continue;
1310 }
1311
1312 contribution *= contribution < 0.0 ? consdata->valsreal[i].inf : consdata->valsreal[i].sup;
1313
1314 if( SCIPisHugeValue(scip, REALABS(contribution)) )
1315 continue;
1316
1317 consdata->glbmaxactivity += contribution;
1318 }
1319
1320 /* the activity was just computed from scratch and is valid now */
1321 consdata->validglbmaxact = TRUE;
1322
1323 /* the activity was just computed from scratch, mark it to be reliable */
1324 consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1326}
1327
1328/** calculates minimum absolute value of coefficients */
1329static
1331 SCIP_CONSDATA* consdata /**< linear constraint data */
1332 )
1333{
1334 int i;
1335 assert(consdata != NULL);
1336 assert(!consdata->validminabsval);
1337
1338 consdata->validminabsval = TRUE;
1339
1340 if( consdata->nvars > 0 )
1341 {
1342 SCIPrationalAbs(consdata->minabsvalexact, consdata->vals[0]);
1343 assert(!SCIPrationalIsZero(consdata->vals[0]));
1344 }
1345 else
1346 SCIPrationalSetReal(consdata->minabsvalexact, 0.0);
1347
1348 for( i = 1; i < consdata->nvars; ++i )
1349 {
1350 assert(!SCIPrationalIsZero(consdata->vals[i]));
1351
1352 if( SCIPrationalIsAbsGT(consdata->minabsvalexact, consdata->vals[i]) )
1353 SCIPrationalAbs(consdata->minabsvalexact, consdata->vals[i]);
1354 }
1355}
1356
1357/** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1358static
1360 SCIP_CONSDATA* consdata /**< linear constraint data */
1361 )
1362{
1363 int v;
1364
1365 assert(!consdata->hasnonbinvalid);
1366 consdata->hasnonbinvar = FALSE;
1367 consdata->hascontvar = FALSE;
1368
1369 for( v = consdata->nvars - 1; v >= 0; --v )
1370 {
1371 SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1372
1373 if( vartype != SCIP_VARTYPE_BINARY )
1374 {
1375 consdata->hasnonbinvar = TRUE;
1376
1377 if( vartype == SCIP_VARTYPE_CONTINUOUS )
1378 {
1379 consdata->hascontvar = TRUE;
1380 break;
1381 }
1382 }
1383 }
1384 assert(consdata->hascontvar || v < 0);
1385
1386 consdata->hasnonbinvalid = TRUE;
1387}
1388
1389#ifdef SCIP_MORE_DEBUG
1390/* checks that the stored maximal activity delta (if not invalid) is correct */
1391static
1393 SCIP* scip, /**< SCIP data structure */
1394 SCIP_CONSDATA* consdata /**< linear constraint data */
1395 )
1396{
1397 if( consdata->maxactdelta != SCIP_INVALID )
1398 {
1399 SCIP_Rational* maxactdelta;
1400 SCIP_Rational* domain;
1401 SCIP_Rational* delta;
1402 SCIP_RATIONAL* lb;
1403 SCIP_RATIONAL* ub;
1404 int v;
1405
1409
1410 for( v = consdata->nvars - 1; v >= 0; --v )
1411 {
1412 lb = SCIPvarGetLbLocalExact(consdata->vars[v]);
1413 ub = SCIPvarGetUbLocalExact(consdata->vars[v]);
1414
1416 {
1417 SCIPrationalSetInfinity(maxactdelta);
1418 break;
1419 }
1420
1421 SCIPrationalDiff(domain, ub, lb);
1422 SCIPrationalAbs(delta, consdata->vals[v]);
1423 SCIPrationalMult(delta, delta, domain);
1424
1425 if( SCIPrationalisGT(delta,maxactdelta) )
1426 {
1427 SCIPrationalSetRational(maxactdelta, delta);
1428 }
1429 }
1430 assert(SCIPrationalIsEQ(maxactdelta, consdata->maxactdelta));
1431
1434 SCIPrationalFreeBuffer(SCIPbuffer(scip), maxactdelta);
1435 }
1436}
1437#else
1438#define checkMaxActivityDelta(scip, consdata) /**/
1439#endif
1440
1441/** recompute maximal activity contribution for a single variable */
1442static
1444 SCIP* scip, /**< SCIP data structure */
1445 SCIP_CONSDATA* consdata /**< linear constraint data */
1446 )
1447{
1448 SCIP_Real delta;
1449 int v;
1450 consdata->maxactdelta = 0.0;
1451
1452 if( !consdata->hasnonbinvalid )
1453 consdataCheckNonbinvar(consdata);
1454
1455 /* easy case, the problem consists only of binary variables */
1456 if( !consdata->hasnonbinvar )
1457 {
1458 for( v = consdata->nvars - 1; v >= 0; --v )
1459 {
1460 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1461 {
1462 delta = SCIPintervalAbsMax(consdata->valsreal[v]);
1463
1464 if( delta > consdata->maxactdelta )
1465 {
1466 consdata->maxactdelta = delta;
1467 consdata->maxactdeltavar = consdata->vars[v];
1468 }
1469 }
1470 }
1471 return;
1472 }
1473
1474 for( v = consdata->nvars - 1; v >= 0; --v )
1475 {
1476 SCIP_Real domain;
1477 SCIP_Real lb;
1478 SCIP_Real ub;
1479
1480 lb = SCIPvarGetLbLocal(consdata->vars[v]);
1481 ub = SCIPvarGetUbLocal(consdata->vars[v]);
1482
1483 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1484 {
1485 consdata->maxactdelta = SCIPinfinity(scip);
1486 consdata->maxactdeltavar = consdata->vars[v];
1487 break;
1488 }
1489
1490 domain = ub - lb;
1491 delta = SCIPintervalAbsMax(consdata->valsreal[v]) * domain;
1492
1493 if( delta > consdata->maxactdelta )
1494 {
1495 consdata->maxactdelta = delta;
1496 consdata->maxactdeltavar = consdata->vars[v];
1497 }
1498 }
1499}
1500
1501/** updates activities for a change in a bound */
1502static
1504 SCIP* scip, /**< SCIP data structure */
1505 SCIP_CONSDATA* consdata, /**< linear constraint data */
1506 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1507 SCIP_Real oldbound, /**< old bound of variable */
1508 SCIP_Real newbound, /**< new bound of variable */
1509 SCIP_INTERVAL valrange, /**< coefficient of constraint entry */
1510 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1511 SCIP_Bool global /**< is it a global or a local bound change? */
1512 )
1513{
1514 SCIP_Real* activity;
1515 SCIP_Real* lastactivity;
1516 int* activityposinf;
1517 int* activityneginf;
1518 int* activityposhuge;
1519 int* activityneghuge;
1520 SCIP_Real oldcontribution;
1521 SCIP_Real newcontribution;
1522 SCIP_Real delta;
1523 SCIP_Bool validact;
1524 SCIP_Bool finitenewbound;
1525 SCIP_Bool hugevalnewcont;
1526 SCIP_Real oldval;
1527 SCIP_Real newval;
1528 SCIP_ROUNDMODE prevmode;
1529
1530 prevmode = SCIPintervalGetRoundingMode();
1531
1532 assert(scip != NULL);
1533 assert(consdata != NULL);
1534 assert(global || (var != NULL));
1535 assert(consdata->validactivities);
1536 assert(consdata->minactivity < SCIP_INVALID);
1537 assert(consdata->maxactivity < SCIP_INVALID);
1538 assert(consdata->lastminactivity < SCIP_INVALID);
1539 assert(consdata->lastmaxactivity < SCIP_INVALID);
1540 assert(consdata->minactivityneginf >= 0);
1541 assert(consdata->minactivityposinf >= 0);
1542 assert(consdata->maxactivityneginf >= 0);
1543 assert(consdata->maxactivityposinf >= 0);
1544 assert(consdata->minactivityneghuge >= 0);
1545 assert(consdata->minactivityposhuge >= 0);
1546 assert(consdata->maxactivityneghuge >= 0);
1547 assert(consdata->maxactivityposhuge >= 0);
1548 assert(consdata->glbminactivity < SCIP_INVALID);
1549 assert(consdata->glbmaxactivity < SCIP_INVALID);
1550 assert(consdata->lastglbminactivity < SCIP_INVALID);
1551 assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1552 assert(consdata->glbminactivityneginf >= 0);
1553 assert(consdata->glbminactivityposinf >= 0);
1554 assert(consdata->glbmaxactivityneginf >= 0);
1555 assert(consdata->glbmaxactivityposinf >= 0);
1556 assert(consdata->glbminactivityneghuge >= 0);
1557 assert(consdata->glbminactivityposhuge >= 0);
1558 assert(consdata->glbmaxactivityneghuge >= 0);
1559 assert(consdata->glbmaxactivityposhuge >= 0);
1560
1561 delta = 0.0;
1562
1563 /* we are updating global activities */
1564 if( global )
1565 {
1566 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1567 * lower bound + pos. coef: update minactivity
1568 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1569 * upper bound + pos. coef: update maxactivity
1570 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1571 */
1572 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1573 {
1574 if( valrange.sup < 0.0 )
1575 {
1576 assert(valrange.inf <= 0.0);
1577
1578 activity = &(consdata->glbmaxactivity);
1579 lastactivity = &(consdata->lastglbmaxactivity);
1580 activityposinf = &(consdata->glbmaxactivityneginf);
1581 activityneginf = &(consdata->glbmaxactivityposinf);
1582 activityposhuge = &(consdata->glbmaxactivityposhuge);
1583 activityneghuge = &(consdata->glbmaxactivityneghuge);
1584 validact = consdata->validglbmaxact;
1586 oldval = oldbound < 0.0 ? valrange.inf : valrange.sup;
1587 newval = newbound < 0.0 ? valrange.inf : valrange.sup;
1588 }
1589 else
1590 {
1591 assert(valrange.inf >= 0.0);
1592
1593 activity = &(consdata->glbminactivity);
1594 lastactivity = &(consdata->lastglbminactivity);
1595 activityposinf = &(consdata->glbminactivityposinf);
1596 activityneginf = &(consdata->glbminactivityneginf);
1597 activityposhuge = &(consdata->glbminactivityposhuge);
1598 activityneghuge = &(consdata->glbminactivityneghuge);
1599 validact = consdata->validglbminact;
1601 oldval = oldbound < 0.0 ? valrange.sup : valrange.inf;
1602 newval = newbound < 0.0 ? valrange.sup : valrange.inf;
1603 }
1604 }
1605 else
1606 {
1607 if( valrange.sup < 0.0 )
1608 {
1609 assert(valrange.inf <= 0.0);
1610
1611 activity = &(consdata->glbminactivity);
1612 lastactivity = &(consdata->lastglbminactivity);
1613 activityposinf = &(consdata->glbminactivityneginf);
1614 activityneginf = &(consdata->glbminactivityposinf);
1615 activityposhuge = &(consdata->glbminactivityposhuge);
1616 activityneghuge = &(consdata->glbminactivityneghuge);
1617 validact = consdata->validglbminact;
1619 oldval = oldbound < 0.0 ? valrange.sup : valrange.inf;
1620 newval = newbound < 0.0 ? valrange.sup : valrange.inf;
1621 }
1622 else
1623 {
1624 assert(valrange.inf >= 0.0);
1625
1626 activity = &(consdata->glbmaxactivity);
1627 lastactivity = &(consdata->lastglbmaxactivity);
1628 activityposinf = &(consdata->glbmaxactivityposinf);
1629 activityneginf = &(consdata->glbmaxactivityneginf);
1630 activityposhuge = &(consdata->glbmaxactivityposhuge);
1631 activityneghuge = &(consdata->glbmaxactivityneghuge);
1632 validact = consdata->validglbmaxact;
1634 oldval = oldbound < 0.0 ? valrange.inf : valrange.sup;
1635 newval = newbound < 0.0 ? valrange.inf : valrange.sup;
1636 }
1637 }
1638 }
1639 /* we are updating local activities */
1640 else
1641 {
1642 /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1643 * lower bound + pos. coef: update minactivity
1644 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1645 * upper bound + pos. coef: update maxactivity
1646 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1647 */
1648 if( boundtype == SCIP_BOUNDTYPE_LOWER )
1649 {
1650 if( valrange.sup < 0.0 )
1651 {
1652 assert(valrange.inf <= 0.0);
1653
1654 activity = &(consdata->maxactivity);
1655 lastactivity = &(consdata->lastmaxactivity);
1656 activityposinf = &(consdata->maxactivityneginf);
1657 activityneginf = &(consdata->maxactivityposinf);
1658 activityposhuge = &(consdata->maxactivityposhuge);
1659 activityneghuge = &(consdata->maxactivityneghuge);
1660 validact = consdata->validmaxact;
1662 oldval = oldbound < 0.0 ? valrange.inf : valrange.sup;
1663 newval = newbound < 0.0 ? valrange.inf : valrange.sup;
1664 }
1665 else
1666 {
1667 assert(valrange.inf >= 0.0);
1668
1669 activity = &(consdata->minactivity);
1670 lastactivity = &(consdata->lastminactivity);
1671 activityposinf = &(consdata->minactivityposinf);
1672 activityneginf = &(consdata->minactivityneginf);
1673 activityposhuge = &(consdata->minactivityposhuge);
1674 activityneghuge = &(consdata->minactivityneghuge);
1675 validact = consdata->validminact;
1677 oldval = oldbound < 0.0 ? valrange.sup : valrange.inf;
1678 newval = newbound < 0.0 ? valrange.sup : valrange.inf;
1679 }
1680 }
1681 else
1682 {
1683 if( valrange.sup < 0.0 )
1684 {
1685 assert(valrange.inf <= 0.0);
1686
1687 activity = &(consdata->minactivity);
1688 lastactivity = &(consdata->lastminactivity);
1689 activityposinf = &(consdata->minactivityneginf);
1690 activityneginf = &(consdata->minactivityposinf);
1691 activityposhuge = &(consdata->minactivityposhuge);
1692 activityneghuge = &(consdata->minactivityneghuge);
1693 validact = consdata->validminact;
1695 oldval = oldbound < 0.0 ? valrange.sup : valrange.inf;
1696 newval = newbound < 0.0 ? valrange.sup : valrange.inf;
1697 }
1698 else
1699 {
1700 assert(valrange.inf >= 0.0);
1701
1702 activity = &(consdata->maxactivity);
1703 lastactivity = &(consdata->lastmaxactivity);
1704 activityposinf = &(consdata->maxactivityposinf);
1705 activityneginf = &(consdata->maxactivityneginf);
1706 activityposhuge = &(consdata->maxactivityposhuge);
1707 activityneghuge = &(consdata->maxactivityneghuge);
1708 validact = consdata->validmaxact;
1710 oldval = oldbound < 0.0 ? valrange.inf : valrange.sup;
1711 newval = newbound < 0.0 ? valrange.inf : valrange.sup;
1712 }
1713 }
1714 }
1715
1716 oldcontribution = SCIPintervalNegateReal(oldval) * oldbound;
1717 newcontribution = newval * newbound;
1718 hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1719 finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1720
1721 if( SCIPisInfinity(scip, REALABS(oldbound)) )
1722 {
1723 /* old bound was +infinity */
1724 if( oldbound > 0.0 )
1725 {
1726 assert((*activityposinf) >= 1);
1727
1728 /* we only have to do something if the new bound is not again +infinity */
1729 if( finitenewbound || newbound < 0.0 )
1730 {
1731 /* decrease the counter for positive infinite contributions */
1732 (*activityposinf)--;
1733
1734 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1735 if( !finitenewbound && newbound < 0.0 )
1736 (*activityneginf)++;
1737 else if( hugevalnewcont )
1738 {
1739 /* if the contribution of this variable is too large, increase the counter for huge values */
1740 if( newcontribution > 0.0 )
1741 (*activityposhuge)++;
1742 else
1743 (*activityneghuge)++;
1744 }
1745 /* "normal case": just add the contribution to the activity */
1746 else
1747 delta = newcontribution;
1748 }
1749 }
1750 /* old bound was -infinity */
1751 else
1752 {
1753 assert(oldbound < 0.0);
1754 assert((*activityneginf) >= 1);
1755
1756 /* we only have to do something ig the new bound is not again -infinity */
1757 if( finitenewbound || newbound > 0.0 )
1758 {
1759 /* decrease the counter for negative infinite contributions */
1760 (*activityneginf)--;
1761
1762 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1763 if( !finitenewbound && newbound > 0.0 )
1764 (*activityposinf)++;
1765 else if( hugevalnewcont )
1766 {
1767 /* if the contribution of this variable is too large, increase the counter for huge values */
1768 if( newcontribution > 0.0 )
1769 (*activityposhuge)++;
1770 else
1771 (*activityneghuge)++;
1772 }
1773 /* "normal case": just add the contribution to the activity */
1774 else
1775 delta = newcontribution;
1776 }
1777 }
1778 }
1779 else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1780 {
1781 /* old contribution was too large and positive */
1782 if( -oldcontribution > 0.0 )
1783 {
1784 assert((*activityposhuge) >= 1);
1785
1786 /* decrease the counter for huge positive contributions; it might be increased again later,
1787 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1788 */
1789 (*activityposhuge)--;
1790
1791 if( !finitenewbound )
1792 {
1793 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1794 if( newbound > 0.0 )
1795 (*activityposinf)++;
1796 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1797 else
1798 (*activityneginf)++;
1799 }
1800 else if( hugevalnewcont )
1801 {
1802 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1803 if( newcontribution > 0.0 )
1804 (*activityposhuge)++;
1805 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1806 else
1807 (*activityneghuge)++;
1808 }
1809 /* "normal case": just add the contribution to the activity */
1810 else
1811 delta = newcontribution;
1812 }
1813 /* old contribution was too large and negative */
1814 else
1815 {
1816 assert(-oldcontribution < 0.0);
1817 assert((*activityneghuge) >= 1);
1818
1819 /* decrease the counter for huge negative contributions; it might be increased again later,
1820 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1821 */
1822 (*activityneghuge)--;
1823
1824 if( !finitenewbound )
1825 {
1826 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1827 if( newbound > 0.0 )
1828 (*activityposinf)++;
1829 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1830 else
1831 (*activityneginf)++;
1832 }
1833 else if( hugevalnewcont )
1834 {
1835 /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1836 if( newcontribution > 0.0 )
1837 (*activityposhuge)++;
1838 /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1839 else
1840 (*activityneghuge)++;
1841 }
1842 /* "normal case": just add the contribution to the activity */
1843 else
1844 delta = newcontribution;
1845 }
1846 }
1847 /* old bound was finite and not too large */
1848 else
1849 {
1850 if( !finitenewbound )
1851 {
1852 /* if the new bound is +infinity, the old contribution has to be subtracted
1853 * and the counter for positive infinite contributions has to be increased
1854 */
1855 if( newbound > 0.0 )
1856 {
1857 (*activityposinf)++;
1858 delta = oldcontribution;
1859 }
1860 /* if the new bound is -infinity, the old contribution has to be subtracted
1861 * and the counter for negative infinite contributions has to be increased
1862 */
1863 else
1864 {
1865 assert(newbound < 0.0 );
1866
1867 (*activityneginf)++;
1868 delta = oldcontribution;
1869 }
1870 }
1871 /* if the contribution of this variable is too large, increase the counter for huge values */
1872 else if( hugevalnewcont )
1873 {
1874 if( newcontribution > 0.0 )
1875 {
1876 (*activityposhuge)++;
1877 delta = oldcontribution;
1878 }
1879 else
1880 {
1881 (*activityneghuge)++;
1882 delta = oldcontribution;
1883 }
1884 }
1885 /* "normal case": just update the activity */
1886 else
1887 delta = newcontribution + oldcontribution;
1888 }
1889
1890 /* update the activity, if the current value is valid and there was a change in the finite part */
1891 if( validact && (delta != 0.0) )
1892 {
1893 /* if the absolute value of the activity is increased, this is regarded as reliable,
1894 * otherwise, we check whether we can still trust the updated value
1895 */
1896 (*activity) = (*activity) + delta;
1897 assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1898
1899 if( REALABS((*lastactivity)) < REALABS(*activity) )
1900 {
1901 (*lastactivity) = (*activity);
1902 }
1903 }
1904
1906}
1907/** updates minimum and maximum activity for a change in lower bound */
1908static
1910 SCIP* scip, /**< SCIP data structure */
1911 SCIP_CONSDATA* consdata, /**< linear constraint data */
1912 SCIP_VAR* var, /**< variable that has been changed */
1913 SCIP_Real oldlb, /**< old lower bound of variable */
1914 SCIP_Real newlb, /**< new lower bound of variable */
1915 SCIP_INTERVAL val /**< coefficient of constraint entry */
1916 )
1917{
1918 assert(scip != NULL);
1919 assert(consdata != NULL);
1920 assert(var != NULL);
1921
1922 if( consdata->validactivities )
1923 {
1924 consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE);
1925
1926 assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1927 assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1928 }
1929}
1930
1931/** updates minimum and maximum activity for a change in upper bound */
1932static
1934 SCIP* scip, /**< SCIP data structure */
1935 SCIP_CONSDATA* consdata, /**< linear constraint data */
1936 SCIP_VAR* var, /**< variable that has been changed */
1937 SCIP_Real oldub, /**< old upper bound of variable */
1938 SCIP_Real newub, /**< new upper bound of variable */
1939 SCIP_INTERVAL val /**< coefficient of constraint entry */
1940 )
1941{
1942 assert(scip != NULL);
1943 assert(consdata != NULL);
1944 assert(var != NULL);
1945
1946 if( consdata->validactivities )
1947 {
1948 consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE);
1949
1950 assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1951 assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1952 }
1953}
1954
1955/** updates minimum and maximum global activity for a change in the global lower bound */
1956static
1958 SCIP* scip, /**< SCIP data structure */
1959 SCIP_CONSDATA* consdata, /**< linear constraint data */
1960 SCIP_Real oldlb, /**< old lower bound of variable */
1961 SCIP_Real newlb, /**< new lower bound of variable */
1962 SCIP_INTERVAL val /**< coefficient of constraint entry */
1963 )
1964{
1965 assert(scip != NULL);
1966 assert(consdata != NULL);
1967
1968 if( consdata->validactivities )
1969 {
1970 consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE);
1971
1972 assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1973 assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1974 }
1975}
1976
1977/** updates minimum and maximum global activity for a change in global upper bound */
1978static
1980 SCIP* scip, /**< SCIP data structure */
1981 SCIP_CONSDATA* consdata, /**< linear constraint data */
1982 SCIP_Real oldub, /**< old upper bound of variable */
1983 SCIP_Real newub, /**< new upper bound of variable */
1984 SCIP_INTERVAL val /**< coefficient of constraint entry */
1985 )
1986{
1987 assert(scip != NULL);
1988 assert(consdata != NULL);
1989
1990 if( consdata->validactivities )
1991 {
1992 consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE);
1993
1994 assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1995 assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1996 }
1997}
1998
1999/** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2000static
2002 SCIP* scip, /**< SCIP data structure */
2003 SCIP_CONSDATA* consdata, /**< linear constraint data */
2004 SCIP_VAR* var, /**< variable of constraint entry */
2005 SCIP_RATIONAL* valExact, /**< coefficient of constraint entry */
2006 SCIP_INTERVAL val /**< coefficient of constraint entry */
2007 )
2008{
2009 assert(scip != NULL);
2010 assert(consdata != NULL);
2011 assert(var != NULL);
2012
2013 /* update maximum absolute value */
2014 if( consdata->validmaxabsval )
2015 {
2016 SCIP_Real absval;
2017
2018 assert(consdata->maxabsval < SCIP_INVALID);
2019
2020 absval = MAX(REALABS(val.inf), REALABS(val.sup)); /*lint !e777 !e666*/
2021 consdata->maxabsval = MAX(consdata->maxabsval, absval);
2022 }
2023
2024 if( consdata->validminabsval )
2025 {
2026 SCIP_Real absval;
2027
2028 assert(consdata->minabsval < SCIP_INVALID);
2029
2030 absval = MAX(REALABS(val.inf), REALABS(val.sup)); /*lint !e777 !e666*/
2031 consdata->minabsval = MIN(consdata->minabsval, absval);
2032 }
2033
2034 /* invalidate maximum absolute value, if this coefficient was the maximum */
2035 if( consdata->validmaxabsval )
2036 {
2037 if( SCIPrationalIsAbsEQ(valExact, consdata->maxabsvalexact) )
2038 {
2039 consdata->validmaxabsval = FALSE;
2040 SCIPrationalSetInfinity(consdata->maxabsvalexact);
2041 }
2042 }
2043
2044 /* invalidate minimum absolute value, if this coefficient was the minimum */
2045 if( consdata->validminabsval )
2046 {
2047 if( SCIPrationalIsAbsEQ(valExact, consdata->minabsvalexact) )
2048 {
2049 consdata->validminabsval = FALSE;
2050 SCIPrationalSetInfinity(consdata->minabsvalexact);
2051 }
2052 }
2053
2054 /* update minimal and maximal activity */
2055 if( consdata->validactivities )
2056 {
2057 assert(consdata->minactivity < SCIP_INVALID);
2058 assert(consdata->maxactivity < SCIP_INVALID);
2059 assert(consdata->glbminactivity < SCIP_INVALID);
2060 assert(consdata->glbmaxactivity < SCIP_INVALID);
2061
2062 consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val);
2063 consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val);
2064 consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val);
2065 consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val);
2066 }
2067}
2068
2069/** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2070static
2072 SCIP* scip, /**< SCIP data structure */
2073 SCIP_CONSDATA* consdata, /**< linear constraint data */
2074 SCIP_VAR* var, /**< variable of constraint entry */
2075 SCIP_RATIONAL* valExact, /**< exact coefficient of constraint entry */
2076 SCIP_INTERVAL val /**< coefficient of constraint entry */
2077 )
2078{
2079 assert(scip != NULL);
2080 assert(consdata != NULL);
2081 assert(var != NULL);
2082
2083 /* invalidate maximum absolute value, if this coefficient was the maximum */
2084 if( consdata->validmaxabsval )
2085 {
2086 SCIP_Real absval;
2087
2088 absval = SCIPintervalAbsMax(val);
2089
2090 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2091 {
2092 consdata->validmaxabsval = FALSE;
2093 consdata->maxabsval = SCIP_INVALID;
2094 }
2095 }
2096
2097 /* invalidate minimum absolute value, if this coefficient was the minimum */
2098 if( consdata->validminabsval )
2099 {
2100 SCIP_Real absval;
2101
2102 absval = SCIPintervalAbsMax(val);
2103
2104 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2105 {
2106 consdata->validminabsval = FALSE;
2107 consdata->minabsval = SCIP_INVALID;
2108 }
2109 }
2110
2111 /* invalidate maximum absolute value, if this coefficient was the maximum */
2112 if( consdata->validmaxabsval )
2113 {
2114 if( SCIPrationalIsAbsEQ(valExact, consdata->maxabsvalexact) )
2115 {
2116 consdata->validmaxabsval = FALSE;
2117 SCIPrationalSetInfinity(consdata->maxabsvalexact);
2118 }
2119 }
2120
2121 /* invalidate minimum absolute value, if this coefficient was the minimum */
2122 if( consdata->validminabsval )
2123 {
2124 if( SCIPrationalIsAbsEQ(valExact, consdata->minabsvalexact) )
2125 {
2126 consdata->validminabsval = FALSE;
2127 SCIPrationalSetInfinity(consdata->minabsvalexact);
2128 }
2129 }
2130
2131 /* update minimal and maximal activity */
2132 if( consdata->validactivities )
2133 {
2134 assert(consdata->minactivity < SCIP_INVALID);
2135 assert(consdata->maxactivity < SCIP_INVALID);
2136 assert(consdata->glbminactivity < SCIP_INVALID);
2137 assert(consdata->glbmaxactivity < SCIP_INVALID);
2138
2139 consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val);
2140 consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val);
2141 consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val);
2142 consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val);
2143 }
2144}
2145
2146/** returns the minimum absolute value of all coefficients in the constraint */
2147static
2149 SCIP* scip, /**< SCIP data structure */
2150 SCIP_CONSDATA* consdata /**< linear constraint data */
2151 )
2152{
2153 assert(scip != NULL);
2154 assert(consdata != NULL);
2155
2156 if( !consdata->validminabsval )
2157 consdataCalcMinAbsvalEx(consdata);
2158 assert(consdata->validminabsval);
2159
2160 return consdata->minabsvalexact;
2161}
2162
2163
2164/** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2165static
2167 SCIP* scip, /**< SCIP data structure */
2168 SCIP_CONSDATA* consdata, /**< linear constraint data */
2169 SCIP_VAR* var, /**< variable of constraint entry */
2170 SCIP_INTERVAL oldval, /**< old coefficient of constraint entry */
2171 SCIP_RATIONAL* oldvalExact, /**< old exact coefficient of constraint entry */
2172 SCIP_INTERVAL newval, /**< new coefficient of constraint entry */
2173 SCIP_RATIONAL* newvalExact /**< new coefficient of constraint entry */
2174 )
2175{
2176 assert(scip != NULL);
2177 assert(consdata != NULL);
2178 assert(var != NULL);
2179
2180 /* update maximum absolute value */
2181 if( consdata->validmaxabsval )
2182 {
2183 SCIP_Real absval;
2184
2185 absval = SCIPintervalAbsMax(newval);
2186
2187 if( absval >= consdata->maxabsval )
2188 {
2189 consdata->maxabsval = absval;
2190 }
2191 else
2192 {
2193 absval = SCIPintervalAbsMax(oldval);
2194
2195 /* invalidate maximum absolute value */
2196 if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2197 {
2198 consdata->validmaxabsval = FALSE;
2199 consdata->maxabsval = SCIP_INVALID;
2200 }
2201 }
2202 }
2203
2204 /* update minimum absolute value */
2205 if( consdata->validminabsval )
2206 {
2207 SCIP_Real absval;
2208
2209 absval = SCIPintervalAbsMax(newval);
2210
2211 if( absval <= consdata->minabsval )
2212 {
2213 consdata->minabsval = absval;
2214 }
2215 else
2216 {
2217 absval = SCIPintervalAbsMax(oldval);
2218
2219 /* invalidate minimum absolute value */
2220 if( SCIPisEQ(scip, absval, consdata->minabsval) )
2221 {
2222 consdata->validminabsval = FALSE;
2223 consdata->minabsval = SCIP_INVALID;
2224 }
2225 }
2226 }
2227 /* update maximum absolute value */
2228 if( consdata->validmaxabsval )
2229 {
2230 if( SCIPrationalIsAbsGT(newvalExact, consdata->maxabsvalexact) )
2231 {
2232 SCIPrationalAbs(consdata->maxabsvalexact, newvalExact);
2233 }
2234 else
2235 {
2236 /* invalidate maximum absolute value */
2237 if( SCIPrationalIsAbsEQ(oldvalExact, consdata->maxabsvalexact) )
2238 {
2239 consdata->validmaxabsval = FALSE;
2240 SCIPrationalSetInfinity(consdata->maxabsvalexact);
2241 }
2242 }
2243 }
2244 /* update minimum absolute value */
2245 if( consdata->validminabsval )
2246 {
2247 if( SCIPrationalIsAbsGT(consdata->minabsvalexact, newvalExact) )
2248 {
2249 SCIPrationalAbs(consdata->minabsvalexact, newvalExact);
2250 }
2251 else
2252 {
2253 /* invalidate minimum absolute value */
2254 if( SCIPrationalIsAbsEQ(oldvalExact, consdata->minabsvalexact) )
2255 {
2256 consdata->validminabsval = FALSE;
2257 SCIPrationalSetInfinity(consdata->minabsvalexact);
2258 }
2259 }
2260 }
2261
2262 /* update maximum activity delta */
2263 if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2264 {
2265 SCIP_Real domain;
2266 SCIP_Real delta;
2267
2268 assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2269 assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2270
2271 domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2272 delta = SCIPintervalAbsMax(newval) * domain;
2273
2274 if( delta > consdata->maxactdelta )
2275 {
2276 consdata->maxactdelta = delta;
2277 consdata->maxactdeltavar = var;
2278 }
2279 else
2280 {
2281 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2282 if( consdata->maxactdeltavar == var )
2283 consdata->maxactdelta = SCIP_INVALID;
2284 }
2285 }
2286
2287 /* @todo as in cons_linear, do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2288 consdataUpdateDelCoef(scip, consdata, var, oldvalExact, oldval);
2289 consdataUpdateAddCoef(scip, consdata, var, newvalExact, newval);
2290}
2291
2292/** ensures that every nonzero is a least minval so that we don't get problem with SCIPs 0 in floating point representation */
2293static
2295 SCIP* scip, /**< SCIP data structure */
2296 SCIP_CONSDATA* consdata, /**< linear constraint data */
2297 SCIP_Real minval /**< minmimal value for coefficients in constraint */
2298 )
2299{
2300 int i;
2301 SCIP_RATIONAL* scalingfactor;
2302 SCIP_RATIONAL* minabsval;
2303
2304 assert(scip != NULL);
2305 assert(consdata != NULL);
2306
2307 minabsval = consdataGetMinAbsvalEx(scip, consdata);
2308
2309 assert(!SCIPrationalIsZero(minabsval) || consdata->nvars == 0);
2310
2311 (void) SCIPrationalCreateBuffer(SCIPbuffer(scip), &scalingfactor);
2312
2313 if( SCIPrationalIsLTReal(minabsval, minval) )
2314 {
2315 SCIPrationalSetReal(scalingfactor, minval);
2316 SCIPrationalDiv(scalingfactor, scalingfactor, minabsval);
2317
2318 for( i = 0; i < consdata->nvars; i++ )
2319 {
2320 SCIPrationalMult(consdata->vals[i], consdata->vals[i], scalingfactor);
2321 SCIPintervalSetRational(&(consdata->valsreal[i]), consdata->vals[i]);
2322 }
2323
2324 SCIPrationalMult(consdata->rhs, consdata->rhs, scalingfactor);
2325 consdata->rhsreal = SCIPrationalRoundReal(consdata->rhs, SCIP_R_ROUND_UPWARDS);
2326
2327 SCIPrationalMult(consdata->lhs, consdata->lhs, scalingfactor);
2328 consdata->lhsreal = SCIPrationalRoundReal(consdata->lhs, SCIP_R_ROUND_DOWNWARDS);
2329 }
2330
2332
2333 SCIPrationalFreeBuffer(SCIPbuffer(scip), &scalingfactor);
2334}
2335
2336/** calculates minimum and maximum local and global activity for constraint from scratch;
2337 * additionally recalculates maximum absolute value of coefficients
2338 */
2339static
2341 SCIP* scip, /**< SCIP data structure */
2342 SCIP_CONSDATA* consdata /**< linear constraint data */
2343 )
2344{
2345 int i;
2346 assert(scip != NULL);
2347 assert(consdata != NULL);
2348 assert(!consdata->validactivities);
2349 assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2350 assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2351 assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2352 assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2353
2354 consdata->validmaxabsval = TRUE;
2355 consdata->validminabsval = TRUE;
2356 consdata->validactivities = TRUE;
2357 consdata->validminact = TRUE;
2358 consdata->validmaxact = TRUE;
2359 consdata->validglbminact = TRUE;
2360 consdata->validglbmaxact = TRUE;
2361 consdata->maxabsval = 0.0;
2362 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : SCIPintervalAbsMax(consdata->valsreal[0]));
2363 consdata->minactivity = 0.0;
2364 consdata->maxactivity = 0.0;
2365 consdata->lastminactivity = 0.0;
2366 consdata->lastmaxactivity = 0.0;
2367 consdata->minactivityneginf = 0;
2368 consdata->minactivityposinf = 0;
2369 consdata->maxactivityneginf = 0;
2370 consdata->maxactivityposinf = 0;
2371 consdata->minactivityneghuge = 0;
2372 consdata->minactivityposhuge = 0;
2373 consdata->maxactivityneghuge = 0;
2374 consdata->maxactivityposhuge = 0;
2375 consdata->glbminactivity = 0.0;
2376 consdata->glbmaxactivity = 0.0;
2377 consdata->lastglbminactivity = 0.0;
2378 consdata->lastglbmaxactivity = 0.0;
2379 consdata->glbminactivityneginf = 0;
2380 consdata->glbminactivityposinf = 0;
2381 consdata->glbmaxactivityneginf = 0;
2382 consdata->glbmaxactivityposinf = 0;
2383 consdata->glbminactivityneghuge = 0;
2384 consdata->glbminactivityposhuge = 0;
2385 consdata->glbmaxactivityneghuge = 0;
2386 consdata->glbmaxactivityposhuge = 0;
2387
2388 for( i = 0; i < consdata->nvars; ++i )
2389 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], consdata->valsreal[i]);
2390 consdata->lastminactivity = consdata->minactivity;
2391 consdata->lastmaxactivity = consdata->maxactivity;
2392 consdata->lastglbminactivity = consdata->glbminactivity;
2393 consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2394}
2395
2396/** computes the activity of a row for a given solution plus a bound on the floating-point error using running error analysis */
2397static
2399 SCIP* scip, /**< SCIP data structure */
2400 SCIP_CONSDATA* consdata, /**< linear constraint data */
2401 SCIP_SOL* sol, /**< primal CIP solution */
2402 SCIP_Real* activity, /**< buffer to return floating-point activity */
2403 SCIP_Real* errorbound /**< buffer to return bound on absolute floating-point error */
2404 )
2405{
2406 SCIP_Real solval;
2407 SCIP_Real sum;
2408 SCIP_Real mu;
2409 SCIP_Real inf;
2410 SCIP_Bool success;
2411 int v;
2412
2413 assert(activity != NULL);
2414 assert(errorbound != NULL);
2415
2416 inf = SCIPinfinity(scip);
2417 *activity = SCIP_UNKNOWN;
2418 *errorbound = inf;
2419
2420 sum = 0.0;
2421 mu = 0.0;
2422 /* normally we want to use the row since all fixed/aggregated variables do not appear there */
2423 if( consdata->rowlhs == NULL )
2424 {
2425 for( v = 0; v < consdata->nvars; ++v )
2426 {
2427 if( SCIPvarGetStatus(consdata->vars[v]) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(consdata->vars[v]) == SCIP_VARSTATUS_LOOSE )
2428 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
2429 else
2430 return FALSE;
2431
2432 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
2433 return FALSE;
2434
2435 sum += consdata->valsreal[v].inf * solval;
2436 mu += REALABS(sum);
2437 /* the factor 3 + eps is needed to account for rounding errors in valsreal[v]/solval */
2438 mu += (3.0 + SCIP_REAL_UNITROUNDOFF) * REALABS(consdata->valsreal[v].inf * solval);
2439 }
2440 }
2441 else
2442 {
2443 success = SCIPgetRowSolActivityWithErrorboundExact(scip, consdata->rowexact, sol, &sum, &mu);
2444
2445 if( !success )
2446 return FALSE;
2447 }
2448
2449 sum = MAX(sum, -inf);
2450 sum = MIN(sum, +inf);
2451 *activity = sum;
2452
2453 if( SCIPisInfinity(scip, sum) || SCIPisInfinity(scip, -sum) )
2454 *errorbound = inf;
2455 else
2456 *errorbound = mu * 1.1 * SCIP_REAL_UNITROUNDOFF;
2457
2458 return TRUE;
2459}
2460
2461/** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2462 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2463 */
2464static
2466 SCIP* scip, /**< SCIP data structure */
2467 SCIP_CONSDATA* consdata, /**< linear constraint */
2468 int posinf, /**< number of coefficients contributing pos. infinite value */
2469 int neginf, /**< number of coefficients contributing neg. infinite value */
2470 int poshuge, /**< number of coefficients contributing huge pos. value */
2471 int neghuge, /**< number of coefficients contributing huge neg. value */
2472 SCIP_Real delta, /**< value to subtract from stored minactivity
2473 * (contribution of the variable set to zero when getting residual activity) */
2474 SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2475 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2476 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2477 SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2478 * i.e. is <= the exact minactivity (in case of huge contributing values) */
2479 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2480 )
2481{
2482 assert(scip != NULL);
2483 assert(consdata != NULL);
2484 assert(posinf >= 0);
2485 assert(neginf >= 0);
2486 assert(poshuge >= 0);
2487 assert(neghuge >= 0);
2488 assert(minactivity != NULL);
2489 assert(isrelax != NULL);
2490 assert(issettoinfinity != NULL);
2491
2492 /* if we have pos. infinite contributions, the minactivity is +infty */
2493 if( posinf > 0 )
2494 {
2495 *minactivity = SCIPinfinity(scip);
2496 *issettoinfinity = TRUE;
2497 *isrelax = FALSE;
2498 }
2499 /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2500 else if( neginf > 0 )
2501 {
2502 *minactivity = -SCIPinfinity(scip);
2503 *issettoinfinity = TRUE;
2504 *isrelax = FALSE;
2505 }
2506 /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2507 else if( neghuge > 0 )
2508 {
2509 *minactivity = -SCIPinfinity(scip);
2510 *issettoinfinity = TRUE;
2511 *isrelax = TRUE;
2512 }
2513 /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */
2514 else if( !goodrelax && poshuge > 0 )
2515 {
2516 *minactivity = -SCIPinfinity(scip);
2517 *issettoinfinity = TRUE;
2518 *isrelax = TRUE;
2519 }
2520 else
2521 {
2522 SCIP_Real tmpactivity;
2523
2524 /* recompute minactivity if it is not valid */
2525 if( global )
2526 {
2527 if( !consdata->validglbminact )
2529 assert(consdata->validglbminact);
2530
2531 tmpactivity = consdata->glbminactivity;
2532 }
2533 else
2534 {
2535 if( !consdata->validminact )
2537 assert(consdata->validminact);
2538
2539 tmpactivity = consdata->minactivity;
2540 }
2541
2542 /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2543 * a feasible relaxation of the minactivity is the number of positive huge contributions
2544 * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2545 */
2546 if( poshuge > 0 )
2547 {
2548 *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2549 *issettoinfinity = FALSE;
2550 *isrelax = TRUE;
2551 }
2552 /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2553 else
2554 {
2555 *minactivity = tmpactivity - delta;
2556 *issettoinfinity = FALSE;
2557 *isrelax = FALSE;
2558 }
2559 }
2560}
2561
2562/** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2563 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2564 */
2565static
2567 SCIP* scip, /**< SCIP data structure */
2568 SCIP_CONSDATA* consdata, /**< linear constraint */
2569 int posinf, /**< number of coefficients contributing pos. infinite value */
2570 int neginf, /**< number of coefficients contributing neg. infinite value */
2571 int poshuge, /**< number of coefficients contributing huge pos. value */
2572 int neghuge, /**< number of coefficients contributing huge neg. value */
2573 SCIP_Real delta, /**< value to subtract from stored maxactivity
2574 * (contribution of the variable set to zero when getting residual activity) */
2575 SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2576 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2577 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2578 SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2579 * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2580 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2581 )
2582{
2583 assert(scip != NULL);
2584 assert(consdata != NULL);
2585 assert(posinf >= 0);
2586 assert(neginf >= 0);
2587 assert(poshuge >= 0);
2588 assert(neghuge >= 0);
2589 assert(maxactivity != NULL);
2590 assert(isrelax != NULL);
2591 assert(issettoinfinity != NULL);
2592
2593 /* if we have neg. infinite contributions, the maxactivity is -infty */
2594 if( neginf > 0 )
2595 {
2596 *maxactivity = -SCIPinfinity(scip);
2597 *issettoinfinity = TRUE;
2598 *isrelax = FALSE;
2599 }
2600 /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2601 else if( posinf > 0 )
2602 {
2603 *maxactivity = SCIPinfinity(scip);
2604 *issettoinfinity = TRUE;
2605 *isrelax = FALSE;
2606 }
2607 /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2608 else if( poshuge > 0 )
2609 {
2610 *maxactivity = SCIPinfinity(scip);
2611 *issettoinfinity = TRUE;
2612 *isrelax = TRUE;
2613 }
2614 /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2615 else if( !goodrelax && neghuge > 0 )
2616 {
2617 *maxactivity = SCIPinfinity(scip);
2618 *issettoinfinity = TRUE;
2619 *isrelax = TRUE;
2620 }
2621 else
2622 {
2623 SCIP_Real tmpactivity;
2624
2625 /* recompute maxactivity if it is not valid */
2626 if( global )
2627 {
2628 if( !consdata->validglbmaxact )
2630 assert(consdata->validglbmaxact);
2631
2632 tmpactivity = consdata->glbmaxactivity;
2633 }
2634 else
2635 {
2636 if( !consdata->validmaxact )
2638 assert(consdata->validmaxact);
2639
2640 tmpactivity = consdata->maxactivity;
2641 }
2642
2643 /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2644 * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2645 * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2646 */
2647 if( neghuge > 0 )
2648 {
2649 *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2650 *issettoinfinity = FALSE;
2651 *isrelax = TRUE;
2652 }
2653 /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2654 else
2655 {
2656 *maxactivity = tmpactivity - delta;
2657 *issettoinfinity = FALSE;
2658 *isrelax = FALSE;
2659 }
2660 }
2661}
2662
2663/** gets activity bounds for constraint */
2664static
2666 SCIP* scip, /**< SCIP data structure */
2667 SCIP_CONSDATA* consdata, /**< linear constraint */
2668 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2669 * relaxed activities ignored, anyway? */
2670 SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2671 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2672 SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2673 * i.e. <= the exact minactivity (in case of huge contributions),
2674 * or equal to the exact minimal activity */
2675 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2676 * i.e. >= the exact maxactivity (in case of huge contributions),
2677 * or equal to the exact maximal activity */
2678 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2679 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2680
2681 )
2682{
2683 assert(scip != NULL);
2684 assert(consdata != NULL);
2685 assert(minactivity != NULL);
2686 assert(maxactivity != NULL);
2687 assert(isminsettoinfinity != NULL);
2688 assert(ismaxsettoinfinity != NULL);
2689
2690 if( !consdata->validactivities )
2691 {
2692 consdataCalcActivities(scip, consdata);
2693 assert(consdata->validminact);
2694 assert(consdata->validmaxact);
2695 }
2696 assert(consdata->minactivity < SCIP_INVALID);
2697 assert(consdata->maxactivity < SCIP_INVALID);
2698 assert(consdata->minactivityneginf >= 0);
2699 assert(consdata->minactivityposinf >= 0);
2700 assert(consdata->maxactivityneginf >= 0);
2701 assert(consdata->maxactivityposinf >= 0);
2702
2703 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2704 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2705 minactivity, minisrelax, isminsettoinfinity);
2706
2707 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2708 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2709 maxactivity, maxisrelax, ismaxsettoinfinity);
2710}
2711
2712/** gets activity bounds for constraint after setting variable to zero */
2713static
2715 SCIP* scip, /**< SCIP data structure */
2716 SCIP_CONSDATA* consdata, /**< linear constraint */
2717 SCIP_VAR* var, /**< variable to calculate activity residual for */
2718 SCIP_INTERVAL val, /**< coefficient value of variable in linear constraint */
2719 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2720 * relaxed acticities ignored, anyway? */
2721 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2722 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2723 SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2724 * relaxation, i.e. <= the exact residual minactivity (in case of huge
2725 * contributions), or equal to the exact residual minactivity */
2726 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2727 * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2728 * contributions), or equal to the exact residual minactivity */
2729 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2730 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2731 )
2732{
2733 SCIP_Real minactbound;
2734 SCIP_Real maxactbound;
2735 SCIP_Real absval;
2736 SCIP_ROUNDMODE prevmode;
2737 prevmode = SCIPintervalGetRoundingMode();
2738
2739 assert(scip != NULL);
2740 assert(consdata != NULL);
2741 assert(var != NULL);
2742 assert(minresactivity != NULL);
2743 assert(maxresactivity != NULL);
2744 assert(minisrelax != NULL);
2745 assert(maxisrelax != NULL);
2746 assert(isminsettoinfinity != NULL);
2747 assert(ismaxsettoinfinity != NULL);
2748
2749 /* get activity bounds of linear constraint */
2750 if( !consdata->validactivities )
2751 {
2752 consdataCalcActivities(scip, consdata);
2753 assert(consdata->validminact);
2754 assert(consdata->validmaxact);
2755 }
2756 assert(consdata->minactivity < SCIP_INVALID);
2757 assert(consdata->maxactivity < SCIP_INVALID);
2758 assert(consdata->minactivityneginf >= 0);
2759 assert(consdata->minactivityposinf >= 0);
2760 assert(consdata->maxactivityneginf >= 0);
2761 assert(consdata->maxactivityposinf >= 0);
2762 assert(consdata->minactivityneghuge >= 0);
2763 assert(consdata->minactivityposhuge >= 0);
2764 assert(consdata->maxactivityneghuge >= 0);
2765 assert(consdata->maxactivityposhuge >= 0);
2766
2767 if( val.sup < 0.0 )
2768 {
2769 assert(val.inf <= 0.0);
2770
2771 minactbound = -SCIPvarGetUbLocal(var);
2772 maxactbound = -SCIPvarGetLbLocal(var);
2773 absval = -val.inf;
2774 }
2775 else
2776 {
2777 assert(val.inf >= 0.0);
2778
2779 minactbound = SCIPvarGetLbLocal(var);
2780 maxactbound = SCIPvarGetUbLocal(var);
2781 absval = val.sup;
2782 }
2783
2784 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2785 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2786 */
2787 if( SCIPisInfinity(scip, minactbound) )
2788 {
2789 assert(consdata->minactivityposinf >= 1);
2790
2791 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2792 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2793 minresactivity, minisrelax, isminsettoinfinity);
2794 }
2795 else if( SCIPisInfinity(scip, -minactbound) )
2796 {
2797 assert(consdata->minactivityneginf >= 1);
2798
2799 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2800 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2801 minresactivity, minisrelax, isminsettoinfinity);
2802 }
2803 else if( SCIPisHugeValue(scip, minactbound * absval) )
2804 {
2805 assert(consdata->minactivityposhuge >= 1);
2806
2807 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2808 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2809 minresactivity, minisrelax, isminsettoinfinity);
2810 }
2811 else if( SCIPisHugeValue(scip, -minactbound * absval) )
2812 {
2813 assert(consdata->minactivityneghuge >= 1);
2814
2815 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2816 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2817 minresactivity, minisrelax, isminsettoinfinity);
2818 }
2819 else
2820 {
2821 SCIP_Real delta;
2822 delta = absval * minactbound;
2825 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2826 consdata->minactivityposhuge, consdata->minactivityneghuge, delta, FALSE, goodrelax,
2827 minresactivity, minisrelax, isminsettoinfinity);
2828 }
2829
2830 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2831 * and contribution of variable set to zero that has to be subtracted from finite part of activity
2832 */
2833 if( SCIPisInfinity(scip, -maxactbound) )
2834 {
2835 assert(consdata->maxactivityneginf >= 1);
2836
2837 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2838 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2839 maxresactivity, maxisrelax, ismaxsettoinfinity);
2840 }
2841 else if( SCIPisInfinity(scip, maxactbound) )
2842 {
2843 assert(consdata->maxactivityposinf >= 1);
2844
2845 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2846 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2847 maxresactivity, maxisrelax, ismaxsettoinfinity);
2848 }
2849 else if( SCIPisHugeValue(scip, absval * maxactbound) )
2850 {
2851 assert(consdata->maxactivityposhuge >= 1);
2852
2853 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2854 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2855 maxresactivity, maxisrelax, ismaxsettoinfinity);
2856 }
2857 else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2858 {
2859 assert(consdata->maxactivityneghuge >= 1);
2860
2861 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2862 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2863 maxresactivity, maxisrelax, ismaxsettoinfinity);
2864 }
2865 else
2866 {
2867 SCIP_Real delta;
2868 delta = absval * maxactbound;
2871 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2872 consdata->maxactivityposhuge, consdata->maxactivityneghuge, delta, FALSE, goodrelax,
2873 maxresactivity, maxisrelax, ismaxsettoinfinity);
2874 }
2876}
2877
2878/** calculates the activity of the linear constraint for given solution */
2879static
2881 SCIP* scip, /**< SCIP data structure */
2882 SCIP_CONSDATA* consdata, /**< linear constraint data */
2883 SCIP_SOL* sol, /**< solution to get activity for, NULL to current solution */
2884 SCIP_Bool useexact, /**< should the exact solution be used */
2885 SCIP_RATIONAL* activity /**< pointer to store the activity */
2886 )
2887{
2888 assert(scip != NULL);
2889 assert(consdata != NULL);
2890
2891 if( (sol == NULL) && !SCIPhasCurrentNodeLP(scip) )
2892 consdataComputePseudoActivity(consdata, activity);
2893 else
2894 {
2895 SCIP_RATIONAL* solval;
2896 int nposinf;
2897 int nneginf;
2898 SCIP_Bool negsign;
2899 int v;
2900
2901 (void) SCIPrationalCreateBuffer(SCIPbuffer(scip), &solval);
2902
2903 SCIPrationalSetFraction(activity, 0LL, 1LL);
2904 nposinf = 0;
2905 nneginf = 0;
2906
2907 for( v = 0; v < consdata->nvars; ++v )
2908 {
2909 if( useexact )
2910 SCIPgetSolValExact(scip, sol, consdata->vars[v], solval);
2911 else
2912 SCIPrationalSetReal(solval, SCIPgetSolVal(scip, sol, consdata->vars[v]));
2913
2914 assert(!SCIPrationalIsZero(consdata->vals[v]));
2915 negsign = SCIPrationalIsNegative(consdata->vals[v]);
2916
2917 if( (SCIPrationalIsInfinity(solval) && !negsign) || (SCIPrationalIsNegInfinity(solval) && negsign) )
2918 ++nposinf;
2919 else if( (SCIPrationalIsInfinity(solval) && negsign) || (SCIPrationalIsNegInfinity(solval) && !negsign) )
2920 ++nneginf;
2921 else
2922 {
2923 SCIPrationalAddProd(activity, solval, consdata->vals[v]);
2924 }
2925 }
2926 assert(nneginf >= 0 && nposinf >= 0);
2927
2928 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", SCIPrationalGetReal(activity), nposinf, nneginf);
2929
2930 /* set activity to infeasible infinity for contradicting contributions */
2931 if( nneginf > 0 && ( nposinf == 0 || !SCIPrationalIsNegInfinity(consdata->lhs) ) )
2933 else if( nposinf > 0 && ( nneginf == 0 || !SCIPrationalIsInfinity(consdata->rhs) ) )
2934 SCIPrationalSetInfinity(activity);
2935
2936 SCIPrationalDebugMessage("corrected activity of linear constraint: %q\n", activity);
2937
2939 }
2940}
2941
2942/** calculates the feasibility of the linear constraint for given solution */
2943static
2945 SCIP* scip, /**< SCIP data structure */
2946 SCIP_CONSDATA* consdata, /**< linear constraint data */
2947 SCIP_SOL* sol, /**< solution to get feasibility for, NULL to current solution */
2948 SCIP_RATIONAL* ret /**< pointer to store the result */
2949 )
2950{
2951 SCIP_RATIONAL* activity;
2952 SCIP_RATIONAL* op1;
2953 SCIP_RATIONAL* op2;
2954
2955 assert(scip != NULL);
2956 assert(consdata != NULL);
2957
2958 (void) SCIPrationalCreateBuffer(SCIPbuffer(scip), &activity);
2961
2962 consdataGetActivity(scip, consdata, sol, FALSE, activity);
2963 SCIPrationalDiff(op1, consdata->rhs, activity);
2964 SCIPrationalDiff(op2, activity, consdata->lhs);
2965
2966 SCIPrationalMin(ret, op1, op2);
2967
2971}
2972
2973/** creates an LP row in a linear constraint data */
2974static
2976 SCIP* scip, /**< SCIP data structure */
2977 SCIP_CONS* cons /**< linear constraint */
2978 );
2979
2980/** prints the certificate for a given original exact linear constraint */
2982 SCIP* scip, /**< SCIP data structure */
2983 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
2984 SCIP_CONS* cons /**< constraint */
2985 )
2986{
2987 SCIP_CONSDATA* consdata;
2988 int* varsindex;
2989 int i;
2990
2991 /*lint --e{715}*/
2992 assert(scip != NULL);
2993 assert(conshdlr != NULL);
2994 assert(cons != NULL);
2995
2996 /* print constraint into certificate output */
2997 if( SCIPisCertified(scip) )
2998 {
2999 consdata = SCIPconsGetData(cons);
3000
3001 SCIP_CALL( SCIPallocBufferArray(scip, &varsindex, consdata->nvars) );
3002 for( i = 0; i < consdata->nvars; ++i )
3003 varsindex[i] = SCIPvarGetCertificateIndex(consdata->vars[i]);
3004
3005 /* print constraint */
3006 if( SCIPrationalIsEQ(consdata->lhs, consdata->rhs) )
3007 {
3008 assert(!SCIPrationalIsAbsInfinity(consdata->lhs));
3009 SCIP_CALL( SCIPcertifyCons(scip, TRUE, NULL, 'E', consdata->lhs, consdata->nvars, varsindex, consdata->vals) );
3010 }
3011 else
3012 {
3013 if( !SCIPrationalIsNegInfinity(consdata->lhs) )
3014 {
3015 SCIP_CALL( SCIPcertifyCons(scip, TRUE, NULL, 'G', consdata->lhs, consdata->nvars, varsindex, consdata->vals) );
3016 }
3017 if( !SCIPrationalIsInfinity(consdata->rhs) )
3018 {
3019 SCIP_CALL( SCIPcertifyCons(scip, TRUE, NULL, 'L', consdata->rhs, consdata->nvars, varsindex, consdata->vals) );
3020 }
3021 }
3022
3023 SCIPfreeBufferArray(scip, &varsindex);
3024 }
3025
3026 return SCIP_OKAY;
3027}
3028
3029/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3030static
3032{ /*lint --e{715}*/
3033 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3034
3035 assert(consdata != NULL);
3036 assert(0 <= ind1 && ind1 < consdata->nvars);
3037 assert(0 <= ind2 && ind2 < consdata->nvars);
3038
3039 return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
3040}
3041
3042/** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3043static
3044SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3045{ /*lint --e{715}*/
3046 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3047 SCIP_VAR* var1;
3048 SCIP_VAR* var2;
3049
3050 assert(consdata != NULL);
3051 assert(0 <= ind1 && ind1 < consdata->nvars);
3052 assert(0 <= ind2 && ind2 < consdata->nvars);
3053
3054 var1 = consdata->vars[ind1];
3055 var2 = consdata->vars[ind2];
3056
3057 /* exactly one variable is binary */
3058 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3059 {
3060 return (SCIPvarIsBinary(var1) ? -1 : +1);
3061 }
3062 /* both variables are binary */
3063 else if( SCIPvarIsBinary(var1) )
3064 {
3065 if( SCIPrationalIsAbsEQ(consdata->vals[ind1], consdata->vals[ind2]) ) {
3066 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3067 }
3068 if( SCIPrationalIsAbsGT(consdata->vals[ind1], consdata->vals[ind2]) )
3069 return -1;
3070 else
3071 return +1;
3072 }
3073 else
3074 {
3075 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3076 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3077
3078 if( vartype1 < vartype2 )
3079 {
3080 return -1;
3081 }
3082 else if( vartype1 > vartype2 )
3083 {
3084 return +1;
3085 }
3086 else
3087 {
3088 /* both variables are continuous */
3089 if( !SCIPvarIsIntegral(var1) )
3090 {
3091 assert(!SCIPvarIsIntegral(var2));
3092 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3093 }
3094 else
3095 {
3096 SCIP_RATIONAL* abscont1;
3097 SCIP_RATIONAL* abscont2;
3098
3099 (void) SCIPrationalCreate(&abscont1);
3100 (void) SCIPrationalCreate(&abscont2);
3101
3103 SCIPrationalMult(abscont1, consdata->vals[ind1], abscont1);
3104
3106 SCIPrationalMult(abscont2, consdata->vals[ind2], abscont2);
3107
3108 if( SCIPrationalIsAbsEQ(abscont1, abscont2) ) {
3109 SCIPrationalFree(&abscont1);
3110 SCIPrationalFree(&abscont2);
3111 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3112 }
3113 if( SCIPrationalIsAbsGT(abscont2, abscont1) )
3114 {
3115 SCIPrationalFree(&abscont1);
3116 SCIPrationalFree(&abscont2);
3117 return 1;
3118 }
3119 else
3120 {
3121 SCIPrationalFree(&abscont1);
3122 SCIPrationalFree(&abscont2);
3123 return -1;
3124 }
3125 }
3126 }
3127 }
3128}
3129
3130/** permutes the constraint's variables according to a given permutation. */
3131static
3133 SCIP_CONSDATA* consdata, /**< the constraint data */
3134 int* perm, /**< the target permutation */
3135 int nvars /**< the number of variables */
3136 )
3137{ /*lint --e{715}*/
3138 SCIP_VAR* varv;
3139 SCIP_EVENTDATA* eventdatav;
3140 SCIP_INTERVAL valrealv;
3141 SCIP_RATIONAL* valv;
3142 int v;
3143 int i;
3144 int nexti;
3145
3146 assert(perm != NULL);
3147 assert(consdata != NULL);
3148
3149 /* permute the variables in the linear constraint according to the target permutation */
3150 eventdatav = NULL;
3151 for( v = 0; v < nvars; ++v )
3152 {
3153 if( perm[v] != v )
3154 {
3155 varv = consdata->vars[v];
3156 valv = consdata->vals[v];
3157 valrealv = consdata->valsreal[v];
3158 if( consdata->eventdata != NULL )
3159 eventdatav = consdata->eventdata[v];
3160 i = v;
3161 do
3162 {
3163 assert(0 <= perm[i] && perm[i] < nvars);
3164 assert(perm[i] != i);
3165 consdata->vars[i] = consdata->vars[perm[i]];
3166 consdata->vals[i] = consdata->vals[perm[i]];
3167 consdata->valsreal[i] = consdata->valsreal[perm[i]];
3168 if( consdata->eventdata != NULL )
3169 {
3170 consdata->eventdata[i] = consdata->eventdata[perm[i]];
3171 consdata->eventdata[i]->varpos = i;
3172 }
3173 nexti = perm[i];
3174 perm[i] = i;
3175 i = nexti;
3176 }
3177 while( perm[i] != v );
3178 consdata->vars[i] = varv;
3179 consdata->vals[i] = valv;
3180 consdata->valsreal[i] = valrealv;
3181 if( consdata->eventdata != NULL )
3182 {
3183 consdata->eventdata[i] = eventdatav;
3184 consdata->eventdata[i]->varpos = i;
3185 }
3186 perm[i] = i;
3187 }
3188 }
3189#ifdef SCIP_DEBUG
3190 /* check sorting */
3191 for( v = 0; v < nvars; ++v )
3192 {
3193 assert(perm[v] == v);
3194 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3195 }
3196#endif
3197}
3198
3199/** sorts linear constraint's variables depending on the stage of the solving process:
3200 * - during PRESOLVING
3201 * sorts variables by binary, integer, implied integral, and continuous variables,
3202 * and the variables of the same type by non-decreasing variable index
3203 *
3204 * - during SOLVING
3205 * sorts variables of the remaining problem by binary, integer, implied integral, and continuous variables,
3206 * and binary and integer variables by their global max activity delta (within each group),
3207 * ties within a group are broken by problem index of the variable.
3208 *
3209 * This fastens the propagation time of the constraint handler.
3210 */
3211static
3213 SCIP* scip, /**< SCIP data structure */
3214 SCIP_CONSDATA* consdata /**< linear constraint data */
3215 )
3216{
3217 assert(scip != NULL);
3218 assert(consdata != NULL);
3219
3220 /* check if there are variables for sorting */
3221 if( consdata->nvars <= 1 )
3222 {
3223 consdata->indexsorted = TRUE;
3224 consdata->coefsorted = TRUE;
3225 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3226 }
3227 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3228 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3229 {
3230 int* perm;
3231 int v;
3232
3233 /* get temporary memory to store the sorted permutation */
3234 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3235
3236 /* call sorting method */
3238 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3239 else
3240 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3241
3242 permSortConsdata(consdata, perm, consdata->nvars);
3243
3244 /* free temporary memory */
3245 SCIPfreeBufferArray(scip, &perm);
3246
3248 {
3249 consdata->indexsorted = FALSE;
3250 consdata->coefsorted = TRUE;
3251
3252 /* count binary variables in the sorted vars array */
3253 consdata->nbinvars = 0;
3254 for( v = 0; v < consdata->nvars; ++v )
3255 {
3256 if( SCIPvarIsBinary(consdata->vars[v]) )
3257 ++consdata->nbinvars;
3258 else
3259 break;
3260 }
3261 }
3262 else
3263 {
3264 consdata->indexsorted = TRUE;
3265 consdata->coefsorted = FALSE;
3266 }
3267 }
3268
3269 return SCIP_OKAY;
3270}
3271
3272
3273/*
3274 * local linear constraint handler methods
3275 */
3276
3277/** sets left hand side of linear constraint */
3278static
3280 SCIP* scip, /**< SCIP data structure */
3281 SCIP_CONS* cons, /**< linear constraint */
3282 SCIP_RATIONAL* lhs /**< new left hand side */
3283 )
3284{
3285 SCIP_CONSDATA* consdata;
3286 SCIP_Bool locked;
3287 int i;
3288
3289 assert(scip != NULL);
3290 assert(cons != NULL);
3291 assert(!SCIPrationalIsInfinity(lhs));
3292
3293 consdata = SCIPconsGetData(cons);
3294 assert(consdata != NULL);
3295 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3296 assert(!SCIPrationalIsInfinity(consdata->lhs));
3297
3298 /* check whether the side is not changed */
3299 if( SCIPrationalIsEQ(consdata->lhs, lhs) )
3300 return SCIP_OKAY;
3301
3302 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3303 if( SCIPrationalIsEQ(lhs, consdata->rhs) )
3304 {
3305 SCIPrationalSetRational(consdata->rhs, lhs);
3306 assert(consdata->rowlhs == NULL);
3307 }
3308
3309 locked = FALSE;
3310 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3311 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3312
3313 /* if necessary, update the rounding locks of variables */
3314 if( locked )
3315 {
3316 if( SCIPrationalIsNegInfinity(consdata->lhs) && !SCIPrationalIsNegInfinity(lhs) )
3317 {
3318 SCIP_VAR** vars;
3319 SCIP_RATIONAL** vals;
3320 int v;
3321
3322 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3323 vars = consdata->vars;
3324 vals = consdata->vals;
3325
3326 for( v = 0; v < consdata->nvars; ++v )
3327 {
3328 assert(vars[v] != NULL);
3329 assert(!SCIPrationalIsZero(vals[v]));
3330
3331 if( SCIPrationalIsPositive(vals[v]) )
3332 {
3333 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3334 }
3335 else
3336 {
3337 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3338 }
3339 }
3340 }
3341 else if( !SCIPrationalIsNegInfinity(consdata->lhs) && SCIPrationalIsNegInfinity(lhs) )
3342 {
3343 SCIP_VAR** vars;
3344 SCIP_RATIONAL** vals;
3345 int v;
3346
3347 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3348 vars = consdata->vars;
3349 vals = consdata->vals;
3350
3351 for( v = 0; v < consdata->nvars; ++v )
3352 {
3353 assert(vars[v] != NULL);
3354 assert(!SCIPrationalIsZero(vals[v]));
3355
3356 if( SCIPrationalIsPositive(vals[v]) )
3357 {
3358 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3359 }
3360 else
3361 {
3362 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3363 }
3364 }
3365 }
3366 }
3367
3368 /* check whether the left hand side is increased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
3369 if( !SCIPrationalIsNegInfinity(lhs) && SCIPrationalIsGT(lhs, consdata->lhs) )
3370 {
3371 consdata->boundstightened = 0;
3372 consdata->presolved = FALSE;
3373 consdata->cliquesadded = FALSE;
3374 consdata->implsadded = FALSE;
3375
3376 /* mark the constraint for propagation */
3377 if( SCIPconsIsTransformed(cons) )
3378 {
3380 }
3381 }
3382
3383 /* set new left hand side and update constraint data */
3384 SCIPrationalSetRational(consdata->lhs, lhs);
3385 consdata->lhsreal = SCIPrationalRoundReal(lhs, SCIP_R_ROUND_DOWNWARDS);
3386 consdata->changed = TRUE;
3387 consdata->normalized = FALSE;
3388 consdata->rangedrowpropagated = 0;
3389
3390 /* update the lhs of the LP row */
3391 if( consdata->rowexact != NULL )
3392 {
3393 SCIP_CALL( SCIPchgRowExactLhs(scip, consdata->rowexact, lhs) );
3394 }
3395
3396 return SCIP_OKAY;
3397}
3398
3399/** sets right hand side of linear constraint */
3400static
3402 SCIP* scip, /**< SCIP data structure */
3403 SCIP_CONS* cons, /**< linear constraint */
3404 SCIP_RATIONAL* rhs /**< new right hand side */
3405 )
3406{
3407 SCIP_CONSDATA* consdata;
3408 SCIP_Bool locked;
3409 int i;
3410
3411 assert(scip != NULL);
3412 assert(cons != NULL);
3413 assert(!SCIPrationalIsNegInfinity(rhs));
3414
3415 consdata = SCIPconsGetData(cons);
3416 assert(consdata != NULL);
3417 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3418 assert(!SCIPrationalIsNegInfinity(consdata->rhs));
3419
3420 /* check whether the side is not changed */
3421 if( SCIPrationalIsEQ(consdata->rhs, rhs) )
3422 return SCIP_OKAY;
3423
3424 /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3425 if( SCIPrationalIsEQ(rhs, consdata->lhs) )
3426 {
3427 SCIPrationalSetRational(consdata->rhs, rhs);
3428 assert(consdata->rowlhs == NULL);
3429 }
3430
3431 locked = FALSE;
3432 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3433 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3434
3435 /* if necessary, update the rounding locks of variables */
3436 if( locked )
3437 {
3438 assert(SCIPconsIsTransformed(cons));
3439
3440 if( SCIPrationalIsInfinity(consdata->rhs) && !SCIPrationalIsInfinity(rhs) )
3441 {
3442 SCIP_VAR** vars;
3443 SCIP_RATIONAL** vals;
3444 int v;
3445
3446 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3447 vars = consdata->vars;
3448 vals = consdata->vals;
3449
3450 for( v = 0; v < consdata->nvars; ++v )
3451 {
3452 assert(vars[v] != NULL);
3453 assert(!SCIPrationalIsZero(vals[v]));
3454
3455 if( SCIPrationalIsPositive(vals[v]) )
3456 {
3457 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3458 }
3459 else
3460 {
3461 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3462 }
3463 }
3464 }
3465 else if( !SCIPrationalIsInfinity(consdata->rhs) && SCIPrationalIsInfinity(rhs) )
3466 {
3467 SCIP_VAR** vars;
3468 SCIP_RATIONAL** vals;
3469 int v;
3470
3471 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3472 vars = consdata->vars;
3473 vals = consdata->vals;
3474
3475 for( v = 0; v < consdata->nvars; ++v )
3476 {
3477 assert(vars[v] != NULL);
3478 assert(!SCIPrationalIsZero(vals[v]));
3479
3480 if( SCIPrationalIsPositive(vals[v]) )
3481 {
3482 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3483 }
3484 else
3485 {
3486 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3487 }
3488 }
3489 }
3490 }
3491
3492 /* check whether the right hand side is decreased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
3493 if( !SCIPrationalIsInfinity(rhs) && SCIPrationalIsLT(rhs, consdata->rhs) )
3494 {
3495 consdata->boundstightened = 0;
3496 consdata->presolved = FALSE;
3497 consdata->cliquesadded = FALSE;
3498 consdata->implsadded = FALSE;
3499
3500 /* mark the constraint for propagation */
3501 if( SCIPconsIsTransformed(cons) )
3502 {
3504 }
3505 }
3506
3507 /* set new right hand side and update constraint data */
3508 SCIPrationalSetRational(consdata->rhs, rhs);
3509 consdata->rhsreal = SCIPrationalRoundReal(rhs, SCIP_R_ROUND_UPWARDS);
3510 consdata->changed = TRUE;
3511 consdata->normalized = FALSE;
3512 consdata->rangedrowpropagated = 0;
3513
3514 /* update the rhs of the LP row */
3515 if( consdata->rowexact != NULL )
3516 {
3517 SCIP_CALL( SCIPchgRowExactRhs(scip, consdata->rowexact, rhs) );
3518 }
3519
3520 return SCIP_OKAY;
3521}
3522
3523/** adds coefficient in linear constraint */
3524static
3526 SCIP* scip, /**< SCIP data structure */
3527 SCIP_CONS* cons, /**< linear constraint */
3528 SCIP_VAR* var, /**< variable of constraint entry */
3529 SCIP_RATIONAL* val /**< coefficient of constraint entry */
3530 )
3531{
3532 SCIP_CONSDATA* consdata;
3533 SCIP_Bool transformed;
3534
3535 assert(scip != NULL);
3536 assert(cons != NULL);
3537 assert(var != NULL);
3538
3539 /* ignore coefficient if it is nearly zero */
3540 if( SCIPrationalIsZero(val) )
3541 return SCIP_OKAY;
3542
3543 consdata = SCIPconsGetData(cons);
3544 assert(consdata != NULL);
3545
3546 /* are we in the transformed problem? */
3547 transformed = SCIPconsIsTransformed(cons);
3548
3549 /* always use transformed variables in transformed constraints */
3550 if( transformed )
3551 {
3552 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3553 }
3554 assert(var != NULL);
3555 assert(transformed == SCIPvarIsTransformed(var));
3556
3557 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3558 consdata->vars[consdata->nvars] = var;
3559 SCIPrationalSetRational(consdata->vals[consdata->nvars], val);
3560 SCIPintervalSetRational(&(consdata->valsreal[consdata->nvars]), val);
3561 consdata->nvars++;
3562
3563 /* capture variable */
3564 SCIP_CALL( SCIPcaptureVar(scip, var) );
3565
3566 /* if we are in transformed problem, the variable needs an additional event data */
3567 if( transformed )
3568 {
3569 if( consdata->eventdata != NULL )
3570 {
3571 SCIP_CONSHDLR* conshdlr;
3572 SCIP_CONSHDLRDATA* conshdlrdata;
3573
3574 /* check for event handler */
3575 conshdlr = SCIPconsGetHdlr(cons);
3576 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3577 assert(conshdlrdata != NULL);
3578 assert(conshdlrdata->eventhdlr != NULL);
3579
3580 /* initialize eventdata array */
3581 consdata->eventdata[consdata->nvars-1] = NULL;
3582
3583 /* catch bound change events of variable */
3584 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3585 }
3586
3587 /* update minimum and maximum activities */
3588 consdataUpdateAddCoef(scip, consdata, var, consdata->vals[consdata->nvars - 1], consdata->valsreal[consdata->nvars - 1]);
3589 }
3590
3591 /* install rounding locks for new variable */
3592 SCIP_CALL( lockRounding(scip, cons, var, val) );
3593
3594 /* mark the constraint for propagation */
3595 if( transformed )
3596 {
3598 }
3599
3600 consdata->boundstightened = 0;
3601 consdata->presolved = FALSE;
3602 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3603
3604 consdata->changed = TRUE;
3605 consdata->normalized = FALSE;
3606 consdata->cliquesadded = FALSE;
3607 consdata->implsadded = FALSE;
3608 consdata->rangedrowpropagated = 0;
3609
3610 if( consdata->nvars == 1 )
3611 {
3612 consdata->indexsorted = TRUE;
3613 consdata->coefsorted = TRUE;
3614 consdata->merged = TRUE;
3615 }
3616 else
3617 {
3618 consdata->merged = FALSE;
3619
3621 {
3622 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3623 consdata->coefsorted = FALSE;
3624 }
3625 else
3626 {
3627 consdata->indexsorted = FALSE;
3628 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3629 }
3630 }
3631
3632 /* update hascontvar and hasnonbinvar flags */
3633 if( consdata->hasnonbinvalid && !consdata->hascontvar )
3634 {
3635 SCIP_VARTYPE vartype = SCIPvarGetType(var);
3636
3637 if( vartype != SCIP_VARTYPE_BINARY )
3638 {
3639 consdata->hasnonbinvar = TRUE;
3640
3641 if( vartype == SCIP_VARTYPE_CONTINUOUS )
3642 consdata->hascontvar = TRUE;
3643 }
3644 }
3645
3646 /* add the new coefficient to the LP row */
3647 if( consdata->rowexact != NULL )
3648 {
3649 SCIP_CALL( SCIPaddVarsToRowExact(scip, consdata->rowexact, 1, &var, &val) );
3650 }
3651
3652 return SCIP_OKAY;
3653}
3654
3655/** deletes coefficient at given position from linear constraint data */
3656static
3658 SCIP* scip, /**< SCIP data structure */
3659 SCIP_CONS* cons, /**< linear constraint */
3660 int pos /**< position of coefficient to delete */
3661 )
3662{
3663 SCIP_CONSDATA* consdata;
3664 SCIP_VAR* var;
3665 SCIP_RATIONAL* val;
3666
3667 assert(scip != NULL);
3668 assert(cons != NULL);
3669
3670 consdata = SCIPconsGetData(cons);
3671 assert(consdata != NULL);
3672 assert(0 <= pos && pos < consdata->nvars);
3673
3674 var = consdata->vars[pos];
3675 val = consdata->vals[pos];
3676 assert(var != NULL);
3677
3678 /* remove rounding locks for deleted variable */
3679 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3680
3681 /* if we are in transformed problem, delete the event data of the variable */
3682 if( SCIPconsIsTransformed(cons) )
3683 {
3684 SCIP_CONSHDLR* conshdlr;
3685 SCIP_CONSHDLRDATA* conshdlrdata;
3686
3687 /* check for event handler */
3688 conshdlr = SCIPconsGetHdlr(cons);
3689 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3690 assert(conshdlrdata != NULL);
3691 assert(conshdlrdata->eventhdlr != NULL);
3692
3693 /* drop bound change events of variable */
3694 if( consdata->eventdata != NULL )
3695 {
3696 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3697 assert(consdata->eventdata[pos] == NULL);
3698 }
3699 }
3700
3701 /* move the last variable to the free slot */
3702 if( pos != consdata->nvars - 1 )
3703 {
3704 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3705 SCIPrationalSetRational(consdata->vals[pos], consdata->vals[consdata->nvars - 1]);
3706 consdata->valsreal[pos] = consdata->valsreal[consdata->nvars -1];
3707
3708 if( consdata->eventdata != NULL )
3709 {
3710 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3711 assert(consdata->eventdata[pos] != NULL);
3712 consdata->eventdata[pos]->varpos = pos;
3713 }
3714
3715 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3716 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3717 }
3718 consdata->nvars--;
3719
3720 /* mark the constraint for propagation */
3721 if( SCIPconsIsTransformed(cons) )
3722 {
3724 }
3725
3726 consdata->boundstightened = 0;
3727 consdata->presolved = FALSE;
3728 consdata->changed = TRUE;
3729 consdata->normalized = FALSE;
3730 consdata->cliquesadded = FALSE;
3731 consdata->implsadded = FALSE;
3732 consdata->rangedrowpropagated = 0;
3733
3734 /* check if hasnonbinvar flag might be incorrect now */
3735 if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3736 {
3737 consdata->hasnonbinvalid = FALSE;
3738 }
3739
3740 /* release variable */
3741 SCIP_CALL( SCIPreleaseVar(scip, &var) );
3742
3743 return SCIP_OKAY;
3744}
3745
3746/** changes coefficient value at given position of linear constraint data */
3747static
3749 SCIP* scip, /**< SCIP data structure */
3750 SCIP_CONS* cons, /**< linear constraint */
3751 int pos, /**< position of coefficient to delete */
3752 SCIP_RATIONAL* newval /**< new value of coefficient */
3753 )
3754{
3755 SCIP_CONSDATA* consdata;
3756 SCIP_VAR* var;
3757 SCIP_RATIONAL* val;
3758 SCIP_Bool locked;
3759 SCIP_INTERVAL newvalfp;
3760 int i;
3761
3762 assert(scip != NULL);
3763 assert(cons != NULL);
3764 assert(!SCIPrationalIsZero(newval));
3765
3766 consdata = SCIPconsGetData(cons);
3767 assert(consdata != NULL);
3768 assert(0 <= pos && pos < consdata->nvars);
3769
3770 var = consdata->vars[pos];
3771 val = consdata->vals[pos];
3772 assert(var != NULL);
3773 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3774
3775 locked = FALSE;
3776 for( i = 0; i < NLOCKTYPES && !locked; i++ )
3777 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3778
3779 /* if necessary, update the rounding locks of the variable */
3780 if( locked && ((SCIPrationalIsNegative(newval) && SCIPrationalIsPositive(val)) || (SCIPrationalIsNegative(val) && SCIPrationalIsPositive(newval))) )
3781 {
3782 assert(SCIPconsIsTransformed(cons));
3783
3784 /* remove rounding locks for variable with old coefficient */
3785 SCIP_CALL( unlockRounding(scip, cons, var, val) );
3786
3787 /* install rounding locks for variable with new coefficient */
3788 SCIP_CALL( lockRounding(scip, cons, var, newval) );
3789 }
3790 SCIPintervalSetRational(&newvalfp, newval);
3791 /* update minimum and maximum activities */
3792 if( SCIPconsIsTransformed(cons) )
3793 consdataUpdateChgCoef(scip, consdata, var, consdata->valsreal[pos], val, newvalfp, newval);
3794
3795 /* change the value */
3796 SCIPrationalSetRational(consdata->vals[pos], newval);
3797 consdata->valsreal[pos] = newvalfp;
3798 if( consdata->coefsorted )
3799 {
3800 if( pos > 0 )
3801 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
3802 if( consdata->coefsorted && pos < consdata->nvars - 1 )
3803 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
3804 }
3805 /* mark the constraint for propagation */
3806 if( SCIPconsIsTransformed(cons) )
3807 {
3809 }
3810
3811 consdata->boundstightened = 0;
3812 consdata->presolved = FALSE;
3813 consdata->changed = TRUE;
3814 consdata->normalized = FALSE;
3815 consdata->cliquesadded = FALSE;
3816 consdata->implsadded = FALSE;
3817 consdata->rangedrowpropagated = 0;
3818
3819 return SCIP_OKAY;
3820}
3821
3822/* perform deletion of variables in all constraints of the constraint handler */
3823static
3825 SCIP* scip, /**< SCIP data structure */
3826 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3827 SCIP_CONS** conss, /**< array of constraints */
3828 int nconss /**< number of constraints */
3829 )
3830{
3831 SCIP_CONSDATA* consdata;
3832 int i;
3833 int v;
3834
3835 assert(scip != NULL);
3836 assert(conshdlr != NULL);
3837 assert(conss != NULL);
3838 assert(nconss >= 0);
3839 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3840
3841 /* iterate over all constraints */
3842 for( i = 0; i < nconss; i++ )
3843 {
3844 consdata = SCIPconsGetData(conss[i]);
3845
3846 /* constraint is marked, that some of its variables were deleted */
3847 if( consdata->varsdeleted )
3848 {
3849 /* iterate over all variables of the constraint and delete them from the constraint */
3850 for( v = consdata->nvars - 1; v >= 0; --v )
3851 {
3852 if( SCIPvarIsDeleted(consdata->vars[v]) )
3853 {
3854 SCIP_CALL( delCoefPos(scip, conss[i], v) );
3855 }
3856 }
3857 consdata->varsdeleted = FALSE;
3858 }
3859 }
3860
3861 return SCIP_OKAY;
3862}
3863
3864/** replaces multiple occurrences of a variable by a single coefficient */
3865static
3867 SCIP* scip, /**< SCIP data structure */
3868 SCIP_CONS* cons /**< linear constraint */
3869 )
3870{
3871 SCIP_CONSDATA* consdata;
3872 SCIP_VAR* var;
3873 SCIP_RATIONAL* valsum;
3874 int v;
3875
3876 assert(scip != NULL);
3877 assert(cons != NULL);
3878
3879 consdata = SCIPconsGetData(cons);
3880 assert(consdata != NULL);
3881
3882 if( consdata->merged )
3883 return SCIP_OKAY;
3884
3886
3887 /* sort the constraint */
3888 SCIP_CALL( consdataSort(scip, consdata) );
3889
3890 /* go backwards through the constraint looking for multiple occurrences of the same variable;
3891 * backward direction is necessary, since delCoefPos() modifies the given position and
3892 * the subsequent ones
3893 */
3894 v = consdata->nvars-1;
3895 while( v >= 1 )
3896 {
3897 var = consdata->vars[v];
3898 if( consdata->vars[v-1] == var )
3899 {
3900 SCIPrationalSetRational(valsum, consdata->vals[v]);
3901 do
3902 {
3903 SCIP_CALL( delCoefPos(scip, cons, v) );
3904 --v;
3905 SCIPrationalAdd(valsum, valsum, consdata->vals[v]);
3906 }
3907 while( v >= 1 && consdata->vars[v-1] == var );
3908
3909 /* modify the last existing occurrence of the variable */
3910 assert(consdata->vars[v] == var);
3911 if( SCIPrationalIsZero(valsum) )
3912 {
3913 SCIP_CALL( delCoefPos(scip, cons, v) );
3914
3915 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3916 * delta needs to be recalculated on the next real propagation
3917 */
3918 if( consdata->maxactdeltavar == var )
3919 {
3920 consdata->maxactdelta = SCIP_INVALID;
3921 consdata->maxactdeltavar = NULL;
3922 }
3923 }
3924 else
3925 {
3926 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
3927 }
3928 }
3929 --v;
3930 }
3931
3933 consdata->merged = TRUE;
3934
3935 return SCIP_OKAY;
3936}
3937
3938/** replaces all fixed and aggregated variables by their non-fixed counterparts */
3939static
3941 SCIP* scip, /**< SCIP data structure */
3942 SCIP_CONS* cons, /**< linear constraint */
3943 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
3944 * information is not needed; in this case, we apply all fixings
3945 * instead of stopping after the first infeasible one */
3946 )
3947{
3948 SCIP_CONSDATA* consdata;
3949 SCIP_VAR* var;
3950 SCIP_VAR** aggrvars;
3951 SCIP_RATIONAL* val;
3952 SCIP_RATIONAL** aggrscalars;
3953 SCIP_RATIONAL* fixedval;
3954 SCIP_RATIONAL* aggrconst;
3955 SCIP_Real negconst;
3956 int v;
3957 int naggrvars;
3958 int i;
3959
3960 assert(scip != NULL);
3961 assert(cons != NULL);
3962
3963 if( infeasible != NULL )
3964 *infeasible = FALSE;
3965
3966 consdata = SCIPconsGetData(cons);
3967 assert(consdata != NULL);
3968
3969 if( consdata->eventdata == NULL )
3970 {
3971 SCIP_CONSHDLR* conshdlr;
3972 SCIP_CONSHDLRDATA* conshdlrdata;
3973
3974 conshdlr = SCIPconsGetHdlr(cons);
3975 assert(conshdlr != NULL);
3976
3977 conshdlrdata = SCIPconshdlrGetData(conshdlr);
3978 assert(conshdlrdata != NULL);
3979
3980 /* catch bound change events of variables */
3981 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
3982 assert(consdata->eventdata != NULL);
3983 }
3984
3985 if( !consdata->removedfixings )
3986 {
3987 SCIP_RATIONAL* lhssubtrahend;
3988 SCIP_RATIONAL* rhssubtrahend;
3989 SCIP_RATIONAL* tmpval;
3990
3994
3995 SCIPdebugMsg(scip, "applying fixings:\n");
3997
3998 v = 0;
3999 while( v < consdata->nvars )
4000 {
4001 var = consdata->vars[v];
4002 val = consdata->vals[v];
4003 assert(SCIPvarIsTransformed(var));
4004
4005 switch( SCIPvarGetStatus(var) )
4006 {
4008 SCIPerrorMessage("original variable in transformed linear constraint\n");
4009 return SCIP_INVALIDDATA;
4010
4013 ++v;
4014 break;
4015
4018 fixedval = SCIPvarGetLbGlobalExact(var);
4019 if( !SCIPrationalIsNegInfinity(consdata->lhs) )
4020 {
4021 if( SCIPrationalIsAbsInfinity(fixedval) )
4022 {
4023 if( SCIPrationalGetSign(val) == SCIPrationalGetSign(fixedval) )
4024 {
4026 SCIP_CALL( chgLhs(scip, cons, tmpval) );
4027 }
4028 else
4029 {
4030 if( infeasible != NULL )
4031 {
4032 /* if lhs gets infinity it means that the problem is infeasible */
4033 *infeasible = TRUE;
4034 return SCIP_OKAY;
4035 }
4036 else
4037 {
4039 SCIP_CALL( chgLhs(scip, cons, tmpval) );
4040 }
4041 }
4042 }
4043 else
4044 SCIPrationalAddProd(lhssubtrahend, val, fixedval);
4045 }
4046 if( !SCIPrationalIsInfinity(consdata->rhs) )
4047 {
4048 if( SCIPrationalIsAbsInfinity(fixedval) )
4049 {
4050 if( SCIPrationalGetSign(val) == SCIPrationalGetSign(fixedval) )
4051 {
4052 if( infeasible != NULL )
4053 {
4054 /* if rhs gets -infinity it means that the problem is infeasible */
4055 *infeasible = TRUE;
4056 return SCIP_OKAY;
4057 }
4058 else
4059 {
4061 SCIP_CALL( chgRhs(scip, cons, tmpval) );
4062 }
4063 }
4064 else
4065 {
4067 SCIP_CALL( chgRhs(scip, cons, tmpval) );
4068 }
4069 }
4070 else
4071 SCIPrationalAddProd(rhssubtrahend, val, fixedval);
4072 }
4073 SCIP_CALL( delCoefPos(scip, cons, v) );
4074 break;
4075
4077 {
4078 SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4079 SCIP_RATIONAL* activescalar;
4080 SCIP_RATIONAL* activeconstant;
4081
4083 SCIP_CALL( SCIPrationalCreateBuffer(SCIPbuffer(scip), &activeconstant) );
4084
4085 SCIPrationalMult(activescalar, val, SCIPvarGetAggrScalarExact(var));
4086 SCIPrationalMult(activeconstant, val, SCIPvarGetAggrConstantExact(var));
4087
4088 assert(activevar != NULL);
4089 SCIP_CALL( SCIPgetProbvarSumExact(scip, &activevar, activescalar, activeconstant) );
4090 assert(activevar != NULL);
4091
4092 if( !SCIPrationalIsZero(activescalar) )
4093 {
4094 SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4095 }
4096
4097 if( !SCIPrationalIsZero(activeconstant) )
4098 {
4099 if( !SCIPrationalIsNegInfinity(consdata->lhs) )
4100 SCIPrationalAdd(lhssubtrahend, lhssubtrahend, activeconstant);
4101 if( !SCIPrationalIsInfinity(consdata->rhs) )
4102 SCIPrationalAdd(rhssubtrahend, rhssubtrahend, activeconstant);
4103 }
4104
4105 SCIP_CALL( delCoefPos(scip, cons, v) );
4106
4107 SCIPrationalFreeBuffer(SCIPbuffer(scip), &activescalar);
4108 SCIPrationalFreeBuffer(SCIPbuffer(scip), &activeconstant);
4109 break;
4110 }
4113 naggrvars = SCIPvarGetMultaggrNVars(var);
4114 aggrvars = SCIPvarGetMultaggrVars(var);
4115 aggrscalars = SCIPvarGetMultaggrScalarsExact(var);
4116 for( i = 0; i < naggrvars; ++i )
4117 {
4118 SCIPrationalMult(tmpval, val, aggrscalars[i]);
4119 SCIP_CALL( addCoef(scip, cons, aggrvars[i], tmpval) );
4120 }
4121 aggrconst = SCIPvarGetMultaggrConstantExact(var);
4122
4123 if( !SCIPrationalIsNegInfinity(consdata->lhs) )
4124 {
4125 SCIPrationalMult(tmpval, val, aggrconst);
4126 SCIPrationalAdd(lhssubtrahend, lhssubtrahend, tmpval);
4127 }
4128 if( !SCIPrationalIsInfinity(consdata->rhs) )
4129 {
4130 SCIPrationalMult(tmpval, val, aggrconst);
4131 SCIPrationalAdd(rhssubtrahend, rhssubtrahend, tmpval);
4132 }
4133
4134 SCIP_CALL( delCoefPos(scip, cons, v) );
4135 break;
4136
4138 SCIPrationalNegate(tmpval, val);
4139 SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), tmpval) );
4140 negconst = SCIPvarGetNegationConstant(var);
4141
4142 if( !SCIPrationalIsNegInfinity(consdata->lhs) )
4143 {
4144 SCIPrationalMultReal(tmpval, val, negconst);
4145 SCIPrationalAdd(lhssubtrahend, lhssubtrahend, tmpval);
4146 }
4147 if( !SCIPrationalIsInfinity(consdata->rhs) )
4148 {
4149 SCIPrationalMultReal(tmpval, val, negconst);
4150 SCIPrationalAdd(rhssubtrahend, rhssubtrahend, tmpval);
4151 }
4152
4153 SCIP_CALL( delCoefPos(scip, cons, v) );
4154 break;
4155
4156 default:
4157 SCIPerrorMessage("unknown variable status\n");
4158 SCIPABORT();
4159 return SCIP_INVALIDDATA; /*lint !e527*/
4160 }
4161 }
4162
4163 if( !SCIPrationalIsAbsInfinity(consdata->lhs) )
4164 {
4165 SCIPrationalDiff(tmpval, consdata->lhs, lhssubtrahend);
4166 SCIP_CALL( chgLhs(scip, cons, tmpval) );
4167 }
4168 if( !SCIPrationalIsAbsInfinity(consdata->rhs) )
4169 {
4170 SCIPrationalDiff(tmpval, consdata->rhs, rhssubtrahend);
4171 SCIP_CALL( chgRhs(scip, cons, tmpval) );
4172 }
4173
4174 consdata->removedfixings = TRUE;
4175
4176 SCIPdebugMsg(scip, "after fixings:\n");
4178
4179 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4180 * to clean up the constraint
4181 */
4182 SCIP_CALL( mergeMultiples(scip, cons) );
4183
4184 SCIPdebugMsg(scip, "after merging:\n");
4186
4188 SCIPrationalFreeBuffer(SCIPbuffer(scip), &rhssubtrahend);
4189 SCIPrationalFreeBuffer(SCIPbuffer(scip), &lhssubtrahend);
4190 }
4191 assert(consdata->removedfixings);
4192
4193#ifndef NDEBUG
4194 /* check, if all fixings are applied */
4195 for( v = 0; v < consdata->nvars; ++v )
4196 assert(SCIPvarIsActive(consdata->vars[v]));
4197#endif
4198
4199 return SCIP_OKAY;
4200}
4201
4202/** prints activity conflict to certificate file */
4203static
4205 SCIP* scip, /**< SCIP data structure */
4206 SCIP_CONS* cons, /**< constraint */
4207 SCIP_CONSDATA* consdata, /**< constraint data */
4208 SCIP_Bool rhs /**< right-hand side */
4209 )
4210{
4211 SCIP_Real side;
4212 SCIP_Real activity;
4213 SCIP_RATIONAL* diff;
4214 int nvals;
4215 SCIP_RATIONAL** vals;
4216
4217 if( !SCIPisCertified(scip) )
4218 return SCIP_OKAY;
4219
4221
4222 if( rhs )
4223 {
4225 side = consdata->rhsreal;
4226 activity = consdata->minactivity;
4227 assert( activity > side );
4228 }
4229 else
4230 {
4232 side = consdata->lhsreal;
4233 activity = consdata->maxactivity;
4234 assert( activity < side );
4235 }
4236
4237 if( consdata->rowexact != NULL )
4238 {
4239 nvals = SCIProwExactGetNNonz(consdata->rowexact);
4240 vals = SCIProwExactGetVals(consdata->rowexact);
4241 }
4242 else
4243 {
4244 nvals = consdata->nvars;
4245 vals = consdata->vals;
4246 }
4247 SCIPrationalSetReal(diff, activity);
4248 SCIPrationalDiffReal(diff, diff, side);
4249
4250 SCIP_CALL( SCIPcertifyActivityConflict(scip, cons, consdata->rowexact, consdata->lhs, consdata->rhs,
4251 nvals, vals, consdata->vars, diff, rhs) );
4252
4254
4255 return SCIP_OKAY;
4256}
4257
4258/** tightens bounds of a single variable due to activity bounds */
4259static
4261 SCIP* scip, /**< SCIP data structure */
4262 SCIP_CONS* cons, /**< linear constraint */
4263 int pos, /**< position of the variable in the vars array */
4264 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4265 int* nchgbds, /**< pointer to count the total number of tightened bounds */
4266 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4267 )
4268{
4269 SCIP_CONSDATA* consdata;
4270 SCIP_VAR* var;
4271 SCIP_INTERVAL valrange;
4272 SCIP_Real lb;
4273 SCIP_Real ub;
4274 SCIP_Real minresactivity;
4275 SCIP_Real maxresactivity;
4276 SCIP_Real lhs;
4277 SCIP_Real rhs;
4278 SCIP_Bool infeasible;
4279 SCIP_Bool tightened;
4280 SCIP_Bool minisrelax;
4281 SCIP_Bool maxisrelax;
4282 SCIP_Bool isminsettoinfinity;
4283 SCIP_Bool ismaxsettoinfinity;
4284 SCIP_ROUNDMODE prevmode;
4285 SCIP_RATIONAL* tmpbound;
4286 SCIP_CONSHDLR* conshdlr;
4287 SCIP_CONSHDLRDATA* conshdlrdata;
4288
4289 conshdlr = SCIPconsGetHdlr(cons);
4290 assert(conshdlr != NULL);
4291
4292 conshdlrdata = SCIPconshdlrGetData(conshdlr);
4293 assert(conshdlrdata != NULL);
4294
4295 prevmode = SCIPintervalGetRoundingMode();
4296
4297 assert(scip != NULL);
4298 assert(cons != NULL);
4299 assert(cutoff != NULL);
4300 assert(nchgbds != NULL);
4301
4302 /* we cannot tighten variables' bounds, if the constraint may be not complete */
4303 if( SCIPconsIsModifiable(cons) )
4304 goto RETURN_SCIP_OKAY;
4305
4306 consdata = SCIPconsGetData(cons);
4307 assert(consdata != NULL);
4308
4309 *cutoff = FALSE;
4310
4311 var = consdata->vars[pos];
4312
4313 /* we cannot tighten bounds of multi-aggregated variables */
4315 {
4316 return SCIP_OKAY;
4317 }
4318 else
4319 {
4320 SCIP_VAR* tmpVar;
4321 SCIP_Real tmpBound;
4322 SCIP_BOUNDTYPE tmpBoundtype;
4323 tmpVar = var;
4324 SCIP_CALL( SCIPvarGetProbvarBound(&tmpVar, &tmpBound, &tmpBoundtype) );
4326 goto RETURN_SCIP_OKAY;
4327 }
4328 }
4329
4330 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && !conshdlrdata->propcont )
4331 return SCIP_OKAY;
4332
4333 valrange = consdata->valsreal[pos];
4334 lhs = consdata->lhsreal;
4335 rhs = consdata->rhsreal;
4336 consdataGetActivityResiduals(scip, consdata, var, valrange, FALSE, &minresactivity, &maxresactivity,
4337 &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
4338 assert(var != NULL);
4339 assert(!SCIPisInfinity(scip, lhs));
4340 assert(!SCIPisInfinity(scip, -rhs));
4341
4342 lb = SCIPvarGetLbLocal(var);
4343 ub = SCIPvarGetUbLocal(var);
4344 assert(SCIPisLE(scip, lb, ub));
4345
4346 if( valrange.sup > 0.0 )
4347 {
4348 /* check, if we can tighten the variable's bounds */
4349 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
4350 {
4351 SCIP_Real newub;
4352 SCIP_INTERVAL ubinterval;
4353
4355
4356 /* newub = (rhs + SCIPintervalNegateReal(minresactivity))/valrange.inf; */
4357 SCIPintervalSet(&ubinterval, rhs);
4358 SCIPintervalSubScalar(SCIPinfinity(scip), &ubinterval, ubinterval, minresactivity);
4359 SCIPintervalDiv(SCIPinfinity(scip), &ubinterval, ubinterval, valrange);
4360 newub = ubinterval.sup;
4361
4362 if( !SCIPisInfinity(scip, newub) &&
4363 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
4364 {
4365 /* activity is never unreliable in exact solving */
4366
4367 /* tighten upper bound */
4368 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
4369 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, valrange.inf, minresactivity, maxresactivity, lhs, rhs, newub);
4370
4372 {
4373 SCIP_Longint boundmaxdenom;
4374
4376 SCIPrationalSetReal(tmpbound, newub);
4377
4378 if( conshdlrdata->limitdenom )
4379 {
4380 boundmaxdenom = conshdlrdata->boundmaxdenom;
4381 SCIPrationalComputeApproximation(tmpbound, tmpbound, boundmaxdenom, 1);
4382 }
4383
4386 SCIP_BOUNDTYPE_UPPER, tmpbound, false, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4387
4389 &infeasible, &tightened) );
4391 }
4392 else
4393 {
4396 SCIP_BOUNDTYPE_UPPER, newub, false, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4397
4398 newub = SCIPadjustedVarUbExactFloat(scip, var, newub);
4399 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
4400 &infeasible, &tightened) );
4401 }
4402
4403 if( infeasible )
4404 {
4405 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4406 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
4407
4408 /* analyze conflict */
4411 *cutoff = TRUE;
4412 goto RETURN_SCIP_OKAY;
4413 }
4414 if( tightened )
4415 {
4416 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
4417 (*nchgbds)++;
4418
4419 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4420 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
4421 }
4422 }
4423 }
4424
4425 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
4426 {
4427 SCIP_Real newlb;
4428 SCIP_INTERVAL lbinterval;
4429
4431 /* newlb = (lhs + SCIPintervalNegateReal(maxresactivity))/valrange.sup; */
4432 SCIPintervalSet(&lbinterval, lhs);
4433 SCIPintervalSubScalar(SCIPinfinity(scip), &lbinterval, lbinterval, maxresactivity);
4434 SCIPintervalDiv(SCIPinfinity(scip), &lbinterval, lbinterval, valrange);
4435 newlb = lbinterval.inf;
4436
4437 if( !SCIPisInfinity(scip, -newlb) &&
4438 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
4439 {
4440 /* tighten lower bound */
4441 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
4442 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, valrange.inf, minresactivity, maxresactivity, lhs, rhs, newlb);
4443
4445 {
4446 SCIP_Longint boundmaxdenom;
4447
4449 SCIPrationalSetReal(tmpbound, newlb);
4450
4451 if( conshdlrdata->limitdenom )
4452 {
4453 boundmaxdenom = conshdlrdata->boundmaxdenom;
4454 SCIPrationalComputeApproximation(tmpbound, tmpbound, boundmaxdenom, -1);
4455 }
4458 SCIP_BOUNDTYPE_LOWER, tmpbound, true, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4459
4461 &infeasible, &tightened) );
4463 }
4464 else
4465 {
4468 SCIP_BOUNDTYPE_LOWER, newlb, true, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4469
4470 newlb = SCIPadjustedVarLbExactFloat(scip, var, newlb);
4471 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
4472 &infeasible, &tightened) );
4473 }
4474
4475 if( infeasible )
4476 {
4477 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4478 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
4479
4482
4483 *cutoff = TRUE;
4484 goto RETURN_SCIP_OKAY;
4485 }
4486 if( tightened )
4487 {
4488 (*nchgbds)++;
4489 SCIPdebug(lb = SCIPvarGetLbLocal(var)); /* get bound again: it may be additionally modified due to integrality */
4490 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4491 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
4492 }
4493 }
4494 }
4495 }
4496 else
4497 {
4498 /* check, if we can tighten the variable's bounds */
4499 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
4500 {
4501 SCIP_Real newlb;
4502 SCIP_INTERVAL lbinterval;
4503
4505
4506 SCIPintervalSet(&lbinterval, rhs);
4507 SCIPintervalSubScalar(SCIPinfinity(scip), &lbinterval, lbinterval, minresactivity);
4508 SCIPintervalDiv(SCIPinfinity(scip), &lbinterval, lbinterval, valrange);
4509 newlb = lbinterval.inf;
4510
4511 assert(newlb <= lbinterval.inf);
4512
4513 if( !SCIPisInfinity(scip, -newlb) &&
4514 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
4515 {
4516 /* tighten lower bound */
4517 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
4518 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, valrange.sup, minresactivity, maxresactivity, lhs, rhs, newlb);
4519
4521 {
4522 SCIP_Longint boundmaxdenom;
4523
4525 SCIPrationalSetReal(tmpbound, newlb);
4526
4527 if( conshdlrdata->limitdenom )
4528 {
4529 boundmaxdenom = conshdlrdata->boundmaxdenom;
4530 SCIPrationalComputeApproximation(tmpbound, tmpbound, boundmaxdenom, -1);
4531 }
4534 SCIP_BOUNDTYPE_LOWER, tmpbound, false, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4535
4537 &infeasible, &tightened) );
4539 }
4540 else
4541 {
4544 SCIP_BOUNDTYPE_LOWER, newlb, false, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4545
4546 newlb = SCIPadjustedVarLbExactFloat(scip, var, newlb);
4547 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
4548 &infeasible, &tightened) );
4549 }
4550
4551 if( infeasible )
4552 {
4553 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4554 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
4555
4558
4559 /**@todo analyze conflict detected in exactlinear constraint handler */
4560 *cutoff = TRUE;
4561 goto RETURN_SCIP_OKAY;
4562 }
4563 if( tightened )
4564 {
4565 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
4566 (*nchgbds)++;
4567 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4568 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
4569 }
4570 }
4571 }
4572
4573 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
4574 {
4575 SCIP_Real newub;
4576 SCIP_INTERVAL ubinterval;
4577
4579
4580 /* newub = (maxresactivity + SCIPintervalNegateReal(lhs))/SCIPintervalNegateReal(valrange.inf); */
4581 SCIPintervalSet(&ubinterval, lhs);
4582 SCIPintervalSubScalar(SCIPinfinity(scip), &ubinterval, ubinterval, maxresactivity);
4583 SCIPintervalDiv(SCIPinfinity(scip), &ubinterval, ubinterval, valrange);
4584 newub = ubinterval.sup;
4585
4586 if( !SCIPisInfinity(scip, newub) &&
4587 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
4588 {
4589 /* tighten upper bound */
4590 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
4591 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, valrange.sup, minresactivity, maxresactivity, lhs, rhs, newub);
4592
4594 {
4595 SCIP_Longint boundmaxdenom;
4596
4598 SCIPrationalSetReal(tmpbound, newub);
4599
4600 if( conshdlrdata->limitdenom )
4601 {
4602 boundmaxdenom = conshdlrdata->boundmaxdenom;
4603 SCIPrationalComputeApproximation(tmpbound, tmpbound, boundmaxdenom, 1);
4604 }
4607 SCIP_BOUNDTYPE_UPPER, tmpbound, true, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4608
4610 &infeasible, &tightened) );
4612 }
4613 else
4614 {
4617 SCIP_BOUNDTYPE_UPPER, newub, true, cons, var, consdata->rowexact, consdata->vals, consdata->lhs, consdata->rhs, consdata->vars, consdata->nvars) );
4618
4619 newub = SCIPadjustedVarUbExactFloat(scip, var, newub);
4620 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
4621 &infeasible, &tightened) );
4622 }
4623
4624 if( infeasible )
4625 {
4626 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4627 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
4628
4631
4632 *cutoff = TRUE;
4633 goto RETURN_SCIP_OKAY;
4634 }
4635 if( tightened )
4636 {
4637 (*nchgbds)++;
4638 SCIPdebug(ub = SCIPvarGetUbLocal(var)); /* get bound again: it may be additionally modified due to integrality */
4639 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4640 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
4641 }
4642 }
4643 }
4644 }
4645 RETURN_SCIP_OKAY:
4647 return SCIP_OKAY;
4648}
4649
4650#define MAXTIGHTENROUNDS 10
4651
4652/** tightens bounds of variables in constraint due to activity bounds */
4653static
4655 SCIP* scip, /**< SCIP data structure */
4656 SCIP_CONS* cons, /**< linear constraint */
4657 SCIP_Bool sortvars, /**< should variables be used in sorted order? */
4658 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4659 int* nchgbds /**< pointer to count the total number of tightened bounds */
4660 )
4661{
4662 SCIP_CONSDATA* consdata;
4663 unsigned int tightenmode;
4664 int nvars;
4665 int nrounds;
4666 int lastchange;
4667 int v;
4668 SCIP_Bool force;
4669
4670 assert(scip != NULL);
4671 assert(cons != NULL);
4672 assert(nchgbds != NULL);
4673 assert(cutoff != NULL);
4674
4675 *cutoff = FALSE;
4676
4677 /* we cannot tighten variables' bounds, if the constraint may be not complete */
4678 if( SCIPconsIsModifiable(cons) )
4679 return SCIP_OKAY;
4680
4681 /* currently, we do not need to call applyFixings() as in cons_linear.c */
4682
4683 consdata = SCIPconsGetData(cons);
4684 assert(consdata != NULL);
4685
4686 nvars = consdata->nvars;
4687 force = (nvars == 1) && !SCIPconsIsModifiable(cons);
4688
4689 /* we are at the root node or during presolving */
4690 if( SCIPgetDepth(scip) < 1 )
4691 tightenmode = 2;
4692 else
4693 tightenmode = 1;
4694
4695 /* stop if we already tightened the constraint and the tightening is not forced */
4696 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
4697 return SCIP_OKAY;
4698
4699 /* ensure that the variables are properly sorted */
4700 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
4701 {
4702 SCIP_CALL( consdataSort(scip, consdata) );
4703 assert(consdata->coefsorted);
4704 }
4705
4706 /* update maximal activity delta if necessary */
4707 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
4709
4710 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
4711 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
4712 checkMaxActivityDelta(scip, consdata);
4713
4714 /* this may happen if all variables are fixed */
4715 if( SCIPisFeasZero(scip, consdata->maxactdelta) )
4716 return SCIP_OKAY;
4717
4718 if( !SCIPisInfinity(scip, consdata->maxactdelta) )
4719 {
4720 SCIP_Real slack;
4721 SCIP_Real surplus;
4722 SCIP_Real minactivity;
4723 SCIP_Real maxactivity;
4724 SCIP_Bool minisrelax;
4725 SCIP_Bool maxisrelax;
4726 SCIP_Bool isminsettoinfinity;
4727 SCIP_Bool ismaxsettoinfinity;
4728
4729 /* use maximal activity delta to skip propagation (cannot deduce anything) */
4730 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax,
4731 &isminsettoinfinity, &ismaxsettoinfinity);
4732
4733 assert(!SCIPisInfinity(scip, minactivity));
4734 assert(!SCIPisInfinity(scip, -maxactivity));
4735
4736 slack = (SCIPisInfinity(scip, consdata->rhsreal) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhsreal - minactivity);
4737 surplus = (SCIPisInfinity(scip, -consdata->lhsreal) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhsreal);
4738
4739 /* check if the constraint will propagate */
4740 if( consdata->maxactdelta <= MIN(slack, surplus) )
4741 return SCIP_OKAY;
4742 }
4743
4744 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
4745 lastchange = -1;
4746
4747 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
4748 {
4749#ifdef SCIP_DEBUG
4750 int oldnchgbdstotal = *nchgbds;
4751#endif
4752
4753 /* ensure that the variables are properly sorted
4754 *
4755 * note: it might happen that integer variables become binary during bound tightening at the root node
4756 */
4757 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
4758 {
4759 SCIP_CALL( consdataSort(scip, consdata) );
4760 assert(consdata->coefsorted);
4761 }
4762
4763 /* mark the constraint to have the variables' bounds tightened */
4764 consdata->boundstightened = (unsigned int)tightenmode;
4765 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
4766 * sorting enables skipping variables
4767 */
4768 v = 0;
4769 while( v < nvars && v != lastchange && !(*cutoff) )
4770 {
4771 int oldnchgbds = *nchgbds;
4772
4773 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
4774
4775 /* if there was no progress, skip the rest of the binary variables */
4776 if( *cutoff )
4777 {
4778 break;
4779 }
4780 else if( *nchgbds > oldnchgbds )
4781 {
4782 lastchange = v;
4783 ++v;
4784 }
4785 else if( consdata->coefsorted && v < consdata->nbinvars - 1
4786 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
4787 v = consdata->nbinvars;
4788 else
4789 ++v;
4790 }
4791
4792#ifdef SCIP_DEBUG
4793 SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
4794 *nchgbds - oldnchgbdstotal, nrounds);
4795#endif
4796 }
4797
4798 return SCIP_OKAY;
4799}
4800
4801/** checks linear constraint for feasibility of given solution or current solution */
4802static
4804 SCIP* scip, /**< SCIP data structure */
4805 SCIP_CONS* cons, /**< linear constraint */
4806 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
4807 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
4808 SCIP_Bool useexactsol, /**< should the sol or solex be checked? */
4809 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
4810 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
4811 )
4812{
4813 SCIP_CONSDATA* consdata;
4814 SCIP_RATIONAL* activity;
4815 SCIP_Bool success;
4816
4817 assert(scip != NULL);
4818 assert(cons != NULL);
4819 assert(violated != NULL);
4820
4821 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
4822 SCIPdebug(consPrintConsSol(scip, cons, sol, useexactsol, NULL));
4823
4824 consdata = SCIPconsGetData(cons);
4825 assert(consdata != NULL);
4826
4827 *violated = FALSE;
4828 activity = consdata->activity;
4829
4830 /* only check exact constraint if fp cons is feasible enough */
4831 if( (consdata->rowexact == NULL || checklprows) && !SCIPrationalIsEQ(consdata->lhs, consdata->rhs) )
4832 {
4833 SCIP_Real activityfp;
4834 SCIP_Real mu;
4835
4836 success = consdataComputeSolActivityWithErrorbound(scip, consdata, sol, &activityfp, &mu);
4837
4838 conshdlrdata->ncheckserrorbound++;
4839
4840 if( !success )
4841 conshdlrdata->nabotserrorbound++;
4842
4843 if( success )
4844 {
4845 if( activityfp - mu > consdata->rhsreal || activityfp + mu < consdata->lhsreal )
4846 {
4847 SCIPdebugMsg(scip, "discarding solution due to fp check: activityfp=%g, lhsreal=%g, rhsreal=%g, mu=%g\n",
4848 activityfp, consdata->lhsreal, consdata->rhsreal, mu);
4849 *violated = TRUE;
4850 conshdlrdata->nsuccesserrorbound++;
4851 return SCIP_OKAY;
4852 }
4853 else if( activityfp + mu < consdata->rhsreal && activityfp - mu >= consdata->lhsreal )
4854 {
4855 SCIPdebugMsg(scip, "skipping exact check due to fp check: activityfp=%g, lhsreal=%g, rhsreal=%g, mu=%g\n",
4856 activityfp, consdata->lhsreal, consdata->rhsreal, mu);
4857 *violated = FALSE;
4858 conshdlrdata->nsuccesserrorbound++;
4859 return SCIP_OKAY;
4860 }
4861 else
4862 {
4863 SCIPdebugMsg(scip, "no decision due to fp check: activityfp=%g, lhsreal=%g, rhsreal=%g, mu=%g\n",
4864 activityfp, consdata->lhsreal, consdata->rhsreal, mu);
4865 }
4866 }
4867 }
4868
4869 if( consdata->rowexact != NULL )
4870 {
4871 if( !checklprows && SCIProwExactIsInLP(consdata->rowexact) && SCIPlpExactIsSolved(scip) )
4872 return SCIP_OKAY;
4873 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
4874 consdataComputePseudoActivity(consdata, activity);
4875 else
4876 {
4877 SCIP_CALL( SCIPgetRowSolActivityExact(scip, consdata->rowexact, sol, useexactsol, activity) );
4878 }
4879 }
4880 else
4881 consdataGetActivity(scip, consdata, sol, useexactsol, activity);
4882
4883 SCIPrationalDebugMessage("consdata activity=%q (lhs=%q, rhs=%q, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
4884 activity, consdata->lhs, consdata->rhs, (void*)consdata->rowexact, checklprows,
4885 consdata->rowexact == NULL ? 0 : SCIProwExactIsInLP(consdata->rowexact), (void*)sol,
4886 consdata->rowexact == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
4887
4888 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
4889 * return infeasible for safety
4890 */
4891 if( ((!SCIPrationalIsNegInfinity(consdata->lhs) && SCIPrationalIsLT(activity, consdata->lhs)) ||
4892 (!SCIPrationalIsInfinity(consdata->rhs) && SCIPrationalIsGT(activity, consdata->rhs))) )
4893 {
4894 *violated = TRUE;
4895
4896 /* only reset constraint age if we are in enforcement */
4897 if( sol == NULL )
4898 {
4900 }
4901 }
4902 else
4903 {
4904 /* only increase constraint age if we are in enforcement */
4905 if( sol == NULL )
4906 {
4907 SCIP_CALL( SCIPincConsAge(scip, cons) );
4908 }
4909 }
4910
4911 return SCIP_OKAY;
4912}
4913
4914/** creates an LP row in a linear constraint data */
4915static
4917 SCIP* scip, /**< SCIP data structure */
4918 SCIP_CONS* cons /**< linear constraint */
4919 )
4920{
4921 SCIP_CONSDATA* consdata;
4922 SCIP_Bool onerowrelax;
4923 SCIP_Bool hasfprelax;
4924
4925 assert(scip != NULL);
4926 assert(cons != NULL);
4927
4928 consdata = SCIPconsGetData(cons);
4929
4930 assert(consdata != NULL);
4931 assert(consdata->rowexact == NULL);
4932
4933 /* create empty fp-rows */
4936
4939
4940 /* create exact row */
4941 SCIP_CALL( SCIPcreateEmptyRowConsExact(scip, &consdata->rowexact, consdata->rowlhs, consdata->rowrhs,
4942 consdata->lhs, consdata->rhs, consdata->hasfprelax) );
4943
4944 SCIP_CALL( SCIPcaptureRowExact(scip, consdata->rowexact) );
4945
4946 SCIP_CALL( SCIPaddVarsToRowExact(scip, consdata->rowexact, consdata->nvars, consdata->vars, consdata->vals) );
4947
4948 onerowrelax = TRUE;
4949 hasfprelax = TRUE;
4950
4951 SCIP_CALL( SCIPgenerateFpRowsFromRowExact(scip, consdata->rowexact, consdata->rowlhs,
4952 consdata->rowrhs, &onerowrelax, &hasfprelax) );
4953
4954 consdata->onerowrelax = onerowrelax;
4955 consdata->hasfprelax = hasfprelax;
4957 if( !(consdata->hasfprelax) || consdata->onerowrelax )
4958 consdata->rowrhs = NULL;
4959
4960 return SCIP_OKAY;
4961}
4962
4963/** adds linear constraint as cut to the LP */
4964static
4966 SCIP* scip, /**< SCIP data structure */
4967 SCIP_CONS* cons, /**< linear constraint */
4968 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
4969 )
4970{
4971 SCIP_CONSDATA* consdata;
4972
4973 assert(scip != NULL);
4974 assert(cons != NULL);
4975
4976 consdata = SCIPconsGetData(cons);
4977 assert(consdata != NULL);
4978
4979 if( consdata->rowexact == NULL )
4980 {
4981 /* convert consdata object into LP row and exact lp row */
4982 SCIP_CALL( createRows(scip, cons) );
4983 }
4984 assert(consdata->rowlhs != NULL);
4985 assert(consdata->rowexact != NULL);
4986
4987 if( consdata->nvars == 0 )
4988 {
4989 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
4990 }
4991
4992 /* insert LP row as cut */
4993 if( !SCIProwIsInLP(consdata->rowlhs) )
4994 {
4995 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
4996 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->rowlhs, NULL)) );
4997 SCIPdebug( SCIP_CALL( SCIPprintRowExact(scip, consdata->rowexact, NULL)) );
4998
4999 /* if presolving is turned off, the row might be trivial */
5000 if( !SCIPrationalIsNegInfinity(consdata->lhs) || !SCIPrationalIsInfinity(consdata->rhs) )
5001 {
5002 SCIP_CALL( SCIPaddRow(scip, consdata->rowlhs, FALSE, cutoff) );
5003 SCIP_CALL( SCIPaddRowExact(scip, consdata->rowexact) );
5004 }
5005#ifndef NDEBUG
5006 else
5007 {
5008 int pr;
5009 int cr;
5010 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
5011 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
5012 assert( pr == 0 || cr == 0 );
5013 }
5014#endif
5015 }
5016
5017 return SCIP_OKAY;
5018}
5019
5020/** separates linear constraint: adds linear constraint as cut, if violated by given solution */
5021static
5023 SCIP* scip, /**< SCIP data structure */
5024 SCIP_CONS* cons, /**< linear constraint */
5025 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
5026 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
5027 int* ncuts, /**< pointer to add up the number of found cuts */
5028 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
5029 )
5030{ /*lint --e{715}*/
5031 SCIP_Bool violated;
5032 int oldncuts;
5033
5034 assert(scip != NULL);
5035 assert(conshdlrdata != NULL);
5036 assert(cons != NULL);
5037 assert(cutoff != NULL);
5038
5039 assert(ncuts != NULL);
5040
5041 oldncuts = *ncuts;
5042 *cutoff = FALSE;
5043
5044 SCIP_CALL( checkCons(scip, cons, conshdlrdata, sol, FALSE, (sol != NULL), &violated) );
5045
5046 if( violated )
5047 {
5048 /* insert LP row as cut */
5049 SCIP_CALL( addRelaxation(scip, cons, cutoff) );
5050 (*ncuts)++;
5051 }
5052
5053 if( *ncuts > oldncuts )
5054 {
5056 }
5057
5058 return SCIP_OKAY;
5059}
5060
5061/** propagation method for linear constraints */
5062static
5064 SCIP* scip, /**< SCIP data structure */
5065 SCIP_CONS* cons, /**< linear constraint */
5066 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
5067 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
5068 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5069 int* nchgbds /**< pointer to count the total number of tightened bounds */
5070 )
5071{
5072 SCIP_CONSDATA* consdata;
5073 SCIP_Real minactivity;
5074 SCIP_Real maxactivity;
5075 SCIP_Bool minactisrelax;
5076 SCIP_Bool maxactisrelax;
5077 SCIP_Bool isminsettoinfinity;
5078 SCIP_Bool ismaxsettoinfinity;
5079
5080 assert(scip != NULL);
5081 assert(cons != NULL);
5082 assert(cutoff != NULL);
5083 assert(nchgbds != NULL);
5084
5085 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
5086
5087 consdata = SCIPconsGetData(cons);
5088 assert(consdata != NULL);
5089
5090 if( consdata->eventdata == NULL )
5091 {
5092 SCIP_CONSHDLR* conshdlr;
5093 SCIP_CONSHDLRDATA* conshdlrdata;
5094
5095 conshdlr = SCIPconsGetHdlr(cons);
5096 assert(conshdlr != NULL);
5097
5098 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5099 assert(conshdlrdata != NULL);
5100
5101 /* catch bound change events of variables */
5102 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
5103 assert(consdata->eventdata != NULL);
5104 }
5105
5106 *cutoff = FALSE;
5107
5108 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
5109 if( !SCIPconsIsModifiable(cons) )
5110 {
5111 SCIP_CONSHDLR* conshdlr;
5112 SCIP_CONSHDLRDATA* conshdlrdata;
5113
5114 conshdlr = SCIPconsGetHdlr(cons);
5115 assert(conshdlr != NULL);
5116
5117 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5118 assert(conshdlrdata != NULL);
5119
5120 if( !SCIPconsIsInitial(cons) )
5121 {
5122 conshdlrdata->nconspropnoninit++;
5123 conshdlrdata->propnonzerosnoninit += consdata->nvars;
5124 }
5125 else
5126 {
5127 conshdlrdata->nconsprop++;
5128 conshdlrdata->propnonzeros += consdata->nvars;
5129 }
5130
5131 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
5133 {
5134 SCIP_CALL( SCIPincConsAge(scip, cons) );
5135 }
5136
5137 /* tighten the variable's bounds */
5138 if( tightenbounds )
5139 {
5140 int oldnchgbds;
5141
5142 oldnchgbds = *nchgbds;
5143
5144 SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
5145
5146 if( *nchgbds > oldnchgbds )
5147 {
5149 }
5150 }
5151
5152 /* check constraint for infeasibility and redundancy */
5153 if( !(*cutoff) )
5154 {
5155 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
5156 &isminsettoinfinity, &ismaxsettoinfinity);
5157
5158 if( SCIPrationalIsGTReal(consdata->lhs, maxactivity) )
5159 {
5160 SCIPrationalDebugMessage("linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%q,%q]\n",
5161 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
5162
5164
5165 /**@todo analyze conflict detected in exactlinear constraint handler */
5167 *cutoff = TRUE;
5168 }
5169 else if( SCIPrationalIsLTReal(consdata->rhs, minactivity) )
5170 {
5171 SCIPrationalDebugMessage("linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%q,%q]\n",
5172 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
5173
5175
5176 /**@todo analyze conflict detected in exactlinear constraint handler */
5178 *cutoff = TRUE;
5179 }
5180 else if( SCIPrationalIsLEReal(consdata->lhs, minactivity) && SCIPrationalIsGEReal(consdata->rhs, maxactivity) )
5181 {
5182 SCIPrationalDebugMessage("linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%q,%q]\n",
5183 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
5184
5185 /* remove the constraint locally unless it has become empty, in which case it is removed globally */
5186 if( consdata->nvars > 0 )
5188 else
5189 SCIP_CALL( SCIPdelCons(scip, cons) );
5190 }
5191 }
5192 }
5193
5194 return SCIP_OKAY;
5195}
5196
5197
5198/*
5199 * Presolving methods
5200 */
5201
5202/** helper function to enforce constraints */
5203static
5205 SCIP* scip, /**< SCIP data structure */
5206 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
5207 SCIP_CONS** conss, /**< constraints to process */
5208 int nconss, /**< number of constraints */
5209 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
5210 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
5211 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
5212 )
5213{
5214 SCIP_CONSHDLRDATA* conshdlrdata;
5215 SCIP_Bool violated;
5216 SCIP_Bool checkexact;
5217 SCIP_Bool cutoff = FALSE;
5218 int c;
5219
5220 assert(scip != NULL);
5221 assert(conshdlr != NULL);
5222 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5223 assert(result != NULL);
5224
5225 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5226 assert(conshdlrdata != NULL);
5227
5228 if( sol == NULL )
5229 checkexact = SCIPlpExactIsSolved(scip);
5230 else
5231 checkexact = SCIPsolIsExact(sol);
5232
5233 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
5235
5236 /* check for violated constraints
5237 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
5238 */
5239 *result = SCIP_FEASIBLE;
5240
5241 /* check all useful linear constraints for feasibility */
5242 for( c = 0; c < nusefulconss; ++c )
5243 {
5244 SCIP_CALL( checkCons(scip, conss[c], conshdlrdata, sol, checkexact, FALSE, &violated) );
5245
5246 if( violated )
5247 {
5248 /* insert LP row as cut */
5249 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
5250 if( cutoff )
5251 *result = SCIP_CUTOFF;
5252 else
5253 *result = SCIP_SEPARATED;
5254 }
5255 }
5256
5257 /* check all obsolete linear constraints for feasibility */
5258 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
5259 {
5260 SCIP_CALL( checkCons(scip, conss[c], conshdlrdata, sol, checkexact, FALSE, &violated) );
5261
5262 if( violated )
5263 {
5264 /* insert LP row as cut */
5265 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
5266 if( cutoff )
5267 *result = SCIP_CUTOFF;
5268 else
5269 *result = SCIP_SEPARATED;
5270 }
5271 }
5272
5273 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
5274
5275 return SCIP_OKAY;
5276}
5277
5278/*
5279 * Callback methods of constraint handler
5280 */
5281
5282/** copy method for constraint handler plugins (called when SCIP copies plugins) */
5283static
5284SCIP_DECL_CONSHDLRCOPY(conshdlrCopyExactLinear)
5285{ /*lint --e{715}*/
5286 assert(scip != NULL);
5287 assert(conshdlr != NULL);
5288 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5289
5290 /* call inclusion method of constraint handler */
5292
5293 *valid = TRUE;
5294
5295 return SCIP_OKAY;
5296}
5297
5298/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
5299static
5300SCIP_DECL_CONSFREE(consFreeExactLinear)
5301{ /*lint --e{715}*/
5302 SCIP_CONSHDLRDATA* conshdlrdata;
5303
5304 assert(scip != NULL);
5305 assert(conshdlr != NULL);
5306 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5307
5308 /* free constraint handler data */
5309 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5310 assert(conshdlrdata != NULL);
5311
5312 conshdlrdataFree(scip, &conshdlrdata);
5313
5314 SCIPconshdlrSetData(conshdlr, NULL);
5315
5316 return SCIP_OKAY;
5317}
5318
5319
5320/** initialization method of constraint handler (called after problem was transformed) */
5321static
5322SCIP_DECL_CONSINIT(consInitExactLinear)
5323{
5324 SCIP_CONSHDLRDATA* conshdlrdata;
5325 int c;
5326
5327 assert(scip != NULL);
5328 assert(SCIPisExact(scip) || nconss == 0);
5329
5330 /* check for event handler */
5331 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5332 assert(conshdlrdata != NULL);
5333 assert(conshdlrdata->eventhdlr != NULL);
5334 assert(nconss == 0 || conss != NULL);
5335
5336 /* catch events for the constraints */
5337 for( c = 0; c < nconss; ++c )
5338 {
5339 /* catch all events */
5340 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
5341 }
5342
5343 return SCIP_OKAY;
5344}
5345
5346
5347/** deinitialization method of constraint handler (called before transformed problem is freed) */
5348static
5349SCIP_DECL_CONSEXIT(consExitExactLinear)
5350{
5351 SCIP_CONSHDLRDATA* conshdlrdata;
5352 int c;
5353
5354 assert(scip != NULL);
5355 assert(SCIPisExact(scip) || nconss == 0);
5356
5357 /* check for event handler */
5358 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5359 assert(conshdlrdata != NULL);
5360 assert(conshdlrdata->eventhdlr != NULL);
5361
5362 /* drop events for the constraints */
5363 for( c = nconss - 1; c >= 0; --c )
5364 {
5365 SCIP_CONSDATA* consdata;
5366
5367 consdata = SCIPconsGetData(conss[c]);
5368 assert(consdata != NULL);
5369
5370 if( consdata->eventdata != NULL )
5371 {
5372 /* drop all events */
5373 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
5374 assert(consdata->eventdata == NULL);
5375 }
5376 }
5377
5378 return SCIP_OKAY;
5379}
5380
5381/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
5382static
5383SCIP_DECL_CONSEXITPRE(consExitpreExactLinear)
5384{ /*lint --e{715}*/
5385 int c;
5386
5387 assert(scip != NULL);
5388 assert(SCIPisExact(scip) || nconss == 0);
5389
5390 /* make sure, only active variables remain in the remaining constraints */
5391 for( c = 0; c < nconss; ++c )
5392 {
5393 if( SCIPconsIsDeleted(conss[c]) )
5394 continue;
5395
5396 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
5397 SCIP_CALL( applyFixings(scip, conss[c], NULL) );
5398 }
5399
5400 return SCIP_OKAY;
5401}
5402
5403
5404/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
5405static
5406SCIP_DECL_CONSEXITSOL(consExitsolExactLinear)
5407{ /*lint --e{715}*/
5408 int c;
5409
5410 assert(scip != NULL);
5411 assert(SCIPisExact(scip) || nconss == 0);
5412
5413 if( !SCIPisExact(scip) )
5414 return SCIP_OKAY;
5415
5416 /* release the rows of all constraints */
5417 for( c = 0; c < nconss; ++c )
5418 {
5419 SCIP_CONSDATA* consdata;
5420
5421 consdata = SCIPconsGetData(conss[c]);
5422 assert(consdata != NULL);
5423
5424 if( consdata->rowlhs != NULL )
5425 {
5426 SCIP_CALL( SCIPreleaseRowExact(scip, &consdata->rowexact) );
5427 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowlhs) );
5428
5429 if( consdata->rowrhs != NULL )
5430 {
5431 assert(!consdata->onerowrelax);
5432 SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowrhs) );
5433 }
5434 }
5435 }
5436
5437 /**@todo when enabling restarts, extend SCIPconvertCutsToConss() in order to convert exact cuts to exactlinear
5438 * constraints and call here
5439 */
5440
5441 return SCIP_OKAY;
5442}
5443
5444
5445/** constraint deactivation notification method of constraint handler */
5446static
5447SCIP_DECL_CONSDEACTIVE(consDeactiveExactLinear)
5448{ /*lint --e{715}*/
5449 assert(scip != NULL);
5450 assert(SCIPisExact(scip));
5451 assert(cons != NULL);
5452
5453 if( SCIPconsIsDeleted(cons) )
5454 {
5455 SCIP_CONSHDLRDATA* conshdlrdata;
5456 SCIP_CONSDATA* consdata;
5457
5458 assert(conshdlr != NULL);
5459 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5460
5461 /* get constraint data */
5462 consdata = SCIPconsGetData(cons);
5463 assert(consdata != NULL);
5464
5465 /* check for event handler */
5466 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5467 assert(conshdlrdata != NULL);
5468 assert(conshdlrdata->eventhdlr != NULL);
5469
5470 /* free event data */
5471 if( consdata->eventdata != NULL )
5472 {
5473 /* drop bound change events of variables */
5474 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
5475 }
5476 assert(consdata->eventdata == NULL);
5477 }
5478
5479 return SCIP_OKAY;
5480}
5481
5482
5483/** frees specific constraint data */
5484static
5485SCIP_DECL_CONSDELETE(consDeleteExactLinear)
5486{ /*lint --e{715}*/
5487 assert(scip != NULL);
5488 assert(SCIPisExact(scip));
5489 assert(conshdlr != NULL);
5490 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5491
5492 if( (*consdata)->eventdata != NULL )
5493 {
5494 SCIP_CONSHDLRDATA* conshdlrdata;
5495
5496 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5497 assert(conshdlrdata != NULL);
5498
5499 /* drop all events */
5500 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
5501 assert((*consdata)->eventdata == NULL);
5502 }
5503 /* free linear constraint */
5504 SCIP_CALL( consdataFree(scip, consdata) );
5505
5506 return SCIP_OKAY;
5507}
5508
5509
5510/** transforms constraint data into data belonging to the transformed problem */
5511static
5512SCIP_DECL_CONSTRANS(consTransExactLinear)
5513{ /*lint --e{715}*/
5514 SCIP_CONSDATA* sourcedata;
5515 SCIP_CONSDATA* targetdata;
5516
5517 assert(scip != NULL);
5518 assert(SCIPisExact(scip));
5519 assert(conshdlr != NULL);
5520 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5522 assert(sourcecons != NULL);
5523 assert(targetcons != NULL);
5524
5525 sourcedata = SCIPconsGetData(sourcecons);
5526 assert(sourcedata != NULL);
5527 assert(sourcedata->rowlhs == NULL && sourcedata->rowexact == NULL); /* in original problem, there cannot be LP rows */
5528
5529 /* create linear constraint data for target constraint */
5530 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs,
5531 sourcedata->rhs) );
5532
5533 if( sourcedata->nvars > 0 )
5534 consdataScaleMinValue(scip, targetdata, 2 * SCIPepsilon(scip));
5535
5536 /* create target constraint */
5537 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
5538 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
5539 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
5540 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
5541 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
5542
5543 return SCIP_OKAY;
5544}
5545
5546/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
5547static
5548SCIP_DECL_CONSINITLP(consInitlpExactLinear)
5549{ /*lint --e{715}*/
5550 int c;
5551
5552 assert(scip != NULL);
5553 assert(SCIPisExact(scip) || nconss == 0);
5554 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5555
5556 *infeasible = FALSE;
5557
5558 for( c = 0; c < nconss && !(*infeasible); ++c )
5559 {
5560 assert(SCIPconsIsInitial(conss[c]));
5561 /* add both the relaxation to the fp-lp as well as the correct constraint to the exact lp */
5562 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
5563 }
5564
5565 return SCIP_OKAY;
5566}
5567
5568/** separation method of constraint handler for LP solutions */
5569static
5570SCIP_DECL_CONSSEPALP(consSepalpExactLinear)
5571{ /*lint --e{715}*/
5572 SCIP_CONSHDLRDATA* conshdlrdata;
5573 SCIP_Bool cutoff;
5574 int c;
5575 int depth;
5576 int nrounds;
5577 int maxsepacuts;
5578 int ncuts;
5579
5580 assert(scip != NULL);
5581 assert(SCIPisExact(scip) || nconss == 0);
5582 assert(conshdlr != NULL);
5583 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5584 assert(result != NULL);
5585
5586 if( !SCIPisExact(scip) )
5587 return SCIP_OKAY;
5588
5589 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5590 assert(conshdlrdata != NULL);
5591 depth = SCIPgetDepth(scip);
5592 nrounds = SCIPgetNSepaRounds(scip);
5593
5594 *result = SCIP_DIDNOTRUN;
5595
5596 /* only call the separator a given number of times at each node */
5597 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
5598 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
5599 return SCIP_OKAY;
5600
5601 /* get the maximal number of cuts allowed in a separation round */
5602 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
5603
5604 *result = SCIP_DIDNOTFIND;
5605 ncuts = 0;
5606 cutoff = FALSE;
5607
5608 /* check all useful linear constraints for feasibility */
5609 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
5610 {
5611 SCIPdebugMsg(scip, "separating exact linear constraint <%s>\n", SCIPconsGetName(conss[c]));
5612 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, &ncuts, &cutoff) );
5613 }
5614
5615 /* adjust return value */
5616 if( cutoff )
5617 *result = SCIP_CUTOFF;
5618 else if( ncuts > 0 )
5619 *result = SCIP_SEPARATED;
5620
5621 return SCIP_OKAY;
5622}
5623
5624
5625/** separation method of constraint handler for arbitrary primal solutions */
5626static
5627SCIP_DECL_CONSSEPASOL(consSepasolExactLinear)
5628{ /*lint --e{715}*/
5629 SCIP_CONSHDLRDATA* conshdlrdata;
5630 int c;
5631 int depth;
5632 int nrounds;
5633 int maxsepacuts;
5634 int ncuts;
5635 SCIP_Bool cutoff;
5636
5637 assert(scip != NULL);
5638 assert(SCIPisExact(scip) || nconss == 0);
5639 assert(conshdlr != NULL);
5640 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5641 assert(result != NULL);
5642
5643 if( !SCIPisExact(scip) )
5644 return SCIP_OKAY;
5645
5646 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5647 assert(conshdlrdata != NULL);
5648 depth = SCIPgetDepth(scip);
5649 nrounds = SCIPgetNSepaRounds(scip);
5650
5651 *result = SCIP_DIDNOTRUN;
5652
5653 /* only call the separator a given number of times at each node */
5654 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
5655 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
5656 return SCIP_OKAY;
5657
5658 /* get the maximal number of cuts allowed in a separation round */
5659 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
5660
5661 *result = SCIP_DIDNOTFIND;
5662 ncuts = 0;
5663 cutoff = FALSE;
5664
5665 /* check all useful linear constraints for feasibility */
5666 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
5667 {
5668 SCIPdebugMsg(scip, "separating exact linear constraint <%s>\n", SCIPconsGetName(conss[c]));
5669 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, &ncuts, &cutoff) );
5670 }
5671
5672 /* adjust return value */
5673 if( cutoff )
5674 *result = SCIP_CUTOFF;
5675 else if( ncuts > 0 )
5676 *result = SCIP_SEPARATED;
5677
5678 return SCIP_OKAY;
5679}
5680
5681
5682/** constraint enforcing method of constraint handler for LP solutions */
5683static
5684SCIP_DECL_CONSENFOLP(consEnfolpExactLinear)
5685{ /*lint --e{715}*/
5686 assert(scip != NULL);
5687 assert(SCIPisExact(scip) || nconss == 0);
5688
5689 if( !SCIPisExact(scip) )
5690 return SCIP_OKAY;
5691
5692 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
5693
5694 return SCIP_OKAY;
5695}
5696
5697/** constraint enforcing method of constraint handler for relaxation solutions */
5698static
5699SCIP_DECL_CONSENFORELAX(consEnforelaxExactLinear)
5700{ /*lint --e{715}*/
5701 assert(scip != NULL);
5702 assert(SCIPisExact(scip) || nconss == 0);
5703
5704 if( !SCIPisExact(scip) )
5705 return SCIP_OKAY;
5706
5707 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
5708
5709 return SCIP_OKAY;
5710}
5711
5712/** constraint enforcing method of constraint handler for pseudo solutions */
5713static
5714SCIP_DECL_CONSENFOPS(consEnfopsExactLinear)
5715{ /*lint --e{715}*/
5716 SCIP_CONSHDLRDATA* conshdlrdata;
5717 SCIP_Bool violated;
5718 int c;
5719
5720 assert(scip != NULL);
5721 assert(SCIPisExact(scip) || nconss == 0);
5722 assert(conshdlr != NULL);
5723 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5724 assert(result != NULL);
5725
5726 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5727 assert(conshdlrdata != NULL);
5728
5729 SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
5730
5731 if( !SCIPisExact(scip) )
5732 {
5733 *result = SCIP_DIDNOTRUN;
5734 return SCIP_OKAY;
5735 }
5736
5737 /* if the solution is infeasible anyway due to objective value, skip the enforcement */
5738 if( objinfeasible )
5739 {
5740 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
5741
5742 *result = SCIP_DIDNOTRUN;
5743 return SCIP_OKAY;
5744 }
5745
5746 /* check all linear constraints for feasibility */
5747 violated = FALSE;
5748 for( c = 0; c < nconss && !violated; ++c )
5749 {
5750 SCIP_CALL( checkCons(scip, conss[c], conshdlrdata, NULL, FALSE, TRUE, &violated) );
5751 }
5752
5753 if( violated )
5754 *result = SCIP_INFEASIBLE;
5755 else
5756 *result = SCIP_FEASIBLE;
5757
5758 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
5759
5760 return SCIP_OKAY;
5761}
5762
5763
5764/** feasibility check method of constraint handler for integral solutions */
5765static
5766SCIP_DECL_CONSCHECK(consCheckExactLinear)
5767{ /*lint --e{715}*/
5768 SCIP_CONSHDLRDATA* conshdlrdata;
5769 SCIP_Bool checkexact;
5770 int c;
5771
5772 assert(scip != NULL);
5773 assert(SCIPisExact(scip) || nconss == 0);
5774 assert(conshdlr != NULL);
5775 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5776 assert(result != NULL);
5777
5778 *result = SCIP_FEASIBLE;
5779
5780 if( !SCIPisExact(scip) )
5781 return SCIP_OKAY;
5782
5783 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5784 assert(conshdlrdata != NULL);
5785
5786 /* if the fp-solution has a stand-in exact solution we check that instead */
5787 checkexact = SCIPsolIsExact(sol);
5788
5789 /* check all linear constraints for feasibility */
5790 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
5791 {
5792 SCIP_Bool violated = FALSE;
5793 SCIP_CALL( checkCons(scip, conss[c], conshdlrdata, sol, checkexact, checklprows, &violated) );
5794
5795 if( violated )
5796 {
5797 *result = SCIP_INFEASIBLE;
5798
5799 if( printreason )
5800 {
5801 SCIP_CONSDATA* consdata;
5802 SCIP_RATIONAL* activity;
5803
5805
5806 consdata = SCIPconsGetData(conss[c]);
5807 assert( consdata != NULL);
5808
5809 consdataGetActivity(scip, consdata, sol, checkexact, activity);
5810
5811 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, checkexact, NULL ) );
5812 SCIPinfoMessage(scip, NULL, ";\n");
5813
5814 if( SCIPrationalIsAbsInfinity(activity) )
5815 SCIPinfoMessage(scip, NULL, "activity invalid due to infinity contributions\n");
5816 else if( SCIPrationalIsLT(activity, consdata->lhs) )
5817 {
5818 SCIPrationalDiff(activity, consdata->lhs, activity);
5819 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by ");
5821 SCIPinfoMessage(scip, NULL, "\n");
5822 }
5823 else if( SCIPrationalIsGT(activity, consdata->rhs) )
5824 {
5825 SCIPrationalDiff(activity, activity, consdata->rhs);
5826 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by ");
5828 SCIPinfoMessage(scip, NULL, "\n");
5829 }
5830
5832 }
5833 }
5834 }
5835
5836 return SCIP_OKAY;
5837}
5838
5839/** domain propagation method of constraint handler */
5840static
5841SCIP_DECL_CONSPROP(consPropExactLinear)
5842{ /*lint --e{715}*/
5843 SCIP_CONSHDLRDATA* conshdlrdata;
5844 SCIP_Bool tightenbounds;
5845 SCIP_Bool cutoff;
5846
5847 int nchgbds;
5848 int i;
5849
5850 assert(scip != NULL);
5851 assert(SCIPisExact(scip) || nconss == 0);
5852 assert(conshdlr != NULL);
5853 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
5854 assert(result != NULL);
5855
5856 if( !SCIPisExact(scip) )
5857 return SCIP_OKAY;
5858
5859 conshdlrdata = SCIPconshdlrGetData(conshdlr);
5860 assert(conshdlrdata != NULL);
5861
5862 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
5863 if( SCIPinProbing(scip) )
5864 tightenbounds = TRUE;
5865 else
5866 {
5867 int depth;
5868 int propfreq;
5869 int tightenboundsfreq;
5870
5871 depth = SCIPgetDepth(scip);
5872 propfreq = SCIPconshdlrGetPropFreq(conshdlr);
5873 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
5874 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
5875 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
5876 }
5877
5878 cutoff = FALSE;
5879 nchgbds = 0;
5880
5881 /* process constraints marked for propagation */
5882 for( i = 0; i < nmarkedconss && !cutoff; i++ )
5883 {
5885 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds,
5886 conshdlrdata->sortvars, &cutoff, &nchgbds) );
5887 }
5888
5889 /* adjust result code */
5890 if( cutoff )
5891 *result = SCIP_CUTOFF;
5892 else if( nchgbds > 0 )
5893 *result = SCIP_REDUCEDDOM;
5894 else
5895 *result = SCIP_DIDNOTFIND;
5896
5897 return SCIP_OKAY;
5898}
5899
5900
5901/** variable rounding lock method of constraint handler */
5902static
5903SCIP_DECL_CONSLOCK(consLockExactLinear)
5904{ /*lint --e{715}*/
5905 SCIP_CONSDATA* consdata;
5906 SCIP_Bool haslhs;
5907 SCIP_Bool hasrhs;
5908 int i;
5909
5910 assert(scip != NULL);
5911 assert(SCIPisExact(scip));
5912 assert(cons != NULL);
5913 consdata = SCIPconsGetData(cons);
5914 assert(consdata != NULL);
5915
5916 haslhs = !SCIPrationalIsNegInfinity(consdata->lhs);
5917 hasrhs = !SCIPrationalIsInfinity(consdata->rhs);
5918
5919 /* update rounding locks of every single variable */
5920 for( i = 0; i < consdata->nvars; ++i )
5921 {
5922 if( SCIPrationalIsPositive(consdata->vals[i]) )
5923 {
5924 if( haslhs )
5925 {
5926 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
5927 }
5928 if( hasrhs )
5929 {
5930 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
5931 }
5932 }
5933 else
5934 {
5935 if( haslhs )
5936 {
5937 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
5938 }
5939 if( hasrhs )
5940 {
5941 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
5942 }
5943 }
5944 }
5945
5946 return SCIP_OKAY;
5947}
5948
5949
5950/** variable deletion method of constraint handler */
5951static
5952SCIP_DECL_CONSDELVARS(consDelvarsExactLinear)
5953{
5954 assert(scip != NULL);
5955 assert(SCIPisExact(scip) || nconss == 0);
5956 assert(conshdlr != NULL);
5957 assert(conss != NULL || nconss == 0);
5958
5959 if( nconss > 0 )
5960 {
5961 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
5962 }
5963
5964 return SCIP_OKAY;
5965}
5966
5967/** constraint display method of constraint handler */
5968static
5969SCIP_DECL_CONSPRINT(consPrintExactLinear)
5970{ /*lint --e{715}*/
5971 assert(scip != NULL);
5972 assert(conshdlr != NULL);
5973 assert(cons != NULL);
5974
5976
5977 return SCIP_OKAY;
5978}
5979
5980/** constraint copying method of constraint handler */
5981static
5982SCIP_DECL_CONSCOPY(consCopyExactLinear)
5983{ /*lint --e{715}*/
5984 SCIP_VAR** sourcevars;
5985 SCIP_INTERVAL* sourcecoefs;
5986 const char* consname;
5987 int nvars;
5988
5989 assert(scip != NULL);
5990 assert(sourcescip != NULL);
5991 assert(sourcecons != NULL);
5992
5993 /* get variables and coefficients of the source constraint */
5994 sourcevars = SCIPgetVarsExactLinear(sourcescip, sourcecons);
5995 sourcecoefs = SCIPgetValsRealExactLinear(sourcescip, sourcecons);
5996 nvars = SCIPgetNVarsExactLinear(sourcescip, sourcecons);
5997
5998 if( name != NULL )
5999 consname = name;
6000 else
6001 consname = SCIPconsGetName(sourcecons);
6002
6003 SCIP_CALL( SCIPcopyConsExactLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
6004 SCIPrationalGetReal(SCIPgetLhsExactLinear(sourcescip, sourcecons)), SCIPrationalGetReal(SCIPgetRhsExactLinear(sourcescip, sourcecons)), varmap, consmap,
6005 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
6006 assert(cons != NULL || *valid == FALSE);
6007
6008 return SCIP_OKAY;
6009}
6010
6011/* find operators '<=', '==', '>=', [free] in input string and return those places. There should only be one operator,
6012 * except for ranged rows for which exactly two operators '<=' must be present
6013 */
6014static
6016 const char* str, /**< null terminated input string */
6017 char** firstoperator, /**< pointer to store the string starting at the first operator */
6018 char** secondoperator, /**< pointer to store the string starting at the second operator */
6019 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
6020 )
6021{
6022 char* curr;
6023
6024 assert(str != NULL);
6025 assert(firstoperator != NULL);
6026 assert(secondoperator != NULL);
6027
6028 *firstoperator = NULL;
6029 *secondoperator = NULL;
6030
6031 curr = (char*)str;
6032 *success = TRUE;
6033
6034 /* loop over the input string to find all operators */
6035 while( *curr && *success )
6036 {
6037 SCIP_Bool found = FALSE;
6038 int increment = 1;
6039
6040 /* try if we found a possible operator */
6041 switch( *curr )
6042 {
6043 case '<':
6044 case '=':
6045 case '>':
6046
6047 /* check if the two characters curr[0,1] form an operator together */
6048 if( curr[1] == '=' )
6049 {
6050 found = TRUE;
6051
6052 /* update increment to continue after this operator */
6053 increment = 2;
6054 }
6055 break;
6056 case '[':
6057 if( strncmp(curr, "[free]", 6) == 0 )
6058 {
6059 found = TRUE;
6060
6061 /* update increment to continue after this operator */
6062 increment = 6;
6063 }
6064 break;
6065 default:
6066 break;
6067 }
6068
6069 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
6070 if( found )
6071 {
6072 if( *firstoperator == NULL )
6073 {
6074 *firstoperator = curr;
6075 }
6076 else
6077 {
6078 if( *secondoperator != NULL )
6079 {
6080 SCIPerrorMessage("Found more than two operators in line %s\n", str);
6081 *success = FALSE;
6082 }
6083 else if( strncmp(*firstoperator, "<=", 2) != 0 )
6084 {
6085 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
6086 *success = FALSE;
6087 }
6088 else if( strncmp(curr, "<=", 2) != 0 )
6089 {
6090 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
6091 *success = FALSE;
6092 }
6093
6094 *secondoperator = curr;
6095 }
6096 }
6097
6098 curr += increment;
6099 }
6100
6101 /* check if we did find at least one operator */
6102 if( *success )
6103 {
6104 if( *firstoperator == NULL )
6105 {
6106 SCIPerrorMessage("Could not find any operator in line %s\n", str);
6107 *success = FALSE;
6108 }
6109 }
6110
6111 return SCIP_OKAY;
6112}
6113
6114/** constraint parsing method of constraint handler */
6115static
6116SCIP_DECL_CONSPARSE(consParseExactLinear)
6117{ /*lint --e{715}*/
6118 SCIP_RETCODE retcode = SCIP_OKAY;
6119 SCIP_VAR** vars = NULL;
6120 SCIP_RATIONAL** coefs = NULL;
6121 int nvars;
6122 int coefssize = 100;
6123 int requsize;
6124 SCIP_RATIONAL* lhs;
6125 SCIP_RATIONAL* rhs;
6126 char* endptr;
6127 char* firstop;
6128 char* secondop;
6129 SCIP_Bool operatorsuccess;
6130 char* lhsstrptr = NULL;
6131 char* rhsstrptr = NULL;
6132 char* varstrptr = (char*)str;
6133
6134 assert(scip != NULL);
6135 assert(success != NULL);
6136 assert(str != NULL);
6137 assert(name != NULL);
6138 assert(cons != NULL);
6139
6140 *success = FALSE;
6141
6142 /* return of string empty */
6143 if( !(*str) )
6144 return SCIP_OKAY;
6145
6146 /* set left and right hand side to their default values */
6149
6152
6153 /* ignore whitespace */
6154 SCIP_CALL_TERMINATE( retcode, SCIPskipSpace((char**)&str), TERMINATE );
6155
6156 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
6157 * and the special word [free]
6158 */
6159 SCIP_CALL_TERMINATE( retcode, findOperators(str, &firstop, &secondop, &operatorsuccess), TERMINATE );
6160
6161 /* if the grammar is not valid for parsing a linear constraint, return */
6162 if( ! operatorsuccess )
6163 {
6164 retcode = SCIP_OKAY;
6165 goto TERMINATE;
6166 }
6167 assert(firstop != NULL);
6168
6169 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
6170 switch( *firstop )
6171 {
6172 case '<':
6173 assert(firstop[1] == '=');
6174 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
6175 if( secondop != NULL )
6176 {
6177 assert(secondop[0] == '<' && secondop[1] == '=');
6178 lhsstrptr = (char *)str;
6179 varstrptr = firstop + 2;
6180 rhsstrptr = secondop + 2;
6181 }
6182 else
6183 {
6184 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
6185 lhsstrptr = NULL;
6186 varstrptr = (char *)str;
6187 rhsstrptr = firstop + 2;
6188 }
6189 break;
6190 case '>':
6191 assert(firstop[1] == '=');
6192 assert(secondop == NULL);
6193 /* we have a_1 x_1 + ... + a_n x_n >= lhs */
6194 lhsstrptr = firstop + 2;
6195 break;
6196 case '=':
6197 assert(firstop[1] == '=');
6198 assert(secondop == NULL);
6199 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
6200 rhsstrptr = firstop + 2;
6201 lhsstrptr = firstop + 2;
6202 break;
6203 case '[':
6204 assert(strncmp(firstop, "[free]", 6) == 0);
6205 assert(secondop == NULL);
6206 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
6207 break;
6208 default:
6209 /* it should not be possible that a different character appears in that position */
6210 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
6211 retcode = SCIP_READERROR;
6212 goto TERMINATE;
6213 }
6214
6215 /* parse left hand side, if necessary */
6216 if( lhsstrptr != NULL )
6217 {
6218 if( ! SCIPparseRational(scip, lhsstrptr, lhs, &endptr) )
6219 {
6220 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
6221 retcode = SCIP_OKAY;
6222 goto TERMINATE;
6223 }
6224
6225 /* in case of an equation, assign the left also to the right hand side */
6226 if( rhsstrptr == lhsstrptr )
6227 SCIPrationalSetRational(rhs, lhs);
6228 }
6229
6230 /* parse right hand side, if different from left hand side */
6231 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
6232 {
6233 if( ! SCIPparseRational(scip, rhsstrptr, rhs, &endptr) )
6234 {
6235 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
6236 retcode = SCIP_OKAY;
6237 goto TERMINATE;
6238 }
6239 }
6240
6241 /* initialize buffers for storing the variables and coefficients */
6242 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
6244
6245 assert(varstrptr != NULL);
6246
6247 /* parse linear sum to get variables and coefficients */
6248 SCIP_CALL_TERMINATE( retcode, SCIPparseVarsLinearsumExact(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success), TERMINATE );
6249
6250 if( *success && requsize > coefssize )
6251 {
6252 /* realloc buffers and try again */
6253 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requsize) );
6254 SCIP_CALL( SCIPrationalReallocBufferArray(SCIPbuffer(scip), &coefs, coefssize, requsize) );
6255
6256 coefssize = requsize;
6257
6258 SCIP_CALL_TERMINATE( retcode, SCIPparseVarsLinearsumExact(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success), TERMINATE );
6259 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
6260 }
6261
6262 if( *success )
6263 {
6264 SCIP_CALL_TERMINATE( retcode, SCIPcreateConsExactLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
6265 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode),
6266 TERMINATE );
6267 }
6268
6269 TERMINATE:
6270 if( !*success )
6271 {
6272 SCIPerrorMessage("no luck in parsing exact linear sum '%s'\n", varstrptr);
6273 }
6274 if( coefs != NULL )
6275 SCIPrationalFreeBufferArray(SCIPbuffer(scip), &coefs, coefssize);
6277
6280
6281 return retcode;
6282}
6283
6284
6285/** constraint method of constraint handler which returns the variables (if possible) */
6286static
6287SCIP_DECL_CONSGETVARS(consGetVarsExactLinear)
6288{ /*lint --e{715}*/
6289 SCIP_CONSDATA* consdata;
6290
6291 consdata = SCIPconsGetData(cons);
6292 assert(consdata != NULL);
6293
6294 if( varssize < consdata->nvars )
6295 (*success) = FALSE;
6296 else
6297 {
6298 assert(vars != NULL);
6299
6300 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
6301 (*success) = TRUE;
6302 }
6303
6304 return SCIP_OKAY;
6305}
6306
6307/**! [Callback for the number of variables]*/
6308/** constraint method of constraint handler which returns the number of variables (if possible) */
6309static
6310SCIP_DECL_CONSGETNVARS(consGetNVarsExactLinear)
6311{ /*lint --e{715}*/
6312 SCIP_CONSDATA* consdata;
6313
6314 consdata = SCIPconsGetData(cons);
6315 assert(consdata != NULL);
6316
6317 (*nvars) = consdata->nvars;
6318 (*success) = TRUE;
6319
6320 return SCIP_OKAY;
6321}
6322/**! [Callback for the number of variables]*/
6323
6324/*
6325 * Callback methods of event handler
6326 */
6327
6328static
6329SCIP_DECL_EVENTEXEC(eventExecExactLinear)
6330{ /*lint --e{715}*/
6331 SCIP_CONS* cons;
6332 SCIP_CONSDATA* consdata;
6333 SCIP_VAR* var;
6334 SCIP_EVENTTYPE eventtype;
6336 assert(scip != NULL);
6337 assert(SCIPisExact(scip));
6338 assert(eventhdlr != NULL);
6339 assert(eventdata != NULL);
6340 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
6341 assert(event != NULL);
6342
6343 cons = eventdata->cons;
6344 assert(cons != NULL);
6345 consdata = SCIPconsGetData(cons);
6346 if( consdata == NULL )
6347 return SCIP_OKAY;
6348 /* we can skip events dropped for deleted constraints */
6349 if( SCIPconsIsDeleted(cons) )
6350 return SCIP_OKAY;
6351
6352 eventtype = SCIPeventGetType(event);
6353 var = SCIPeventGetVar(event);
6354 updateActivities = ((consdata->rowexact != NULL) == eventdata->rowvar) && consdata->validactivities;
6355 assert(!consdata->validactivities || (consdata->validminact && consdata->validmaxact && consdata->validglbminact && consdata->validglbmaxact));
6356
6357 if( ((eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0) )
6358 {
6359 SCIP_Real oldbound;
6360 SCIP_Real newbound;
6361 SCIP_INTERVAL valrange;
6362 int varpos;
6363 varpos = eventdata->varpos;
6364
6365 oldbound = SCIPeventGetOldbound(event);
6366 newbound = SCIPeventGetNewbound(event);
6367 assert(var != NULL);
6368 valrange = consdata->valsreal[varpos];
6369
6370 /* we only need to update the activities if the constraint is active,
6371 * otherwise we mark them to be invalid
6372 */
6373 if( SCIPconsIsActive(cons) )
6374 {
6375 /* update the activity values */
6376 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
6377 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, valrange);
6378 else
6379 {
6380 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
6381 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, valrange);
6382 }
6383 }
6384 else
6386
6387 consdata->presolved = FALSE;
6388 consdata->rangedrowpropagated = 0;
6389
6390 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
6391 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
6392 {
6394
6395 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
6396 if( consdata->maxactdeltavar == var )
6397 {
6398 consdata->maxactdelta = SCIP_INVALID;
6399 consdata->maxactdeltavar = NULL;
6400 }
6401
6402 /* check whether bound tightening might now be successful */
6403 if( consdata->boundstightened > 0)
6404 {
6405 switch( eventtype )
6406 {
6408 if( (valrange.sup > 0.0 ? !SCIPisInfinity(scip, consdata->rhsreal) : !SCIPisInfinity(scip, -consdata->lhsreal)) )
6409 consdata->boundstightened = 0;
6410 break;
6412 if( (valrange.sup > 0.0 ? !SCIPisInfinity(scip, -consdata->lhsreal) : !SCIPisInfinity(scip, consdata->rhsreal)) )
6413 consdata->boundstightened = 0;
6414 break;
6415 default:
6416 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype);
6417 return SCIP_INVALIDDATA;
6418 }
6419 }
6420 }
6421 /* update maximal activity delta if a bound was relaxed */
6422 else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
6423 {
6424 SCIP_Real lb;
6425 SCIP_Real ub;
6426 SCIP_Real domain;
6427 SCIP_Real delta;
6428
6429 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
6430
6431 lb = SCIPvarGetLbLocal(var);
6432 ub = SCIPvarGetUbLocal(var);
6433
6434 domain = ub - lb;
6435 delta = SCIPintervalAbsMax(valrange) * domain;
6436
6437 if( delta > consdata->maxactdelta )
6438 {
6439 consdata->maxactdelta = delta;
6440 consdata->maxactdeltavar = var;
6441 }
6442 }
6443 }
6444 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
6445 {
6446 /* we want to remove the fixed variable */
6447 consdata->presolved = FALSE;
6448 consdata->removedfixings = FALSE;
6449 consdata->rangedrowpropagated = 0;
6450
6451 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
6452 if( consdata->maxactdeltavar == var )
6453 {
6454 consdata->maxactdelta = SCIP_INVALID;
6455 consdata->maxactdeltavar = NULL;
6456 }
6457 }
6458 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
6459 {
6460 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
6463 consdata->presolved = FALSE;
6464 }
6465 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
6466 {
6467 SCIP_Real oldbound;
6468 SCIP_Real newbound;
6469 SCIP_INTERVAL valrange;
6470 int varpos;
6471
6472 varpos = eventdata->varpos;
6473
6474 if( updateActivities )
6475 {
6476 oldbound = SCIPeventGetOldbound(event);
6477 newbound = SCIPeventGetNewbound(event);
6478 assert(var != NULL);
6479 assert(consdata->vars[varpos] == var);
6480 valrange = consdata->valsreal[varpos];
6481
6482 consdata->rangedrowpropagated = 0;
6483
6484 /* update the activity values */
6485 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
6486 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, valrange);
6487 else
6488 {
6489 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
6490 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, valrange);
6491 }
6492 }
6493
6494 /* if the variable is binary but not fixed it had to become binary due to this global change */
6496 {
6498 consdata->indexsorted = FALSE;
6499 else
6500 consdata->coefsorted = FALSE;
6501 }
6502 }
6503 else if( ((eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0) )
6504 {
6506
6507 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
6508 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
6509
6510 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
6511 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
6512 }
6513 else if( (eventtype & SCIP_EVENTTYPE_VARDELETED) )
6514 {
6515 consdata->varsdeleted = TRUE;
6516 }
6517 return SCIP_OKAY;
6518}
6519
6520
6521/*
6522 * Callback methods of conflict handler
6523 */
6524
6525/*
6526 * constraint specific interface methods
6527 */
6528
6529/** creates the handler for linear constraints and includes it in SCIP */
6531 SCIP* scip /**< SCIP data structure */
6532 )
6533{
6534 SCIP_CONSHDLRDATA* conshdlrdata;
6535 SCIP_CONSHDLR* conshdlr;
6536 SCIP_EVENTHDLR* eventhdlr;
6537
6538 assert(scip != NULL);
6539
6540 /* create event handler for bound change events */
6542 eventExecExactLinear, NULL) );
6543
6544 /* create constraint handler data */
6545 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
6546
6547 /* include constraint handler */
6550 consEnfolpExactLinear, consEnfopsExactLinear, consCheckExactLinear, consLockExactLinear,
6551 conshdlrdata) );
6552
6553 assert(conshdlr != NULL);
6554
6555 /* mark constraint handler as exact */
6556 SCIPconshdlrMarkExact(conshdlr);
6557
6558 /* set non-fundamental callbacks via specific setter functions */
6559 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyExactLinear, consCopyExactLinear) );
6560 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveExactLinear) );
6561 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteExactLinear) );
6562 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsExactLinear) );
6563 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitExactLinear) );
6564 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreExactLinear) );
6565 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolExactLinear) );
6566 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeExactLinear) );
6567 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsExactLinear) );
6568 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsExactLinear) );
6569 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitExactLinear) );
6570 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpExactLinear) );
6571 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseExactLinear) );
6572 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintExactLinear) );
6573 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropExactLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
6575 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpExactLinear, consSepasolExactLinear, CONSHDLR_SEPAFREQ,
6577 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransExactLinear) );
6578 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxExactLinear) );
6579
6580 /* add constraint handler parameters */
6582 "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
6583 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
6584 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
6586 "constraints/" CONSHDLR_NAME "/maxrounds",
6587 "maximal number of separation rounds per node (-1: unlimited)",
6588 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
6590 "constraints/" CONSHDLR_NAME "/maxroundsroot",
6591 "maximal number of separation rounds per node in the root node (-1: unlimited)",
6592 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
6594 "constraints/" CONSHDLR_NAME "/maxsepacuts",
6595 "maximal number of cuts separated per separation round",
6596 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
6598 "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
6599 "maximal number of cuts separated per separation round in the root node",
6600 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
6602 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
6603 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
6605 "constraints/" CONSHDLR_NAME "/propcont",
6606 "should bounds on continuous variables be tightened by propagation?",
6607 &conshdlrdata->propcont, TRUE, TRUE, NULL, NULL) );
6609 "constraints/" CONSHDLR_NAME "/limitdenom",
6610 "should denominators of rational bounds on continuous variables be controlled?",
6611 &conshdlrdata->limitdenom, TRUE, DEFAULT_LIMITDENOM, NULL, NULL) );
6613 "constraints/" CONSHDLR_NAME "/boundmaxdenom",
6614 "maximal denominator for rational bounds on continuous variables after propagation",
6615 &conshdlrdata->boundmaxdenom, TRUE, DEFAULT_BOUNDMAXDENOM, 1L, SCIP_LONGINT_MAX, NULL, NULL) );
6616
6617 return SCIP_OKAY;
6618}
6619
6620/** creates and captures a linear constraint
6621 *
6622 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
6623 */
6625 SCIP* scip, /**< SCIP data structure */
6626 SCIP_CONS** cons, /**< pointer to hold the created constraint */
6627 const char* name, /**< name of constraint */
6628 int nvars, /**< number of nonzeros in the constraint */
6629 SCIP_VAR** vars, /**< array with variables of constraint entries */
6630 SCIP_RATIONAL** vals, /**< array with coefficients of constraint entries */
6631 SCIP_RATIONAL* lhs, /**< left hand side of constraint */
6632 SCIP_RATIONAL* rhs, /**< right hand side of constraint */
6633 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
6634 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
6635 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
6636 * Usually set to TRUE. */
6637 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
6638 * TRUE for model constraints, FALSE for additional, redundant constraints. */
6639 SCIP_Bool check, /**< should the constraint be checked for feasibility?
6640 * TRUE for model constraints, FALSE for additional, redundant constraints. */
6641 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
6642 * Usually set to TRUE. */
6643 SCIP_Bool local, /**< is constraint only valid locally?
6644 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
6645 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
6646 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
6647 * adds coefficients to this constraint. */
6648 SCIP_Bool dynamic, /**< is constraint subject to aging?
6649 * Usually set to FALSE. Set to TRUE for own cuts which
6650 * are separated as constraints. */
6651 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
6652 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
6653 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
6654 * if it may be moved to a more global node?
6655 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
6656 )
6657{
6658 SCIP_CONSHDLR* conshdlr;
6659 SCIP_CONSDATA* consdata;
6660 int i;
6661
6662 assert(scip != NULL);
6663 assert(cons != NULL);
6664
6665 /* find the linear constraint handler */
6666 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
6667 if( conshdlr == NULL )
6668 {
6669 SCIPerrorMessage("linear constraint handler not found\n");
6670 return SCIP_PLUGINNOTFOUND;
6671 }
6672
6673 /* terminate if a coefficient is infinite */
6674 for( i = 0; i < nvars; ++i )
6675 {
6676 if( SCIPrationalIsAbsInfinity(vals[i]) )
6677 {
6678 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
6679 " consider adjusting the infinity threshold\n", SCIPvarGetName(vars[i]), name);
6680 SCIPABORT();
6681 return SCIP_INVALIDDATA;
6682 }
6683 }
6684
6685 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
6686 * constraint after presolving we have to ensure that it holds active variables
6687 */
6688 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
6689 {
6690 SCIP_VAR** consvars;
6691 SCIP_RATIONAL** consvals;
6692 SCIP_RATIONAL* constant;
6693 int nconsvars;
6694 int requiredsize;
6695
6697
6698 nconsvars = nvars;
6699 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
6700 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
6701
6702 /* get active variables for new constraint */
6703 SCIP_CALL( SCIPgetProbvarLinearSumExact(scip, consvars, consvals, &nconsvars, nconsvars, constant, &requiredsize, TRUE) );
6704
6705 /* if space was not enough we need to resize the buffers */
6706 if( requiredsize > nconsvars )
6707 {
6708 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
6709 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
6710
6711 SCIP_CALL( SCIPgetProbvarLinearSumExact(scip, consvars, consvals, &nconsvars, requiredsize, constant, &requiredsize, TRUE) );
6712 assert(requiredsize <= nconsvars);
6713 }
6714
6715 /* adjust sides and check that we do not subtract infinity values */
6716 if( SCIPrationalIsAbsInfinity(constant) )
6717 {
6718 SCIPfreeBufferArray(scip, &consvals);
6719 SCIPfreeBufferArray(scip, &consvars);
6721 SCIPerrorMessage("while creating constraint <%s> inactive variables lead to an infinite constant\n", name);
6722 SCIPABORT();
6723 return SCIP_INVALIDDATA;
6724 }
6725 else
6726 {
6727 if( !SCIPrationalIsAbsInfinity(lhs) )
6728 SCIPrationalDiff(lhs, lhs, constant);
6729 if( !SCIPrationalIsAbsInfinity(rhs) )
6730 SCIPrationalDiff(rhs, rhs, constant);
6731 }
6732
6733 /* create constraint data */
6734 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
6735
6736 SCIPfreeBufferArray(scip, &consvals);
6737 SCIPfreeBufferArray(scip, &consvars);
6739 }
6740 else
6741 {
6742 /* create constraint data */
6743 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
6744 }
6745 assert(consdata != NULL);
6746
6747 /* create constraint */
6748 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
6749 local, modifiable, dynamic, removable, stickingatnode) );
6750
6751 return SCIP_OKAY;
6752}
6753
6754/** creates and captures a linear constraint
6755 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
6756 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
6757 *
6758 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
6759 *
6760 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
6761 */
6763 SCIP* scip, /**< SCIP data structure */
6764 SCIP_CONS** cons, /**< pointer to hold the created constraint */
6765 const char* name, /**< name of constraint */
6766 int nvars, /**< number of nonzeros in the constraint */
6767 SCIP_VAR** vars, /**< array with variables of constraint entries */
6768 SCIP_RATIONAL** vals, /**< array with coefficients of constraint entries */
6769 SCIP_RATIONAL* lhs, /**< left hand side of constraint */
6770 SCIP_RATIONAL* rhs /**< right hand side of constraint */
6771 )
6772{
6773 assert(scip != NULL);
6774
6775 SCIP_CALL( SCIPcreateConsExactLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
6777
6778 return SCIP_OKAY;
6779}
6780
6781/** creates a linear constraint from an exact linear constraint by rounding values to floating-point and captures it */
6783 SCIP* scip, /**< target SCIP data structure */
6784 SCIP_CONS** cons, /**< pointer to store the created target constraint */
6785 SCIP* sourcescip, /**< source SCIP data structure */
6786 const char* name, /**< name of constraint */
6787 int nvars, /**< number of variables in source variable array */
6788 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
6789 SCIP_INTERVAL* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
6790 SCIP_Real lhs, /**< left hand side of the linear constraint */
6791 SCIP_Real rhs, /**< right hand side of the linear constraint */
6792 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
6793 * variables of the target SCIP */
6794 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
6795 * target constraints */
6796 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
6797 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
6798 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
6799 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
6800 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
6801 SCIP_Bool local, /**< is constraint only valid locally? */
6802 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
6803 SCIP_Bool dynamic, /**< is constraint subject to aging? */
6804 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
6805 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
6806 * if it may be moved to a more global node? */
6807 SCIP_Bool global, /**< create a global or a local copy? */
6808 SCIP_Bool* valid /**< pointer to store if the copying was valid */
6809 )
6810{
6811 SCIP_VAR** vars;
6812 SCIP_Real* coefs;
6813
6814 SCIP_Real constant;
6815 int requiredsize;
6816 int v;
6817 SCIP_Bool success;
6818
6819 /**@todo This method is currently only used for subSCIPs in floating-point heuristics, but should be extended to be
6820 * able to perform an exact copy in the future. This would allow application of the cons_components presolver,
6821 * for example. In this case, whether an exact or an fp copy is created, could probably be decided by checking
6822 * SCIPisExact() for the target SCIP.
6823 */
6824 assert(!SCIPisExact(scip));
6825 (*valid) = FALSE;
6826
6827 if( SCIPisGT(scip, lhs, rhs) )
6828 {
6829 return SCIP_OKAY;
6830 }
6831
6832 if( nvars == 0 )
6833 {
6834 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
6835 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
6836 return SCIP_OKAY;
6837 }
6838
6839 /* duplicate variable array */
6840 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
6841
6842 /* duplicate coefficient array */
6843 if( sourcecoefs != NULL )
6844 {
6845 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
6846 for( int i = 0; i < nvars; i++ )
6847 {
6848 coefs[i] = SCIPintervalGetSup(sourcecoefs[i]);
6849 assert(!SCIPisInfinity(scip, coefs[i]) && !SCIPisInfinity(scip, -coefs[i]));
6850 }
6851 }
6852 else
6853 {
6854 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
6855 for( v = 0; v < nvars; ++v )
6856 coefs[v] = 1.0;
6857 }
6858
6859 constant = 0.0;
6860
6861 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
6862 * the target SCIP
6863 */
6864 if( !SCIPvarIsOriginal(vars[0]) )
6865 {
6866 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize) );
6867
6868 if( requiredsize > nvars )
6869 {
6870 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
6871 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
6872
6873 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize) );
6874 assert(requiredsize <= nvars);
6875 }
6876 }
6877 else
6878 {
6879 for( v = 0; v < nvars; ++v )
6880 {
6881 assert(SCIPvarIsOriginal(vars[v]));
6882 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
6883 assert(vars[v] != NULL);
6884 }
6885 }
6886
6887 success = TRUE;
6888 /* map variables of the source constraint to variables of the target SCIP */
6889 for( v = 0; v < nvars && success; ++v )
6890 {
6891 SCIP_VAR* var;
6892 var = vars[v];
6893
6894 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
6895 assert(!(success) || vars[v] != NULL);
6896 }
6897
6898 /* only create the target constraint, if all variables could be copied */
6899 if( success )
6900 {
6901 if( !SCIPisInfinity(scip, -lhs) )
6902 lhs -= constant;
6903
6904 if( !SCIPisInfinity(scip, rhs) )
6905 rhs -= constant;
6906
6907 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
6908 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
6909 }
6910
6911 /* free buffer array */
6912 SCIPfreeBufferArray(scip, &coefs);
6913 SCIPfreeBufferArray(scip, &vars);
6914
6915 return SCIP_OKAY;
6916}
6917
6918/** adds coefficient to linear constraint (if it is not zero) */
6920 SCIP* scip, /**< SCIP data structure */
6921 SCIP_CONS* cons, /**< constraint data */
6922 SCIP_VAR* var, /**< variable of constraint entry */
6923 SCIP_RATIONAL* val /**< coefficient of constraint entry */
6924 )
6925{
6926 assert(scip != NULL);
6927 assert(cons != NULL);
6928 assert(var != NULL);
6929
6930 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
6931 {
6932 SCIPerrorMessage("constraint is not of type exactlinear\n");
6933 return SCIP_INVALIDDATA;
6934 }
6935
6936 /* terminate if coefficient is infinite */
6937 if( SCIPrationalIsAbsInfinity(val) )
6938 {
6939 SCIPerrorMessage("coefficient of variable <%s> in constraint <%s> is infinite,"
6940 " consider adjusting the infinity threshold\n", SCIPvarGetName(var), SCIPconsGetName(cons));
6941 SCIPABORT();
6942 return SCIP_INVALIDDATA;
6943 }
6944
6945 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
6946 * constraint after presolving we have to ensure that it holds active variables
6947 */
6949 {
6950 SCIP_CONSDATA* consdata;
6951 SCIP_VAR** consvars;
6952 SCIP_RATIONAL** consvals;
6953 SCIP_RATIONAL* constant;
6954 SCIP_RATIONAL* rhs;
6955 SCIP_RATIONAL* lhs;
6956 int nconsvars;
6957 int requiredsize;
6958 int v;
6959
6960 SCIPerrorMessage("adding coefficients after presolving not supported yet in exact solving mode \n");
6961 SCIPABORT();
6962
6963 nconsvars = 1;
6964 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
6965 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
6966 consvars[0] = var;
6967 SCIP_CALL( SCIPrationalCopyBlock(SCIPblkmem(scip), &consvals[0], val) );
6969
6970 /* get active variables for new constraint */
6971 SCIP_CALL( SCIPgetProbvarLinearSumExact(scip, consvars, consvals, &nconsvars, nconsvars, constant, &requiredsize, TRUE) );
6972
6973 /* if space was not enough we need to resize the buffers */
6974 if( requiredsize > nconsvars )
6975 {
6976 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
6977 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
6978
6979 SCIP_CALL( SCIPgetProbvarLinearSumExact(scip, consvars, consvals, &nconsvars, requiredsize, constant, &requiredsize, TRUE) );
6980 assert(requiredsize <= nconsvars);
6981 }
6982
6983 consdata = SCIPconsGetData(cons);
6984 assert(consdata != NULL);
6985
6986 SCIP_CALL( SCIPrationalCopyBlock(SCIPblkmem(scip), &lhs, consdata->lhs) );
6987 SCIP_CALL( SCIPrationalCopyBlock(SCIPblkmem(scip), &rhs, consdata->rhs) );
6988
6989 /* adjust sides and check that we do not subtract infinity values */
6990 if( SCIPrationalIsAbsInfinity(constant) )
6991 {
6992 SCIPfreeBufferArray(scip, &consvals);
6993 SCIPfreeBufferArray(scip, &consvars);
6994
6995 SCIPerrorMessage("adding variable <%s> to constraint <%s> leads to infinite constant and cannot be handled safely\n",
6996 SCIPvarGetName(var), SCIPconsGetName(cons));
6997
6998 SCIPABORT();
6999 return SCIP_INVALIDDATA; /*lint !e527*/
7000 }
7001 /* constant is not infinite */
7002 else
7003 {
7004 if( !SCIPrationalIsAbsInfinity(lhs) )
7005 SCIPrationalDiff(lhs, lhs, constant);
7006 if( !SCIPrationalIsAbsInfinity(rhs) )
7007 SCIPrationalDiff(rhs, rhs, constant);
7008 }
7009
7010 /* add all active variables to constraint */
7011 for( v = nconsvars - 1; v >= 0; --v )
7012 {
7013 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
7014 }
7015
7016 /* update left and right hand sides */
7017 SCIP_CALL( chgLhs(scip, cons, lhs) );
7018 SCIP_CALL( chgRhs(scip, cons, rhs) );
7019
7021 SCIPfreeBufferArray(scip, &consvals);
7022 SCIPfreeBufferArray(scip, &consvars);
7023 }
7024 else
7025 {
7026 SCIP_CALL( addCoef(scip, cons, var, val) );
7027 }
7028
7029 return SCIP_OKAY;
7030}
7031
7032/** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
7033 * not yet contained in the constraint
7034 *
7035 * @note This method may only be called during problem creation stage for an original constraint and variable.
7036 *
7037 * @note This method requires linear time to search for occurences of the variable in the constraint data.
7038 */
7040 SCIP* scip, /**< SCIP data structure */
7041 SCIP_CONS* cons, /**< constraint data */
7042 SCIP_VAR* var, /**< variable of constraint entry */
7043 SCIP_RATIONAL* val /**< new coefficient of constraint entry */
7044 )
7045{
7046 SCIP_CONSDATA* consdata;
7047 SCIP_VAR** vars;
7048 SCIP_Bool found;
7049 int i;
7050
7051 assert(scip != NULL);
7052 assert(cons != NULL);
7053 assert(var != NULL);
7054
7055 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7056 {
7057 SCIPerrorMessage("constraint is not of type exactlinear\n");
7058 return SCIP_INVALIDDATA;
7059 }
7060
7062 {
7063 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
7064 return SCIP_INVALIDDATA;
7065 }
7066
7067 consdata = SCIPconsGetData(cons);
7068 assert(consdata != NULL);
7069
7070 vars = consdata->vars;
7071 found = FALSE;
7072 i = 0;
7073 while( i < consdata->nvars )
7074 {
7075 if( vars[i] == var )
7076 {
7077 if( found || SCIPrationalIsZero(val) )
7078 {
7079 SCIP_CALL( delCoefPos(scip, cons, i) );
7080
7081 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
7082 i--;
7083 }
7084 else
7085 {
7086 SCIP_CALL( chgCoefPos(scip, cons, i, val) );
7087 }
7088 found = TRUE;
7089 }
7090 i++;
7091 }
7092
7093 if( !found && !SCIPrationalIsZero(val) )
7094 {
7095 SCIP_CALL( SCIPaddCoefExactLinear(scip, cons, var, val) );
7096 }
7097
7098 return SCIP_OKAY;
7099}
7100
7101/** deletes variable from linear constraint
7102 *
7103 * @note This method may only be called during problem creation stage for an original constraint and variable.
7104 *
7105 * @note This method requires linear time to search for occurences of the variable in the constraint data.
7106 */
7108 SCIP* scip, /**< SCIP data structure */
7109 SCIP_CONS* cons, /**< constraint data */
7110 SCIP_VAR* var /**< variable of constraint entry */
7111 )
7112{
7113 SCIP_RATIONAL* temp;
7114
7115 assert(scip != NULL);
7116 assert(cons != NULL);
7117 assert(var != NULL);
7118
7120
7121 SCIP_CALL( SCIPchgCoefExactLinear(scip, cons, var, temp) );
7122
7124
7125 return SCIP_OKAY;
7126}
7127
7128/** gets left hand side of linear constraint */
7130 SCIP* scip, /**< SCIP data structure */
7131 SCIP_CONS* cons /**< constraint data */
7132 )
7133{
7134 SCIP_CONSDATA* consdata;
7135
7136 assert(scip != NULL);
7137 assert(cons != NULL);
7138
7139 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7140 {
7141 SCIPerrorMessage("constraint is not of type exactlinear\n");
7142 SCIPABORT();
7143 return NULL; /*lint !e527*/
7144 }
7145
7146 consdata = SCIPconsGetData(cons);
7147 assert(consdata != NULL);
7148
7149 return consdata->lhs;
7150}
7151
7152/** gets right hand side of linear constraint */
7154 SCIP* scip, /**< SCIP data structure */
7155 SCIP_CONS* cons /**< constraint data */
7156 )
7157{
7158 SCIP_CONSDATA* consdata;
7159
7160 assert(scip != NULL);
7161 assert(cons != NULL);
7162
7163 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7164 {
7165 SCIPerrorMessage("constraint is not of type exactlinear\n");
7166 SCIPABORT();
7167 return NULL; /*lint !e527*/
7168 }
7169
7170 consdata = SCIPconsGetData(cons);
7171 assert(consdata != NULL);
7172
7173 return consdata->rhs;
7174}
7175
7176/** changes left hand side of linear constraint */
7178 SCIP* scip, /**< SCIP data structure */
7179 SCIP_CONS* cons, /**< constraint data */
7180 SCIP_RATIONAL* lhs /**< new left hand side */
7181 )
7182{
7183 assert(scip != NULL);
7184 assert(cons != NULL);
7185
7186 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7187 {
7188 SCIPerrorMessage("constraint is not of type exactlinear\n");
7189 return SCIP_INVALIDDATA;
7190 }
7191
7192 SCIP_CALL( chgLhs(scip, cons, lhs) );
7193
7194 return SCIP_OKAY;
7195}
7196
7197/** changes right hand side of linear constraint */
7199 SCIP* scip, /**< SCIP data structure */
7200 SCIP_CONS* cons, /**< constraint data */
7201 SCIP_RATIONAL* rhs /**< new right hand side */
7202 )
7203{
7204 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7205 {
7206 SCIPerrorMessage("constraint is not of type exactlinear\n");
7207 return SCIP_INVALIDDATA;
7208 }
7209
7210 SCIP_CALL( chgRhs(scip, cons, rhs) );
7211
7212 return SCIP_OKAY;
7213}
7214
7215/** gets the number of variables in the linear constraint */
7217 SCIP* scip, /**< SCIP data structure */
7218 SCIP_CONS* cons /**< constraint data */
7219 )
7220{
7221 SCIP_CONSDATA* consdata;
7222
7223 assert(scip != NULL);
7224 assert(cons != NULL);
7225
7226 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7227 {
7228 SCIPerrorMessage("constraint is not of type exactlinear\n");
7229 SCIPABORT();
7230 return -1; /*lint !e527*/
7231 }
7232
7233 consdata = SCIPconsGetData(cons);
7234 assert(consdata != NULL);
7235
7236 return consdata->nvars;
7237}
7238
7239/** gets the array of variables in the linear constraint; the user must not modify this array! */
7241 SCIP* scip, /**< SCIP data structure */
7242 SCIP_CONS* cons /**< constraint data */
7243 )
7244{
7245 SCIP_CONSDATA* consdata;
7246
7247 assert(scip != NULL);
7248 assert(cons != NULL);
7249
7250 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7251 {
7252 SCIPerrorMessage("constraint is not of type exactlinear\n");
7253 SCIPABORT();
7254 return NULL; /*lint !e527*/
7255 }
7256
7257 consdata = SCIPconsGetData(cons);
7258 assert(consdata != NULL);
7259
7260 return consdata->vars;
7261}
7262
7263/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
7265 SCIP* scip, /**< SCIP data structure */
7266 SCIP_CONS* cons /**< constraint data */
7267 )
7268{
7269 SCIP_CONSDATA* consdata;
7270
7271 assert(scip != NULL);
7272 assert(cons != NULL);
7273
7274 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7275 {
7276 SCIPerrorMessage("constraint is not of type exactlinear\n");
7277 SCIPABORT();
7278 return NULL; /*lint !e527*/
7279 }
7280
7281 consdata = SCIPconsGetData(cons);
7282 assert(consdata != NULL);
7283
7284 return consdata->valsreal;
7285}
7286
7287/** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
7289 SCIP* scip, /**< SCIP data structure */
7290 SCIP_CONS* cons /**< constraint data */
7291 )
7292{
7293 SCIP_CONSDATA* consdata;
7294
7295 assert(scip != NULL);
7296 assert(cons != NULL);
7297
7298 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7299 {
7300 SCIPerrorMessage("constraint is not of type exactlinear\n");
7301 SCIPABORT();
7302 return NULL; /*lint !e527*/
7303 }
7304
7305 consdata = SCIPconsGetData(cons);
7306 assert(consdata != NULL);
7307
7308 return consdata->vals;
7309}
7310
7311/** gets the activity of the linear constraint in the given solution
7312 *
7313 * @note if the activity comprises positive and negative infinity contributions, the result is currently undefined
7314 */
7316 SCIP* scip, /**< SCIP data structure */
7317 SCIP_CONS* cons, /**< constraint data */
7318 SCIP_SOL* sol, /**< solution, or NULL to use current node's solution */
7319 SCIP_RATIONAL* ret
7320 )
7321{
7322 SCIP_CONSDATA* consdata;
7323
7324 assert(scip != NULL);
7325 assert(cons != NULL);
7326
7327 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7328 {
7329 SCIPerrorMessage("constraint is not of type exactlinear\n");
7330 SCIPABORT();
7331 SCIPrationalSetInfinity(ret); /*lint !e527*/
7332 }
7333
7334 consdata = SCIPconsGetData(cons);
7335 assert(consdata != NULL);
7336
7337 if( consdata->rowexact != NULL )
7338 {
7339 SCIP_CALL( SCIPgetRowSolActivityExact(scip, consdata->rowexact, sol, FALSE, ret) );
7340 }
7341 else
7342 consdataGetActivity(scip, consdata, sol, TRUE, ret);
7343
7344 return SCIP_OKAY;
7345}
7346
7347/** gets the feasibility of the linear constraint in the given solution */
7349 SCIP* scip, /**< SCIP data structure */
7350 SCIP_CONS* cons, /**< constraint data */
7351 SCIP_SOL* sol, /**< solution, or NULL to use current node's solution */
7352 SCIP_RATIONAL* ret /**< pointer to store the result */
7353 )
7354{
7355 SCIP_CONSDATA* consdata;
7356
7357 assert(scip != NULL);
7358 assert(cons != NULL);
7359
7360 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7361 {
7362 SCIPerrorMessage("constraint is not of type exactlinear\n");
7363 SCIPABORT();
7364 }
7365
7366 consdata = SCIPconsGetData(cons);
7367 assert(consdata != NULL);
7368
7369 if( consdata->rowexact != NULL )
7370 SCIP_CALL( SCIPgetRowSolFeasibilityExact(scip, consdata->rowexact, sol, ret) );
7371 else
7372 consdataGetFeasibility(scip, consdata, sol, ret);
7373
7374 return SCIP_OKAY;
7375}
7376
7377/** gets the dual solution of the linear constraint in the current LP
7378 *
7379 * @note this method currently returns the value from the floating-point LP
7380 */
7382 SCIP* scip, /**< SCIP data structure */
7383 SCIP_CONS* cons, /**< constraint data */
7384 SCIP_RATIONAL* ret /**< result pointer */
7385 )
7386{
7387 SCIP_CONSDATA* consdata;
7388
7389 assert(scip != NULL);
7390 assert(cons != NULL);
7391 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
7392
7393 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7394 {
7395 SCIPerrorMessage("constraint is not of type exactlinear\n");
7396 SCIPABORT();
7397 }
7398
7399 consdata = SCIPconsGetData(cons);
7400 assert(consdata != NULL);
7401
7402 if( consdata->rowlhs != NULL )
7403 SCIPrationalSetReal(ret, SCIProwGetDualsol(consdata->rowlhs));
7404 else
7405 SCIPrationalSetReal(ret, 0.0);
7406}
7407
7408/** gets the dual Farkas value of the linear constraint in the current infeasible LP
7409 *
7410 * @note this method currently returns an approximate value from the floating-point LP
7411 */
7413 SCIP* scip, /**< SCIP data structure */
7414 SCIP_CONS* cons, /**< constraint data */
7415 SCIP_RATIONAL* ret /**< result pointer */
7416 )
7417{
7418 SCIP_CONSDATA* consdata;
7419
7420 assert(scip != NULL);
7421 assert(cons != NULL);
7422 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
7423
7424 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7425 {
7426 SCIPerrorMessage("constraint is not of type exactlinear\n");
7427 SCIPABORT();
7428 }
7429
7430 consdata = SCIPconsGetData(cons);
7431 assert(consdata != NULL);
7432
7433 if( consdata->rowlhs != NULL )
7434 SCIPrationalSetReal(ret, SCIProwGetDualfarkas(consdata->rowlhs));
7435 else
7436 SCIPrationalSetReal(ret, 0.0);
7437}
7438
7439/** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
7440 * the user must not modify the row!
7441 */
7443 SCIP* scip, /**< SCIP data structure */
7444 SCIP_CONS* cons /**< constraint data */
7445 )
7446{
7447 SCIP_CONSDATA* consdata;
7448
7449 assert(scip != NULL);
7450 assert(cons != NULL);
7451
7452 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7453 {
7454 SCIPerrorMessage("constraint is not of type exactlinear\n");
7455 SCIPABORT();
7456 return NULL; /*lint !e527*/
7457 }
7458
7459 consdata = SCIPconsGetData(cons);
7460 assert(consdata != NULL);
7461
7462 return consdata->rowlhs;
7463}
7464
7465/** returns the exact linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
7466 * the user must not modify the row!
7467 */
7469 SCIP* scip, /**< SCIP data structure */
7470 SCIP_CONS* cons /**< constraint data */
7471 )
7472{
7473 SCIP_CONSDATA* consdata;
7474
7475 assert(scip != NULL);
7476 assert(cons != NULL);
7477
7478 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
7479 {
7480 SCIPerrorMessage("constraint is not of type exactlinear\n");
7481 SCIPABORT();
7482 return NULL; /*lint !e527*/
7483 }
7484
7485 consdata = SCIPconsGetData(cons);
7486 assert(consdata != NULL);
7487
7488 return consdata->rowexact;
7489}
static long bound
internal methods for clocks and timing issues
enum Proprule PROPRULE
Definition: cons_and.c:173
Proprule
Definition: cons_and.c:166
struct InferInfo INFERINFO
enum Proprule PROPRULE
static SCIP_DECL_CONSINITLP(consInitlpExactLinear)
static SCIP_DECL_CONSINIT(consInitExactLinear)
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
#define CONSHDLR_NEEDSCONS
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
#define CONSHDLR_SEPAFREQ
static SCIP_DECL_CONSTRANS(consTransExactLinear)
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff)
static SCIP_DECL_CONSDELVARS(consDelvarsExactLinear)
static SCIP_DECL_CONSEXITPRE(consExitpreExactLinear)
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_INTERVAL val)
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_RATIONAL *valExact, SCIP_INTERVAL val)
static void getMaxActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *maxactivity, SCIP_Bool *isrelax, SCIP_Bool *issettoinfinity)
#define CONSHDLR_CHECKPRIORITY
#define CONSHDLR_DESC
static SCIP_RATIONAL * consdataGetMinAbsvalEx(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_DECL_CONSDELETE(consDeleteExactLinear)
static void consdataCalcMinAbsvalEx(SCIP_CONSDATA *consdata)
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_RATIONAL *newval)
static SCIP_DECL_CONSCHECK(consCheckExactLinear)
#define CONSHDLR_PROP_TIMING
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_RATIONAL *val)
static SCIP_Bool consdataComputeSolActivityWithErrorbound(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol, SCIP_Real *activity, SCIP_Real *errorbound)
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
static SCIP_DECL_CONSPARSE(consParseExactLinear)
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE printActivityConflictToCertificate(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool rhs)
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_RATIONAL *valExact, SCIP_INTERVAL val)
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *rhs)
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
#define checkMaxActivityDelta(scip, consdata)
#define DEFAULT_LIMITDENOM
#define CONSHDLR_SEPAPRIORITY
#define DEFAULT_MAXROUNDSROOT
static void consdataGetActivityResiduals(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_INTERVAL val, SCIP_Bool goodrelax, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, int *ncuts, SCIP_Bool *cutoff)
static SCIP_DECL_CONSENFORELAX(consEnforelaxExactLinear)
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
static SCIP_RETCODE consPrintConsSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool useexactsol, FILE *file)
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
#define DEFAULT_SORTVARS
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
#define DEFAULT_BOUNDMAXDENOM
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_INTERVAL val)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs)
static SCIP_DECL_CONSDEACTIVE(consDeactiveExactLinear)
#define DEFAULT_MAXSEPACUTSROOT
@ PROPRULE_1_RANGEDROW
@ PROPRULE_1_LHS
@ PROPRULE_INVALID
@ PROPRULE_1_RHS
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_INTERVAL val)
static SCIP_RETCODE findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, SCIP_Bool useexactsol, SCIP_Bool checklprows, SCIP_Bool *violated)
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *lhs)
static SCIP_DECL_CONSGETVARS(consGetVarsExactLinear)
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
static SCIP_DECL_CONSPROP(consPropExactLinear)
static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_INTERVAL val)
#define CONSHDLR_PROPFREQ
static void consdataComputePseudoActivity(SCIP_CONSDATA *consdata, SCIP_RATIONAL *pseudoactivity)
static SCIP_RETCODE createRows(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyExactLinear)
static SCIP_DECL_CONSGETNVARS(consGetNVarsExactLinear)
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
#define DEFAULT_MAXSEPACUTS
static void consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol, SCIP_Bool useexact, SCIP_RATIONAL *activity)
static void consdataScaleMinValue(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real minval)
#define CONSHDLR_EAGERFREQ
#define DEFAULT_TIGHTENBOUNDSFREQ
static SCIP_DECL_CONSCOPY(consCopyExactLinear)
static SCIP_DECL_CONSEXITSOL(consExitsolExactLinear)
#define EVENTHDLR_DESC
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
static SCIP_DECL_CONSFREE(consFreeExactLinear)
#define DEFAULT_MAXROUNDS
static SCIP_DECL_CONSLOCK(consLockExactLinear)
static SCIP_DECL_EVENTEXEC(eventExecExactLinear)
static SCIP_DECL_CONSENFOPS(consEnfopsExactLinear)
#define CONSHDLR_ENFOPRIORITY
static int getInferInt(PROPRULE proprule, int pos)
static SCIP_DECL_CONSENFOLP(consEnfolpExactLinear)
#define CONSHDLR_DELAYSEPA
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_RATIONAL *val)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
static void consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol, SCIP_RATIONAL *ret)
#define CONSHDLR_NAME
static SCIP_DECL_CONSSEPALP(consSepalpExactLinear)
static int inferInfoToInt(INFERINFO inferinfo)
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
#define EVENTHDLR_NAME
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_INTERVAL oldval, SCIP_RATIONAL *oldvalExact, SCIP_INTERVAL newval, SCIP_RATIONAL *newvalExact)
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_RATIONAL *val)
static SCIP_DECL_CONSPRINT(consPrintExactLinear)
#define CONSHDLR_DELAYPROP
static void consdataUpdateActivities(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_INTERVAL valrange, SCIP_BOUNDTYPE boundtype, SCIP_Bool global)
static SCIP_DECL_CONSSEPASOL(consSepasolExactLinear)
static void getMinActivity(SCIP *scip, SCIP_CONSDATA *consdata, int posinf, int neginf, int poshuge, int neghuge, SCIP_Real delta, SCIP_Bool global, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Bool *isrelax, SCIP_Bool *issettoinfinity)
static SCIP_DECL_CONSEXIT(consExitExactLinear)
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
#define MAXTIGHTENROUNDS
Constraint handler for linear constraints in their most general form, .
Constraint handler for knapsack constraints of the form , x binary and .
Constraint handler for linear constraints in their most general form, .
constraint handler for nonlinear constraints specified by algebraic expressions
methods for debugging
common defines and data types used in all packages of SCIP
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_MAXTREEDEPTH
Definition: def.h:297
#define SCIP_REAL_UNITROUNDOFF
Definition: def.h:160
#define SCIP_INVALID
Definition: def.h:178
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define SCIP_UNKNOWN
Definition: def.h:179
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:376
#define SCIPABORT()
Definition: def.h:327
#define REALABS(x)
Definition: def.h:182
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPchgLhsExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *lhs)
SCIP_RATIONAL * SCIPgetLhsExactLinear(SCIP *scip, SCIP_CONS *cons)
void SCIPgetFpDualsolExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *ret)
SCIP_RATIONAL * SCIPgetRhsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *rhs)
SCIP_RETCODE SCIPcreateConsExactLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *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_VAR ** SCIPgetVarsExactLinear(SCIP *scip, SCIP_CONS *cons)
void SCIPgetFpDualfarkasExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_RATIONAL *ret)
SCIP_RETCODE SCIPcopyConsExactLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_INTERVAL *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)
int SCIPgetNVarsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddCoefExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_RATIONAL *val)
SCIP_RETCODE SCIPcertifyConsOrigExactLinear(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetActivityExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_RATIONAL *ret)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcreateConsBasicExactLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs)
SCIP_ROWEXACT * SCIPgetRowExactExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_INTERVAL * SCIPgetValsRealExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RATIONAL ** SCIPgetValsExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPdelCoefExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
SCIP_ROW * SCIPgetRowExactLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPgetFeasibilityExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_RATIONAL *ret)
SCIP_RETCODE SCIPchgCoefExactLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_RATIONAL *val)
SCIP_RETCODE SCIPincludeConshdlrExactLinear(SCIP *scip)
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:662
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:713
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:647
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3420
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:4067
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip_message.c:88
#define SCIPdebugMsg
Definition: scip_message.h:78
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:111
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:83
SCIP_RETCODE 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 SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip_param.c:269
SCIP_RETCODE SCIPcertifyCons(SCIP *scip, SCIP_Bool isorigfile, const char *consname, const char sense, SCIP_RATIONAL *side, int len, int *ind, SCIP_RATIONAL **val)
SCIP_RETCODE SCIPcertifyActivityVarBound(SCIP *scip, const char *linename, SCIP_BOUNDTYPE boundtype, SCIP_Real newbound, SCIP_Bool ismaxactivity, SCIP_CONS *constraint, SCIP_VAR *variable, SCIP_ROWEXACT *row, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, SCIP_VAR **vars, int nvars)
SCIP_RETCODE SCIPcertifyActivityConflict(SCIP *scip, SCIP_CONS *cons, SCIP_ROWEXACT *row, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, int nvals, SCIP_RATIONAL **vals, SCIP_VAR **vars, SCIP_RATIONAL *diff, SCIP_Bool userhs)
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_RETCODE SCIPcertifyActivityVarBoundExact(SCIP *scip, const char *linename, SCIP_BOUNDTYPE boundtype, SCIP_RATIONAL *newbound, SCIP_Bool ismaxactivity, SCIP_CONS *constraint, SCIP_VAR *variable, SCIP_ROWEXACT *row, SCIP_RATIONAL **vals, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, SCIP_VAR **vars, int nvars)
SCIP_Bool SCIPshouldCertificateTrackBounds(SCIP *scip)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:808
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4346
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip_cons.c:396
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip_cons.c:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:281
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:181
void SCIPconshdlrMarkExact(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4370
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:693
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:323
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5282
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:420
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip_cons.c:468
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip_cons.c:762
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4336
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:854
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8419
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8648
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8409
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8558
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8688
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8588
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8518
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8698
SCIP_Bool SCIPconsIsLockedType(SCIP_CONS *cons, SCIP_LOCKTYPE locktype)
Definition: cons.c:8782
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8578
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2042
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8450
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip_cons.c:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8608
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8628
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1812
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:2014
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8638
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8668
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8568
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1784
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8658
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:225
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_VARTYPE SCIPeventGetNewtype(SCIP_EVENT *event)
Definition: event.c:1479
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
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1391
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:1217
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1415
SCIP_VARTYPE SCIPeventGetOldtype(SCIP_EVENT *event)
Definition: event.c:1462
SCIP_Bool SCIPisExact(SCIP *scip)
Definition: scip_exact.c:193
SCIP_RETCODE SCIPaddRowExact(SCIP *scip, SCIP_ROWEXACT *rowexact)
Definition: scip_exact.c:257
void SCIPintervalSetRoundingModeUpwards(void)
void SCIPintervalSetRoundingModeDownwards(void)
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
SCIP_Real SCIPintervalAbsMax(SCIP_INTERVAL interval)
void SCIPintervalSubScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
int SCIP_ROUNDMODE
Definition: intervalarith.h:65
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
void SCIPintervalDiv(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
SCIP_Real SCIPintervalNegateReal(SCIP_Real x)
void SCIPintervalSetRational(SCIP_INTERVAL *resultant, SCIP_RATIONAL *value)
SCIP_RETCODE SCIPreleaseRowExact(SCIP *scip, SCIP_ROWEXACT **row)
Definition: scip_lpexact.c:110
SCIP_Bool SCIPgetRowSolActivityWithErrorboundExact(SCIP *scip, SCIP_ROWEXACT *row, SCIP_SOL *sol, SCIP_Real *activity, SCIP_Real *errorbound)
Definition: scip_lpexact.c:396
SCIP_RETCODE SCIPprintRowExact(SCIP *scip, SCIP_ROWEXACT *row, FILE *file)
Definition: scip_lpexact.c:419
SCIP_RETCODE SCIPgenerateFpRowsFromRowExact(SCIP *scip, SCIP_ROWEXACT *row, SCIP_ROW *rowlhs, SCIP_ROW *rowrhs, SCIP_Bool *onerowrelax, SCIP_Bool *hasfprelax)
Definition: scip_lpexact.c:309
SCIP_RETCODE SCIPgetRowSolActivityExact(SCIP *scip, SCIP_ROWEXACT *row, SCIP_SOL *sol, SCIP_Bool useexact, SCIP_RATIONAL *result)
Definition: scip_lpexact.c:367
SCIP_RETCODE SCIPgetRowSolFeasibilityExact(SCIP *scip, SCIP_ROWEXACT *row, SCIP_SOL *sol, SCIP_RATIONAL *result)
Definition: scip_lpexact.c:335
SCIP_RETCODE SCIPchgRowExactLhs(SCIP *scip, SCIP_ROWEXACT *row, SCIP_RATIONAL *lhs)
Definition: scip_lpexact.c:131
SCIP_RETCODE SCIPcreateEmptyRowConsExact(SCIP *scip, SCIP_ROWEXACT **rowexact, SCIP_ROW *fprow, SCIP_ROW *fprowrhs, SCIP_RATIONAL *lhs, SCIP_RATIONAL *rhs, SCIP_Bool isfprelaxable)
Definition: scip_lpexact.c:228
SCIP_RETCODE SCIPchgRowExactRhs(SCIP *scip, SCIP_ROWEXACT *row, SCIP_RATIONAL *rhs)
Definition: scip_lpexact.c:155
SCIP_RETCODE SCIPaddVarsToRowExact(SCIP *scip, SCIP_ROWEXACT *row, int nvars, SCIP_VAR **vars, SCIP_RATIONAL **vals)
Definition: scip_lpexact.c:182
SCIP_Bool SCIPlpExactIsSolved(SCIP *scip)
Definition: scip_lpexact.c:456
SCIP_RETCODE SCIPcaptureRowExact(SCIP *scip, SCIP_ROWEXACT *row)
Definition: scip_lpexact.c:88
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:87
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
BMS_BUFMEM * SCIPbuffer(SCIP *scip)
Definition: scip_mem.c:72
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
#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 SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:137
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
SCIP_Bool SCIPrationalIsLTReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1576
void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1342
SCIP_RETCODE SCIPrationalCreateBlock(BMS_BLKMEM *blkmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:108
SCIP_RETCODE SCIPrationalCreate(SCIP_RATIONAL **rational)
Definition: rational.cpp:94
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1066
SCIP_Bool SCIPrationalIsAbsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1421
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:618
void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:935
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
Definition: rational.cpp:2085
SCIP_RETCODE SCIPrationalCreateString(BMS_BLKMEM *mem, SCIP_RATIONAL **rational, const char *desc)
Definition: rational.cpp:796
void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
Definition: rational.cpp:461
#define SCIPrationalDebugMessage
Definition: rational.h:641
void SCIPrationalAbs(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
Definition: rational.cpp:1310
void SCIPrationalDiv(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1132
SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1680
SCIP_Bool SCIPrationalIsLT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1503
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition: rational.cpp:603
SCIP_Bool SCIPrationalIsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1474
SCIP_RETCODE SCIPrationalCopyBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **result, SCIP_RATIONAL *src)
Definition: rational.cpp:151
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
SCIP_RETCODE SCIPrationalCopyBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***target, SCIP_RATIONAL **src, int len)
Definition: rational.cpp:249
void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:983
SCIP_Bool SCIPrationalIsLEReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1615
SCIP_Bool SCIPrationalIsPositive(SCIP_RATIONAL *rational)
Definition: rational.cpp:1640
int SCIPrationalGetSign(const SCIP_RATIONAL *rational)
Definition: rational.cpp:2048
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
void SCIPrationalAddProd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1173
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
Definition: rational.cpp:1624
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition: rational.cpp:569
SCIP_Bool SCIPrationalIsGEReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1606
void SCIPrationalMessage(SCIP_MESSAGEHDLR *msg, FILE *file, SCIP_RATIONAL *rational)
Definition: rational.cpp:1790
void SCIPrationalSetNegInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:630
void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
Definition: rational.cpp:582
void SCIPrationalNegate(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
Definition: rational.cpp:1297
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
Definition: rational.cpp:1650
void SCIPrationalDiffReal(SCIP_RATIONAL *res, SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1009
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1660
void SCIPrationalFreeBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***ratblockarray, int size)
Definition: rational.cpp:501
SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
Definition: rational.cpp:2110
SCIP_Bool SCIPrationalIsEQReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1437
SCIP_RETCODE SCIPrationalCreateBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition: rational.cpp:214
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1670
void SCIPrationalFree(SCIP_RATIONAL **rational)
Definition: rational.cpp:450
SCIP_Bool SCIPrationalIsGTReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1546
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1404
SCIP_RETCODE SCIPrationalReallocBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***result, int oldlen, int newlen)
Definition: rational.cpp:314
void SCIPrationalMultReal(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_Real op2)
Definition: rational.cpp:1097
void SCIPrationalComputeApproximation(SCIP_RATIONAL *res, SCIP_RATIONAL *src, SCIP_Longint maxdenom, int forcegreater)
Definition: rational.cpp:2464
void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
Definition: rational.cpp:518
SCIP_Bool SCIPrationalIsAbsGT(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1530
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 SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2176
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_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
Definition: scip_sol.c:2349
void SCIPgetSolValExact(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_RATIONAL *res)
Definition: scip_sol.c:1803
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1765
SCIP_Bool SCIPsolIsExact(SCIP_SOL *sol)
Definition: sol.c:4150
int SCIPgetNSepaRounds(SCIP *scip)
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPparseRational(SCIP *scip, const char *str, SCIP_RATIONAL *value, char **endptr)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(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_Real SCIPgetHugeValue(SCIP *scip)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip_tree.c:146
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:18320
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:17801
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:23534
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:23889
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:5210
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:23642
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:23478
SCIP_RATIONAL * SCIPvarGetAggrScalarExact(SCIP_VAR *var)
Definition: var.c:23760
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:2119
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:23386
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Real SCIPadjustedVarLbExactFloat(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:5602
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_RATIONAL * SCIPvarGetAggrConstantExact(SCIP_VAR *var)
Definition: var.c:23783
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:23430
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
int SCIPvarGetCertificateIndex(SCIP_VAR *var)
Definition: var.c:25098
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:5118
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:5296
SCIP_RETCODE SCIPinferVarLbConsExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:7296
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:23662
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1887
SCIP_RATIONAL * SCIPvarGetMultaggrConstantExact(SCIP_VAR *var)
Definition: var.c:23855
SCIP_RETCODE SCIPgetProbvarLinearSumExact(SCIP *scip, SCIP_VAR **vars, SCIP_RATIONAL **scalars, int *nvars, int varssize, SCIP_RATIONAL *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip_var.c:2443
SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
Definition: var.c:24278
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_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_RETCODE SCIPparseVarsLinearsumExact(SCIP *scip, char *str, SCIP_VAR **vars, SCIP_RATIONAL **vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip_var.c:1007
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:2332
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:23806
SCIP_RETCODE SCIPinferVarUbConsExact(SCIP *scip, SCIP_VAR *var, SCIP_RATIONAL *newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:7174
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:23794
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
SCIP_RATIONAL * SCIPvarGetBestBoundLocalExact(SCIP_VAR *var)
Definition: var.c:24325
SCIP_RATIONAL * SCIPvarGetLbGlobalExact(SCIP_VAR *var)
Definition: var.c:24130
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:23878
SCIP_RATIONAL ** SCIPvarGetMultaggrScalarsExact(SCIP_VAR *var)
Definition: var.c:23830
SCIP_Real SCIPadjustedVarUbExactFloat(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:5666
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:23417
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
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_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
Definition: var.c:24244
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:17274
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:361
SCIP_RETCODE SCIPgetProbvarSumExact(SCIP *scip, SCIP_VAR **var, SCIP_RATIONAL *scalar, SCIP_RATIONAL *constant)
Definition: scip_var.c:2538
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:2078
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1853
SCIP_RETCODE SCIPwriteVarsLinearsumExact(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_RATIONAL **vals, int nvars, SCIP_Bool type)
Definition: scip_var.c:533
SCIP_RATIONAL * SCIPvarGetUbGlobalExact(SCIP_VAR *var)
Definition: var.c:24152
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:23736
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5581
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10816
static SCIP_RETCODE updateActivities(SCIP *scip, SCIP_Real *minactivities, SCIP_Real *maxactivities, SCIP_ROW **violrows, int *violrowpos, int *nviolrows, int *nviolfracrows, int *nfracsinrow, int nlprows, SCIP_VAR *var, SCIP_Real oldsolval, SCIP_Real newsolval)
interval arithmetics for provable bounds
SCIP_Bool SCIProwExactIsInLP(SCIP_ROWEXACT *row)
Definition: lpexact.c:5036
SCIP_RATIONAL ** SCIProwExactGetVals(SCIP_ROWEXACT *row)
Definition: lpexact.c:5016
int SCIProwExactGetNNonz(SCIP_ROWEXACT *row)
Definition: lpexact.c:5006
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
public methods for conflict analysis handlers
public methods for managing constraints
public methods for managing events
public methods for LP management
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:102
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for problem variables
wrapper for rational number arithmetic
public methods for branching rule plugins and branching
public methods for certified solving
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
public methods for event handler plugins and event handlers
public methods for exact solving
general public methods
public methods for the LP relaxation, rows and columns
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
Definition: sepa_flower.c:1221
internal methods for storing separated exact cuts
SCIP_Real sup
Definition: intervalarith.h:57
SCIP_Real inf
Definition: intervalarith.h:56
datastructures for problem statistics
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:127
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:73
#define SCIP_EVENTTYPE_TYPECHANGED
Definition: type_event.h:86
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:76
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:122
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:179
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:79
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:72
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:71
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:157
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:75
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:126
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:123
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:124
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:156
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:125
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:77
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:58
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:57
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:60
@ SCIP_R_ROUND_UPWARDS
Definition: type_rational.h:58
@ SCIP_R_ROUND_DOWNWARDS
Definition: type_rational.h:57
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ 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_INFEASIBLE
Definition: type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
type definitions for return codes for SCIP methods
@ SCIP_READERROR
Definition: type_retcode.h:45
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PROBLEM
Definition: type_set.h:45
@ SCIP_STAGE_INITSOLVE
Definition: type_set.h:52
@ SCIP_STAGE_EXITPRESOLVE
Definition: type_set.h:50
@ SCIP_STAGE_TRANSFORMING
Definition: type_set.h:46
@ SCIP_STAGE_PRESOLVED
Definition: type_set.h:51
#define NLOCKTYPES
Definition: type_var.h:138
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition: type_var.h:64
@ SCIP_VARSTATUS_ORIGINAL
Definition: type_var.h:51
@ SCIP_VARSTATUS_FIXED
Definition: type_var.h:54
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:53
@ SCIP_VARSTATUS_MULTAGGR
Definition: type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition: type_var.h:57
@ SCIP_VARSTATUS_AGGREGATED
Definition: type_var.h:55
@ SCIP_VARSTATUS_LOOSE
Definition: type_var.h:52
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:144
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73
internal methods for problem variables