1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the program and library */ 4 /* SCIP --- Solving Constraint Integer Programs */ 5 /* */ 6 /* Copyright (c) 2002-2023 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_linear.c 26 * @ingroup DEFPLUGINS_CONS 27 * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$. 28 * @author Tobias Achterberg 29 * @author Timo Berthold 30 * @author Marc Pfetsch 31 * @author Kati Wolter 32 * @author Michael Winkler 33 * @author Gerald Gamrath 34 * @author Domenico Salvagnin 35 * 36 * Linear constraints are separated with a high priority, because they are easy 37 * to separate. Instead of using the global cut pool, the same effect can be 38 * implemented by adding linear constraints to the root node, such that they are 39 * separated each time, the linear constraints are separated. A constraint 40 * handler, which generates linear constraints in this way should have a lower 41 * separation priority than the linear constraint handler, and it should have a 42 * separation frequency that is a multiple of the frequency of the linear 43 * constraint handler. In this way, it can be avoided to separate the same cut 44 * twice, because if a separation run of the handler is always preceded by a 45 * separation of the linear constraints, the priorily added constraints are 46 * always satisfied. 47 * 48 * Linear constraints are enforced and checked with a very low priority. Checking 49 * of (many) linear constraints is much more involved than checking the solution 50 * values for integrality. Because we are separating the linear constraints quite 51 * often, it is only necessary to enforce them for integral solutions. A constraint 52 * handler which generates pool cuts in its enforcing method should have an 53 * enforcing priority smaller than that of the linear constraint handler to avoid 54 * regenerating constraints which already exist. 55 */ 56 57 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 58 59 #include "blockmemshell/memory.h" 60 #include "scip/cons_nonlinear.h" 61 #include "scip/cons_knapsack.h" 62 #include "scip/cons_linear.h" 63 #include "scip/debug.h" 64 #include "scip/pub_conflict.h" 65 #include "scip/pub_cons.h" 66 #include "scip/pub_event.h" 67 #include "scip/pub_expr.h" 68 #include "scip/pub_lp.h" 69 #include "scip/pub_message.h" 70 #include "scip/pub_misc.h" 71 #include "scip/pub_misc_sort.h" 72 #include "scip/pub_var.h" 73 #include "scip/scip_branch.h" 74 #include "scip/scip_conflict.h" 75 #include "scip/scip_cons.h" 76 #include "scip/scip_copy.h" 77 #include "scip/scip_cut.h" 78 #include "scip/scip_event.h" 79 #include "scip/scip_general.h" 80 #include "scip/scip_lp.h" 81 #include "scip/scip_mem.h" 82 #include "scip/scip_message.h" 83 #include "scip/scip_numerics.h" 84 #include "scip/scip_param.h" 85 #include "scip/scip_prob.h" 86 #include "scip/scip_probing.h" 87 #include "scip/scip_sol.h" 88 #include "scip/scip_solvingstats.h" 89 #include "scip/scip_tree.h" 90 #include "scip/scip_var.h" 91 #include "scip/symmetry_graph.h" 92 #include "symmetry/struct_symmetry.h" 93 #include "scip/dbldblarith.h" 94 95 96 #define CONSHDLR_NAME "linear" 97 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs" 98 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */ 99 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */ 100 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */ 101 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */ 102 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */ 103 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation, 104 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */ 105 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */ 106 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */ 107 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */ 108 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */ 109 110 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */ 111 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP 112 113 #define EVENTHDLR_NAME "linear" 114 #define EVENTHDLR_DESC "bound change event handler for linear constraints" 115 116 #define CONFLICTHDLR_NAME "linear" 117 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints" 118 #define CONFLICTHDLR_PRIORITY -1000000 119 120 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */ 121 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */ 122 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */ 123 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */ 124 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */ 125 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */ 126 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */ 127 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */ 128 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise 129 * comparison round */ 130 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster 131 * propagation? */ 132 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative 133 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */ 134 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation 135 * (0.0: disable constraint aggregation) */ 136 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint 137 * (faster, but numerically less stable) */ 138 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared 139 * to best node's dual bound for separating knapsack cardinality cuts */ 140 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only 141 * the ones with non-zero dual value? */ 142 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */ 143 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */ 144 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */ 145 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */ 146 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill 147 * constraints using the cheapest variable? */ 148 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective 149 * function defining an upper bound and prevent these constraints from 150 * entering the LP */ 151 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective 152 * function defining a lower bound and prevent these constraints from 153 * entering the LP */ 154 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the 155 * objective function */ 156 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */ 157 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */ 158 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */ 159 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */ 160 161 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be 162 * removed afterwards? */ 163 #define DEFAULT_MAXMULTAGGRQUOT 1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */ 164 #define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */ 165 #define DEFAULT_EXTRACTCLIQUES TRUE /**< should cliques be extracted? */ 166 167 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */ 168 #define MAXSCALEDCOEF 0 /**< maximal coefficient value after scaling */ 169 #define MAXSCALEDCOEFINTEGER 0 /**< maximal coefficient value after scaling if all variables are of integral 170 * type 171 */ 172 #define MAXACTVAL 1e+09 /**< maximal absolute value of full and partial activities such that 173 * redundancy-based simplifications are allowed to be applied 174 */ 175 176 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */ 177 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */ 178 179 180 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of expressions constraints */ 181 182 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue), 183 * maybe in fullDualPresolve(), see convertLongEquality() 184 */ 185 186 187 /** constraint data for linear constraints */ 188 struct SCIP_ConsData 189 { 190 SCIP_Real lhs; /**< left hand side of row (for ranged rows) */ 191 SCIP_Real rhs; /**< right hand side of row */ 192 SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */ 193 SCIP_Real minabsval; /**< minimal absolute value of all coefficients */ 194 QUAD_MEMBER(SCIP_Real minactivity); /**< minimal value w.r.t. the variable's local bounds for the constraint's 195 * activity, ignoring the coefficients contributing with infinite value */ 196 QUAD_MEMBER(SCIP_Real maxactivity); /**< maximal value w.r.t. the variable's local bounds for the constraint's 197 * activity, ignoring the coefficients contributing with infinite value */ 198 SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation 199 * over all contributing values */ 200 SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation 201 * over all contributing values */ 202 QUAD_MEMBER(SCIP_Real glbminactivity); /**< minimal value w.r.t. the variable's global bounds for the constraint's 203 * activity, ignoring the coefficients contributing with infinite value */ 204 QUAD_MEMBER(SCIP_Real glbmaxactivity); /**< maximal value w.r.t. the variable's global bounds for the constraint's 205 * activity, ignoring the coefficients contributing with infinite value */ 206 SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation 207 * over all contributing values */ 208 SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation 209 * over all contributing values */ 210 SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */ 211 SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */ 212 uint64_t possignature; /**< bit signature of coefficients that may take a positive value */ 213 uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */ 214 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */ 215 SCIP_NLROW* nlrow; /**< NLP row, if constraint has been added to NLP relaxation */ 216 SCIP_VAR** vars; /**< variables of constraint entries */ 217 SCIP_Real* vals; /**< coefficients of constraint entries */ 218 SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */ 219 int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */ 220 int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */ 221 int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */ 222 int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */ 223 int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */ 224 int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */ 225 int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */ 226 int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */ 227 int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */ 228 int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */ 229 int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */ 230 int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */ 231 int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */ 232 int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */ 233 int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */ 234 int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */ 235 int varssize; /**< size of the vars- and vals-arrays */ 236 int nvars; /**< number of nonzeros in constraint */ 237 int nbinvars; /**< the number of binary variables in the constraint, only valid after 238 * sorting in stage >= SCIP_STAGE_INITSOLVE 239 */ 240 unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */ 241 unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint? 242 * (0: no, 1: yes, 2: with potentially adding artificial constraint */ 243 unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */ 244 unsigned int validminabsval:1; /**< is the minimum absolute value valid? */ 245 unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */ 246 unsigned int validminact:1; /**< is the local minactivity valid? */ 247 unsigned int validmaxact:1; /**< is the local maxactivity valid? */ 248 unsigned int validglbminact:1; /**< is the global minactivity valid? */ 249 unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */ 250 unsigned int presolved:1; /**< is constraint already presolved? */ 251 unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */ 252 unsigned int validsignature:1; /**< is the bit signature valid? */ 253 unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */ 254 unsigned int normalized:1; /**< is the constraint in normalized form? */ 255 unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */ 256 unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */ 257 unsigned int indexsorted:1; /**< are the constraint's variables sorted by type and index? */ 258 unsigned int merged:1; /**< are the constraint's equal variables already merged? */ 259 unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */ 260 unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */ 261 unsigned int coefsorted:1; /**< are variables sorted by type and their absolute activity delta? */ 262 unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */ 263 unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */ 264 unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */ 265 unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */ 266 unsigned int checkabsolute:1; /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */ 267 }; 268 269 /** event data for bound change event */ 270 struct SCIP_EventData 271 { 272 SCIP_CONS* cons; /**< linear constraint to process the bound change for */ 273 int varpos; /**< position of variable in vars array */ 274 int filterpos; /**< position of event in variable's event filter */ 275 }; 276 277 /** constraint handler data */ 278 struct SCIP_ConshdlrData 279 { 280 SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */ 281 SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */ 282 SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation 283 * (0.0: disable constraint aggregation) */ 284 SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared 285 * to best node's dual bound for separating knapsack cardinality cuts */ 286 SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */ 287 SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint 288 * (faster, but numerically less stable) */ 289 int linconsupgradessize;/**< size of linconsupgrade array */ 290 int nlinconsupgrades; /**< number of linear constraint upgrade methods */ 291 int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */ 292 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */ 293 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */ 294 int maxsepacuts; /**< maximal number of cuts separated per separation round */ 295 int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */ 296 int nmincomparisons; /**< number for minimal pairwise presolving comparisons */ 297 int naddconss; /**< number of added constraints */ 298 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */ 299 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */ 300 SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only 301 * the ones with non-zero dual value? */ 302 SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */ 303 SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */ 304 SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */ 305 SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */ 306 SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill 307 * constraints using the cheapest variable? */ 308 SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */ 309 SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative 310 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */ 311 SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective 312 * function defining an upper bound and prevent these constraints from 313 * entering the LP */ 314 SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective 315 * function defining a lower bound and prevent these constraints from 316 * entering the LP */ 317 SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to 318 * the objective function */ 319 SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect 320 * infeasibility, and extract sub-constraints from ranged rows and 321 * equations */ 322 SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/ 323 int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */ 324 int rangedrowfreq; /**< frequency for applying ranged row propagation */ 325 SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be 326 * removed afterwards? */ 327 SCIP_Real maxmultaggrquot; /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */ 328 SCIP_Real maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */ 329 SCIP_Bool extractcliques; /**< should cliques be extracted? */ 330 }; 331 332 /** linear constraint update method */ 333 struct SCIP_LinConsUpgrade 334 { 335 SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */ 336 int priority; /**< priority of upgrading method */ 337 SCIP_Bool active; /**< is upgrading enabled */ 338 }; 339 340 341 /* 342 * Propagation rules 343 */ 344 345 enum Proprule 346 { 347 PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single 348 * variable due to the right hand side of the inequality */ 349 PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single 350 * variable due to the left hand side of the inequality */ 351 PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a 352 * single variable in this reanged row */ 353 PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */ 354 }; 355 typedef enum Proprule PROPRULE; 356 357 /** inference information */ 358 struct InferInfo 359 { 360 union 361 { 362 struct 363 { 364 unsigned int proprule:8; /**< propagation rule that was applied */ 365 unsigned int pos:24; /**< variable position, the propagation rule was applied at */ 366 } asbits; 367 int asint; /**< inference information as a single int value */ 368 } val; 369 }; 370 typedef struct InferInfo INFERINFO; 371 372 /** converts an integer into an inference information */ 373 static 374 INFERINFO intToInferInfo( 375 int i /**< integer to convert */ 376 ) 377 { 378 INFERINFO inferinfo; 379 380 inferinfo.val.asint = i; 381 382 return inferinfo; 383 } 384 385 /** converts an inference information into an int */ 386 static 387 int inferInfoToInt( 388 INFERINFO inferinfo /**< inference information to convert */ 389 ) 390 { 391 return inferinfo.val.asint; 392 } 393 394 /** returns the propagation rule stored in the inference information */ 395 static 396 int inferInfoGetProprule( 397 INFERINFO inferinfo /**< inference information to convert */ 398 ) 399 { 400 return (int) inferinfo.val.asbits.proprule; 401 } 402 403 /** returns the position stored in the inference information */ 404 static 405 int inferInfoGetPos( 406 INFERINFO inferinfo /**< inference information to convert */ 407 ) 408 { 409 return (int) inferinfo.val.asbits.pos; 410 } 411 412 /** constructs an inference information out of a propagation rule and a position number */ 413 static 414 INFERINFO getInferInfo( 415 PROPRULE proprule, /**< propagation rule that deduced the value */ 416 int pos /**< variable position, the propagation rule was applied at */ 417 ) 418 { 419 INFERINFO inferinfo; 420 421 assert(pos >= 0); 422 /* in the inferinfo struct only 24 bits for 'pos' are reserved */ 423 assert(pos < (1<<24)); 424 425 inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/ 426 inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/ 427 428 return inferinfo; 429 } 430 431 /** constructs an inference information out of a propagation rule and a position number, returns info as int */ 432 static 433 int getInferInt( 434 PROPRULE proprule, /**< propagation rule that deduced the value */ 435 int pos /**< variable position, the propagation rule was applied at */ 436 ) 437 { 438 return inferInfoToInt(getInferInfo(proprule, pos)); 439 } 440 441 442 /* 443 * memory growing methods for dynamically allocated arrays 444 */ 445 446 /** ensures, that linconsupgrades array can store at least num entries */ 447 static 448 SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize( 449 SCIP* scip, /**< SCIP data structure */ 450 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */ 451 int num /**< minimum number of entries to store */ 452 ) 453 { 454 assert(scip != NULL); 455 assert(conshdlrdata != NULL); 456 assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize); 457 458 if( num > conshdlrdata->linconsupgradessize ) 459 { 460 int newsize; 461 462 newsize = SCIPcalcMemGrowSize(scip, num); 463 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) ); 464 conshdlrdata->linconsupgradessize = newsize; 465 } 466 assert(num <= conshdlrdata->linconsupgradessize); 467 468 return SCIP_OKAY; 469 } 470 471 /** ensures, that vars and vals arrays can store at least num entries */ 472 static 473 SCIP_RETCODE consdataEnsureVarsSize( 474 SCIP* scip, /**< SCIP data structure */ 475 SCIP_CONSDATA* consdata, /**< linear constraint data */ 476 int num /**< minimum number of entries to store */ 477 ) 478 { 479 assert(scip != NULL); 480 assert(consdata != NULL); 481 assert(consdata->nvars <= consdata->varssize); 482 483 if( num > consdata->varssize ) 484 { 485 int newsize; 486 487 newsize = SCIPcalcMemGrowSize(scip, num); 488 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) ); 489 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) ); 490 if( consdata->eventdata != NULL ) 491 { 492 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) ); 493 } 494 consdata->varssize = newsize; 495 } 496 assert(num <= consdata->varssize); 497 498 return SCIP_OKAY; 499 } 500 501 502 /* 503 * local methods for managing linear constraint update methods 504 */ 505 506 /** creates a linear constraint upgrade data object */ 507 static 508 SCIP_RETCODE linconsupgradeCreate( 509 SCIP* scip, /**< SCIP data structure */ 510 SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */ 511 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */ 512 int priority /**< priority of upgrading method */ 513 ) 514 { 515 assert(scip != NULL); 516 assert(linconsupgrade != NULL); 517 assert(linconsupgd != NULL); 518 519 SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) ); 520 (*linconsupgrade)->linconsupgd = linconsupgd; 521 (*linconsupgrade)->priority = priority; 522 (*linconsupgrade)->active = TRUE; 523 524 return SCIP_OKAY; 525 } 526 527 /** frees a linear constraint upgrade data object */ 528 static 529 void linconsupgradeFree( 530 SCIP* scip, /**< SCIP data structure */ 531 SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */ 532 ) 533 { 534 assert(scip != NULL); 535 assert(linconsupgrade != NULL); 536 assert(*linconsupgrade != NULL); 537 538 SCIPfreeBlockMemory(scip, linconsupgrade); 539 } 540 541 /** creates constraint handler data for linear constraint handler */ 542 static 543 SCIP_RETCODE conshdlrdataCreate( 544 SCIP* scip, /**< SCIP data structure */ 545 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */ 546 SCIP_EVENTHDLR* eventhdlr /**< event handler */ 547 ) 548 { 549 assert(scip != NULL); 550 assert(conshdlrdata != NULL); 551 assert(eventhdlr != NULL); 552 553 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) ); 554 (*conshdlrdata)->linconsupgrades = NULL; 555 (*conshdlrdata)->linconsupgradessize = 0; 556 (*conshdlrdata)->nlinconsupgrades = 0; 557 (*conshdlrdata)->naddconss = 0; 558 559 /* set event handler for updating linear constraint activity bounds */ 560 (*conshdlrdata)->eventhdlr = eventhdlr; 561 562 return SCIP_OKAY; 563 } 564 565 /** frees constraint handler data for linear constraint handler */ 566 static 567 void conshdlrdataFree( 568 SCIP* scip, /**< SCIP data structure */ 569 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */ 570 ) 571 { 572 int i; 573 574 assert(scip != NULL); 575 assert(conshdlrdata != NULL); 576 assert(*conshdlrdata != NULL); 577 578 for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i ) 579 { 580 linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]); 581 } 582 SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize); 583 584 SCIPfreeBlockMemory(scip, conshdlrdata); 585 } 586 587 /** creates a linear constraint upgrade data object */ 588 static 589 SCIP_Bool conshdlrdataHasUpgrade( 590 SCIP* scip, /**< SCIP data structure */ 591 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */ 592 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */ 593 const char* conshdlrname /**< name of the constraint handler */ 594 ) 595 { 596 int i; 597 598 assert(scip != NULL); 599 assert(conshdlrdata != NULL); 600 assert(linconsupgd != NULL); 601 assert(conshdlrname != NULL); 602 603 for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i ) 604 { 605 if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd ) 606 { 607 #ifdef SCIP_DEBUG 608 SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname); 609 #endif 610 return TRUE; 611 } 612 } 613 614 return FALSE; 615 } 616 617 /** adds a linear constraint update method to the constraint handler's data */ 618 static 619 SCIP_RETCODE conshdlrdataIncludeUpgrade( 620 SCIP* scip, /**< SCIP data structure */ 621 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */ 622 SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */ 623 ) 624 { 625 int i; 626 627 assert(scip != NULL); 628 assert(conshdlrdata != NULL); 629 assert(linconsupgrade != NULL); 630 631 SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) ); 632 633 for( i = conshdlrdata->nlinconsupgrades; 634 i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i ) 635 { 636 conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1]; 637 } 638 assert(0 <= i && i <= conshdlrdata->nlinconsupgrades); 639 conshdlrdata->linconsupgrades[i] = linconsupgrade; 640 conshdlrdata->nlinconsupgrades++; 641 642 return SCIP_OKAY; 643 } 644 645 /* 646 * local methods 647 */ 648 649 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */ 650 static 651 SCIP_RETCODE lockRounding( 652 SCIP* scip, /**< SCIP data structure */ 653 SCIP_CONS* cons, /**< linear constraint */ 654 SCIP_VAR* var, /**< variable of constraint entry */ 655 SCIP_Real val /**< coefficient of constraint entry */ 656 ) 657 { 658 SCIP_CONSDATA* consdata; 659 660 assert(scip != NULL); 661 assert(cons != NULL); 662 assert(var != NULL); 663 664 consdata = SCIPconsGetData(cons); 665 assert(consdata != NULL); 666 assert(!SCIPisZero(scip, val)); 667 668 if( SCIPisPositive(scip, val) ) 669 { 670 SCIP_CALL( SCIPlockVarCons(scip, var, cons, 671 !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) ); 672 } 673 else 674 { 675 SCIP_CALL( SCIPlockVarCons(scip, var, cons, 676 !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) ); 677 } 678 679 return SCIP_OKAY; 680 } 681 682 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */ 683 static 684 SCIP_RETCODE unlockRounding( 685 SCIP* scip, /**< SCIP data structure */ 686 SCIP_CONS* cons, /**< linear constraint */ 687 SCIP_VAR* var, /**< variable of constraint entry */ 688 SCIP_Real val /**< coefficient of constraint entry */ 689 ) 690 { 691 SCIP_CONSDATA* consdata; 692 693 assert(scip != NULL); 694 assert(cons != NULL); 695 assert(var != NULL); 696 697 consdata = SCIPconsGetData(cons); 698 assert(consdata != NULL); 699 assert(!SCIPisZero(scip, val)); 700 701 if( SCIPisPositive(scip, val) ) 702 { 703 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs), 704 !SCIPisInfinity(scip, consdata->rhs)) ); 705 } 706 else 707 { 708 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs), 709 !SCIPisInfinity(scip, -consdata->lhs)) ); 710 } 711 712 return SCIP_OKAY; 713 } 714 715 /** creates event data for variable at given position, and catches events */ 716 /**! [SnippetDebugAssertions] */ 717 static 718 SCIP_RETCODE consCatchEvent( 719 SCIP* scip, /**< SCIP data structure */ 720 SCIP_CONS* cons, /**< linear constraint */ 721 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */ 722 int pos /**< array position of variable to catch bound change events for */ 723 ) 724 { 725 SCIP_CONSDATA* consdata; 726 assert(scip != NULL); 727 assert(cons != NULL); 728 assert(eventhdlr != NULL); 729 730 consdata = SCIPconsGetData(cons); 731 assert(consdata != NULL); 732 733 assert(0 <= pos && pos < consdata->nvars); 734 assert(consdata->vars != NULL); 735 assert(consdata->vars[pos] != NULL); 736 assert(SCIPvarIsTransformed(consdata->vars[pos])); 737 assert(consdata->eventdata != NULL); 738 assert(consdata->eventdata[pos] == NULL); 739 740 SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/ 741 consdata->eventdata[pos]->cons = cons; 742 consdata->eventdata[pos]->varpos = pos; 743 744 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos], 745 SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_VARFIXED | SCIP_EVENTTYPE_VARUNLOCKED 746 | SCIP_EVENTTYPE_GBDCHANGED | SCIP_EVENTTYPE_VARDELETED | SCIP_EVENTTYPE_TYPECHANGED, 747 eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) ); 748 749 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]); 750 751 return SCIP_OKAY; 752 } 753 /**! [SnippetDebugAssertions] */ 754 755 /** deletes event data for variable at given position, and drops events */ 756 static 757 SCIP_RETCODE consDropEvent( 758 SCIP* scip, /**< SCIP data structure */ 759 SCIP_CONS* cons, /**< linear constraint */ 760 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */ 761 int pos /**< array position of variable to catch bound change events for */ 762 ) 763 { 764 SCIP_CONSDATA* consdata; 765 assert(scip != NULL); 766 assert(cons != NULL); 767 assert(eventhdlr != NULL); 768 769 consdata = SCIPconsGetData(cons); 770 assert(consdata != NULL); 771 772 assert(0 <= pos && pos < consdata->nvars); 773 assert(consdata->vars[pos] != NULL); 774 assert(consdata->eventdata != NULL); 775 assert(consdata->eventdata[pos] != NULL); 776 assert(consdata->eventdata[pos]->cons == cons); 777 assert(consdata->eventdata[pos]->varpos == pos); 778 779 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], 780 SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_VARFIXED | SCIP_EVENTTYPE_VARUNLOCKED 781 | SCIP_EVENTTYPE_GBDCHANGED | SCIP_EVENTTYPE_VARDELETED | SCIP_EVENTTYPE_TYPECHANGED, 782 eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) ); 783 784 SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/ 785 786 return SCIP_OKAY; 787 } 788 789 /** catches bound change events for all variables in transformed linear constraint */ 790 static 791 SCIP_RETCODE consCatchAllEvents( 792 SCIP* scip, /**< SCIP data structure */ 793 SCIP_CONS* cons, /**< linear constraint */ 794 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */ 795 ) 796 { 797 SCIP_CONSDATA* consdata; 798 int i; 799 800 assert(scip != NULL); 801 assert(cons != NULL); 802 803 consdata = SCIPconsGetData(cons); 804 assert(consdata != NULL); 805 assert(consdata->eventdata == NULL); 806 807 /* allocate eventdata array */ 808 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) ); 809 assert(consdata->eventdata != NULL); 810 BMSclearMemoryArray(consdata->eventdata, consdata->nvars); 811 812 /* catch event for every single variable */ 813 for( i = 0; i < consdata->nvars; ++i ) 814 { 815 SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) ); 816 } 817 818 return SCIP_OKAY; 819 } 820 821 /** drops bound change events for all variables in transformed linear constraint */ 822 static 823 SCIP_RETCODE consDropAllEvents( 824 SCIP* scip, /**< SCIP data structure */ 825 SCIP_CONS* cons, /**< linear constraint */ 826 SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */ 827 ) 828 { 829 SCIP_CONSDATA* consdata; 830 int i; 831 832 assert(scip != NULL); 833 assert(cons != NULL); 834 835 consdata = SCIPconsGetData(cons); 836 assert(consdata != NULL); 837 assert(consdata->eventdata != NULL); 838 839 /* drop event of every single variable */ 840 for( i = consdata->nvars - 1; i >= 0; --i ) 841 { 842 SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) ); 843 } 844 845 /* free eventdata array */ 846 SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize); 847 assert(consdata->eventdata == NULL); 848 849 return SCIP_OKAY; 850 } 851 852 /** creates a linear constraint data */ 853 static 854 SCIP_RETCODE consdataCreate( 855 SCIP* scip, /**< SCIP data structure */ 856 SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */ 857 int nvars, /**< number of nonzeros in the constraint */ 858 SCIP_VAR** vars, /**< array with variables of constraint entries */ 859 SCIP_Real* vals, /**< array with coefficients of constraint entries */ 860 SCIP_Real lhs, /**< left hand side of row */ 861 SCIP_Real rhs /**< right hand side of row */ 862 ) 863 { 864 int v; 865 SCIP_Real constant; 866 867 assert(scip != NULL); 868 assert(consdata != NULL); 869 assert(nvars == 0 || vars != NULL); 870 assert(nvars == 0 || vals != NULL); 871 872 if( SCIPisInfinity(scip, rhs) ) 873 rhs = SCIPinfinity(scip); 874 else if( SCIPisInfinity(scip, -rhs) ) 875 rhs = -SCIPinfinity(scip); 876 877 if( SCIPisInfinity(scip, -lhs) ) 878 lhs = -SCIPinfinity(scip); 879 else if( SCIPisInfinity(scip, lhs) ) 880 lhs = SCIPinfinity(scip); 881 882 if( SCIPisGT(scip, lhs, rhs) ) 883 { 884 SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n"); 885 SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs); 886 } 887 888 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) ); 889 890 (*consdata)->varssize = 0; 891 (*consdata)->nvars = nvars; 892 (*consdata)->hascontvar = FALSE; 893 (*consdata)->hasnonbinvar = FALSE; 894 (*consdata)->hasnonbinvalid = TRUE; 895 (*consdata)->vars = NULL; 896 (*consdata)->vals = NULL; 897 898 constant = 0.0; 899 if( nvars > 0 ) 900 { 901 int k; 902 903 SCIP_VAR** varsbuffer; 904 SCIP_Real* valsbuffer; 905 906 /* copy variables into temporary buffer */ 907 SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) ); 908 SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) ); 909 k = 0; 910 911 /* loop over variables and sort out fixed ones */ 912 for( v = 0; v < nvars; ++v ) 913 { 914 SCIP_VAR* var; 915 SCIP_Real val; 916 917 var = vars[v]; 918 val = vals[v]; 919 920 assert(var != NULL); 921 if( !SCIPisZero(scip, val) ) 922 { 923 /* treat fixed variable as a constant if problem compression is enabled */ 924 if( SCIPisConsCompressionEnabled(scip) && SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) ) 925 { 926 constant += SCIPvarGetLbGlobal(var) * val; 927 } 928 else 929 { 930 varsbuffer[k] = var; 931 valsbuffer[k] = val; 932 k++; 933 934 /* update hascontvar and hasnonbinvar flags */ 935 if( !(*consdata)->hascontvar ) 936 { 937 SCIP_VARTYPE vartype = SCIPvarGetType(var); 938 939 if( vartype != SCIP_VARTYPE_BINARY ) 940 { 941 (*consdata)->hasnonbinvar = TRUE; 942 943 if( vartype == SCIP_VARTYPE_CONTINUOUS ) 944 (*consdata)->hascontvar = TRUE; 945 } 946 } 947 } 948 } 949 } 950 (*consdata)->nvars = k; 951 952 if( k > 0 ) 953 { 954 /* copy the possibly reduced buffer arrays into block */ 955 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) ); 956 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) ); 957 (*consdata)->varssize = k; 958 } 959 /* free temporary buffer */ 960 SCIPfreeBufferArray(scip, &valsbuffer); 961 SCIPfreeBufferArray(scip, &varsbuffer); 962 } 963 964 (*consdata)->eventdata = NULL; 965 966 /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */ 967 if( !SCIPisZero(scip, constant) ) 968 { 969 if( !SCIPisInfinity(scip, REALABS(lhs)) ) 970 lhs -= constant; 971 972 if( !SCIPisInfinity(scip, REALABS(rhs)) ) 973 rhs -= constant; 974 } 975 976 (*consdata)->row = NULL; 977 (*consdata)->nlrow = NULL; 978 (*consdata)->lhs = lhs; 979 (*consdata)->rhs = rhs; 980 (*consdata)->maxabsval = SCIP_INVALID; 981 (*consdata)->minabsval = SCIP_INVALID; 982 QUAD_ASSIGN((*consdata)->minactivity, SCIP_INVALID); 983 QUAD_ASSIGN((*consdata)->maxactivity, SCIP_INVALID); 984 (*consdata)->lastminactivity = SCIP_INVALID; 985 (*consdata)->lastmaxactivity = SCIP_INVALID; 986 (*consdata)->maxactdelta = SCIP_INVALID; 987 (*consdata)->maxactdeltavar = NULL; 988 (*consdata)->minactivityneginf = -1; 989 (*consdata)->minactivityposinf = -1; 990 (*consdata)->maxactivityneginf = -1; 991 (*consdata)->maxactivityposinf = -1; 992 (*consdata)->minactivityneghuge = -1; 993 (*consdata)->minactivityposhuge = -1; 994 (*consdata)->maxactivityneghuge = -1; 995 (*consdata)->maxactivityposhuge = -1; 996 QUAD_ASSIGN((*consdata)->glbminactivity, SCIP_INVALID); 997 QUAD_ASSIGN((*consdata)->glbmaxactivity, SCIP_INVALID); 998 (*consdata)->lastglbminactivity = SCIP_INVALID; 999 (*consdata)->lastglbmaxactivity = SCIP_INVALID; 1000 (*consdata)->glbminactivityneginf = -1; 1001 (*consdata)->glbminactivityposinf = -1; 1002 (*consdata)->glbmaxactivityneginf = -1; 1003 (*consdata)->glbmaxactivityposinf = -1; 1004 (*consdata)->glbminactivityneghuge = -1; 1005 (*consdata)->glbminactivityposhuge = -1; 1006 (*consdata)->glbmaxactivityneghuge = -1; 1007 (*consdata)->glbmaxactivityposhuge = -1; 1008 (*consdata)->possignature = 0; 1009 (*consdata)->negsignature = 0; 1010 (*consdata)->validmaxabsval = FALSE; 1011 (*consdata)->validminabsval = FALSE; 1012 (*consdata)->validactivities = FALSE; 1013 (*consdata)->validminact = FALSE; 1014 (*consdata)->validmaxact = FALSE; 1015 (*consdata)->validglbminact = FALSE; 1016 (*consdata)->validglbmaxact = FALSE; 1017 (*consdata)->boundstightened = 0; 1018 (*consdata)->presolved = FALSE; 1019 (*consdata)->removedfixings = FALSE; 1020 (*consdata)->validsignature = FALSE; 1021 (*consdata)->changed = TRUE; 1022 (*consdata)->normalized = FALSE; 1023 (*consdata)->upgradetried = FALSE; 1024 (*consdata)->upgraded = FALSE; 1025 (*consdata)->indexsorted = (nvars <= 1); 1026 (*consdata)->merged = (nvars <= 1); 1027 (*consdata)->cliquesadded = FALSE; 1028 (*consdata)->implsadded = FALSE; 1029 (*consdata)->coefsorted = FALSE; 1030 (*consdata)->nbinvars = -1; 1031 (*consdata)->varsdeleted = FALSE; 1032 (*consdata)->rangedrowpropagated = 0; 1033 (*consdata)->checkabsolute = FALSE; 1034 1035 if( SCIPisTransformed(scip) ) 1036 { 1037 /* get transformed variables */ 1038 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) ); 1039 } 1040 1041 /* capture variables */ 1042 for( v = 0; v < (*consdata)->nvars; v++ ) 1043 { 1044 /* likely implies a deleted variable */ 1045 if( (*consdata)->vars[v] == NULL ) 1046 { 1047 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize); 1048 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize); 1049 SCIPfreeBlockMemory(scip, consdata); 1050 return SCIP_INVALIDDATA; 1051 } 1052 1053 assert(!SCIPisZero(scip, (*consdata)->vals[v])); 1054 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) ); 1055 } 1056 1057 return SCIP_OKAY; 1058 } 1059 1060 /** frees a linear constraint data */ 1061 static 1062 SCIP_RETCODE consdataFree( 1063 SCIP* scip, /**< SCIP data structure */ 1064 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */ 1065 ) 1066 { 1067 int v; 1068 1069 assert(scip != NULL); 1070 assert(consdata != NULL); 1071 assert(*consdata != NULL); 1072 assert((*consdata)->varssize >= 0); 1073 1074 /* release the row */ 1075 if( (*consdata)->row != NULL ) 1076 { 1077 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) ); 1078 } 1079 1080 /* release the nlrow */ 1081 if( (*consdata)->nlrow != NULL ) 1082 { 1083 SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) ); 1084 } 1085 1086 /* release variables */ 1087 for( v = 0; v < (*consdata)->nvars; v++ ) 1088 { 1089 assert((*consdata)->vars[v] != NULL); 1090 assert(!SCIPisZero(scip, (*consdata)->vals[v])); 1091 SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) ); 1092 } 1093 1094 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize); 1095 SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize); 1096 SCIPfreeBlockMemory(scip, consdata); 1097 1098 return SCIP_OKAY; 1099 } 1100 1101 /** prints linear constraint in CIP format to file stream */ 1102 static 1103 SCIP_RETCODE consdataPrint( 1104 SCIP* scip, /**< SCIP data structure */ 1105 SCIP_CONSDATA* consdata, /**< linear constraint data */ 1106 FILE* file /**< output file (or NULL for standard output) */ 1107 ) 1108 { 1109 assert(scip != NULL); 1110 assert(consdata != NULL); 1111 1112 /* print left hand side for ranged rows */ 1113 if( !SCIPisInfinity(scip, -consdata->lhs) 1114 && !SCIPisInfinity(scip, consdata->rhs) 1115 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) ) 1116 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs); 1117 1118 /* print coefficients and variables */ 1119 if( consdata->nvars == 0 ) 1120 SCIPinfoMessage(scip, file, "0"); 1121 else 1122 { 1123 /* post linear sum of the linear constraint */ 1124 SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) ); 1125 } 1126 1127 /* print right hand side */ 1128 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) ) 1129 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs); 1130 else if( !SCIPisInfinity(scip, consdata->rhs) ) 1131 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs); 1132 else if( !SCIPisInfinity(scip, -consdata->lhs) ) 1133 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs); 1134 else 1135 SCIPinfoMessage(scip, file, " [free]"); 1136 1137 return SCIP_OKAY; 1138 } 1139 1140 /** prints linear constraint and contained solution values of variables to file stream */ 1141 static 1142 SCIP_RETCODE consPrintConsSol( 1143 SCIP* scip, /**< SCIP data structure */ 1144 SCIP_CONS* cons, /**< linear constraint */ 1145 SCIP_SOL* sol, /**< solution to print */ 1146 FILE* file /**< output file (or NULL for standard output) */ 1147 ) 1148 { 1149 SCIP_CONSDATA* consdata; 1150 1151 assert(scip != NULL); 1152 assert(cons != NULL); 1153 1154 consdata = SCIPconsGetData(cons); 1155 assert(consdata != NULL); 1156 1157 SCIPmessageFPrintInfo(SCIPgetMessagehdlr(scip), file, " [%s] <%s>: ", SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), SCIPconsGetName(cons)); 1158 1159 /* print left hand side for ranged rows */ 1160 if( !SCIPisInfinity(scip, -consdata->lhs) 1161 && !SCIPisInfinity(scip, consdata->rhs) 1162 && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) ) 1163 SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs); 1164 1165 /* print coefficients and variables */ 1166 if( consdata->nvars == 0 ) 1167 SCIPinfoMessage(scip, file, "0"); 1168 else 1169 { 1170 int v; 1171 1172 /* post linear sum of the linear constraint */ 1173 for( v = 0; v < consdata->nvars; ++v ) 1174 { 1175 if( consdata->vals != NULL ) 1176 { 1177 if( consdata->vals[v] == 1.0 ) 1178 { 1179 if( v > 0 ) 1180 SCIPinfoMessage(scip, file, " +"); 1181 } 1182 else if( consdata->vals[v] == -1.0 ) 1183 SCIPinfoMessage(scip, file, " -"); 1184 else 1185 SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]); 1186 } 1187 else if( consdata->nvars > 0 ) 1188 SCIPinfoMessage(scip, file, " +"); 1189 1190 /* print variable name */ 1191 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) ); 1192 1193 SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v])); 1194 } 1195 } 1196 1197 /* print right hand side */ 1198 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) ) 1199 SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs); 1200 else if( !SCIPisInfinity(scip, consdata->rhs) ) 1201 SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs); 1202 else if( !SCIPisInfinity(scip, -consdata->lhs) ) 1203 SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs); 1204 else 1205 SCIPinfoMessage(scip, file, " [free]"); 1206 1207 SCIPinfoMessage(scip, file, ";\n"); 1208 1209 return SCIP_OKAY; 1210 } 1211 1212 /** invalidates activity bounds, such that they are recalculated in next get */ 1213 static 1214 void consdataInvalidateActivities( 1215 SCIP_CONSDATA* consdata /**< linear constraint */ 1216 ) 1217 { 1218 assert(consdata != NULL); 1219 1220 consdata->validactivities = FALSE; 1221 consdata->validminact = FALSE; 1222 consdata->validmaxact = FALSE; 1223 consdata->validglbminact = FALSE; 1224 consdata->validglbmaxact = FALSE; 1225 consdata->validmaxabsval = FALSE; 1226 consdata->validminabsval = FALSE; 1227 consdata->hasnonbinvalid = FALSE; 1228 QUAD_ASSIGN(consdata->minactivity, SCIP_INVALID); 1229 QUAD_ASSIGN(consdata->maxactivity, SCIP_INVALID); 1230 consdata->lastminactivity = SCIP_INVALID; 1231 consdata->lastmaxactivity = SCIP_INVALID; 1232 consdata->maxabsval = SCIP_INVALID; 1233 consdata->minabsval = SCIP_INVALID; 1234 consdata->maxactdelta = SCIP_INVALID; 1235 consdata->maxactdeltavar = NULL; 1236 consdata->minactivityneginf = -1; 1237 consdata->minactivityposinf = -1; 1238 consdata->maxactivityneginf = -1; 1239 consdata->maxactivityposinf = -1; 1240 consdata->minactivityneghuge = -1; 1241 consdata->minactivityposhuge = -1; 1242 consdata->maxactivityneghuge = -1; 1243 consdata->maxactivityposhuge = -1; 1244 QUAD_ASSIGN(consdata->glbminactivity, SCIP_INVALID); 1245 QUAD_ASSIGN(consdata->glbmaxactivity, SCIP_INVALID); 1246 consdata->lastglbminactivity = SCIP_INVALID; 1247 consdata->lastglbmaxactivity = SCIP_INVALID; 1248 consdata->glbminactivityneginf = -1; 1249 consdata->glbminactivityposinf = -1; 1250 consdata->glbmaxactivityneginf = -1; 1251 consdata->glbmaxactivityposinf = -1; 1252 consdata->glbminactivityneghuge = -1; 1253 consdata->glbminactivityposhuge = -1; 1254 consdata->glbmaxactivityneghuge = -1; 1255 consdata->glbmaxactivityposhuge = -1; 1256 } 1257 1258 /** compute the pseudo activity of a constraint */ 1259 static 1260 SCIP_Real consdataComputePseudoActivity( 1261 SCIP* scip, /**< SCIP data structure */ 1262 SCIP_CONSDATA* consdata /**< linear constraint data */ 1263 ) 1264 { 1265 int i; 1266 int pseudoactivityposinf; 1267 int pseudoactivityneginf; 1268 SCIP_Real pseudoactivity; 1269 SCIP_Real bound; 1270 SCIP_Real val; 1271 1272 pseudoactivity = 0; 1273 pseudoactivityposinf = 0; 1274 pseudoactivityneginf = 0; 1275 1276 for( i = consdata->nvars - 1; i >= 0; --i ) 1277 { 1278 val = consdata->vals[i]; 1279 bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]); 1280 if( SCIPisInfinity(scip, bound) ) 1281 { 1282 if( val > 0.0 ) 1283 pseudoactivityposinf++; 1284 else 1285 pseudoactivityneginf++; 1286 } 1287 else 1288 { 1289 if( SCIPisInfinity(scip, -bound) ) 1290 { 1291 if( val > 0.0 ) 1292 pseudoactivityneginf++; 1293 else 1294 pseudoactivityposinf++; 1295 } 1296 else 1297 pseudoactivity += val * bound; 1298 } 1299 } 1300 1301 if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 ) 1302 return SCIP_INVALID; 1303 else if( pseudoactivityneginf > 0 ) 1304 return -SCIPinfinity(scip); 1305 else if( pseudoactivityposinf > 0 ) 1306 return SCIPinfinity(scip); 1307 1308 return pseudoactivity; 1309 } 1310 1311 /** recompute the minactivity of a constraint */ 1312 static 1313 void consdataRecomputeMinactivity( 1314 SCIP* scip, /**< SCIP data structure */ 1315 SCIP_CONSDATA* consdata /**< linear constraint data */ 1316 ) 1317 { 1318 int i; 1319 SCIP_Real bound; 1320 1321 QUAD_ASSIGN(consdata->minactivity, 0.0); 1322 1323 for( i = consdata->nvars - 1; i >= 0; --i ) 1324 { 1325 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]); 1326 if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) 1327 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) ) 1328 SCIPquadprecSumQD(consdata->minactivity, consdata->minactivity, consdata->vals[i] * bound); 1329 } 1330 1331 /* the activity was just computed from scratch and is valid now */ 1332 consdata->validminact = TRUE; 1333 1334 /* the activity was just computed from scratch, mark it to be reliable */ 1335 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity); 1336 } 1337 1338 /** recompute the maxactivity of a constraint */ 1339 static 1340 void consdataRecomputeMaxactivity( 1341 SCIP* scip, /**< SCIP data structure */ 1342 SCIP_CONSDATA* consdata /**< linear constraint data */ 1343 ) 1344 { 1345 int i; 1346 SCIP_Real bound; 1347 1348 QUAD_ASSIGN(consdata->maxactivity, 0.0); 1349 1350 for( i = consdata->nvars - 1; i >= 0; --i ) 1351 { 1352 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]); 1353 if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) 1354 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) ) 1355 SCIPquadprecSumQD(consdata->maxactivity, consdata->maxactivity, consdata->vals[i] * bound); 1356 } 1357 1358 /* the activity was just computed from scratch and is valid now */ 1359 consdata->validmaxact = TRUE; 1360 1361 /* the activity was just computed from scratch, mark it to be reliable */ 1362 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity); 1363 } 1364 1365 /** recompute the global minactivity of a constraint */ 1366 static 1367 void consdataRecomputeGlbMinactivity( 1368 SCIP* scip, /**< SCIP data structure */ 1369 SCIP_CONSDATA* consdata /**< linear constraint data */ 1370 ) 1371 { 1372 int i; 1373 SCIP_Real bound; 1374 1375 QUAD_ASSIGN(consdata->glbminactivity, 0.0); 1376 1377 for( i = consdata->nvars - 1; i >= 0; --i ) 1378 { 1379 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]); 1380 if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) 1381 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) ) 1382 SCIPquadprecSumQD(consdata->glbminactivity, consdata->glbminactivity, consdata->vals[i] * bound); 1383 } 1384 1385 /* the activity was just computed from scratch and is valid now */ 1386 consdata->validglbminact = TRUE; 1387 1388 /* the activity was just computed from scratch, mark it to be reliable */ 1389 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity); 1390 } 1391 1392 /** recompute the global maxactivity of a constraint */ 1393 static 1394 void consdataRecomputeGlbMaxactivity( 1395 SCIP* scip, /**< SCIP data structure */ 1396 SCIP_CONSDATA* consdata /**< linear constraint data */ 1397 ) 1398 { 1399 int i; 1400 SCIP_Real bound; 1401 1402 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0); 1403 1404 for( i = consdata->nvars - 1; i >= 0; --i ) 1405 { 1406 bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]); 1407 if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) 1408 && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) ) 1409 SCIPquadprecSumQD(consdata->glbmaxactivity, consdata->glbmaxactivity, consdata->vals[i] * bound); 1410 } 1411 1412 /* the activity was just computed from scratch and is valid now */ 1413 consdata->validglbmaxact = TRUE; 1414 1415 /* the activity was just computed from scratch, mark it to be reliable */ 1416 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity); 1417 } 1418 1419 /** calculates maximum absolute value of coefficients */ 1420 static 1421 void consdataCalcMaxAbsval( 1422 SCIP_CONSDATA* consdata /**< linear constraint data */ 1423 ) 1424 { 1425 SCIP_Real absval; 1426 int i; 1427 1428 assert(consdata != NULL); 1429 assert(!consdata->validmaxabsval); 1430 assert(consdata->maxabsval >= SCIP_INVALID); 1431 1432 consdata->validmaxabsval = TRUE; 1433 consdata->maxabsval = 0.0; 1434 for( i = 0; i < consdata->nvars; ++i ) 1435 { 1436 absval = consdata->vals[i]; 1437 absval = REALABS(absval); 1438 if( absval > consdata->maxabsval ) 1439 consdata->maxabsval = absval; 1440 } 1441 } 1442 1443 /** calculates minimum absolute value of coefficients */ 1444 static 1445 void consdataCalcMinAbsval( 1446 SCIP_CONSDATA* consdata /**< linear constraint data */ 1447 ) 1448 { 1449 SCIP_Real absval; 1450 int i; 1451 1452 assert(consdata != NULL); 1453 assert(!consdata->validminabsval); 1454 assert(consdata->minabsval >= SCIP_INVALID); 1455 1456 consdata->validminabsval = TRUE; 1457 1458 if( consdata->nvars > 0 ) 1459 consdata->minabsval = REALABS(consdata->vals[0]); 1460 else 1461 consdata->minabsval = 0.0; 1462 1463 for( i = 1; i < consdata->nvars; ++i ) 1464 { 1465 absval = consdata->vals[i]; 1466 absval = REALABS(absval); 1467 if( absval < consdata->minabsval ) 1468 consdata->minabsval = absval; 1469 } 1470 } 1471 1472 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */ 1473 static 1474 void consdataCheckNonbinvar( 1475 SCIP_CONSDATA* consdata /**< linear constraint data */ 1476 ) 1477 { 1478 int v; 1479 1480 assert(!consdata->hasnonbinvalid); 1481 consdata->hasnonbinvar = FALSE; 1482 consdata->hascontvar = FALSE; 1483 1484 for( v = consdata->nvars - 1; v >= 0; --v ) 1485 { 1486 SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]); 1487 1488 if( vartype != SCIP_VARTYPE_BINARY ) 1489 { 1490 consdata->hasnonbinvar = TRUE; 1491 1492 if( vartype == SCIP_VARTYPE_CONTINUOUS ) 1493 { 1494 consdata->hascontvar = TRUE; 1495 break; 1496 } 1497 } 1498 } 1499 assert(consdata->hascontvar || v < 0); 1500 1501 consdata->hasnonbinvalid = TRUE; 1502 } 1503 1504 1505 #ifdef CHECKMAXACTDELTA 1506 /** checks that the stored maximal activity delta (if not invalid) is correct */ 1507 static 1508 void checkMaxActivityDelta( 1509 SCIP* scip, /**< SCIP data structure */ 1510 SCIP_CONSDATA* consdata /**< linear constraint data */ 1511 ) 1512 { 1513 if( consdata->maxactdelta != SCIP_INVALID ) 1514 { 1515 SCIP_Real maxactdelta = 0.0; 1516 SCIP_Real domain; 1517 SCIP_Real delta; 1518 SCIP_Real lb; 1519 SCIP_Real ub; 1520 int v; 1521 1522 for( v = consdata->nvars - 1; v >= 0; --v ) 1523 { 1524 lb = SCIPvarGetLbLocal(consdata->vars[v]); 1525 ub = SCIPvarGetUbLocal(consdata->vars[v]); 1526 1527 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) ) 1528 { 1529 maxactdelta = SCIPinfinity(scip); 1530 break; 1531 } 1532 1533 domain = ub - lb; 1534 delta = REALABS(consdata->vals[v]) * domain; 1535 1536 if( delta > maxactdelta ) 1537 { 1538 maxactdelta = delta; 1539 } 1540 } 1541 assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta)); 1542 } 1543 } 1544 #else 1545 #define checkMaxActivityDelta(scip, consdata) /**/ 1546 #endif 1547 1548 /** recompute maximal activity contribution for a single variable */ 1549 static 1550 void consdataRecomputeMaxActivityDelta( 1551 SCIP* scip, /**< SCIP data structure */ 1552 SCIP_CONSDATA* consdata /**< linear constraint data */ 1553 ) 1554 { 1555 SCIP_Real delta; 1556 int v; 1557 1558 consdata->maxactdelta = 0.0; 1559 1560 if( !consdata->hasnonbinvalid ) 1561 consdataCheckNonbinvar(consdata); 1562 1563 /* easy case, the problem consists only of binary variables */ 1564 if( !consdata->hasnonbinvar ) 1565 { 1566 for( v = consdata->nvars - 1; v >= 0; --v ) 1567 { 1568 if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 ) 1569 { 1570 delta = REALABS(consdata->vals[v]); 1571 1572 if( delta > consdata->maxactdelta ) 1573 { 1574 consdata->maxactdelta = delta; 1575 consdata->maxactdeltavar = consdata->vars[v]; 1576 } 1577 } 1578 } 1579 return; 1580 } 1581 1582 for( v = consdata->nvars - 1; v >= 0; --v ) 1583 { 1584 SCIP_Real domain; 1585 SCIP_Real lb; 1586 SCIP_Real ub; 1587 1588 lb = SCIPvarGetLbLocal(consdata->vars[v]); 1589 ub = SCIPvarGetUbLocal(consdata->vars[v]); 1590 1591 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) ) 1592 { 1593 consdata->maxactdelta = SCIPinfinity(scip); 1594 consdata->maxactdeltavar = consdata->vars[v]; 1595 break; 1596 } 1597 1598 domain = ub - lb; 1599 delta = REALABS(consdata->vals[v]) * domain; 1600 1601 if( delta > consdata->maxactdelta ) 1602 { 1603 consdata->maxactdelta = delta; 1604 consdata->maxactdeltavar = consdata->vars[v]; 1605 } 1606 } 1607 } 1608 1609 1610 /** updates activities for a change in a bound */ 1611 static 1612 void consdataUpdateActivities( 1613 SCIP* scip, /**< SCIP data structure */ 1614 SCIP_CONSDATA* consdata, /**< linear constraint data */ 1615 SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */ 1616 SCIP_Real oldbound, /**< old bound of variable */ 1617 SCIP_Real newbound, /**< new bound of variable */ 1618 SCIP_Real val, /**< coefficient of constraint entry */ 1619 SCIP_BOUNDTYPE boundtype, /**< type of the bound change */ 1620 SCIP_Bool global, /**< is it a global or a local bound change? */ 1621 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 1622 ) 1623 { 1624 QUAD_MEMBER(SCIP_Real* activity); 1625 QUAD_MEMBER(SCIP_Real delta); 1626 SCIP_Real* lastactivity; 1627 int* activityposinf; 1628 int* activityneginf; 1629 int* activityposhuge; 1630 int* activityneghuge; 1631 SCIP_Real oldcontribution; 1632 SCIP_Real newcontribution; 1633 SCIP_Bool validact; 1634 SCIP_Bool finitenewbound; 1635 SCIP_Bool hugevalnewcont; 1636 1637 assert(scip != NULL); 1638 assert(consdata != NULL); 1639 assert(global || (var != NULL)); 1640 assert(consdata->validactivities); 1641 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID); 1642 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID); 1643 assert(consdata->lastminactivity < SCIP_INVALID); 1644 assert(consdata->lastmaxactivity < SCIP_INVALID); 1645 assert(consdata->minactivityneginf >= 0); 1646 assert(consdata->minactivityposinf >= 0); 1647 assert(consdata->maxactivityneginf >= 0); 1648 assert(consdata->maxactivityposinf >= 0); 1649 assert(consdata->minactivityneghuge >= 0); 1650 assert(consdata->minactivityposhuge >= 0); 1651 assert(consdata->maxactivityneghuge >= 0); 1652 assert(consdata->maxactivityposhuge >= 0); 1653 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID); 1654 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID); 1655 assert(consdata->lastglbminactivity < SCIP_INVALID); 1656 assert(consdata->lastglbmaxactivity < SCIP_INVALID); 1657 assert(consdata->glbminactivityneginf >= 0); 1658 assert(consdata->glbminactivityposinf >= 0); 1659 assert(consdata->glbmaxactivityneginf >= 0); 1660 assert(consdata->glbmaxactivityposinf >= 0); 1661 assert(consdata->glbminactivityneghuge >= 0); 1662 assert(consdata->glbminactivityposhuge >= 0); 1663 assert(consdata->glbmaxactivityneghuge >= 0); 1664 assert(consdata->glbmaxactivityposhuge >= 0); 1665 1666 QUAD_ASSIGN(delta, 0.0); 1667 1668 /* we are updating global activities */ 1669 if( global ) 1670 { 1671 /* depending on the boundtype and the coefficient, we choose the activity to be updated: 1672 * lower bound + pos. coef: update minactivity 1673 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched 1674 * upper bound + pos. coef: update maxactivity 1675 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched 1676 */ 1677 if( boundtype == SCIP_BOUNDTYPE_LOWER ) 1678 { 1679 if( val > 0.0 ) 1680 { 1681 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity); 1682 lastactivity = &(consdata->lastglbminactivity); 1683 activityposinf = &(consdata->glbminactivityposinf); 1684 activityneginf = &(consdata->glbminactivityneginf); 1685 activityposhuge = &(consdata->glbminactivityposhuge); 1686 activityneghuge = &(consdata->glbminactivityneghuge); 1687 validact = consdata->validglbminact; 1688 } 1689 else 1690 { 1691 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity); 1692 lastactivity = &(consdata->lastglbmaxactivity); 1693 activityposinf = &(consdata->glbmaxactivityneginf); 1694 activityneginf = &(consdata->glbmaxactivityposinf); 1695 activityposhuge = &(consdata->glbmaxactivityposhuge); 1696 activityneghuge = &(consdata->glbmaxactivityneghuge); 1697 validact = consdata->validglbmaxact; 1698 } 1699 } 1700 else 1701 { 1702 if( val > 0.0 ) 1703 { 1704 QUAD_ASSIGN_Q(activity, &consdata->glbmaxactivity); 1705 lastactivity = &(consdata->lastglbmaxactivity); 1706 activityposinf = &(consdata->glbmaxactivityposinf); 1707 activityneginf = &(consdata->glbmaxactivityneginf); 1708 activityposhuge = &(consdata->glbmaxactivityposhuge); 1709 activityneghuge = &(consdata->glbmaxactivityneghuge); 1710 validact = consdata->validglbmaxact; 1711 } 1712 else 1713 { 1714 QUAD_ASSIGN_Q(activity, &consdata->glbminactivity); 1715 lastactivity = &(consdata->lastglbminactivity); 1716 activityposinf = &(consdata->glbminactivityneginf); 1717 activityneginf = &(consdata->glbminactivityposinf); 1718 activityposhuge = &(consdata->glbminactivityposhuge); 1719 activityneghuge = &(consdata->glbminactivityneghuge); 1720 validact = consdata->validglbminact; 1721 } 1722 } 1723 } 1724 /* we are updating local activities */ 1725 else 1726 { 1727 /* depending on the boundtype and the coefficient, we choose the activity to be updated: 1728 * lower bound + pos. coef: update minactivity 1729 * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched 1730 * upper bound + pos. coef: update maxactivity 1731 * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched 1732 */ 1733 if( boundtype == SCIP_BOUNDTYPE_LOWER ) 1734 { 1735 if( val > 0.0 ) 1736 { 1737 QUAD_ASSIGN_Q(activity, &consdata->minactivity); 1738 lastactivity = &(consdata->lastminactivity); 1739 activityposinf = &(consdata->minactivityposinf); 1740 activityneginf = &(consdata->minactivityneginf); 1741 activityposhuge = &(consdata->minactivityposhuge); 1742 activityneghuge = &(consdata->minactivityneghuge); 1743 validact = consdata->validminact; 1744 } 1745 else 1746 { 1747 QUAD_ASSIGN_Q(activity, &consdata->maxactivity); 1748 lastactivity = &(consdata->lastmaxactivity); 1749 activityposinf = &(consdata->maxactivityneginf); 1750 activityneginf = &(consdata->maxactivityposinf); 1751 activityposhuge = &(consdata->maxactivityposhuge); 1752 activityneghuge = &(consdata->maxactivityneghuge); 1753 validact = consdata->validmaxact; 1754 } 1755 } 1756 else 1757 { 1758 if( val > 0.0 ) 1759 { 1760 QUAD_ASSIGN_Q(activity, &consdata->maxactivity); 1761 lastactivity = &(consdata->lastmaxactivity); 1762 activityposinf = &(consdata->maxactivityposinf); 1763 activityneginf = &(consdata->maxactivityneginf); 1764 activityposhuge = &(consdata->maxactivityposhuge); 1765 activityneghuge = &(consdata->maxactivityneghuge); 1766 validact = consdata->validmaxact; 1767 } 1768 else 1769 { 1770 QUAD_ASSIGN_Q(activity, &consdata->minactivity); 1771 lastactivity = &(consdata->lastminactivity); 1772 activityposinf = &(consdata->minactivityneginf); 1773 activityneginf = &(consdata->minactivityposinf); 1774 activityposhuge = &(consdata->minactivityposhuge); 1775 activityneghuge = &(consdata->minactivityneghuge); 1776 validact = consdata->validminact; 1777 } 1778 } 1779 } 1780 1781 oldcontribution = val * oldbound; 1782 newcontribution = val * newbound; 1783 hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution)); 1784 finitenewbound = !SCIPisInfinity(scip, REALABS(newbound)); 1785 1786 if( SCIPisInfinity(scip, REALABS(oldbound)) ) 1787 { 1788 /* old bound was +infinity */ 1789 if( oldbound > 0.0 ) 1790 { 1791 assert((*activityposinf) >= 1); 1792 1793 /* we only have to do something if the new bound is not again +infinity */ 1794 if( finitenewbound || newbound < 0.0 ) 1795 { 1796 /* decrease the counter for positive infinite contributions */ 1797 (*activityposinf)--; 1798 1799 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */ 1800 if( !finitenewbound && newbound < 0.0 ) 1801 (*activityneginf)++; 1802 else if( hugevalnewcont ) 1803 { 1804 /* if the contribution of this variable is too large, increase the counter for huge values */ 1805 if( newcontribution > 0.0 ) 1806 (*activityposhuge)++; 1807 else 1808 (*activityneghuge)++; 1809 } 1810 /* "normal case": just add the contribution to the activity */ 1811 else 1812 QUAD_ASSIGN(delta, newcontribution); 1813 } 1814 } 1815 /* old bound was -infinity */ 1816 else 1817 { 1818 assert(oldbound < 0.0); 1819 assert((*activityneginf) >= 1); 1820 1821 /* we only have to do something ig the new bound is not again -infinity */ 1822 if( finitenewbound || newbound > 0.0 ) 1823 { 1824 /* decrease the counter for negative infinite contributions */ 1825 (*activityneginf)--; 1826 1827 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */ 1828 if( !finitenewbound && newbound > 0.0 ) 1829 (*activityposinf)++; 1830 else if( hugevalnewcont ) 1831 { 1832 /* if the contribution of this variable is too large, increase the counter for huge values */ 1833 if( newcontribution > 0.0 ) 1834 (*activityposhuge)++; 1835 else 1836 (*activityneghuge)++; 1837 } 1838 /* "normal case": just add the contribution to the activity */ 1839 else 1840 QUAD_ASSIGN(delta, newcontribution); 1841 } 1842 } 1843 } 1844 else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) ) 1845 { 1846 /* old contribution was too large and positive */ 1847 if( oldcontribution > 0.0 ) 1848 { 1849 assert((*activityposhuge) >= 1); 1850 1851 /* decrease the counter for huge positive contributions; it might be increased again later, 1852 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound 1853 */ 1854 (*activityposhuge)--; 1855 1856 if( !finitenewbound ) 1857 { 1858 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */ 1859 if( newbound > 0.0 ) 1860 (*activityposinf)++; 1861 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */ 1862 else 1863 (*activityneginf)++; 1864 } 1865 else if( hugevalnewcont ) 1866 { 1867 /* if the contribution of this variable is too large and positive, increase the corresponding counter */ 1868 if( newcontribution > 0.0 ) 1869 (*activityposhuge)++; 1870 /* if the contribution of this variable is too large and negative, increase the corresponding counter */ 1871 else 1872 (*activityneghuge)++; 1873 } 1874 /* "normal case": just add the contribution to the activity */ 1875 else 1876 QUAD_ASSIGN(delta, newcontribution); 1877 } 1878 /* old contribution was too large and negative */ 1879 else 1880 { 1881 assert(oldcontribution < 0.0); 1882 assert((*activityneghuge) >= 1); 1883 1884 /* decrease the counter for huge negative contributions; it might be increased again later, 1885 * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound 1886 */ 1887 (*activityneghuge)--; 1888 1889 if( !finitenewbound ) 1890 { 1891 /* if the bound changed to +infinity, increase the counter for positive infinite contributions */ 1892 if( newbound > 0.0 ) 1893 (*activityposinf)++; 1894 /* if the bound changed to -infinity, increase the counter for negative infinite contributions */ 1895 else 1896 (*activityneginf)++; 1897 } 1898 else if( hugevalnewcont ) 1899 { 1900 /* if the contribution of this variable is too large and positive, increase the corresponding counter */ 1901 if( newcontribution > 0.0 ) 1902 (*activityposhuge)++; 1903 /* if the contribution of this variable is too large and negative, increase the corresponding counter */ 1904 else 1905 (*activityneghuge)++; 1906 } 1907 /* "normal case": just add the contribution to the activity */ 1908 else 1909 QUAD_ASSIGN(delta, newcontribution); 1910 } 1911 } 1912 /* old bound was finite and not too large */ 1913 else 1914 { 1915 if( !finitenewbound ) 1916 { 1917 /* if the new bound is +infinity, the old contribution has to be subtracted 1918 * and the counter for positive infinite contributions has to be increased 1919 */ 1920 if( newbound > 0.0 ) 1921 { 1922 (*activityposinf)++; 1923 QUAD_ASSIGN(delta, -oldcontribution); 1924 } 1925 /* if the new bound is -infinity, the old contribution has to be subtracted 1926 * and the counter for negative infinite contributions has to be increased 1927 */ 1928 else 1929 { 1930 assert(newbound < 0.0 ); 1931 1932 (*activityneginf)++; 1933 QUAD_ASSIGN(delta, -oldcontribution); 1934 } 1935 } 1936 /* if the contribution of this variable is too large, increase the counter for huge values */ 1937 else if( hugevalnewcont ) 1938 { 1939 if( newcontribution > 0.0 ) 1940 { 1941 (*activityposhuge)++; 1942 QUAD_ASSIGN(delta, -oldcontribution); 1943 } 1944 else 1945 { 1946 (*activityneghuge)++; 1947 QUAD_ASSIGN(delta, -oldcontribution); 1948 } 1949 } 1950 /* "normal case": just update the activity */ 1951 else 1952 { 1953 QUAD_ASSIGN(delta, newcontribution); 1954 SCIPquadprecSumQD(delta, delta, -oldcontribution); 1955 } 1956 } 1957 1958 /* update the activity, if the current value is valid and there was a change in the finite part */ 1959 if( validact && (QUAD_TO_DBL(delta) != 0.0) ) 1960 { 1961 SCIP_Real curractivity; 1962 1963 /* if the absolute value of the activity is increased, this is regarded as reliable, 1964 * otherwise, we check whether we can still trust the updated value 1965 */ 1966 SCIPquadprecSumQD(*activity, *activity, QUAD_TO_DBL(delta)); 1967 1968 curractivity = QUAD_TO_DBL(*activity); 1969 assert(!SCIPisInfinity(scip, -curractivity) && !SCIPisInfinity(scip, curractivity)); 1970 1971 if( REALABS((*lastactivity)) < REALABS(curractivity) ) 1972 { 1973 (*lastactivity) = curractivity; 1974 } 1975 else 1976 { 1977 if( checkreliability && SCIPisUpdateUnreliable(scip, curractivity, (*lastactivity)) ) 1978 { 1979 SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n", 1980 (global ? "global " : ""), curractivity); 1981 1982 /* mark the activity that was just changed and is not reliable anymore to be invalid */ 1983 if( global ) 1984 { 1985 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) ) 1986 consdata->validglbminact = FALSE; 1987 else 1988 consdata->validglbmaxact = FALSE; 1989 } 1990 else 1991 { 1992 if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) ) 1993 consdata->validminact = FALSE; 1994 else 1995 consdata->validmaxact = FALSE; 1996 } 1997 } 1998 } 1999 } 2000 } 2001 2002 /** updates minimum and maximum activity for a change in lower bound */ 2003 static 2004 void consdataUpdateActivitiesLb( 2005 SCIP* scip, /**< SCIP data structure */ 2006 SCIP_CONSDATA* consdata, /**< linear constraint data */ 2007 SCIP_VAR* var, /**< variable that has been changed */ 2008 SCIP_Real oldlb, /**< old lower bound of variable */ 2009 SCIP_Real newlb, /**< new lower bound of variable */ 2010 SCIP_Real val, /**< coefficient of constraint entry */ 2011 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 2012 ) 2013 { 2014 assert(scip != NULL); 2015 assert(consdata != NULL); 2016 assert(var != NULL); 2017 2018 if( consdata->validactivities ) 2019 { 2020 consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability); 2021 2022 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity))); 2023 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity))); 2024 } 2025 } 2026 2027 /** updates minimum and maximum activity for a change in upper bound */ 2028 static 2029 void consdataUpdateActivitiesUb( 2030 SCIP* scip, /**< SCIP data structure */ 2031 SCIP_CONSDATA* consdata, /**< linear constraint data */ 2032 SCIP_VAR* var, /**< variable that has been changed */ 2033 SCIP_Real oldub, /**< old upper bound of variable */ 2034 SCIP_Real newub, /**< new upper bound of variable */ 2035 SCIP_Real val, /**< coefficient of constraint entry */ 2036 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 2037 ) 2038 { 2039 assert(scip != NULL); 2040 assert(consdata != NULL); 2041 assert(var != NULL); 2042 2043 if( consdata->validactivities ) 2044 { 2045 consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability); 2046 2047 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->minactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->minactivity))); 2048 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->maxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->maxactivity))); 2049 } 2050 } 2051 2052 /** updates minimum and maximum global activity for a change in the global lower bound */ 2053 static 2054 void consdataUpdateActivitiesGlbLb( 2055 SCIP* scip, /**< SCIP data structure */ 2056 SCIP_CONSDATA* consdata, /**< linear constraint data */ 2057 SCIP_Real oldlb, /**< old lower bound of variable */ 2058 SCIP_Real newlb, /**< new lower bound of variable */ 2059 SCIP_Real val, /**< coefficient of constraint entry */ 2060 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 2061 ) 2062 { 2063 assert(scip != NULL); 2064 assert(consdata != NULL); 2065 2066 if( consdata->validactivities ) 2067 { 2068 consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability); 2069 2070 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity))); 2071 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity))); 2072 } 2073 } 2074 2075 /** updates minimum and maximum global activity for a change in global upper bound */ 2076 static 2077 void consdataUpdateActivitiesGlbUb( 2078 SCIP* scip, /**< SCIP data structure */ 2079 SCIP_CONSDATA* consdata, /**< linear constraint data */ 2080 SCIP_Real oldub, /**< old upper bound of variable */ 2081 SCIP_Real newub, /**< new upper bound of variable */ 2082 SCIP_Real val, /**< coefficient of constraint entry */ 2083 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 2084 ) 2085 { 2086 assert(scip != NULL); 2087 assert(consdata != NULL); 2088 2089 if( consdata->validactivities ) 2090 { 2091 consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability); 2092 2093 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbminactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbminactivity))); 2094 assert(!SCIPisInfinity(scip, -QUAD_TO_DBL(consdata->glbmaxactivity)) && !SCIPisInfinity(scip, QUAD_TO_DBL(consdata->glbmaxactivity))); 2095 } 2096 } 2097 2098 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */ 2099 static 2100 void consdataUpdateAddCoef( 2101 SCIP* scip, /**< SCIP data structure */ 2102 SCIP_CONSDATA* consdata, /**< linear constraint data */ 2103 SCIP_VAR* var, /**< variable of constraint entry */ 2104 SCIP_Real val, /**< coefficient of constraint entry */ 2105 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 2106 ) 2107 { 2108 assert(scip != NULL); 2109 assert(consdata != NULL); 2110 assert(var != NULL); 2111 2112 /* update maximum absolute value */ 2113 if( consdata->validmaxabsval ) 2114 { 2115 SCIP_Real absval; 2116 2117 assert(consdata->maxabsval < SCIP_INVALID); 2118 2119 absval = REALABS(val); 2120 consdata->maxabsval = MAX(consdata->maxabsval, absval); 2121 } 2122 2123 if( consdata->validminabsval ) 2124 { 2125 SCIP_Real absval; 2126 2127 assert(consdata->minabsval < SCIP_INVALID); 2128 2129 absval = REALABS(val); 2130 consdata->minabsval = MIN(consdata->minabsval, absval); 2131 } 2132 2133 /* update minimal and maximal activity */ 2134 if( consdata->validactivities ) 2135 { 2136 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID); 2137 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID); 2138 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID); 2139 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID); 2140 2141 consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability); 2142 consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability); 2143 consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability); 2144 consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability); 2145 } 2146 } 2147 2148 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */ 2149 static 2150 void consdataUpdateDelCoef( 2151 SCIP* scip, /**< SCIP data structure */ 2152 SCIP_CONSDATA* consdata, /**< linear constraint data */ 2153 SCIP_VAR* var, /**< variable of constraint entry */ 2154 SCIP_Real val, /**< coefficient of constraint entry */ 2155 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 2156 ) 2157 { 2158 assert(scip != NULL); 2159 assert(consdata != NULL); 2160 assert(var != NULL); 2161 2162 /* invalidate maximum absolute value, if this coefficient was the maximum */ 2163 if( consdata->validmaxabsval ) 2164 { 2165 SCIP_Real absval; 2166 2167 absval = REALABS(val); 2168 2169 if( SCIPisEQ(scip, absval, consdata->maxabsval) ) 2170 { 2171 consdata->validmaxabsval = FALSE; 2172 consdata->maxabsval = SCIP_INVALID; 2173 } 2174 } 2175 2176 /* invalidate minimum absolute value, if this coefficient was the minimum */ 2177 if( consdata->validminabsval ) 2178 { 2179 SCIP_Real absval; 2180 2181 absval = REALABS(val); 2182 2183 if( SCIPisEQ(scip, absval, consdata->minabsval) ) 2184 { 2185 consdata->validminabsval = FALSE; 2186 consdata->minabsval = SCIP_INVALID; 2187 } 2188 } 2189 2190 /* update minimal and maximal activity */ 2191 if( consdata->validactivities ) 2192 { 2193 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID); 2194 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID); 2195 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID); 2196 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID); 2197 2198 consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability); 2199 consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability); 2200 consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability); 2201 consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability); 2202 } 2203 } 2204 2205 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */ 2206 static 2207 void consdataUpdateChgCoef( 2208 SCIP* scip, /**< SCIP data structure */ 2209 SCIP_CONSDATA* consdata, /**< linear constraint data */ 2210 SCIP_VAR* var, /**< variable of constraint entry */ 2211 SCIP_Real oldval, /**< old coefficient of constraint entry */ 2212 SCIP_Real newval, /**< new coefficient of constraint entry */ 2213 SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */ 2214 ) 2215 { 2216 assert(scip != NULL); 2217 assert(consdata != NULL); 2218 assert(var != NULL); 2219 2220 /* old zero coefficients should be handled by consdataUpdateAddCoef() */ 2221 assert(!SCIPisZero(scip, oldval)); 2222 2223 /* new zero coefficients should be handled by consdataUpdateDelCoef() */ 2224 assert(!SCIPisZero(scip, newval)); 2225 2226 /* update maximum absolute value */ 2227 if( consdata->validmaxabsval ) 2228 { 2229 SCIP_Real absval; 2230 2231 absval = REALABS(newval); 2232 2233 if( SCIPisGE(scip, absval, consdata->maxabsval) ) 2234 { 2235 consdata->maxabsval = absval; 2236 } 2237 else 2238 { 2239 absval = REALABS(oldval); 2240 2241 /* invalidate maximum absolute value */ 2242 if( SCIPisEQ(scip, absval, consdata->maxabsval) ) 2243 { 2244 consdata->validmaxabsval = FALSE; 2245 consdata->maxabsval = SCIP_INVALID; 2246 } 2247 } 2248 } 2249 2250 /* update minimum absolute value */ 2251 if( consdata->validminabsval ) 2252 { 2253 SCIP_Real absval; 2254 2255 absval = REALABS(newval); 2256 2257 if( SCIPisLE(scip, absval, consdata->minabsval) ) 2258 { 2259 consdata->minabsval = absval; 2260 } 2261 else 2262 { 2263 absval = REALABS(oldval); 2264 2265 /* invalidate minimum absolute value */ 2266 if( SCIPisEQ(scip, absval, consdata->minabsval) ) 2267 { 2268 consdata->validminabsval = FALSE; 2269 consdata->minabsval = SCIP_INVALID; 2270 } 2271 } 2272 } 2273 2274 /* update maximum activity delta */ 2275 if( !SCIPisInfinity(scip, consdata->maxactdelta ) ) 2276 { 2277 SCIP_Real domain; 2278 SCIP_Real delta; 2279 2280 assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var))); 2281 assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var))); 2282 2283 domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var); 2284 delta = REALABS(newval) * domain; 2285 2286 if( delta > consdata->maxactdelta ) 2287 { 2288 consdata->maxactdelta = delta; 2289 consdata->maxactdeltavar = var; 2290 } 2291 else 2292 { 2293 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */ 2294 if( consdata->maxactdeltavar == var ) 2295 consdata->maxactdelta = SCIP_INVALID; 2296 } 2297 } 2298 2299 /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */ 2300 consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability); 2301 consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability); 2302 } 2303 2304 /** returns the maximum absolute value of all coefficients in the constraint */ 2305 static 2306 SCIP_Real consdataGetMaxAbsval( 2307 SCIP_CONSDATA* consdata /**< linear constraint data */ 2308 ) 2309 { 2310 assert(consdata != NULL); 2311 2312 if( !consdata->validmaxabsval ) 2313 consdataCalcMaxAbsval(consdata); 2314 assert(consdata->validmaxabsval); 2315 assert(consdata->maxabsval < SCIP_INVALID); 2316 2317 return consdata->maxabsval; 2318 } 2319 2320 /** returns the minimum absolute value of all coefficients in the constraint */ 2321 static 2322 SCIP_Real consdataGetMinAbsval( 2323 SCIP_CONSDATA* consdata /**< linear constraint data */ 2324 ) 2325 { 2326 assert(consdata != NULL); 2327 2328 if( !consdata->validminabsval ) 2329 consdataCalcMinAbsval(consdata); 2330 assert(consdata->validminabsval); 2331 assert(consdata->minabsval < SCIP_INVALID); 2332 2333 return consdata->minabsval; 2334 } 2335 2336 /** calculates minimum and maximum local and global activity for constraint from scratch; 2337 * additionally recalculates maximum absolute value of coefficients 2338 */ 2339 static 2340 void consdataCalcActivities( 2341 SCIP* scip, /**< SCIP data structure */ 2342 SCIP_CONSDATA* consdata /**< linear constraint data */ 2343 ) 2344 { 2345 int i; 2346 2347 assert(scip != NULL); 2348 assert(consdata != NULL); 2349 assert(!consdata->validactivities); 2350 assert(QUAD_TO_DBL(consdata->minactivity) >= SCIP_INVALID || consdata->validminact); 2351 assert(QUAD_TO_DBL(consdata->maxactivity) >= SCIP_INVALID || consdata->validmaxact); 2352 assert(QUAD_TO_DBL(consdata->glbminactivity) >= SCIP_INVALID || consdata->validglbminact); 2353 assert(QUAD_TO_DBL(consdata->glbmaxactivity) >= SCIP_INVALID || consdata->validglbmaxact); 2354 2355 consdata->validmaxabsval = TRUE; 2356 consdata->validminabsval = TRUE; 2357 consdata->validactivities = TRUE; 2358 consdata->validminact = TRUE; 2359 consdata->validmaxact = TRUE; 2360 consdata->validglbminact = TRUE; 2361 consdata->validglbmaxact = TRUE; 2362 consdata->maxabsval = 0.0; 2363 consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0])); 2364 QUAD_ASSIGN(consdata->minactivity, 0.0); 2365 QUAD_ASSIGN(consdata->maxactivity, 0.0); 2366 consdata->lastminactivity = 0.0; 2367 consdata->lastmaxactivity = 0.0; 2368 consdata->minactivityneginf = 0; 2369 consdata->minactivityposinf = 0; 2370 consdata->maxactivityneginf = 0; 2371 consdata->maxactivityposinf = 0; 2372 consdata->minactivityneghuge = 0; 2373 consdata->minactivityposhuge = 0; 2374 consdata->maxactivityneghuge = 0; 2375 consdata->maxactivityposhuge = 0; 2376 QUAD_ASSIGN(consdata->glbminactivity, 0.0); 2377 QUAD_ASSIGN(consdata->glbmaxactivity, 0.0); 2378 consdata->lastglbminactivity = 0.0; 2379 consdata->lastglbmaxactivity = 0.0; 2380 consdata->glbminactivityneginf = 0; 2381 consdata->glbminactivityposinf = 0; 2382 consdata->glbmaxactivityneginf = 0; 2383 consdata->glbmaxactivityposinf = 0; 2384 consdata->glbminactivityneghuge = 0; 2385 consdata->glbminactivityposhuge = 0; 2386 consdata->glbmaxactivityneghuge = 0; 2387 consdata->glbmaxactivityposhuge = 0; 2388 2389 for( i = 0; i < consdata->nvars; ++i ) 2390 consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE); 2391 2392 consdata->lastminactivity = QUAD_TO_DBL(consdata->minactivity); 2393 consdata->lastmaxactivity = QUAD_TO_DBL(consdata->maxactivity); 2394 consdata->lastglbminactivity = QUAD_TO_DBL(consdata->glbminactivity); 2395 consdata->lastglbmaxactivity = QUAD_TO_DBL(consdata->glbmaxactivity); 2396 } 2397 2398 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions 2399 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity 2400 */ 2401 static 2402 void getMinActivity( 2403 SCIP* scip, /**< SCIP data structure */ 2404 SCIP_CONSDATA* consdata, /**< linear constraint */ 2405 int posinf, /**< number of coefficients contributing pos. infinite value */ 2406 int neginf, /**< number of coefficients contributing neg. infinite value */ 2407 int poshuge, /**< number of coefficients contributing huge pos. value */ 2408 int neghuge, /**< number of coefficients contributing huge neg. value */ 2409 SCIP_Real delta, /**< value to subtract from stored minactivity 2410 * (contribution of the variable set to zero when getting residual activity) */ 2411 SCIP_Bool global, /**< should the global or local minimal activity be returned? */ 2412 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */ 2413 SCIP_Real* minactivity, /**< pointer to store the minimal activity */ 2414 SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation, 2415 * i.e. is <= the exact minactivity (in case of huge contributing values) */ 2416 SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */ 2417 ) 2418 { 2419 assert(scip != NULL); 2420 assert(consdata != NULL); 2421 assert(posinf >= 0); 2422 assert(neginf >= 0); 2423 assert(poshuge >= 0); 2424 assert(neghuge >= 0); 2425 assert(minactivity != NULL); 2426 assert(isrelax != NULL); 2427 assert(issettoinfinity != NULL); 2428 2429 /* if we have pos. infinite contributions, the minactivity is +infty */ 2430 if( posinf > 0 ) 2431 { 2432 *minactivity = SCIPinfinity(scip); 2433 *issettoinfinity = TRUE; 2434 *isrelax = FALSE; 2435 } 2436 /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */ 2437 else if( neginf > 0 ) 2438 { 2439 *minactivity = -SCIPinfinity(scip); 2440 *issettoinfinity = TRUE; 2441 *isrelax = FALSE; 2442 } 2443 /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */ 2444 else if( neghuge > 0 ) 2445 { 2446 *minactivity = -SCIPinfinity(scip); 2447 *issettoinfinity = TRUE; 2448 *isrelax = TRUE; 2449 } 2450 /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */ 2451 else if( !goodrelax && poshuge > 0 ) 2452 { 2453 *minactivity = -SCIPinfinity(scip); 2454 *issettoinfinity = TRUE; 2455 *isrelax = TRUE; 2456 } 2457 else 2458 { 2459 SCIP_Real tmpactivity; 2460 2461 /* recompute minactivity if it is not valid */ 2462 if( global ) 2463 { 2464 if( !consdata->validglbminact ) 2465 consdataRecomputeGlbMinactivity(scip, consdata); 2466 assert(consdata->validglbminact); 2467 2468 tmpactivity = QUAD_TO_DBL(consdata->glbminactivity); 2469 } 2470 else 2471 { 2472 if( !consdata->validminact ) 2473 consdataRecomputeMinactivity(scip, consdata); 2474 assert(consdata->validminact); 2475 2476 tmpactivity = QUAD_TO_DBL(consdata->minactivity); 2477 } 2478 2479 /* we have no infinite and no neg. huge contributions, but pos. huge contributions; 2480 * a feasible relaxation of the minactivity is the number of positive huge contributions 2481 * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta 2482 */ 2483 if( poshuge > 0 ) 2484 { 2485 *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta); 2486 *issettoinfinity = FALSE; 2487 *isrelax = TRUE; 2488 } 2489 /* all counters are zero, so the minactivity is just stored and we subtract the delta */ 2490 else 2491 { 2492 *minactivity = tmpactivity - delta; 2493 *issettoinfinity = FALSE; 2494 *isrelax = FALSE; 2495 } 2496 } 2497 } 2498 2499 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions 2500 * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity 2501 */ 2502 static 2503 void getMaxActivity( 2504 SCIP* scip, /**< SCIP data structure */ 2505 SCIP_CONSDATA* consdata, /**< linear constraint */ 2506 int posinf, /**< number of coefficients contributing pos. infinite value */ 2507 int neginf, /**< number of coefficients contributing neg. infinite value */ 2508 int poshuge, /**< number of coefficients contributing huge pos. value */ 2509 int neghuge, /**< number of coefficients contributing huge neg. value */ 2510 SCIP_Real delta, /**< value to subtract from stored maxactivity 2511 * (contribution of the variable set to zero when getting residual activity) */ 2512 SCIP_Bool global, /**< should the global or local maximal activity be returned? */ 2513 SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */ 2514 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */ 2515 SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation, 2516 * i.e. is >= the exact maxactivity (in case of huge contributing values) */ 2517 SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */ 2518 ) 2519 { 2520 assert(scip != NULL); 2521 assert(consdata != NULL); 2522 assert(posinf >= 0); 2523 assert(neginf >= 0); 2524 assert(poshuge >= 0); 2525 assert(neghuge >= 0); 2526 assert(maxactivity != NULL); 2527 assert(isrelax != NULL); 2528 assert(issettoinfinity != NULL); 2529 2530 /* if we have neg. infinite contributions, the maxactivity is -infty */ 2531 if( neginf > 0 ) 2532 { 2533 *maxactivity = -SCIPinfinity(scip); 2534 *issettoinfinity = TRUE; 2535 *isrelax = FALSE; 2536 } 2537 /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */ 2538 else if( posinf > 0 ) 2539 { 2540 *maxactivity = SCIPinfinity(scip); 2541 *issettoinfinity = TRUE; 2542 *isrelax = FALSE; 2543 } 2544 /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */ 2545 else if( poshuge > 0 ) 2546 { 2547 *maxactivity = SCIPinfinity(scip); 2548 *issettoinfinity = TRUE; 2549 *isrelax = TRUE; 2550 } 2551 /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */ 2552 else if( !goodrelax && neghuge > 0 ) 2553 { 2554 *maxactivity = SCIPinfinity(scip); 2555 *issettoinfinity = TRUE; 2556 *isrelax = TRUE; 2557 } 2558 else 2559 { 2560 SCIP_Real tmpactivity; 2561 2562 /* recompute maxactivity if it is not valid */ 2563 if( global ) 2564 { 2565 if( !consdata->validglbmaxact ) 2566 consdataRecomputeGlbMaxactivity(scip, consdata); 2567 assert(consdata->validglbmaxact); 2568 2569 tmpactivity = QUAD_TO_DBL(consdata->glbmaxactivity); 2570 } 2571 else 2572 { 2573 if( !consdata->validmaxact ) 2574 consdataRecomputeMaxactivity(scip, consdata); 2575 assert(consdata->validmaxact); 2576 2577 tmpactivity = QUAD_TO_DBL(consdata->maxactivity); 2578 } 2579 2580 /* we have no infinite, and no pos. huge contributions, but neg. huge contributions; 2581 * a feasible relaxation of the maxactivity is minus the number of negative huge contributions 2582 * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta 2583 */ 2584 if( neghuge > 0 ) 2585 { 2586 *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta; 2587 *issettoinfinity = FALSE; 2588 *isrelax = TRUE; 2589 } 2590 /* all counters are zero, so the maxactivity is just stored and we subtract the delta */ 2591 else 2592 { 2593 *maxactivity = tmpactivity - delta; 2594 *issettoinfinity = FALSE; 2595 *isrelax = FALSE; 2596 } 2597 } 2598 } 2599 2600 /** gets activity bounds for constraint */ 2601 static 2602 void consdataGetActivityBounds( 2603 SCIP* scip, /**< SCIP data structure */ 2604 SCIP_CONSDATA* consdata, /**< linear constraint */ 2605 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are 2606 * relaxed activities ignored, anyway? */ 2607 SCIP_Real* minactivity, /**< pointer to store the minimal activity */ 2608 SCIP_Real* maxactivity, /**< pointer to store the maximal activity */ 2609 SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation, 2610 * i.e. <= the exact minactivity (in case of huge contributions), 2611 * or equal to the exact minimal activity */ 2612 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation, 2613 * i.e. >= the exact maxactivity (in case of huge contributions), 2614 * or equal to the exact maximal activity */ 2615 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */ 2616 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */ 2617 2618 ) 2619 { 2620 assert(scip != NULL); 2621 assert(consdata != NULL); 2622 assert(minactivity != NULL); 2623 assert(maxactivity != NULL); 2624 assert(isminsettoinfinity != NULL); 2625 assert(ismaxsettoinfinity != NULL); 2626 2627 if( !consdata->validactivities ) 2628 { 2629 consdataCalcActivities(scip, consdata); 2630 assert(consdata->validminact); 2631 assert(consdata->validmaxact); 2632 } 2633 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID); 2634 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID); 2635 assert(consdata->minactivityneginf >= 0); 2636 assert(consdata->minactivityposinf >= 0); 2637 assert(consdata->maxactivityneginf >= 0); 2638 assert(consdata->maxactivityposinf >= 0); 2639 2640 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf, 2641 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax, 2642 minactivity, minisrelax, isminsettoinfinity); 2643 2644 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf, 2645 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax, 2646 maxactivity, maxisrelax, ismaxsettoinfinity); 2647 } 2648 2649 /** calculates activity bounds for constraint after setting variable to zero */ 2650 static 2651 void consdataGetReliableResidualActivity( 2652 SCIP* scip, /**< SCIP data structure */ 2653 SCIP_CONSDATA* consdata, /**< linear constraint */ 2654 SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */ 2655 SCIP_Real* resactivity, /**< pointer to store the residual activity */ 2656 SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */ 2657 SCIP_Bool useglobalbounds /**< should global or local bounds be used? */ 2658 ) 2659 { 2660 SCIP_VAR* var; 2661 SCIP_Real val; 2662 SCIP_Real lb; 2663 SCIP_Real ub; 2664 int v; 2665 2666 assert(scip != NULL); 2667 assert(consdata != NULL); 2668 assert(cancelvar != NULL); 2669 assert(resactivity != NULL); 2670 2671 *resactivity = 0.0; 2672 2673 for( v = 0; v < consdata->nvars; ++v ) 2674 { 2675 var = consdata->vars[v]; 2676 assert(var != NULL); 2677 if( var == cancelvar ) 2678 continue; 2679 2680 val = consdata->vals[v]; 2681 2682 if( useglobalbounds ) 2683 { 2684 lb = SCIPvarGetLbGlobal(var); 2685 ub = SCIPvarGetUbGlobal(var); 2686 } 2687 else 2688 { 2689 lb = SCIPvarGetLbLocal(var); 2690 ub = SCIPvarGetUbLocal(var); 2691 } 2692 2693 assert(!SCIPisZero(scip, val)); 2694 assert(SCIPisLE(scip, lb, ub)); 2695 2696 if( val > 0.0 ) 2697 { 2698 if( isminresact ) 2699 { 2700 assert(!SCIPisInfinity(scip, -lb)); 2701 assert(!SCIPisHugeValue(scip, REALABS(val*lb))); 2702 *resactivity += val*lb; 2703 } 2704 else 2705 { 2706 assert(!SCIPisInfinity(scip, ub)); 2707 assert(!SCIPisHugeValue(scip, REALABS(val*ub))); 2708 *resactivity += val*ub; 2709 } 2710 } 2711 else 2712 { 2713 if( isminresact) 2714 { 2715 assert(!SCIPisInfinity(scip, ub)); 2716 assert(!SCIPisHugeValue(scip, REALABS(val*ub))); 2717 *resactivity += val*ub; 2718 } 2719 else 2720 { 2721 assert(!SCIPisInfinity(scip, -lb)); 2722 assert(!SCIPisHugeValue(scip, REALABS(val*lb))); 2723 *resactivity += val*lb; 2724 } 2725 } 2726 } 2727 assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity))); 2728 } 2729 2730 /** gets activity bounds for constraint after setting variable to zero */ 2731 static 2732 void consdataGetActivityResiduals( 2733 SCIP* scip, /**< SCIP data structure */ 2734 SCIP_CONSDATA* consdata, /**< linear constraint */ 2735 SCIP_VAR* var, /**< variable to calculate activity residual for */ 2736 SCIP_Real val, /**< coefficient value of variable in linear constraint */ 2737 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are 2738 * relaxed acticities ignored, anyway? */ 2739 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */ 2740 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */ 2741 SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a 2742 * relaxation, i.e. <= the exact residual minactivity (in case of huge 2743 * contributions), or equal to the exact residual minactivity */ 2744 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a 2745 * relaxation, i.e. <= the exact residual maxactivity (in case of huge 2746 * contributions), or equal to the exact residual minactivity */ 2747 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */ 2748 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */ 2749 ) 2750 { 2751 SCIP_Real minactbound; 2752 SCIP_Real maxactbound; 2753 SCIP_Real absval; 2754 2755 assert(scip != NULL); 2756 assert(consdata != NULL); 2757 assert(var != NULL); 2758 assert(minresactivity != NULL); 2759 assert(maxresactivity != NULL); 2760 assert(minisrelax != NULL); 2761 assert(maxisrelax != NULL); 2762 assert(isminsettoinfinity != NULL); 2763 assert(ismaxsettoinfinity != NULL); 2764 2765 /* get activity bounds of linear constraint */ 2766 if( !consdata->validactivities ) 2767 { 2768 consdataCalcActivities(scip, consdata); 2769 assert(consdata->validminact); 2770 assert(consdata->validmaxact); 2771 } 2772 assert(QUAD_TO_DBL(consdata->minactivity) < SCIP_INVALID); 2773 assert(QUAD_TO_DBL(consdata->maxactivity) < SCIP_INVALID); 2774 assert(consdata->minactivityneginf >= 0); 2775 assert(consdata->minactivityposinf >= 0); 2776 assert(consdata->maxactivityneginf >= 0); 2777 assert(consdata->maxactivityposinf >= 0); 2778 assert(consdata->minactivityneghuge >= 0); 2779 assert(consdata->minactivityposhuge >= 0); 2780 assert(consdata->maxactivityneghuge >= 0); 2781 assert(consdata->maxactivityposhuge >= 0); 2782 2783 if( val > 0.0 ) 2784 { 2785 minactbound = SCIPvarGetLbLocal(var); 2786 maxactbound = SCIPvarGetUbLocal(var); 2787 absval = val; 2788 } 2789 else 2790 { 2791 minactbound = -SCIPvarGetUbLocal(var); 2792 maxactbound = -SCIPvarGetLbLocal(var); 2793 absval = -val; 2794 } 2795 2796 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values 2797 * and contribution of variable set to zero that has to be subtracted from finite part of activity 2798 */ 2799 if( SCIPisInfinity(scip, minactbound) ) 2800 { 2801 assert(consdata->minactivityposinf >= 1); 2802 2803 getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf, 2804 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax, 2805 minresactivity, minisrelax, isminsettoinfinity); 2806 } 2807 else if( SCIPisInfinity(scip, -minactbound) ) 2808 { 2809 assert(consdata->minactivityneginf >= 1); 2810 2811 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1, 2812 consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax, 2813 minresactivity, minisrelax, isminsettoinfinity); 2814 } 2815 else if( SCIPisHugeValue(scip, minactbound * absval) ) 2816 { 2817 assert(consdata->minactivityposhuge >= 1); 2818 2819 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf, 2820 consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax, 2821 minresactivity, minisrelax, isminsettoinfinity); 2822 } 2823 else if( SCIPisHugeValue(scip, -minactbound * absval) ) 2824 { 2825 assert(consdata->minactivityneghuge >= 1); 2826 2827 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf, 2828 consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax, 2829 minresactivity, minisrelax, isminsettoinfinity); 2830 } 2831 else 2832 { 2833 getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf, 2834 consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax, 2835 minresactivity, minisrelax, isminsettoinfinity); 2836 } 2837 2838 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values 2839 * and contribution of variable set to zero that has to be subtracted from finite part of activity 2840 */ 2841 if( SCIPisInfinity(scip, -maxactbound) ) 2842 { 2843 assert(consdata->maxactivityneginf >= 1); 2844 2845 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1, 2846 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax, 2847 maxresactivity, maxisrelax, ismaxsettoinfinity); 2848 } 2849 else if( SCIPisInfinity(scip, maxactbound) ) 2850 { 2851 assert(consdata->maxactivityposinf >= 1); 2852 2853 getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf, 2854 consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax, 2855 maxresactivity, maxisrelax, ismaxsettoinfinity); 2856 } 2857 else if( SCIPisHugeValue(scip, absval * maxactbound) ) 2858 { 2859 assert(consdata->maxactivityposhuge >= 1); 2860 2861 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf, 2862 consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax, 2863 maxresactivity, maxisrelax, ismaxsettoinfinity); 2864 } 2865 else if( SCIPisHugeValue(scip, -absval * maxactbound) ) 2866 { 2867 assert(consdata->maxactivityneghuge >= 1); 2868 2869 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf, 2870 consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax, 2871 maxresactivity, maxisrelax, ismaxsettoinfinity); 2872 } 2873 else 2874 { 2875 getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf, 2876 consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax, 2877 maxresactivity, maxisrelax, ismaxsettoinfinity); 2878 } 2879 } 2880 2881 /** gets global activity bounds for constraint */ 2882 static 2883 void consdataGetGlbActivityBounds( 2884 SCIP* scip, /**< SCIP data structure */ 2885 SCIP_CONSDATA* consdata, /**< linear constraint */ 2886 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are 2887 * relaxed acticities ignored, anyway? */ 2888 SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */ 2889 SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */ 2890 SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation, 2891 * i.e. <= the exact minactivity (in case of huge contributions), 2892 * or equal to the exact minimal activity */ 2893 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation, 2894 * i.e. >= the exact maxactivity (in case of huge contributions), 2895 * or equal to the exact maximal activity */ 2896 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */ 2897 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */ 2898 ) 2899 { 2900 assert(scip != NULL); 2901 assert(consdata != NULL); 2902 assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL) 2903 || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL)); 2904 2905 if( !consdata->validactivities ) 2906 { 2907 consdataCalcActivities(scip, consdata); 2908 assert(consdata->validglbminact); 2909 assert(consdata->validglbmaxact); 2910 } 2911 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID); 2912 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID); 2913 assert(consdata->glbminactivityneginf >= 0); 2914 assert(consdata->glbminactivityposinf >= 0); 2915 assert(consdata->glbmaxactivityneginf >= 0); 2916 assert(consdata->glbmaxactivityposinf >= 0); 2917 assert(consdata->glbminactivityneghuge >= 0); 2918 assert(consdata->glbminactivityposhuge >= 0); 2919 assert(consdata->glbmaxactivityneghuge >= 0); 2920 assert(consdata->glbmaxactivityposhuge >= 0); 2921 2922 if( glbminactivity != NULL ) 2923 { 2924 assert(isminsettoinfinity != NULL); 2925 assert(minisrelax != NULL); 2926 2927 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf, 2928 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax, 2929 glbminactivity, minisrelax, isminsettoinfinity); 2930 } 2931 2932 if( glbmaxactivity != NULL ) 2933 { 2934 assert(ismaxsettoinfinity != NULL); 2935 assert(maxisrelax != NULL); 2936 2937 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf, 2938 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax, 2939 glbmaxactivity, maxisrelax, ismaxsettoinfinity); 2940 } 2941 } 2942 2943 /** gets global activity bounds for constraint after setting variable to zero */ 2944 static 2945 void consdataGetGlbActivityResiduals( 2946 SCIP* scip, /**< SCIP data structure */ 2947 SCIP_CONSDATA* consdata, /**< linear constraint */ 2948 SCIP_VAR* var, /**< variable to calculate activity residual for */ 2949 SCIP_Real val, /**< coefficient value of variable in linear constraint */ 2950 SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are 2951 * relaxed acticities ignored, anyway? */ 2952 SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */ 2953 SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */ 2954 SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a 2955 * relaxation, i.e. <= the exact residual minactivity (in case of huge 2956 * contributions), or equal to the exact residual minactivity */ 2957 SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a 2958 * relaxation, i.e. <= the exact residual maxactivity (in case of huge 2959 * contributions), or equal to the exact residual minactivity */ 2960 SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */ 2961 SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */ 2962 ) 2963 { 2964 SCIP_Real minactbound; 2965 SCIP_Real maxactbound; 2966 SCIP_Real absval; 2967 2968 assert(scip != NULL); 2969 assert(consdata != NULL); 2970 assert(var != NULL); 2971 assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL ) 2972 || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL)); 2973 2974 /* get activity bounds of linear constraint */ 2975 if( !consdata->validactivities ) 2976 consdataCalcActivities(scip, consdata); 2977 2978 assert(QUAD_TO_DBL(consdata->glbminactivity) < SCIP_INVALID); 2979 assert(QUAD_TO_DBL(consdata->glbmaxactivity) < SCIP_INVALID); 2980 assert(consdata->glbminactivityneginf >= 0); 2981 assert(consdata->glbminactivityposinf >= 0); 2982 assert(consdata->glbmaxactivityneginf >= 0); 2983 assert(consdata->glbmaxactivityposinf >= 0); 2984 2985 if( val > 0.0 ) 2986 { 2987 minactbound = SCIPvarGetLbGlobal(var); 2988 maxactbound = SCIPvarGetUbGlobal(var); 2989 absval = val; 2990 } 2991 else 2992 { 2993 minactbound = -SCIPvarGetUbGlobal(var); 2994 maxactbound = -SCIPvarGetLbGlobal(var); 2995 absval = -val; 2996 } 2997 2998 if( minresactivity != NULL ) 2999 { 3000 assert(isminsettoinfinity != NULL); 3001 assert(minisrelax != NULL); 3002 3003 /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values 3004 * and contribution of variable set to zero that has to be subtracted from finite part of activity 3005 */ 3006 if( SCIPisInfinity(scip, minactbound) ) 3007 { 3008 assert(consdata->glbminactivityposinf >= 1); 3009 3010 getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf, 3011 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax, 3012 minresactivity, minisrelax, isminsettoinfinity); 3013 } 3014 else if( SCIPisInfinity(scip, -minactbound) ) 3015 { 3016 assert(consdata->glbminactivityneginf >= 1); 3017 3018 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1, 3019 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax, 3020 minresactivity, minisrelax, isminsettoinfinity); 3021 } 3022 else if( SCIPisHugeValue(scip, minactbound * absval) ) 3023 { 3024 assert(consdata->glbminactivityposhuge >= 1); 3025 3026 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf, 3027 consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax, 3028 minresactivity, minisrelax, isminsettoinfinity); 3029 } 3030 else if( SCIPisHugeValue(scip, -minactbound * absval) ) 3031 { 3032 assert(consdata->glbminactivityneghuge >= 1); 3033 3034 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf, 3035 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax, 3036 minresactivity, minisrelax, isminsettoinfinity); 3037 } 3038 else 3039 { 3040 getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf, 3041 consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE, 3042 goodrelax, minresactivity, minisrelax, isminsettoinfinity); 3043 } 3044 } 3045 3046 if( maxresactivity != NULL ) 3047 { 3048 assert(ismaxsettoinfinity != NULL); 3049 assert(maxisrelax != NULL); 3050 3051 /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values 3052 * and contribution of variable set to zero that has to be subtracted from finite part of activity 3053 */ 3054 if( SCIPisInfinity(scip, -maxactbound) ) 3055 { 3056 assert(consdata->glbmaxactivityneginf >= 1); 3057 3058 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1, 3059 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax, 3060 maxresactivity, maxisrelax, ismaxsettoinfinity); 3061 } 3062 else if( SCIPisInfinity(scip, maxactbound) ) 3063 { 3064 assert(consdata->glbmaxactivityposinf >= 1); 3065 3066 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf, 3067 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax, 3068 maxresactivity, maxisrelax, ismaxsettoinfinity); 3069 } 3070 else if( SCIPisHugeValue(scip, absval * maxactbound) ) 3071 { 3072 assert(consdata->glbmaxactivityposhuge >= 1); 3073 3074 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf, 3075 consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax, 3076 maxresactivity, maxisrelax, ismaxsettoinfinity); 3077 } 3078 else if( SCIPisHugeValue(scip, -absval * maxactbound) ) 3079 { 3080 assert(consdata->glbmaxactivityneghuge >= 1); 3081 3082 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf, 3083 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax, 3084 maxresactivity, maxisrelax, ismaxsettoinfinity); 3085 } 3086 else 3087 { 3088 getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf, 3089 consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE, 3090 goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity); 3091 } 3092 } 3093 } 3094 3095 /** calculates the activity of the linear constraint for given solution */ 3096 static 3097 SCIP_Real consdataGetActivity( 3098 SCIP* scip, /**< SCIP data structure */ 3099 SCIP_CONSDATA* consdata, /**< linear constraint data */ 3100 SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */ 3101 ) 3102 { 3103 SCIP_Real activity; 3104 3105 assert(scip != NULL); 3106 assert(consdata != NULL); 3107 3108 if( sol == NULL && !SCIPhasCurrentNodeLP(scip) ) 3109 activity = consdataComputePseudoActivity(scip, consdata); 3110 else 3111 { 3112 SCIP_Real solval; 3113 int nposinf; 3114 int nneginf; 3115 SCIP_Bool negsign; 3116 int v; 3117 3118 activity = 0.0; 3119 nposinf = 0; 3120 nneginf = 0; 3121 3122 for( v = 0; v < consdata->nvars; ++v ) 3123 { 3124 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]); 3125 3126 if( consdata->vals[v] < 0 ) 3127 negsign = TRUE; 3128 else 3129 negsign = FALSE; 3130 3131 if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) ) 3132 ++nposinf; 3133 else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) ) 3134 ++nneginf; 3135 else 3136 activity += consdata->vals[v] * solval; 3137 } 3138 assert(nneginf >= 0 && nposinf >= 0); 3139 3140 SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf); 3141 3142 /* check for amount of infinity values and correct the activity */ 3143 if( nposinf > 0 && nneginf > 0 ) 3144 activity = (consdata->rhs + consdata->lhs) / 2; 3145 else if( nposinf > 0 ) 3146 activity = SCIPinfinity(scip); 3147 else if( nneginf > 0 ) 3148 activity = -SCIPinfinity(scip); 3149 3150 SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity); 3151 } 3152 3153 if( activity == SCIP_INVALID ) /*lint !e777*/ 3154 return activity; 3155 else if( activity < 0 ) 3156 activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/ 3157 else 3158 activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/ 3159 3160 return activity; 3161 } 3162 3163 /** calculates the feasibility of the linear constraint for given solution */ 3164 static 3165 SCIP_Real consdataGetFeasibility( 3166 SCIP* scip, /**< SCIP data structure */ 3167 SCIP_CONSDATA* consdata, /**< linear constraint data */ 3168 SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */ 3169 ) 3170 { 3171 SCIP_Real activity; 3172 3173 assert(scip != NULL); 3174 assert(consdata != NULL); 3175 3176 activity = consdataGetActivity(scip, consdata, sol); 3177 3178 if( activity == SCIP_INVALID ) /*lint !e777*/ 3179 return -SCIPinfinity(scip); 3180 3181 return MIN(consdata->rhs - activity, activity - consdata->lhs); 3182 } 3183 3184 /** updates bit signatures after adding a single coefficient */ 3185 static 3186 void consdataUpdateSignatures( 3187 SCIP_CONSDATA* consdata, /**< linear constraint data */ 3188 int pos /**< position of coefficient to update signatures for */ 3189 ) 3190 { 3191 uint64_t varsignature; 3192 SCIP_Real lb; 3193 SCIP_Real ub; 3194 SCIP_Real val; 3195 3196 assert(consdata != NULL); 3197 assert(consdata->validsignature); 3198 3199 varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos])); 3200 lb = SCIPvarGetLbGlobal(consdata->vars[pos]); 3201 ub = SCIPvarGetUbGlobal(consdata->vars[pos]); 3202 val = consdata->vals[pos]; 3203 if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) ) 3204 consdata->possignature |= varsignature; 3205 if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) ) 3206 consdata->negsignature |= varsignature; 3207 } 3208 3209 /** calculates the bit signatures of the given constraint data */ 3210 static 3211 void consdataCalcSignatures( 3212 SCIP_CONSDATA* consdata /**< linear constraint data */ 3213 ) 3214 { 3215 assert(consdata != NULL); 3216 3217 if( !consdata->validsignature ) 3218 { 3219 int i; 3220 3221 consdata->validsignature = TRUE; 3222 consdata->possignature = 0; 3223 consdata->negsignature = 0; 3224 for( i = 0; i < consdata->nvars; ++i ) 3225 consdataUpdateSignatures(consdata, i); 3226 } 3227 } 3228 3229 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */ 3230 static 3231 SCIP_DECL_SORTINDCOMP(consdataCompVar) 3232 { /*lint --e{715}*/ 3233 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr; 3234 SCIP_VAR* var1; 3235 SCIP_VAR* var2; 3236 3237 assert(consdata != NULL); 3238 assert(0 <= ind1 && ind1 < consdata->nvars); 3239 assert(0 <= ind2 && ind2 < consdata->nvars); 3240 3241 var1 = consdata->vars[ind1]; 3242 var2 = consdata->vars[ind2]; 3243 3244 /* exactly one variable is binary */ 3245 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) ) 3246 { 3247 return (SCIPvarIsBinary(var1) ? -1 : +1); 3248 } 3249 /* both variables are binary */ 3250 else if( SCIPvarIsBinary(var1) ) 3251 { 3252 return SCIPvarCompare(var1, var2); 3253 } 3254 else 3255 { 3256 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1); 3257 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2); 3258 3259 if( vartype1 < vartype2 ) 3260 return -1; 3261 else if( vartype1 > vartype2 ) 3262 return +1; 3263 else 3264 return SCIPvarCompare(var1, var2); 3265 } 3266 } 3267 3268 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */ 3269 static 3270 SCIP_DECL_SORTINDCOMP(consdataCompVarProp) 3271 { /*lint --e{715}*/ 3272 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr; 3273 SCIP_VAR* var1; 3274 SCIP_VAR* var2; 3275 3276 assert(consdata != NULL); 3277 assert(0 <= ind1 && ind1 < consdata->nvars); 3278 assert(0 <= ind2 && ind2 < consdata->nvars); 3279 3280 var1 = consdata->vars[ind1]; 3281 var2 = consdata->vars[ind2]; 3282 3283 /* exactly one variable is binary */ 3284 if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) ) 3285 { 3286 return (SCIPvarIsBinary(var1) ? -1 : +1); 3287 } 3288 /* both variables are binary */ 3289 else if( SCIPvarIsBinary(var1) ) 3290 { 3291 SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]); 3292 SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]); 3293 3294 if( EPSGT(abscoef1, abscoef2, 1e-9) ) 3295 return -1; 3296 else if( EPSGT(abscoef2, abscoef1, 1e-9) ) 3297 return +1; 3298 else 3299 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2)); 3300 } 3301 else 3302 { 3303 SCIP_VARTYPE vartype1 = SCIPvarGetType(var1); 3304 SCIP_VARTYPE vartype2 = SCIPvarGetType(var2); 3305 3306 if( vartype1 < vartype2 ) 3307 { 3308 return -1; 3309 } 3310 else if( vartype1 > vartype2 ) 3311 { 3312 return +1; 3313 } 3314 else 3315 { 3316 /* both variables are continuous */ 3317 if( !SCIPvarIsIntegral(var1) ) 3318 { 3319 assert(!SCIPvarIsIntegral(var2)); 3320 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2)); 3321 } 3322 else 3323 { 3324 SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1))); 3325 SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2))); 3326 3327 if( EPSGT(abscont1, abscont2, 1e-9) ) 3328 return -1; 3329 else if( EPSGT(abscont2, abscont1, 1e-9) ) 3330 return +1; 3331 else 3332 return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2)); 3333 } 3334 } 3335 } 3336 } 3337 3338 /** permutes the constraint's variables according to a given permutation. */ 3339 static 3340 void permSortConsdata( 3341 SCIP_CONSDATA* consdata, /**< the constraint data */ 3342 int* perm, /**< the target permutation */ 3343 int nvars /**< the number of variables */ 3344 ) 3345 { /*lint --e{715}*/ 3346 SCIP_VAR* varv; 3347 SCIP_EVENTDATA* eventdatav; 3348 SCIP_Real valv; 3349 int v; 3350 int i; 3351 int nexti; 3352 3353 assert(perm != NULL); 3354 assert(consdata != NULL); 3355 3356 /* permute the variables in the linear constraint according to the target permutation */ 3357 eventdatav = NULL; 3358 for( v = 0; v < nvars; ++v ) 3359 { 3360 if( perm[v] != v ) 3361 { 3362 varv = consdata->vars[v]; 3363 valv = consdata->vals[v]; 3364 if( consdata->eventdata != NULL ) 3365 eventdatav = consdata->eventdata[v]; 3366 i = v; 3367 do 3368 { 3369 assert(0 <= perm[i] && perm[i] < nvars); 3370 assert(perm[i] != i); 3371 consdata->vars[i] = consdata->vars[perm[i]]; 3372 consdata->vals[i] = consdata->vals[perm[i]]; 3373 if( consdata->eventdata != NULL ) 3374 { 3375 consdata->eventdata[i] = consdata->eventdata[perm[i]]; 3376 consdata->eventdata[i]->varpos = i; 3377 } 3378 nexti = perm[i]; 3379 perm[i] = i; 3380 i = nexti; 3381 } 3382 while( perm[i] != v ); 3383 consdata->vars[i] = varv; 3384 consdata->vals[i] = valv; 3385 if( consdata->eventdata != NULL ) 3386 { 3387 consdata->eventdata[i] = eventdatav; 3388 consdata->eventdata[i]->varpos = i; 3389 } 3390 perm[i] = i; 3391 } 3392 } 3393 #ifdef SCIP_DEBUG 3394 /* check sorting */ 3395 for( v = 0; v < nvars; ++v ) 3396 { 3397 assert(perm[v] == v); 3398 assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v); 3399 } 3400 #endif 3401 } 3402 3403 /** sorts linear constraint's variables depending on the stage of the solving process: 3404 * - during PRESOLVING 3405 * sorts variables by binaries, integers, implicit integers, and continuous variables, 3406 * and the variables of the same type by non-decreasing variable index 3407 * 3408 * - during SOLVING 3409 * sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables, 3410 * and binary and integer variables by their global max activity delta (within each group), 3411 * ties within a group are broken by problem index of the variable. 3412 * 3413 * This fastens the propagation time of the constraint handler. 3414 */ 3415 static 3416 SCIP_RETCODE consdataSort( 3417 SCIP* scip, /**< SCIP data structure */ 3418 SCIP_CONSDATA* consdata /**< linear constraint data */ 3419 ) 3420 { 3421 assert(scip != NULL); 3422 assert(consdata != NULL); 3423 3424 /* check if there are variables for sorting */ 3425 if( consdata->nvars <= 1 ) 3426 { 3427 consdata->indexsorted = TRUE; 3428 consdata->coefsorted = TRUE; 3429 consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0); 3430 } 3431 else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE) 3432 || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) ) 3433 { 3434 int* perm; 3435 int v; 3436 3437 /* get temporary memory to store the sorted permutation */ 3438 SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) ); 3439 3440 /* call sorting method */ 3441 if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE ) 3442 SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars); 3443 else 3444 SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars); 3445 3446 permSortConsdata(consdata, perm, consdata->nvars); 3447 3448 /* free temporary memory */ 3449 SCIPfreeBufferArray(scip, &perm); 3450 3451 if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE ) 3452 { 3453 consdata->indexsorted = FALSE; 3454 consdata->coefsorted = TRUE; 3455 3456 /* count binary variables in the sorted vars array */ 3457 consdata->nbinvars = 0; 3458 for( v = 0; v < consdata->nvars; ++v ) 3459 { 3460 if( SCIPvarIsBinary(consdata->vars[v]) ) 3461 ++consdata->nbinvars; 3462 else 3463 break; 3464 } 3465 } 3466 else 3467 { 3468 consdata->indexsorted = TRUE; 3469 consdata->coefsorted = FALSE; 3470 } 3471 } 3472 3473 return SCIP_OKAY; 3474 } 3475 3476 3477 /* 3478 * local linear constraint handler methods 3479 */ 3480 3481 /** sets left hand side of linear constraint */ 3482 static 3483 SCIP_RETCODE chgLhs( 3484 SCIP* scip, /**< SCIP data structure */ 3485 SCIP_CONS* cons, /**< linear constraint */ 3486 SCIP_Real lhs /**< new left hand side */ 3487 ) 3488 { 3489 SCIP_CONSDATA* consdata; 3490 SCIP_Bool locked; 3491 int i; 3492 3493 assert(scip != NULL); 3494 assert(cons != NULL); 3495 assert(!SCIPisInfinity(scip, lhs)); 3496 3497 /* adjust value to not be smaller than -inf */ 3498 if ( SCIPisInfinity(scip, -lhs) ) 3499 lhs = -SCIPinfinity(scip); 3500 3501 consdata = SCIPconsGetData(cons); 3502 assert(consdata != NULL); 3503 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL)); 3504 assert(!SCIPisInfinity(scip, consdata->lhs)); 3505 3506 /* check whether the side is not changed */ 3507 if( SCIPisEQ(scip, consdata->lhs, lhs) ) 3508 return SCIP_OKAY; 3509 3510 /* ensure that rhs >= lhs is satisfied without numerical tolerance */ 3511 if( SCIPisEQ(scip, lhs, consdata->rhs) ) 3512 { 3513 consdata->rhs = lhs; 3514 assert(consdata->row == NULL); 3515 } 3516 3517 locked = FALSE; 3518 for( i = 0; i < NLOCKTYPES && !locked; i++ ) 3519 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i); 3520 3521 /* if necessary, update the rounding locks of variables */ 3522 if( locked ) 3523 { 3524 if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) ) 3525 { 3526 SCIP_VAR** vars; 3527 SCIP_Real* vals; 3528 int v; 3529 3530 /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */ 3531 vars = consdata->vars; 3532 vals = consdata->vals; 3533 3534 for( v = 0; v < consdata->nvars; ++v ) 3535 { 3536 assert(vars[v] != NULL); 3537 assert(!SCIPisZero(scip, vals[v])); 3538 3539 if( SCIPisPositive(scip, vals[v]) ) 3540 { 3541 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) ); 3542 } 3543 else 3544 { 3545 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) ); 3546 } 3547 } 3548 } 3549 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) ) 3550 { 3551 SCIP_VAR** vars; 3552 SCIP_Real* vals; 3553 int v; 3554 3555 /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */ 3556 vars = consdata->vars; 3557 vals = consdata->vals; 3558 3559 for( v = 0; v < consdata->nvars; ++v ) 3560 { 3561 assert(vars[v] != NULL); 3562 assert(!SCIPisZero(scip, vals[v])); 3563 3564 if( SCIPisPositive(scip, vals[v]) ) 3565 { 3566 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) ); 3567 } 3568 else 3569 { 3570 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) ); 3571 } 3572 } 3573 } 3574 } 3575 3576 /* 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 */ 3577 if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) ) 3578 { 3579 consdata->boundstightened = 0; 3580 consdata->presolved = FALSE; 3581 consdata->cliquesadded = FALSE; 3582 consdata->implsadded = FALSE; 3583 3584 /* mark the constraint for propagation */ 3585 if( SCIPconsIsTransformed(cons) ) 3586 { 3587 SCIP_CALL( SCIPmarkConsPropagate(scip, cons) ); 3588 } 3589 } 3590 3591 /* set new left hand side and update constraint data */ 3592 consdata->lhs = lhs; 3593 consdata->changed = TRUE; 3594 consdata->normalized = FALSE; 3595 consdata->upgradetried = FALSE; 3596 consdata->rangedrowpropagated = 0; 3597 3598 /* update the lhs of the LP row */ 3599 if( consdata->row != NULL ) 3600 { 3601 SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) ); 3602 } 3603 3604 return SCIP_OKAY; 3605 } 3606 3607 /** sets right hand side of linear constraint */ 3608 static 3609 SCIP_RETCODE chgRhs( 3610 SCIP* scip, /**< SCIP data structure */ 3611 SCIP_CONS* cons, /**< linear constraint */ 3612 SCIP_Real rhs /**< new right hand side */ 3613 ) 3614 { 3615 SCIP_CONSDATA* consdata; 3616 SCIP_Bool locked; 3617 int i; 3618 3619 assert(scip != NULL); 3620 assert(cons != NULL); 3621 assert(!SCIPisInfinity(scip, -rhs)); 3622 3623 /* adjust value to not be larger than inf */ 3624 if ( SCIPisInfinity(scip, rhs) ) 3625 rhs = SCIPinfinity(scip); 3626 3627 consdata = SCIPconsGetData(cons); 3628 assert(consdata != NULL); 3629 assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL)); 3630 assert(!SCIPisInfinity(scip, -consdata->rhs)); 3631 3632 /* check whether the side is not changed */ 3633 if( SCIPisEQ(scip, consdata->rhs, rhs) ) 3634 return SCIP_OKAY; 3635 3636 /* ensure that rhs >= lhs is satisfied without numerical tolerance */ 3637 if( SCIPisEQ(scip, rhs, consdata->lhs) ) 3638 { 3639 consdata->lhs = rhs; 3640 assert(consdata->row == NULL); 3641 } 3642 3643 locked = FALSE; 3644 for( i = 0; i < NLOCKTYPES && !locked; i++ ) 3645 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i); 3646 3647 /* if necessary, update the rounding locks of variables */ 3648 if( locked ) 3649 { 3650 assert(SCIPconsIsTransformed(cons)); 3651 3652 if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) ) 3653 { 3654 SCIP_VAR** vars; 3655 SCIP_Real* vals; 3656 int v; 3657 3658 /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */ 3659 vars = consdata->vars; 3660 vals = consdata->vals; 3661 3662 for( v = 0; v < consdata->nvars; ++v ) 3663 { 3664 assert(vars[v] != NULL); 3665 assert(!SCIPisZero(scip, vals[v])); 3666 3667 if( SCIPisPositive(scip, vals[v]) ) 3668 { 3669 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) ); 3670 } 3671 else 3672 { 3673 SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) ); 3674 } 3675 } 3676 } 3677 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) ) 3678 { 3679 SCIP_VAR** vars; 3680 SCIP_Real* vals; 3681 int v; 3682 3683 /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */ 3684 vars = consdata->vars; 3685 vals = consdata->vals; 3686 3687 for( v = 0; v < consdata->nvars; ++v ) 3688 { 3689 assert(vars[v] != NULL); 3690 assert(!SCIPisZero(scip, vals[v])); 3691 3692 if( SCIPisPositive(scip, vals[v]) ) 3693 { 3694 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) ); 3695 } 3696 else 3697 { 3698 SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) ); 3699 } 3700 } 3701 } 3702 } 3703 3704 /* 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 */ 3705 if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) ) 3706 { 3707 consdata->boundstightened = 0; 3708 consdata->presolved = FALSE; 3709 consdata->cliquesadded = FALSE; 3710 consdata->implsadded = FALSE; 3711 3712 /* mark the constraint for propagation */ 3713 if( SCIPconsIsTransformed(cons) ) 3714 { 3715 SCIP_CALL( SCIPmarkConsPropagate(scip, cons) ); 3716 } 3717 } 3718 3719 /* set new right hand side and update constraint data */ 3720 consdata->rhs = rhs; 3721 consdata->changed = TRUE; 3722 consdata->normalized = FALSE; 3723 consdata->upgradetried = FALSE; 3724 consdata->rangedrowpropagated = 0; 3725 3726 /* update the rhs of the LP row */ 3727 if( consdata->row != NULL ) 3728 { 3729 SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) ); 3730 } 3731 3732 return SCIP_OKAY; 3733 } 3734 3735 /** adds coefficient in linear constraint */ 3736 static 3737 SCIP_RETCODE addCoef( 3738 SCIP* scip, /**< SCIP data structure */ 3739 SCIP_CONS* cons, /**< linear constraint */ 3740 SCIP_VAR* var, /**< variable of constraint entry */ 3741 SCIP_Real val /**< coefficient of constraint entry */ 3742 ) 3743 { 3744 SCIP_CONSDATA* consdata; 3745 SCIP_Bool transformed; 3746 3747 assert(scip != NULL); 3748 assert(cons != NULL); 3749 assert(var != NULL); 3750 3751 /* relaxation-only variables must not be used in checked or enforced constraints */ 3752 assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons))); 3753 3754 /* ignore coefficient if it is nearly zero */ 3755 if( SCIPisZero(scip, val) ) 3756 return SCIP_OKAY; 3757 3758 consdata = SCIPconsGetData(cons); 3759 assert(consdata != NULL); 3760 3761 /* are we in the transformed problem? */ 3762 transformed = SCIPconsIsTransformed(cons); 3763 3764 /* always use transformed variables in transformed constraints */ 3765 if( transformed ) 3766 { 3767 SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) ); 3768 } 3769 assert(var != NULL); 3770 assert(transformed == SCIPvarIsTransformed(var)); 3771 3772 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) ); 3773 consdata->vars[consdata->nvars] = var; 3774 consdata->vals[consdata->nvars] = val; 3775 consdata->nvars++; 3776 3777 /* capture variable */ 3778 SCIP_CALL( SCIPcaptureVar(scip, var) ); 3779 3780 /* if we are in transformed problem, the variable needs an additional event data */ 3781 if( transformed ) 3782 { 3783 if( consdata->eventdata != NULL ) 3784 { 3785 SCIP_CONSHDLR* conshdlr; 3786 SCIP_CONSHDLRDATA* conshdlrdata; 3787 3788 /* check for event handler */ 3789 conshdlr = SCIPconsGetHdlr(cons); 3790 conshdlrdata = SCIPconshdlrGetData(conshdlr); 3791 assert(conshdlrdata != NULL); 3792 assert(conshdlrdata->eventhdlr != NULL); 3793 3794 /* initialize eventdata array */ 3795 consdata->eventdata[consdata->nvars-1] = NULL; 3796 3797 /* catch bound change events of variable */ 3798 SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) ); 3799 } 3800 3801 /* update minimum and maximum activities */ 3802 consdataUpdateAddCoef(scip, consdata, var, val, FALSE); 3803 3804 /* update maximum activity delta */ 3805 if( !SCIPisInfinity(scip, consdata->maxactdelta ) ) 3806 { 3807 SCIP_Real lb; 3808 SCIP_Real ub; 3809 3810 lb = SCIPvarGetLbLocal(var); 3811 ub = SCIPvarGetUbLocal(var); 3812 3813 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) ) 3814 { 3815 consdata->maxactdelta = SCIPinfinity(scip); 3816 consdata->maxactdeltavar = var; 3817 } 3818 else 3819 { 3820 SCIP_Real domain = ub - lb; 3821 SCIP_Real delta = REALABS(val) * domain; 3822 3823 if( delta > consdata->maxactdelta ) 3824 { 3825 consdata->maxactdelta = delta; 3826 consdata->maxactdeltavar = var; 3827 } 3828 } 3829 } 3830 } 3831 3832 /* install rounding locks for new variable */ 3833 SCIP_CALL( lockRounding(scip, cons, var, val) ); 3834 3835 /* mark the constraint for propagation */ 3836 if( transformed ) 3837 { 3838 SCIP_CALL( SCIPmarkConsPropagate(scip, cons) ); 3839 } 3840 3841 consdata->boundstightened = 0; 3842 consdata->presolved = FALSE; 3843 consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var); 3844 3845 if( consdata->validsignature ) 3846 consdataUpdateSignatures(consdata, consdata->nvars-1); 3847 3848 consdata->changed = TRUE; 3849 consdata->normalized = FALSE; 3850 consdata->upgradetried = FALSE; 3851 consdata->cliquesadded = FALSE; 3852 consdata->implsadded = FALSE; 3853 consdata->rangedrowpropagated = 0; 3854 3855 if( consdata->nvars == 1 ) 3856 { 3857 consdata->indexsorted = TRUE; 3858 consdata->coefsorted = TRUE; 3859 consdata->merged = TRUE; 3860 } 3861 else 3862 { 3863 consdata->merged = FALSE; 3864 3865 if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE ) 3866 { 3867 consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0); 3868 consdata->coefsorted = FALSE; 3869 } 3870 else 3871 { 3872 consdata->indexsorted = FALSE; 3873 consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0); 3874 } 3875 } 3876 3877 /* update hascontvar and hasnonbinvar flags */ 3878 if( consdata->hasnonbinvalid && !consdata->hascontvar ) 3879 { 3880 SCIP_VARTYPE vartype = SCIPvarGetType(var); 3881 3882 if( vartype != SCIP_VARTYPE_BINARY ) 3883 { 3884 consdata->hasnonbinvar = TRUE; 3885 3886 if( vartype == SCIP_VARTYPE_CONTINUOUS ) 3887 consdata->hascontvar = TRUE; 3888 } 3889 } 3890 3891 /* add the new coefficient to the LP row */ 3892 if( consdata->row != NULL ) 3893 { 3894 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) ); 3895 } 3896 3897 return SCIP_OKAY; 3898 } 3899 3900 /** deletes coefficient at given position from linear constraint data */ 3901 static 3902 SCIP_RETCODE delCoefPos( 3903 SCIP* scip, /**< SCIP data structure */ 3904 SCIP_CONS* cons, /**< linear constraint */ 3905 int pos /**< position of coefficient to delete */ 3906 ) 3907 { 3908 SCIP_CONSDATA* consdata; 3909 SCIP_VAR* var; 3910 SCIP_Real val; 3911 3912 assert(scip != NULL); 3913 assert(cons != NULL); 3914 3915 consdata = SCIPconsGetData(cons); 3916 assert(consdata != NULL); 3917 assert(0 <= pos && pos < consdata->nvars); 3918 3919 var = consdata->vars[pos]; 3920 val = consdata->vals[pos]; 3921 assert(var != NULL); 3922 3923 /* remove rounding locks for deleted variable */ 3924 SCIP_CALL( unlockRounding(scip, cons, var, val) ); 3925 3926 /* if we are in transformed problem, delete the event data of the variable */ 3927 if( SCIPconsIsTransformed(cons) ) 3928 { 3929 SCIP_CONSHDLR* conshdlr; 3930 SCIP_CONSHDLRDATA* conshdlrdata; 3931 3932 /* check for event handler */ 3933 conshdlr = SCIPconsGetHdlr(cons); 3934 conshdlrdata = SCIPconshdlrGetData(conshdlr); 3935 assert(conshdlrdata != NULL); 3936 assert(conshdlrdata->eventhdlr != NULL); 3937 3938 /* drop bound change events of variable */ 3939 if( consdata->eventdata != NULL ) 3940 { 3941 SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) ); 3942 assert(consdata->eventdata[pos] == NULL); 3943 } 3944 } 3945 3946 /* move the last variable to the free slot */ 3947 if( pos != consdata->nvars - 1 ) 3948 { 3949 consdata->vars[pos] = consdata->vars[consdata->nvars-1]; 3950 consdata->vals[pos] = consdata->vals[consdata->nvars-1]; 3951 3952 if( consdata->eventdata != NULL ) 3953 { 3954 consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1]; 3955 assert(consdata->eventdata[pos] != NULL); 3956 consdata->eventdata[pos]->varpos = pos; 3957 } 3958 3959 consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars); 3960 consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars); 3961 } 3962 consdata->nvars--; 3963 3964 /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds 3965 * of the remaining variable, or give exactly 0.0) 3966 */ 3967 if( consdata->nvars <= 1 ) 3968 consdataInvalidateActivities(consdata); 3969 else 3970 { 3971 if( SCIPconsIsTransformed(cons) ) 3972 { 3973 /* if we are in transformed problem, update minimum and maximum activities */ 3974 consdataUpdateDelCoef(scip, consdata, var, val, TRUE); 3975 3976 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity 3977 * delta needs to be recalculated on the next real propagation 3978 */ 3979 if( consdata->maxactdeltavar == var ) 3980 { 3981 consdata->maxactdelta = SCIP_INVALID; 3982 consdata->maxactdeltavar = NULL; 3983 } 3984 } 3985 } 3986 3987 /* mark the constraint for propagation */ 3988 if( SCIPconsIsTransformed(cons) ) 3989 { 3990 SCIP_CALL( SCIPmarkConsPropagate(scip, cons) ); 3991 } 3992 3993 consdata->boundstightened = 0; 3994 consdata->presolved = FALSE; 3995 consdata->validsignature = FALSE; 3996 consdata->changed = TRUE; 3997 consdata->normalized = FALSE; 3998 consdata->upgradetried = FALSE; 3999 consdata->cliquesadded = FALSE; 4000 consdata->implsadded = FALSE; 4001 consdata->rangedrowpropagated = 0; 4002 4003 /* check if hasnonbinvar flag might be incorrect now */ 4004 if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY ) 4005 { 4006 consdata->hasnonbinvalid = FALSE; 4007 } 4008 4009 /* delete coefficient from the LP row */ 4010 if( consdata->row != NULL ) 4011 { 4012 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) ); 4013 } 4014 4015 /* release variable */ 4016 SCIP_CALL( SCIPreleaseVar(scip, &var) ); 4017 4018 return SCIP_OKAY; 4019 } 4020 4021 /** changes coefficient value at given position of linear constraint data */ 4022 static 4023 SCIP_RETCODE chgCoefPos( 4024 SCIP* scip, /**< SCIP data structure */ 4025 SCIP_CONS* cons, /**< linear constraint */ 4026 int pos, /**< position of coefficient to delete */ 4027 SCIP_Real newval /**< new value of coefficient */ 4028 ) 4029 { 4030 SCIP_CONSDATA* consdata; 4031 SCIP_VAR* var; 4032 SCIP_Real val; 4033 SCIP_Bool locked; 4034 int i; 4035 4036 assert(scip != NULL); 4037 assert(cons != NULL); 4038 assert(!SCIPisZero(scip, newval)); 4039 4040 consdata = SCIPconsGetData(cons); 4041 assert(consdata != NULL); 4042 assert(0 <= pos && pos < consdata->nvars); 4043 assert(!SCIPisZero(scip, newval)); 4044 4045 var = consdata->vars[pos]; 4046 val = consdata->vals[pos]; 4047 assert(var != NULL); 4048 assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var)); 4049 4050 locked = FALSE; 4051 for( i = 0; i < NLOCKTYPES && !locked; i++ ) 4052 locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i); 4053 4054 /* if necessary, update the rounding locks of the variable */ 4055 if( locked && newval * val < 0.0 ) 4056 { 4057 assert(SCIPconsIsTransformed(cons)); 4058 4059 /* remove rounding locks for variable with old coefficient */ 4060 SCIP_CALL( unlockRounding(scip, cons, var, val) ); 4061 4062 /* install rounding locks for variable with new coefficient */ 4063 SCIP_CALL( lockRounding(scip, cons, var, newval) ); 4064 } 4065 4066 /* change the value */ 4067 consdata->vals[pos] = newval; 4068 4069 if( consdata->coefsorted ) 4070 { 4071 if( pos > 0 ) 4072 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0); 4073 if( consdata->coefsorted && pos < consdata->nvars - 1 ) 4074 consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0); 4075 } 4076 4077 /* update minimum and maximum activities */ 4078 if( SCIPconsIsTransformed(cons) ) 4079 consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE); 4080 4081 /* mark the constraint for propagation */ 4082 if( SCIPconsIsTransformed(cons) ) 4083 { 4084 SCIP_CALL( SCIPmarkConsPropagate(scip, cons) ); 4085 } 4086 4087 consdata->boundstightened = 0; 4088 consdata->presolved = FALSE; 4089 consdata->validsignature = consdata->validsignature && (newval * val > 0.0); 4090 consdata->changed = TRUE; 4091 consdata->normalized = FALSE; 4092 consdata->upgradetried = FALSE; 4093 consdata->cliquesadded = FALSE; 4094 consdata->implsadded = FALSE; 4095 consdata->rangedrowpropagated = 0; 4096 4097 return SCIP_OKAY; 4098 } 4099 4100 /** scales a linear constraint with a constant scalar */ 4101 static 4102 SCIP_RETCODE scaleCons( 4103 SCIP* scip, /**< SCIP data structure */ 4104 SCIP_CONS* cons, /**< linear constraint to scale */ 4105 SCIP_Real scalar /**< value to scale constraint with */ 4106 ) 4107 { 4108 SCIP_CONSDATA* consdata; 4109 SCIP_Real newval; 4110 SCIP_Real absscalar; 4111 int i; 4112 4113 assert(scip != NULL); 4114 assert(cons != NULL); 4115 4116 consdata = SCIPconsGetData(cons); 4117 assert(consdata != NULL); 4118 assert(consdata->row == NULL); 4119 assert(!SCIPisEQ(scip, scalar, 1.0)); 4120 4121 if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar)) 4122 || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) ) 4123 { 4124 SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n", 4125 SCIPconsGetName(cons), scalar); 4126 4127 return SCIP_OKAY; 4128 } 4129 4130 /* scale the coefficients */ 4131 for( i = consdata->nvars - 1; i >= 0; --i ) 4132 { 4133 newval = scalar * consdata->vals[i]; 4134 4135 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before 4136 * flooring down our new value 4137 */ 4138 if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) ) 4139 newval = SCIPfeasFloor(scip, newval + 0.5); 4140 4141 if( SCIPisZero(scip, newval) ) 4142 { 4143 SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n", 4144 consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar); 4145 SCIP_CALL( delCoefPos(scip, cons, i) ); 4146 } 4147 else 4148 consdata->vals[i] = newval; 4149 } 4150 4151 /* scale the sides */ 4152 if( scalar < 0.0 ) 4153 { 4154 SCIP_Real lhs; 4155 4156 lhs = consdata->lhs; 4157 consdata->lhs = -consdata->rhs; 4158 consdata->rhs = -lhs; 4159 } 4160 absscalar = REALABS(scalar); 4161 if( !SCIPisInfinity(scip, -consdata->lhs) ) 4162 { 4163 newval = absscalar * consdata->lhs; 4164 4165 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before 4166 * flooring down our new value 4167 */ 4168 if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) ) 4169 consdata->lhs = SCIPfeasFloor(scip, newval + 0.5); 4170 else 4171 consdata->lhs = newval; 4172 } 4173 if( !SCIPisInfinity(scip, consdata->rhs) ) 4174 { 4175 newval = absscalar * consdata->rhs; 4176 4177 /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up 4178 * our new value 4179 */ 4180 if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) ) 4181 consdata->rhs = SCIPfeasCeil(scip, newval - 0.5); 4182 else 4183 consdata->rhs = newval; 4184 } 4185 4186 consdataInvalidateActivities(consdata); 4187 consdata->cliquesadded = FALSE; 4188 consdata->implsadded = FALSE; 4189 4190 return SCIP_OKAY; 4191 } 4192 4193 /** perform deletion of variables in all constraints of the constraint handler */ 4194 static 4195 SCIP_RETCODE performVarDeletions( 4196 SCIP* scip, /**< SCIP data structure */ 4197 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4198 SCIP_CONS** conss, /**< array of constraints */ 4199 int nconss /**< number of constraints */ 4200 ) 4201 { 4202 SCIP_CONSDATA* consdata; 4203 int i; 4204 int v; 4205 4206 assert(scip != NULL); 4207 assert(conshdlr != NULL); 4208 assert(conss != NULL); 4209 assert(nconss >= 0); 4210 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 4211 4212 /* iterate over all constraints */ 4213 for( i = 0; i < nconss; i++ ) 4214 { 4215 consdata = SCIPconsGetData(conss[i]); 4216 4217 /* constraint is marked, that some of its variables were deleted */ 4218 if( consdata->varsdeleted ) 4219 { 4220 /* iterate over all variables of the constraint and delete them from the constraint */ 4221 for( v = consdata->nvars - 1; v >= 0; --v ) 4222 { 4223 if( SCIPvarIsDeleted(consdata->vars[v]) ) 4224 { 4225 SCIP_CALL( delCoefPos(scip, conss[i], v) ); 4226 } 4227 } 4228 consdata->varsdeleted = FALSE; 4229 } 4230 } 4231 4232 return SCIP_OKAY; 4233 } 4234 4235 4236 /** normalizes a linear constraint with the following rules: 4237 * - if all coefficients have them same absolute value, change them to (-)1.0 4238 * - multiplication with +1 or -1: 4239 * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply, 4240 * if the current rule doesn't determine the sign): 4241 * 1. the right hand side must not be negative 4242 * 2. the right hand side must not be infinite 4243 * 3. the absolute value of the right hand side must be greater than that of the left hand side 4244 * 4. the number of positive coefficients must not be smaller than the number of negative coefficients 4245 * 5. multiply with +1 4246 * - rationals to integrals 4247 * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients 4248 * by the smallest common multiple of all denominators to get integral coefficients. 4249 * Forbid large denominators due to numerical stability. 4250 * - division by greatest common divisor 4251 * If all coefficients are integral, divide them by the greatest common divisor. 4252 */ 4253 static 4254 SCIP_RETCODE normalizeCons( 4255 SCIP* scip, /**< SCIP data structure */ 4256 SCIP_CONS* cons, /**< linear constraint to normalize */ 4257 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */ 4258 ) 4259 { 4260 SCIP_CONSDATA* consdata; 4261 SCIP_Real* vals; 4262 SCIP_Longint scm; 4263 SCIP_Longint nominator; 4264 SCIP_Longint denominator; 4265 SCIP_Longint gcd; 4266 SCIP_Longint maxmult; 4267 SCIP_Real epsilon; 4268 SCIP_Real feastol; 4269 SCIP_Real maxabsval; 4270 SCIP_Real minabsval; 4271 SCIP_Bool success; 4272 SCIP_Bool onlyintegral; 4273 int nvars; 4274 int mult; 4275 int nposcoeffs; 4276 int nnegcoeffs; 4277 int i; 4278 int v; 4279 4280 assert(scip != NULL); 4281 assert(cons != NULL); 4282 assert(infeasible != NULL); 4283 4284 *infeasible = FALSE; 4285 4286 /* we must not change a modifiable constraint in any way */ 4287 if( SCIPconsIsModifiable(cons) ) 4288 return SCIP_OKAY; 4289 4290 /* get constraint data */ 4291 consdata = SCIPconsGetData(cons); 4292 assert(consdata != NULL); 4293 4294 /* check, if the constraint is already normalized */ 4295 if( consdata->normalized ) 4296 return SCIP_OKAY; 4297 4298 /* get coefficient arrays */ 4299 vals = consdata->vals; 4300 nvars = consdata->nvars; 4301 assert(nvars == 0 || vals != NULL); 4302 4303 if( nvars == 0 ) 4304 { 4305 consdata->normalized = TRUE; 4306 return SCIP_OKAY; 4307 } 4308 4309 assert(vals != NULL); 4310 4311 /* get maximal and minimal absolute coefficient */ 4312 maxabsval = consdataGetMaxAbsval(consdata); 4313 minabsval = consdataGetMinAbsval(consdata); 4314 4315 /* return if scaling by maxval will eliminate coefficients */ 4316 if( SCIPisZero(scip, minabsval/maxabsval) ) 4317 return SCIP_OKAY; 4318 4319 /* check if all coefficients are in absolute value equal, and not 1.0 */ 4320 if( !SCIPisEQ(scip, maxabsval, 1.0) ) 4321 { 4322 SCIP_Bool abscoefsequ; 4323 4324 abscoefsequ = TRUE; 4325 4326 for( v = nvars - 1; v >= 0; --v ) 4327 { 4328 if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) ) 4329 { 4330 abscoefsequ = FALSE; 4331 break; 4332 } 4333 } 4334 4335 /* all coefficients are in absolute value equal, so change them to (-)1.0 */ 4336 if( abscoefsequ ) 4337 { 4338 SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval); 4339 SCIPdebugPrintCons(scip, cons, NULL); 4340 SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) ); 4341 4342 if( consdata->validmaxabsval ) 4343 { 4344 if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) ) 4345 consdata->maxabsval = 1.0; 4346 if( !SCIPisEQ(scip, consdata->minabsval, 1.0) ) 4347 consdata->minabsval = 1.0; 4348 4349 maxabsval = 1.0; 4350 } 4351 else 4352 { 4353 /* get maximal absolute coefficient */ 4354 maxabsval = consdataGetMaxAbsval(consdata); 4355 } 4356 4357 /* get new consdata information, because scaleCons() might have deleted variables */ 4358 vals = consdata->vals; 4359 nvars = consdata->nvars; 4360 4361 assert(nvars == 0 || vals != NULL); 4362 } 4363 } 4364 4365 /* nvars might have changed */ 4366 if( nvars == 0 ) 4367 { 4368 consdata->normalized = TRUE; 4369 return SCIP_OKAY; 4370 } 4371 4372 assert(vals != NULL); 4373 4374 /* calculate the maximal multiplier for common divisor calculation: 4375 * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol 4376 * which means, a value of feastol/epsilon should be used as maximal multiplier; 4377 * additionally, we don't want to scale the constraint if this would lead to too 4378 * large coefficients 4379 */ 4380 epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */ 4381 feastol = SCIPfeastol(scip); 4382 maxmult = (SCIP_Longint)(feastol/epsilon + feastol); 4383 4384 if( !consdata->hasnonbinvalid ) 4385 consdataCheckNonbinvar(consdata); 4386 4387 /* if all variables are of integral type we will allow a greater multiplier */ 4388 if( !consdata->hascontvar ) 4389 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/ 4390 else 4391 maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/ 4392 4393 /* 4394 * multiplication with +1 or -1 4395 */ 4396 mult = 0; 4397 4398 /* 1. the right hand side must not be negative */ 4399 if( SCIPisPositive(scip, consdata->lhs) ) 4400 mult = +1; 4401 else if( SCIPisNegative(scip, consdata->rhs) ) 4402 mult = -1; 4403 4404 if( mult == 0 ) 4405 { 4406 /* 2. the right hand side must not be infinite */ 4407 if( SCIPisInfinity(scip, -consdata->lhs) ) 4408 mult = +1; 4409 else if( SCIPisInfinity(scip, consdata->rhs) ) 4410 mult = -1; 4411 } 4412 4413 if( mult == 0 ) 4414 { 4415 /* 3. the absolute value of the right hand side must be greater than that of the left hand side */ 4416 if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) ) 4417 mult = +1; 4418 else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) ) 4419 mult = -1; 4420 } 4421 4422 if( mult == 0 ) 4423 { 4424 /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */ 4425 nposcoeffs = 0; 4426 nnegcoeffs = 0; 4427 for( i = 0; i < nvars; ++i ) 4428 { 4429 if( vals[i] > 0.0 ) 4430 nposcoeffs++; 4431 else 4432 nnegcoeffs++; 4433 } 4434 if( nposcoeffs > nnegcoeffs ) 4435 mult = +1; 4436 else if( nposcoeffs < nnegcoeffs ) 4437 mult = -1; 4438 } 4439 4440 if( mult == 0 ) 4441 { 4442 /* 5. multiply with +1 */ 4443 mult = +1; 4444 } 4445 4446 assert(mult == +1 || mult == -1); 4447 if( mult == -1 ) 4448 { 4449 /* scale the constraint with -1 */ 4450 SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n"); 4451 SCIPdebugPrintCons(scip, cons, NULL); 4452 SCIP_CALL( scaleCons(scip, cons, -1.0) ); 4453 4454 /* scalecons() can delete variables, but scaling with -1 should not do that */ 4455 assert(nvars == consdata->nvars); 4456 } 4457 4458 /* 4459 * rationals to integrals 4460 * 4461 * @todo try scaling only on behalf of non-continuous variables 4462 */ 4463 success = TRUE; 4464 scm = 1; 4465 for( i = 0; i < nvars && success && scm <= maxmult; ++i ) 4466 { 4467 if( !SCIPisIntegral(scip, vals[i]) ) 4468 { 4469 /* epsilon has been slightly decreased above - to be on the safe side */ 4470 success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator); 4471 if( success ) 4472 scm = SCIPcalcSmaComMul(scm, denominator); 4473 } 4474 } 4475 assert(scm >= 1); 4476 4477 /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by 4478 * their greatest common divisor 4479 */ 4480 onlyintegral = TRUE; 4481 if( scm == 1 ) 4482 { 4483 for( i = nvars - 1; i >= 0; --i ) 4484 { 4485 if( !SCIPisIntegral(scip, vals[i]) ) 4486 { 4487 onlyintegral = FALSE; 4488 break; 4489 } 4490 } 4491 } 4492 4493 success = success && (scm <= maxmult || (scm == 1 && onlyintegral)); 4494 if( success && scm != 1 ) 4495 { 4496 /* scale the constraint with the smallest common multiple of all denominators */ 4497 SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm); 4498 SCIPdebugPrintCons(scip, cons, NULL); 4499 SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) ); 4500 4501 if( consdata->validmaxabsval ) 4502 { 4503 consdata->maxabsval *= REALABS((SCIP_Real)scm); 4504 if( !SCIPisIntegral(scip, consdata->maxabsval) ) 4505 { 4506 consdata->validmaxabsval = FALSE; 4507 consdata->maxabsval = SCIP_INVALID; 4508 consdataCalcMaxAbsval(consdata); 4509 } 4510 } 4511 4512 if( consdata->validminabsval ) 4513 { 4514 consdata->minabsval *= REALABS((SCIP_Real)scm); 4515 if( !SCIPisIntegral(scip, consdata->minabsval) ) 4516 { 4517 consdata->validminabsval = FALSE; 4518 consdata->minabsval = SCIP_INVALID; 4519 consdataCalcMinAbsval(consdata); 4520 } 4521 } 4522 4523 /* get new consdata information, because scalecons() might have deleted variables */ 4524 vals = consdata->vals; 4525 nvars = consdata->nvars; 4526 assert(nvars == 0 || vals != NULL); 4527 } 4528 4529 /* 4530 * division by greatest common divisor 4531 */ 4532 if( success && nvars >= 1 ) 4533 { 4534 /* all coefficients are integral: divide them by their greatest common divisor */ 4535 assert(SCIPisIntegral(scip, vals[0])); 4536 4537 gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol); 4538 for( i = 1; i < nvars && gcd > 1; ++i ) 4539 { 4540 assert(SCIPisIntegral(scip, vals[i])); 4541 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol)); 4542 } 4543 4544 if( gcd > 1 ) 4545 { 4546 /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */ 4547 if( !consdata->hascontvar && onlyintegral ) 4548 { 4549 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) ) 4550 { 4551 *infeasible = TRUE; 4552 4553 SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd); 4554 SCIPdebugPrintCons(scip, cons, NULL); 4555 4556 return SCIP_OKAY; 4557 } 4558 } 4559 4560 /* divide the constraint by the greatest common divisor of the coefficients */ 4561 SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd); 4562 SCIPdebugPrintCons(scip, cons, NULL); 4563 SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) ); 4564 4565 if( consdata->validmaxabsval ) 4566 { 4567 consdata->maxabsval /= REALABS((SCIP_Real)gcd); 4568 } 4569 if( consdata->validminabsval ) 4570 { 4571 consdata->minabsval /= REALABS((SCIP_Real)gcd); 4572 } 4573 } 4574 } 4575 4576 /* mark constraint to be normalized */ 4577 consdata->normalized = TRUE; 4578 4579 SCIPdebugMsg(scip, "normalized constraint:\n"); 4580 SCIPdebugPrintCons(scip, cons, NULL); 4581 4582 return SCIP_OKAY; 4583 } 4584 4585 /** replaces multiple occurrences of a variable by a single coefficient */ 4586 static 4587 SCIP_RETCODE mergeMultiples( 4588 SCIP* scip, /**< SCIP data structure */ 4589 SCIP_CONS* cons /**< linear constraint */ 4590 ) 4591 { 4592 SCIP_CONSDATA* consdata; 4593 SCIP_VAR* var; 4594 SCIP_Real valsum; 4595 int v; 4596 4597 assert(scip != NULL); 4598 assert(cons != NULL); 4599 4600 consdata = SCIPconsGetData(cons); 4601 assert(consdata != NULL); 4602 4603 if( consdata->merged ) 4604 return SCIP_OKAY; 4605 4606 /* sort the constraint */ 4607 SCIP_CALL( consdataSort(scip, consdata) ); 4608 4609 /* go backwards through the constraint looking for multiple occurrences of the same variable; 4610 * backward direction is necessary, since delCoefPos() modifies the given position and 4611 * the subsequent ones 4612 */ 4613 v = consdata->nvars-1; 4614 while( v >= 1 ) 4615 { 4616 var = consdata->vars[v]; 4617 if( consdata->vars[v-1] == var ) 4618 { 4619 valsum = consdata->vals[v]; 4620 do 4621 { 4622 SCIP_CALL( delCoefPos(scip, cons, v) ); 4623 --v; 4624 valsum += consdata->vals[v]; 4625 } 4626 while( v >= 1 && consdata->vars[v-1] == var ); 4627 4628 /* modify the last existing occurrence of the variable */ 4629 assert(consdata->vars[v] == var); 4630 if( SCIPisZero(scip, valsum) ) 4631 { 4632 SCIP_CALL( delCoefPos(scip, cons, v) ); 4633 4634 /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity 4635 * delta needs to be recalculated on the next real propagation 4636 */ 4637 if( consdata->maxactdeltavar == var ) 4638 { 4639 consdata->maxactdelta = SCIP_INVALID; 4640 consdata->maxactdeltavar = NULL; 4641 } 4642 } 4643 else 4644 { 4645 SCIP_CALL( chgCoefPos(scip, cons, v, valsum) ); 4646 } 4647 } 4648 --v; 4649 } 4650 4651 consdata->merged = TRUE; 4652 4653 return SCIP_OKAY; 4654 } 4655 4656 /** replaces all fixed and aggregated variables by their non-fixed counterparts */ 4657 static 4658 SCIP_RETCODE applyFixings( 4659 SCIP* scip, /**< SCIP data structure */ 4660 SCIP_CONS* cons, /**< linear constraint */ 4661 SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this 4662 * information is not needed; in this case, we apply all fixings 4663 * instead of stopping after the first infeasible one */ 4664 ) 4665 { 4666 SCIP_CONSDATA* consdata; 4667 SCIP_VAR* var; 4668 SCIP_VAR** aggrvars; 4669 SCIP_Real val; 4670 SCIP_Real* aggrscalars; 4671 SCIP_Real fixedval; 4672 SCIP_Real aggrconst; 4673 int v; 4674 int naggrvars; 4675 int i; 4676 4677 assert(scip != NULL); 4678 assert(cons != NULL); 4679 4680 if( infeasible != NULL ) 4681 *infeasible = FALSE; 4682 4683 consdata = SCIPconsGetData(cons); 4684 assert(consdata != NULL); 4685 4686 if( consdata->eventdata == NULL ) 4687 { 4688 SCIP_CONSHDLR* conshdlr; 4689 SCIP_CONSHDLRDATA* conshdlrdata; 4690 4691 conshdlr = SCIPconsGetHdlr(cons); 4692 assert(conshdlr != NULL); 4693 4694 conshdlrdata = SCIPconshdlrGetData(conshdlr); 4695 assert(conshdlrdata != NULL); 4696 4697 /* catch bound change events of variables */ 4698 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) ); 4699 assert(consdata->eventdata != NULL); 4700 } 4701 4702 if( !consdata->removedfixings ) 4703 { 4704 SCIP_Real lhssubtrahend; 4705 SCIP_Real rhssubtrahend; 4706 4707 /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row) 4708 * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row 4709 */ 4710 assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row)); 4711 4712 lhssubtrahend = 0.0; 4713 rhssubtrahend = 0.0; 4714 4715 SCIPdebugMsg(scip, "applying fixings:\n"); 4716 SCIPdebugPrintCons(scip, cons, NULL); 4717 4718 v = 0; 4719 while( v < consdata->nvars ) 4720 { 4721 var = consdata->vars[v]; 4722 val = consdata->vals[v]; 4723 assert(SCIPvarIsTransformed(var)); 4724 4725 switch( SCIPvarGetStatus(var) ) 4726 { 4727 case SCIP_VARSTATUS_ORIGINAL: 4728 SCIPerrorMessage("original variable in transformed linear constraint\n"); 4729 return SCIP_INVALIDDATA; 4730 4731 case SCIP_VARSTATUS_LOOSE: 4732 case SCIP_VARSTATUS_COLUMN: 4733 ++v; 4734 break; 4735 4736 case SCIP_VARSTATUS_FIXED: 4737 assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var))); 4738 fixedval = SCIPvarGetLbGlobal(var); 4739 if( !SCIPisInfinity(scip, -consdata->lhs) ) 4740 { 4741 if( SCIPisInfinity(scip, ABS(fixedval)) ) 4742 { 4743 if( val * fixedval > 0.0 ) 4744 { 4745 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) ); 4746 } 4747 else 4748 { 4749 if( infeasible != NULL ) 4750 { 4751 /* if lhs gets infinity it means that the problem is infeasible */ 4752 *infeasible = TRUE; 4753 return SCIP_OKAY; 4754 } 4755 else 4756 { 4757 SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) ); 4758 } 4759 } 4760 } 4761 else 4762 lhssubtrahend += val * fixedval; 4763 } 4764 if( !SCIPisInfinity(scip, consdata->rhs) ) 4765 { 4766 if( SCIPisInfinity(scip, ABS(fixedval)) ) 4767 { 4768 if( val * fixedval > 0.0 ) 4769 { 4770 if( infeasible != NULL ) 4771 { 4772 /* if rhs gets -infinity it means that the problem is infeasible */ 4773 *infeasible = TRUE; 4774 return SCIP_OKAY; 4775 } 4776 else 4777 { 4778 SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) ); 4779 } 4780 } 4781 else 4782 { 4783 SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) ); 4784 } 4785 } 4786 else 4787 rhssubtrahend += val * fixedval; 4788 } 4789 SCIP_CALL( delCoefPos(scip, cons, v) ); 4790 break; 4791 4792 case SCIP_VARSTATUS_AGGREGATED: 4793 { 4794 SCIP_VAR* activevar = SCIPvarGetAggrVar(var); 4795 SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var); 4796 SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var); 4797 4798 assert(activevar != NULL); 4799 SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) ); 4800 assert(activevar != NULL); 4801 4802 if( !SCIPisZero(scip, activescalar) ) 4803 { 4804 SCIP_CALL( addCoef(scip, cons, activevar, activescalar) ); 4805 } 4806 4807 if( !SCIPisZero(scip, activeconstant) ) 4808 { 4809 if( !SCIPisInfinity(scip, -consdata->lhs) ) 4810 lhssubtrahend += activeconstant; 4811 if( !SCIPisInfinity(scip, consdata->rhs) ) 4812 rhssubtrahend += activeconstant; 4813 } 4814 4815 SCIP_CALL( delCoefPos(scip, cons, v) ); 4816 break; 4817 } 4818 case SCIP_VARSTATUS_MULTAGGR: 4819 SCIP_CALL( SCIPflattenVarAggregationGraph(scip, var) ); 4820 naggrvars = SCIPvarGetMultaggrNVars(var); 4821 aggrvars = SCIPvarGetMultaggrVars(var); 4822 aggrscalars = SCIPvarGetMultaggrScalars(var); 4823 for( i = 0; i < naggrvars; ++i ) 4824 { 4825 SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) ); 4826 } 4827 aggrconst = SCIPvarGetMultaggrConstant(var); 4828 4829 if( !SCIPisInfinity(scip, -consdata->lhs) ) 4830 lhssubtrahend += val * aggrconst; 4831 if( !SCIPisInfinity(scip, consdata->rhs) ) 4832 rhssubtrahend += val * aggrconst; 4833 4834 SCIP_CALL( delCoefPos(scip, cons, v) ); 4835 break; 4836 4837 case SCIP_VARSTATUS_NEGATED: 4838 SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) ); 4839 aggrconst = SCIPvarGetNegationConstant(var); 4840 4841 if( !SCIPisInfinity(scip, -consdata->lhs) ) 4842 lhssubtrahend += val * aggrconst; 4843 if( !SCIPisInfinity(scip, consdata->rhs) ) 4844 rhssubtrahend += val * aggrconst; 4845 4846 SCIP_CALL( delCoefPos(scip, cons, v) ); 4847 break; 4848 4849 default: 4850 SCIPerrorMessage("unknown variable status\n"); 4851 SCIPABORT(); 4852 return SCIP_INVALIDDATA; /*lint !e527*/ 4853 } 4854 } 4855 4856 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) ) 4857 { 4858 /* for large numbers that are relatively equal, substraction can lead to cancellation, 4859 * causing wrong fixings of other variables --> better use a real zero here; 4860 * for small numbers, polishing the difference might lead to wrong results --> 4861 * better use the exact difference in this case 4862 */ 4863 if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) ) 4864 { 4865 SCIP_CALL( chgLhs(scip, cons, 0.0) ); 4866 } 4867 else 4868 { 4869 SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) ); 4870 } 4871 } 4872 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs)) 4873 { 4874 /* for large numbers that are relatively equal, substraction can lead to cancellation, 4875 * causing wrong fixings of other variables --> better use a real zero here; 4876 * for small numbers, polishing the difference might lead to wrong results --> 4877 * better use the exact difference in this case 4878 */ 4879 if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) ) 4880 { 4881 SCIP_CALL( chgRhs(scip, cons, 0.0) ); 4882 } 4883 else 4884 { 4885 SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) ); 4886 } 4887 } 4888 consdata->removedfixings = TRUE; 4889 4890 SCIPdebugMsg(scip, "after fixings:\n"); 4891 SCIPdebugPrintCons(scip, cons, NULL); 4892 4893 /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have 4894 * to clean up the constraint 4895 */ 4896 SCIP_CALL( mergeMultiples(scip, cons) ); 4897 4898 SCIPdebugMsg(scip, "after merging:\n"); 4899 SCIPdebugPrintCons(scip, cons, NULL); 4900 } 4901 assert(consdata->removedfixings); 4902 4903 #ifndef NDEBUG 4904 /* check, if all fixings are applied */ 4905 for( v = 0; v < consdata->nvars; ++v ) 4906 assert(SCIPvarIsActive(consdata->vars[v])); 4907 #endif 4908 4909 return SCIP_OKAY; 4910 } 4911 4912 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis' 4913 * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the 4914 * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the 4915 * conflict detecting constraint by using NULL as inferred variable 4916 */ 4917 static 4918 SCIP_RETCODE addConflictBounds( 4919 SCIP* scip, /**< SCIP data structure */ 4920 SCIP_CONS* cons, /**< constraint that inferred the bound change */ 4921 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */ 4922 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */ 4923 int inferpos, /**< position of the inferred variable in the vars array */ 4924 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */ 4925 ) 4926 { 4927 SCIP_CONSDATA* consdata; 4928 SCIP_VAR** vars; 4929 SCIP_Real* vals; 4930 int nvars; 4931 int i; 4932 4933 assert(scip != NULL); 4934 assert(cons != NULL); 4935 4936 consdata = SCIPconsGetData(cons); 4937 4938 assert(consdata != NULL); 4939 4940 vars = consdata->vars; 4941 vals = consdata->vals; 4942 nvars = consdata->nvars; 4943 4944 assert(vars != NULL || nvars == 0); 4945 assert(vals != NULL || nvars == 0); 4946 4947 assert(-1 <= inferpos && inferpos < nvars); 4948 assert((infervar == NULL) == (inferpos == -1)); 4949 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/ 4950 4951 /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal 4952 * residual value, depending on whether the left or right hand side is responsible for the bound change: 4953 * - if the right hand side is the reason, the minimal residual activity is responsible 4954 * - if the left hand side is the reason, the maximal residual activity is responsible 4955 */ 4956 4957 /* if the variable is integral we only need to add reason bounds until the propagation could be applied */ 4958 if( infervar == NULL || SCIPvarIsIntegral(infervar) ) 4959 { 4960 SCIP_Real minresactivity; 4961 SCIP_Real maxresactivity; 4962 SCIP_Bool minisrelax; 4963 SCIP_Bool maxisrelax; 4964 SCIP_Bool isminsettoinfinity; 4965 SCIP_Bool ismaxsettoinfinity; 4966 4967 minresactivity = -SCIPinfinity(scip); 4968 maxresactivity = SCIPinfinity(scip); 4969 4970 /* calculate the minimal and maximal global activity of all other variables involved in the constraint */ 4971 if( infervar != NULL ) 4972 { 4973 assert(vals != NULL); /* for flexelint */ 4974 if( reasonisrhs ) 4975 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL, 4976 &minisrelax, NULL, &isminsettoinfinity, NULL); 4977 else 4978 consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity, 4979 NULL, &maxisrelax, NULL, &ismaxsettoinfinity); 4980 } 4981 else 4982 { 4983 if( reasonisrhs ) 4984 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL, 4985 &minisrelax, NULL, &isminsettoinfinity, NULL); 4986 else 4987 consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity, 4988 NULL, &maxisrelax, NULL, &ismaxsettoinfinity); 4989 } 4990 4991 /* we can only do something clever, if the residual activity is finite and not relaxed */ 4992 if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/ 4993 { 4994 SCIP_Real rescap; 4995 SCIP_Bool resactisinf; 4996 4997 resactisinf = FALSE; 4998 4999 /* calculate the residual capacity that would be left, if the variable would be set to one more / one less 5000 * than its inferred bound 5001 */ 5002 if( infervar != NULL ) 5003 { 5004 assert(vals != NULL); /* for flexelint */ 5005 5006 if( reasonisrhs ) 5007 { 5008 if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) ) 5009 { 5010 consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE); 5011 if( SCIPisInfinity(scip, -minresactivity) ) 5012 resactisinf = TRUE; 5013 } 5014 rescap = consdata->rhs - minresactivity; 5015 } 5016 else 5017 { 5018 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) ) 5019 { 5020 consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE); 5021 if( SCIPisInfinity(scip, maxresactivity) ) 5022 resactisinf = TRUE; 5023 } 5024 rescap = consdata->lhs - maxresactivity; 5025 } 5026 5027 if( reasonisrhs == (vals[inferpos] > 0.0) ) 5028 rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0); 5029 else 5030 rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0); 5031 } 5032 else 5033 rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity); 5034 5035 if( !resactisinf ) 5036 { 5037 /* now add bounds as reasons until the residual capacity is exceeded */ 5038 for( i = 0; i < nvars; ++i ) 5039 { 5040 assert( vars != NULL && vals != NULL ); /* for lint */ 5041 5042 /* zero coefficients and the inferred variable can be ignored */ 5043 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) ) 5044 continue; 5045 5046 /* check if the residual capacity is exceeded */ 5047 if( (reasonisrhs && SCIPisFeasNegative(scip, rescap)) 5048 || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) ) 5049 break; 5050 5051 /* update the residual capacity due to the local bound of this variable */ 5052 if( reasonisrhs == (vals[i] > 0.0) ) 5053 { 5054 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */ 5055 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) ); 5056 rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i])); 5057 } 5058 else 5059 { 5060 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */ 5061 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) ); 5062 rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i])); 5063 } 5064 } 5065 return SCIP_OKAY; 5066 } 5067 } 5068 } 5069 5070 /* for a bound change on a continuous variable, all locally changed bounds are responsible */ 5071 for( i = 0; i < nvars; ++i ) 5072 { 5073 assert(vars != NULL); /* for flexelint */ 5074 assert(vals != NULL); /* for flexelint */ 5075 5076 /* zero coefficients and the inferred variable can be ignored */ 5077 if( vars[i] == infervar || SCIPisZero(scip, vals[i]) ) 5078 continue; 5079 5080 if( reasonisrhs == (vals[i] > 0.0) ) 5081 { 5082 /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */ 5083 SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) ); 5084 } 5085 else 5086 { 5087 /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */ 5088 SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) ); 5089 } 5090 } 5091 5092 return SCIP_OKAY; 5093 } 5094 5095 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed 5096 * variables to the conflict analysis' candidate store; the conflict analysis can be initialized 5097 * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable 5098 */ 5099 static 5100 SCIP_RETCODE addConflictFixedVars( 5101 SCIP* scip, /**< SCIP data structure */ 5102 SCIP_CONS* cons, /**< constraint that inferred the bound change */ 5103 SCIP_VAR* infervar, /**< variable that was deduced, or NULL */ 5104 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */ 5105 int inferpos /**< position of the inferred variable in the vars array, or -1 */ 5106 ) 5107 { 5108 SCIP_CONSDATA* consdata; 5109 SCIP_VAR** vars; 5110 int nvars; 5111 int v; 5112 5113 assert(scip != NULL); 5114 assert(cons != NULL); 5115 5116 consdata = SCIPconsGetData(cons); 5117 assert(consdata != NULL); 5118 vars = consdata->vars; 5119 nvars = consdata->nvars; 5120 assert(vars != NULL || nvars == 0); 5121 assert(-1 <= inferpos && inferpos < nvars); 5122 assert((infervar == NULL) == (inferpos == -1)); 5123 assert(inferpos == -1 || vars != NULL); 5124 assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/ 5125 5126 /* collect all fixed variables */ 5127 for( v = nvars - 1; v >= 0; --v ) 5128 { 5129 assert(vars != NULL); /* for flexelint */ 5130 5131 /* need to add old bounds before propagation of inferrence variable */ 5132 if( vars[v] == infervar ) 5133 { 5134 assert(vars[v] != NULL); 5135 5136 if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) ) 5137 { 5138 /* @todo get boundchange index before this last boundchange and correct the index */ 5139 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) ); 5140 } 5141 5142 if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) ) 5143 { 5144 /* @todo get boundchange index before this last boundchange and correct the index */ 5145 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) ); 5146 } 5147 5148 continue; 5149 } 5150 5151 /* check for fixed variables */ 5152 if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) ) 5153 { 5154 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */ 5155 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) ); 5156 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) ); 5157 } 5158 } 5159 5160 return SCIP_OKAY; 5161 } 5162 5163 /** add reasoning variables to conflict candidate queue which led to the conflict */ 5164 static 5165 SCIP_RETCODE addConflictReasonVars( 5166 SCIP* scip, /**< SCIP data structure */ 5167 SCIP_VAR** vars, /**< variables reasoning the infeasibility */ 5168 int nvars, /**< number of variables reasoning the infeasibility */ 5169 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */ 5170 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */ 5171 ) 5172 { 5173 int v; 5174 5175 assert(scip != NULL); 5176 5177 /* collect all variables for which the local bounds differ from their global bounds */ 5178 for( v = nvars - 1; v >= 0; --v ) 5179 { 5180 assert(vars != NULL); 5181 5182 /* check for local bound changes variables */ 5183 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) ) 5184 { 5185 /* add conflict bound */ 5186 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) ); 5187 } 5188 5189 if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) ) 5190 { 5191 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) ); 5192 } 5193 } 5194 5195 if( var != NULL ) 5196 { 5197 if( bound < SCIPvarGetLbLocal(var) ) 5198 { 5199 SCIP_CALL( SCIPaddConflictLb(scip, var, 0) ); 5200 } 5201 5202 if( bound > SCIPvarGetUbLocal(var) ) 5203 { 5204 SCIP_CALL( SCIPaddConflictUb(scip, var, 0) ); 5205 } 5206 } 5207 5208 return SCIP_OKAY; 5209 } 5210 5211 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding 5212 * propagation rule (see propagateCons()): 5213 * (1) activity residuals of all other variables tighten bounds of single variable 5214 */ 5215 static 5216 SCIP_RETCODE resolvePropagation( 5217 SCIP* scip, /**< SCIP data structure */ 5218 SCIP_CONS* cons, /**< constraint that inferred the bound change */ 5219 SCIP_VAR* infervar, /**< variable that was deduced */ 5220 INFERINFO inferinfo, /**< inference information */ 5221 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */ 5222 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */ 5223 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */ 5224 ) 5225 { 5226 SCIP_CONSDATA* consdata; 5227 SCIP_VAR** vars; 5228 #ifndef NDEBUG 5229 SCIP_Real* vals; 5230 #endif 5231 int nvars; 5232 int inferpos; 5233 5234 assert(scip != NULL); 5235 assert(cons != NULL); 5236 assert(result != NULL); 5237 5238 consdata = SCIPconsGetData(cons); 5239 assert(consdata != NULL); 5240 vars = consdata->vars; 5241 nvars = consdata->nvars; 5242 #ifndef NDEBUG 5243 vals = consdata->vals; 5244 assert(vars != NULL); 5245 assert(vals != NULL); 5246 #endif 5247 5248 /* get the position of the inferred variable in the vars array */ 5249 inferpos = inferInfoGetPos(inferinfo); 5250 if( inferpos >= nvars || vars[inferpos] != infervar ) 5251 { 5252 /* find inference variable in constraint */ 5253 /**@todo use a binary search here; the variables can be sorted by variable index */ 5254 for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos ) 5255 {} 5256 } 5257 assert(inferpos < nvars); 5258 assert(vars[inferpos] == infervar); 5259 assert(!SCIPisZero(scip, vals[inferpos])); 5260 5261 switch( inferInfoGetProprule(inferinfo) ) 5262 { 5263 case PROPRULE_1_RHS: 5264 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear 5265 * constraint (only taking the other variables into account) didn't leave enough space for a larger 5266 * domain in order to not exceed the right hand side of the inequality 5267 */ 5268 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER)); 5269 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) ); 5270 *result = SCIP_SUCCESS; 5271 break; 5272 5273 case PROPRULE_1_LHS: 5274 /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear 5275 * constraint (only taking the other variables into account) didn't leave enough space for a larger 5276 * domain in order to not fall below the left hand side of the inequality 5277 */ 5278 assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER)); 5279 SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) ); 5280 *result = SCIP_SUCCESS; 5281 break; 5282 5283 case PROPRULE_1_RANGEDROW: 5284 /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow 5285 * the given inference variable to their bounds in this given ranged row 5286 */ 5287 5288 /* check that we really have a ranged row here */ 5289 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs)); 5290 SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) ); 5291 *result = SCIP_SUCCESS; 5292 break; 5293 5294 case PROPRULE_INVALID: 5295 default: 5296 SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n", 5297 inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo), 5298 boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar)); 5299 SCIP_CALL( SCIPprintCons(scip, cons, NULL) ); 5300 SCIPinfoMessage(scip, NULL, ";\n"); 5301 return SCIP_INVALIDDATA; 5302 } 5303 5304 return SCIP_OKAY; 5305 } 5306 5307 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */ 5308 static 5309 SCIP_RETCODE analyzeConflict( 5310 SCIP* scip, /**< SCIP data structure */ 5311 SCIP_CONS* cons, /**< conflict detecting constraint */ 5312 SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */ 5313 ) 5314 { 5315 /* conflict analysis can only be applied in solving stage and if it is turned on */ 5316 if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) ) 5317 return SCIP_OKAY; 5318 5319 /* initialize conflict analysis */ 5320 SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) ); 5321 5322 /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */ 5323 SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) ); 5324 5325 /* analyze the conflict */ 5326 SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) ); 5327 5328 return SCIP_OKAY; 5329 } 5330 5331 /** check if there is any hope of tightening some bounds */ 5332 static 5333 SCIP_Bool canTightenBounds( 5334 SCIP_CONS* cons /**< linear constraint */ 5335 ) 5336 { 5337 SCIP_CONSDATA* consdata; 5338 int infcountmin; 5339 int infcountmax; 5340 5341 consdata = SCIPconsGetData(cons); 5342 assert(consdata != NULL); 5343 5344 infcountmin = consdata->minactivityneginf 5345 + consdata->minactivityposinf 5346 + consdata->minactivityneghuge 5347 + consdata->minactivityposhuge; 5348 infcountmax = consdata->maxactivityneginf 5349 + consdata->maxactivityposinf 5350 + consdata->maxactivityneghuge 5351 + consdata->maxactivityposhuge; 5352 5353 if( infcountmin > 1 && infcountmax > 1 ) 5354 return FALSE; 5355 5356 return TRUE; 5357 } 5358 5359 /** tighten upper bound */ 5360 static 5361 SCIP_RETCODE tightenVarUb( 5362 SCIP* scip, /**< SCIP data structure */ 5363 SCIP_CONS* cons, /**< linear constraint */ 5364 int pos, /**< variable position */ 5365 PROPRULE proprule, /**< propagation rule that deduced the value */ 5366 SCIP_Real newub, /**< new upper bound */ 5367 SCIP_Real oldub, /**< old upper bound */ 5368 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */ 5369 int* nchgbds, /**< pointer to count the total number of tightened bounds */ 5370 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */ 5371 ) 5372 { 5373 SCIP_CONSDATA* consdata; 5374 SCIP_VAR* var; 5375 SCIP_Real lb; 5376 SCIP_Bool infeasible; 5377 SCIP_Bool tightened; 5378 5379 assert(cons != NULL); 5380 assert(!SCIPisInfinity(scip, newub)); 5381 5382 consdata = SCIPconsGetData(cons); 5383 assert(consdata != NULL); 5384 var = consdata->vars[pos]; 5385 assert(var != NULL); 5386 5387 lb = SCIPvarGetLbLocal(var); 5388 newub = SCIPadjustedVarUb(scip, var, newub); 5389 5390 if( force || SCIPisUbBetter(scip, newub, lb, oldub) ) 5391 { 5392 SCIP_VARTYPE vartype; 5393 5394 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n", 5395 SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], 5396 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newub); 5397 5398 vartype = SCIPvarGetType(var); 5399 5400 /* tighten upper bound */ 5401 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) ); 5402 5403 if( infeasible ) 5404 { 5405 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 5406 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub); 5407 5408 /* analyze conflict */ 5409 SCIP_CALL( analyzeConflict(scip, cons, TRUE) ); 5410 5411 *cutoff = TRUE; 5412 } 5413 else if( tightened ) 5414 { 5415 assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub)); 5416 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n", 5417 SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var)); 5418 5419 (*nchgbds)++; 5420 5421 /* if variable type was changed we might be able to upgrade the constraint */ 5422 if( vartype != SCIPvarGetType(var) ) 5423 consdata->upgradetried = FALSE; 5424 } 5425 } 5426 return SCIP_OKAY; 5427 } 5428 5429 /** tighten lower bound */ 5430 static 5431 SCIP_RETCODE tightenVarLb( 5432 SCIP* scip, /**< SCIP data structure */ 5433 SCIP_CONS* cons, /**< linear constraint */ 5434 int pos, /**< variable position */ 5435 PROPRULE proprule, /**< propagation rule that deduced the value */ 5436 SCIP_Real newlb, /**< new lower bound */ 5437 SCIP_Real oldlb, /**< old lower bound */ 5438 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */ 5439 int* nchgbds, /**< pointer to count the total number of tightened bounds */ 5440 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */ 5441 ) 5442 { 5443 SCIP_CONSDATA* consdata; 5444 SCIP_VAR* var; 5445 SCIP_Real ub; 5446 SCIP_Bool infeasible; 5447 SCIP_Bool tightened; 5448 5449 assert(cons != NULL); 5450 assert(!SCIPisInfinity(scip, newlb)); 5451 5452 consdata = SCIPconsGetData(cons); 5453 assert(consdata != NULL); 5454 var = consdata->vars[pos]; 5455 assert(var != NULL); 5456 5457 ub = SCIPvarGetUbLocal(var); 5458 newlb = SCIPadjustedVarLb(scip, var, newlb); 5459 5460 if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) ) 5461 { 5462 SCIP_VARTYPE vartype; 5463 5464 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n", 5465 SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], 5466 QUAD_TO_DBL(consdata->minactivity), QUAD_TO_DBL(consdata->maxactivity), consdata->lhs, consdata->rhs, newlb); 5467 5468 vartype = SCIPvarGetType(var); 5469 5470 /* tighten lower bound */ 5471 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) ); 5472 5473 if( infeasible ) 5474 { 5475 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 5476 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub); 5477 5478 /* analyze conflict */ 5479 SCIP_CALL( analyzeConflict(scip, cons, FALSE) ); 5480 5481 *cutoff = TRUE; 5482 } 5483 else if( tightened ) 5484 { 5485 assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb)); 5486 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n", 5487 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub); 5488 5489 (*nchgbds)++; 5490 5491 /* if variable type was changed we might be able to upgrade the constraint */ 5492 if( vartype != SCIPvarGetType(var) ) 5493 consdata->upgradetried = FALSE; 5494 } 5495 } 5496 return SCIP_OKAY; 5497 } 5498 5499 /** tightens bounds of a single variable due to activity bounds (easy case) */ 5500 static 5501 SCIP_RETCODE tightenVarBoundsEasy( 5502 SCIP* scip, /**< SCIP data structure */ 5503 SCIP_CONS* cons, /**< linear constraint */ 5504 int pos, /**< position of the variable in the vars array */ 5505 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */ 5506 int* nchgbds, /**< pointer to count the total number of tightened bounds */ 5507 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */ 5508 ) 5509 { 5510 SCIP_CONSDATA* consdata; 5511 SCIP_VAR* var; 5512 SCIP_Real val; 5513 SCIP_Real lb; 5514 SCIP_Real ub; 5515 SCIP_Real lhs; 5516 SCIP_Real rhs; 5517 5518 assert(scip != NULL); 5519 assert(cons != NULL); 5520 assert(cutoff != NULL); 5521 assert(nchgbds != NULL); 5522 5523 /* we cannot tighten variables' bounds, if the constraint may be not complete */ 5524 if( SCIPconsIsModifiable(cons) ) 5525 return SCIP_OKAY; 5526 5527 consdata = SCIPconsGetData(cons); 5528 assert(consdata != NULL); 5529 assert(0 <= pos && pos < consdata->nvars); 5530 5531 *cutoff = FALSE; 5532 5533 var = consdata->vars[pos]; 5534 assert(var != NULL); 5535 5536 /* we cannot tighten bounds of multi-aggregated variables */ 5537 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR ) 5538 return SCIP_OKAY; 5539 5540 val = consdata->vals[pos]; 5541 lhs = consdata->lhs; 5542 rhs = consdata->rhs; 5543 assert(!SCIPisZero(scip, val)); 5544 assert(!SCIPisInfinity(scip, lhs)); 5545 assert(!SCIPisInfinity(scip, -rhs)); 5546 5547 lb = SCIPvarGetLbLocal(var); 5548 ub = SCIPvarGetUbLocal(var); 5549 assert(SCIPisLE(scip, lb, ub)); 5550 5551 /* recompute activities if needed */ 5552 if( !consdata->validactivities ) 5553 consdataCalcActivities(scip, consdata); 5554 assert(consdata->validactivities); 5555 if( !consdata->validminact ) 5556 consdataRecomputeMinactivity(scip, consdata); 5557 assert(consdata->validminact); 5558 5559 if( val > 0.0 ) 5560 { 5561 /* check, if we can tighten the variable's upper bound */ 5562 if( !SCIPisInfinity(scip, rhs) ) 5563 { 5564 SCIP_Real slack; 5565 SCIP_Real alpha; 5566 5567 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */ 5568 assert(consdata->validminact); 5569 5570 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */ 5571 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) ) 5572 { 5573 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n", 5574 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs); 5575 5576 *cutoff = TRUE; 5577 return SCIP_OKAY; 5578 } 5579 5580 slack = rhs - QUAD_TO_DBL(consdata->minactivity); 5581 5582 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set 5583 * it to zero 5584 */ 5585 if( !SCIPisPositive(scip, slack) ) 5586 slack = 0.0; 5587 5588 alpha = val * (ub - lb); 5589 assert(!SCIPisNegative(scip, alpha)); 5590 5591 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) ) 5592 { 5593 SCIP_Real newub; 5594 5595 /* compute new upper bound */ 5596 newub = lb + (slack / val); 5597 5598 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) ); 5599 5600 if( *cutoff ) 5601 { 5602 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 5603 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub); 5604 5605 return SCIP_OKAY; 5606 } 5607 5608 /* collect the new upper bound which is needed for the lower bound computation */ 5609 ub = SCIPvarGetUbLocal(var); 5610 } 5611 } 5612 5613 /* check, if we can tighten the variable's lower bound */ 5614 if( !SCIPisInfinity(scip, -lhs) ) 5615 { 5616 SCIP_Real slack; 5617 SCIP_Real alpha; 5618 5619 /* make sure the max activity is reliable */ 5620 if( !consdata->validmaxact ) 5621 { 5622 consdataRecomputeMaxactivity(scip, consdata); 5623 } 5624 assert(consdata->validmaxact); 5625 5626 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */ 5627 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) ) 5628 { 5629 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n", 5630 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs); 5631 5632 *cutoff = TRUE; 5633 return SCIP_OKAY; 5634 } 5635 5636 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs; 5637 5638 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set 5639 * it to zero 5640 */ 5641 if( !SCIPisPositive(scip, slack) ) 5642 slack = 0.0; 5643 5644 alpha = val * (ub - lb); 5645 assert(!SCIPisNegative(scip, alpha)); 5646 5647 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) ) 5648 { 5649 SCIP_Real newlb; 5650 5651 /* compute new lower bound */ 5652 newlb = ub - (slack / val); 5653 5654 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) ); 5655 5656 if( *cutoff ) 5657 { 5658 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 5659 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub); 5660 5661 return SCIP_OKAY; 5662 } 5663 } 5664 } 5665 } 5666 else 5667 { 5668 /* check, if we can tighten the variable's lower bound */ 5669 if( !SCIPisInfinity(scip, rhs) ) 5670 { 5671 SCIP_Real slack; 5672 SCIP_Real alpha; 5673 5674 /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */ 5675 assert(consdata->validminact); 5676 5677 /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */ 5678 if( SCIPisFeasLT(scip, rhs, QUAD_TO_DBL(consdata->minactivity)) ) 5679 { 5680 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n", 5681 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->minactivity), rhs); 5682 5683 *cutoff = TRUE; 5684 return SCIP_OKAY; 5685 } 5686 5687 slack = rhs - QUAD_TO_DBL(consdata->minactivity); 5688 5689 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set 5690 * it to zero 5691 */ 5692 if( !SCIPisPositive(scip, slack) ) 5693 slack = 0.0; 5694 5695 alpha = val * (lb - ub); 5696 assert(!SCIPisNegative(scip, alpha)); 5697 5698 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) ) 5699 { 5700 SCIP_Real newlb; 5701 5702 /* compute new lower bound */ 5703 newlb = ub + slack / val; 5704 5705 SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) ); 5706 5707 if( *cutoff ) 5708 { 5709 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 5710 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub); 5711 5712 return SCIP_OKAY; 5713 } 5714 /* collect the new lower bound which is needed for the upper bound computation */ 5715 lb = SCIPvarGetLbLocal(var); 5716 } 5717 } 5718 5719 /* check, if we can tighten the variable's upper bound */ 5720 if( !SCIPisInfinity(scip, -lhs) ) 5721 { 5722 SCIP_Real slack; 5723 SCIP_Real alpha; 5724 5725 /* make sure the max activity is reliable */ 5726 if( !consdata->validmaxact ) 5727 { 5728 consdataRecomputeMaxactivity(scip, consdata); 5729 } 5730 assert(consdata->validmaxact); 5731 5732 /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */ 5733 if( SCIPisFeasLT(scip, QUAD_TO_DBL(consdata->maxactivity), lhs) ) 5734 { 5735 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n", 5736 SCIPconsGetName(cons), SCIPvarGetName(var), QUAD_TO_DBL(consdata->maxactivity), lhs); 5737 5738 *cutoff = TRUE; 5739 return SCIP_OKAY; 5740 } 5741 5742 slack = QUAD_TO_DBL(consdata->maxactivity) - lhs; 5743 5744 /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set 5745 * it to zero 5746 */ 5747 if( !SCIPisPositive(scip, slack) ) 5748 slack = 0.0; 5749 5750 alpha = val * (lb - ub); 5751 assert(!SCIPisNegative(scip, alpha)); 5752 5753 if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) ) 5754 { 5755 SCIP_Real newub; 5756 5757 /* compute new upper bound */ 5758 newub = lb - (slack / val); 5759 5760 SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) ); 5761 5762 if( *cutoff ) 5763 { 5764 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 5765 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub); 5766 5767 return SCIP_OKAY; 5768 } 5769 } 5770 } 5771 } 5772 5773 return SCIP_OKAY; 5774 } 5775 5776 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */ 5777 static 5778 SCIP_RETCODE analyzeConflictRangedRow( 5779 SCIP* scip, /**< SCIP data structure */ 5780 SCIP_CONS* cons, /**< conflict detecting constraint */ 5781 SCIP_VAR** vars, /**< variables reasoning the infeasibility */ 5782 int nvars, /**< number of variables reasoning the infeasibility */ 5783 SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */ 5784 SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */ 5785 ) 5786 { 5787 #ifndef NDEBUG 5788 SCIP_CONSDATA* consdata; 5789 5790 assert(scip != NULL); 5791 assert(cons != NULL); 5792 5793 consdata = SCIPconsGetData(cons); 5794 assert(consdata != NULL); 5795 assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs)); 5796 #endif 5797 5798 /* conflict analysis can only be applied in solving stage and if it is turned on */ 5799 if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) ) 5800 return SCIP_OKAY; 5801 5802 /* initialize conflict analysis */ 5803 SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) ); 5804 5805 /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */ 5806 SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) ); 5807 5808 /* add reasoning variables to conflict candidate queue which led to the conflict */ 5809 SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) ); 5810 5811 /* analyze the conflict */ 5812 SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) ); 5813 5814 return SCIP_OKAY; 5815 } 5816 5817 /** propagate ranged rows 5818 * 5819 * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible 5820 * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of 5821 * variables better. 5822 * 5823 * Example: 5824 * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2 5825 * 5826 * x3 needs to be a multiple of 3, so the instance is infeasible. 5827 * 5828 * Example: 5829 * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2 5830 * 5831 * The only possible value for x3 is 2, so the variable will be fixed. 5832 * 5833 * @todo add holes if possible 5834 */ 5835 static 5836 SCIP_RETCODE rangedRowPropagation( 5837 SCIP* scip, /**< SCIP data structure */ 5838 SCIP_CONS* cons, /**< linear constraint */ 5839 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 5840 int* nfixedvars, /**< pointer to count number of fixed variables */ 5841 int* nchgbds, /**< pointer to count the number of bound changes */ 5842 int* naddconss /**< pointer to count number of added constraints */ 5843 ) 5844 { 5845 SCIP_CONSHDLRDATA* conshdlrdata; 5846 SCIP_CONSHDLR* conshdlr; 5847 SCIP_CONSDATA* consdata; 5848 SCIP_VAR** infcheckvars; 5849 SCIP_Real* infcheckvals; 5850 SCIP_Real minactinfvars; 5851 SCIP_Real maxactinfvars; 5852 SCIP_Real lb; 5853 SCIP_Real ub; 5854 SCIP_Real feastol; 5855 SCIP_Real fixedact; 5856 SCIP_Real lhs; 5857 SCIP_Real rhs; 5858 SCIP_Real absminbincoef; 5859 SCIP_Longint gcd; 5860 SCIP_Longint gcdtmp; 5861 SCIP_Bool minactinfvarsinvalid; 5862 SCIP_Bool maxactinfvarsinvalid; 5863 SCIP_Bool possiblegcd; 5864 SCIP_Bool gcdisone; 5865 SCIP_Bool addartconss; 5866 int ninfcheckvars; 5867 int nunfixedvars; 5868 int nfixedconsvars; 5869 int ncontvars; 5870 int pos; 5871 int v; 5872 5873 assert(scip != NULL); 5874 assert(cons != NULL); 5875 assert(cutoff != NULL); 5876 assert(nfixedvars != NULL); 5877 assert(nchgbds != NULL); 5878 assert(naddconss != NULL); 5879 5880 /* modifiable constraint can be changed so we do not have all necessary information */ 5881 if( SCIPconsIsModifiable(cons) ) 5882 return SCIP_OKAY; 5883 5884 consdata = SCIPconsGetData(cons); 5885 assert(consdata != NULL); 5886 5887 /* we already did full ranged row propagation */ 5888 if( consdata->rangedrowpropagated == 2 ) 5889 return SCIP_OKAY; 5890 5891 /* at least three variables are needed */ 5892 if( consdata->nvars < 3 ) 5893 return SCIP_OKAY; 5894 5895 /* do nothing on normal inequalities */ 5896 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) ) 5897 return SCIP_OKAY; 5898 5899 /* get constraint handler data */ 5900 conshdlr = SCIPconsGetHdlr(cons); 5901 assert(conshdlr != NULL); 5902 conshdlrdata = SCIPconshdlrGetData(conshdlr); 5903 assert(conshdlrdata != NULL); 5904 5905 addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip); 5906 5907 /* we may add artificial constraints */ 5908 if( addartconss ) 5909 consdata->rangedrowpropagated = 2; 5910 /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since 5911 * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without 5912 * artificial constraints 5913 */ 5914 else 5915 { 5916 if( consdata->rangedrowpropagated > 0 ) 5917 return SCIP_OKAY; 5918 5919 consdata->rangedrowpropagated = 1; 5920 } 5921 fixedact = 0; 5922 nfixedconsvars = 0; 5923 /* calculate fixed activity and number of fixed variables */ 5924 for( v = consdata->nvars - 1; v >= 0; --v ) 5925 { 5926 /* all zero coefficients should be eliminated */ 5927 assert(!SCIPisZero(scip, consdata->vals[v])); 5928 5929 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) ) 5930 { 5931 fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v]; 5932 ++nfixedconsvars; 5933 } 5934 } 5935 5936 /* do not work with huge fixed activities */ 5937 if( SCIPisHugeValue(scip, REALABS(fixedact)) ) 5938 return SCIP_OKAY; 5939 5940 /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */ 5941 assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact)); 5942 lhs = consdata->lhs - fixedact; 5943 rhs = consdata->rhs - fixedact; 5944 nunfixedvars = consdata->nvars - nfixedconsvars; 5945 5946 /* allocate temporary memory for variables and coefficients which may lead to infeasibility */ 5947 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) ); 5948 SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) ); 5949 5950 absminbincoef = SCIP_REAL_MAX; 5951 ncontvars = 0; 5952 gcdisone = TRUE; 5953 possiblegcd = TRUE; 5954 5955 /* we now partition all unfixed variables in two groups: 5956 * 5957 * the first one contains all integral variable with integral 5958 * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly 5959 * given 5960 * 5961 * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding 5962 * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object 5963 */ 5964 5965 /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed 5966 * variables 5967 */ 5968 ninfcheckvars = 0; 5969 v = -1; 5970 pos = -1; 5971 do 5972 { 5973 ++v; 5974 5975 /* partition the variables, do not change the order of collection, because it might be used later on */ 5976 while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS || 5977 !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) ) 5978 { 5979 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) ) 5980 { 5981 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ) 5982 { 5983 ++ncontvars; 5984 } 5985 else if( SCIPvarIsBinary(consdata->vars[v]) ) 5986 { 5987 SCIP_Real absval; 5988 5989 absval = REALABS(consdata->vals[v]); 5990 5991 if( absminbincoef > absval ) 5992 absminbincoef = absval; 5993 } 5994 5995 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0); 5996 possiblegcd = FALSE; 5997 infcheckvars[ninfcheckvars] = consdata->vars[v]; 5998 infcheckvals[ninfcheckvars] = consdata->vals[v]; 5999 ++ninfcheckvars; 6000 6001 if( pos == -1 ) 6002 pos = v; 6003 } 6004 ++v; 6005 } 6006 } 6007 while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) ); 6008 6009 /* if the first group of variables is empty, we stop */ 6010 /* @todo try to propagate/split up a constraint of the form: 6011 * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c, 6012 * with k \in Z, c \in (d,d + 1], d \in Z, (a_1*y_1 + ... + a_n*y_n) \in (c-1 + d,d + 1] 6013 */ 6014 if( v == consdata->nvars ) 6015 goto TERMINATE; 6016 6017 /* we need at least two non-continuous variables */ 6018 if( ncontvars + 2 > nunfixedvars ) 6019 goto TERMINATE; 6020 6021 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]))); 6022 assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5); 6023 6024 feastol = SCIPfeastol(scip); 6025 6026 gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol); 6027 assert(gcd >= 2); 6028 6029 /* go on to partition the variables, do not change the order of collection, because it might be used later on; 6030 * calculate gcd over the first part of variables */ 6031 for( ; v < consdata->nvars; ++v ) 6032 { 6033 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) ) 6034 continue; 6035 6036 if( SCIPvarIsBinary(consdata->vars[v]) ) 6037 { 6038 SCIP_Real absval; 6039 6040 absval = REALABS(consdata->vals[v]); 6041 6042 if( absminbincoef > absval ) 6043 absminbincoef = absval; 6044 } 6045 6046 if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS || 6047 SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) ) 6048 { 6049 if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ) 6050 ++ncontvars; 6051 6052 gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0); 6053 possiblegcd = FALSE; 6054 infcheckvars[ninfcheckvars] = consdata->vars[v]; 6055 infcheckvals[ninfcheckvars] = consdata->vals[v]; 6056 6057 ++ninfcheckvars; 6058 6059 if( pos == -1 ) 6060 pos = v; 6061 } 6062 else 6063 { 6064 assert(REALABS(consdata->vals[v]) > 1.5); 6065 6066 gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol)); 6067 assert(gcdtmp >= 1); 6068 6069 if( gcdtmp == 1 ) 6070 { 6071 infcheckvars[ninfcheckvars] = consdata->vars[v]; 6072 infcheckvals[ninfcheckvars] = consdata->vals[v]; 6073 6074 ++ninfcheckvars; 6075 6076 if( pos == -1 ) 6077 pos = v; 6078 } 6079 else 6080 gcd = gcdtmp; 6081 } 6082 } 6083 assert(gcd >= 2); 6084 6085 /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by 6086 * normalizeCons() */ 6087 if( ninfcheckvars == 0 ) 6088 goto TERMINATE; 6089 6090 assert(pos >= 0); 6091 6092 minactinfvarsinvalid = FALSE; 6093 maxactinfvarsinvalid = FALSE; 6094 maxactinfvars = 0.0; 6095 minactinfvars = 0.0; 6096 6097 /* calculate activities over all infcheckvars */ 6098 for( v = ninfcheckvars - 1; v >= 0; --v ) 6099 { 6100 lb = SCIPvarGetLbLocal(infcheckvars[v]); 6101 ub = SCIPvarGetUbLocal(infcheckvars[v]); 6102 6103 if( SCIPisInfinity(scip, -lb) ) 6104 { 6105 if( infcheckvals[v] < 0.0 ) 6106 maxactinfvarsinvalid = TRUE; 6107 else 6108 minactinfvarsinvalid = TRUE; 6109 } 6110 else 6111 { 6112 if( infcheckvals[v] < 0.0 ) 6113 maxactinfvars += infcheckvals[v] * lb; 6114 else 6115 minactinfvars += infcheckvals[v] * lb; 6116 } 6117 6118 if( SCIPisInfinity(scip, ub) ) 6119 { 6120 if( infcheckvals[v] > 0.0 ) 6121 maxactinfvarsinvalid = TRUE; 6122 else 6123 minactinfvarsinvalid = TRUE; 6124 } 6125 else 6126 { 6127 if( infcheckvals[v] > 0.0 ) 6128 maxactinfvars += infcheckvals[v] * ub; 6129 else 6130 minactinfvars += infcheckvals[v] * ub; 6131 } 6132 6133 /* better abort on to big values */ 6134 if( SCIPisHugeValue(scip, -minactinfvars) ) 6135 minactinfvarsinvalid = TRUE; 6136 if( SCIPisHugeValue(scip, maxactinfvars) ) 6137 maxactinfvarsinvalid = TRUE; 6138 6139 if( minactinfvarsinvalid || maxactinfvarsinvalid ) 6140 goto TERMINATE; 6141 } 6142 assert(!minactinfvarsinvalid && !maxactinfvarsinvalid); 6143 6144 SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n", 6145 minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars); 6146 6147 /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */ 6148 /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid 6149 * activities */ 6150 /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding, 6151 * !!!note!!! 6152 * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which 6153 * are not at their global bound 6154 */ 6155 6156 /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to 6157 * infeasibility */ 6158 if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) && 6159 SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) ) 6160 { 6161 SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons)); 6162 SCIPdebugPrintCons(scip, cons, NULL); 6163 6164 /* start conflict analysis */ 6165 /* @todo improve conflict analysis by adding relaxed bounds */ 6166 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) ); 6167 6168 *cutoff = TRUE; 6169 } 6170 else if( ncontvars == 0 ) 6171 { 6172 SCIP_Longint gcdinfvars = -1; 6173 6174 /* check for gcd over all infcheckvars */ 6175 if( possiblegcd ) 6176 { 6177 v = ninfcheckvars - 1; 6178 gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol); 6179 assert(gcdinfvars >= 2); 6180 6181 for( ; v >= 0 && gcdinfvars >= 2; --v ) 6182 { 6183 gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol)); 6184 } 6185 } 6186 else if( gcdisone ) 6187 gcdinfvars = 1; 6188 6189 SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd); 6190 6191 /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */ 6192 if( gcdinfvars >= 1 ) 6193 { 6194 SCIP_Real value; 6195 SCIP_Real value2; 6196 SCIP_Real minvalue = SCIP_INVALID; 6197 SCIP_Real maxvalue = SCIP_INVALID; 6198 int nsols = 0; 6199 6200 value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip)); 6201 6202 /* check how many possible solutions exist */ 6203 while( SCIPisLE(scip, value, maxactinfvars) ) 6204 { 6205 value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd)); 6206 6207 /* value2 might violate lhs due to numerics, in this case take the next divisible number */ 6208 if( !SCIPisGE(scip, value2, lhs) ) 6209 { 6210 value2 += gcd; 6211 } 6212 6213 if( SCIPisLE(scip, value2, rhs) ) 6214 { 6215 ++nsols; 6216 6217 /* early termination if we found more than two solutions */ 6218 if( nsols == 3 ) 6219 break; 6220 6221 if( minvalue == SCIP_INVALID ) /*lint !e777*/ 6222 minvalue = value; 6223 6224 maxvalue = value; 6225 } 6226 value += gcdinfvars; 6227 } 6228 assert(nsols < 2 || minvalue <= maxvalue); 6229 6230 /* determine last possible solution for better bounding */ 6231 if( nsols == 3 ) 6232 { 6233 #ifndef NDEBUG 6234 SCIP_Real secondsolval = maxvalue; 6235 #endif 6236 value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip)); 6237 6238 /* check how many possible solutions exist */ 6239 while( SCIPisGE(scip, value, minactinfvars) ) 6240 { 6241 value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd)); 6242 6243 /* value2 might violate rhs due to numerics, in this case take the next divisible number */ 6244 if( !SCIPisLE(scip, value2, rhs) ) 6245 { 6246 value2 -= gcd; 6247 } 6248 6249 if( SCIPisGE(scip, value2, lhs) ) 6250 { 6251 maxvalue = value; 6252 assert(maxvalue > minvalue); 6253 break; 6254 } 6255 value -= gcdinfvars; 6256 } 6257 assert(maxvalue > secondsolval); 6258 } 6259 6260 SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n", 6261 nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars); 6262 6263 /* no possible solution found */ 6264 if( nsols == 0 ) 6265 { 6266 SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n", 6267 gcdinfvars, gcd, lhs, rhs); 6268 SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons)); 6269 SCIPdebugPrintCons(scip, cons, NULL); 6270 6271 /* start conflict analysis */ 6272 /* @todo improve conflict analysis by adding relaxed bounds */ 6273 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) ); 6274 6275 *cutoff = TRUE; 6276 } 6277 /* if only one solution exist we can extract a new constraint or fix variables */ 6278 else if( nsols == 1 ) 6279 { 6280 assert(minvalue == maxvalue); /*lint !e777*/ 6281 6282 /* we can fix the only variable in our second set of variables */ 6283 if( ninfcheckvars == 1 ) 6284 { 6285 SCIP_Bool fixed; 6286 6287 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0]))); 6288 6289 SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n", 6290 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), 6291 SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]); 6292 6293 /* fix variable to only possible value */ 6294 SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons, 6295 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) ); 6296 6297 if( *cutoff ) 6298 { 6299 /* start conflict analysis */ 6300 /* @todo improve conflict analysis by adding relaxed bounds */ 6301 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) ); 6302 } 6303 6304 if( fixed ) 6305 ++(*nfixedvars); 6306 } 6307 else 6308 { 6309 /* check for exactly one unfixed variable which is not part of the infcheckvars */ 6310 if( ninfcheckvars == nunfixedvars - 1 ) 6311 { 6312 SCIP_Real bound; 6313 SCIP_Bool foundvar = FALSE; 6314 SCIP_Bool fixed; 6315 int w = 0; 6316 6317 assert(ninfcheckvars > 0); 6318 6319 /* find variable which is not an infcheckvar and fix it */ 6320 for( v = 0; v < consdata->nvars - 1; ++v ) 6321 { 6322 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) ) 6323 { 6324 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] ) 6325 { 6326 #ifndef NDEBUG 6327 int v2 = v + 1; 6328 int w2 = w; 6329 6330 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE); 6331 6332 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 ) 6333 { 6334 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) ) 6335 continue; 6336 6337 assert(consdata->vars[v2] == infcheckvars[w2]); 6338 ++w2; 6339 } 6340 assert(w2 == ninfcheckvars); 6341 #endif 6342 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v]))); 6343 6344 foundvar = TRUE; 6345 6346 if( consdata->vals[v] < 0 ) 6347 { 6348 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]); 6349 } 6350 else 6351 { 6352 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]); 6353 } 6354 6355 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n", 6356 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), 6357 SCIPvarGetUbLocal(consdata->vars[v]), bound); 6358 6359 /* fix variable to only possible value */ 6360 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons, 6361 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) ); 6362 6363 if( *cutoff ) 6364 { 6365 /* start conflict analysis */ 6366 /* @todo improve conflict analysis by adding relaxed bounds */ 6367 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, 6368 consdata->vars[v], bound) ); 6369 } 6370 6371 if( fixed ) 6372 ++(*nfixedvars); 6373 6374 break; 6375 } 6376 6377 ++w; 6378 } 6379 } 6380 6381 /* maybe last variable was the not infcheckvar */ 6382 if( !foundvar ) 6383 { 6384 assert(v == consdata->nvars - 1); 6385 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v]))); 6386 6387 if( consdata->vals[v] < 0 ) 6388 { 6389 bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]); 6390 } 6391 else 6392 { 6393 bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]); 6394 } 6395 6396 SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n", 6397 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), 6398 SCIPvarGetUbLocal(consdata->vars[v]), bound); 6399 6400 /* fix variable to only possible value */ 6401 SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons, 6402 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) ); 6403 6404 if( *cutoff ) 6405 { 6406 /* start conflict analysis */ 6407 /* @todo improve conflict analysis by adding relaxed bounds */ 6408 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, 6409 consdata->vars[v], bound) ); 6410 } 6411 6412 if( fixed ) 6413 ++(*nfixedvars); 6414 } 6415 } 6416 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) ) 6417 { 6418 /* aggregation possible if we have two variables, but this will be done later on */ 6419 SCIP_CONS* newcons; 6420 char name[SCIP_MAXSTRLEN]; 6421 6422 /* create, add, and release new artificial constraint */ 6423 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss); 6424 ++conshdlrdata->naddconss; 6425 6426 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name); 6427 6428 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, 6429 maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) ); 6430 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) ); 6431 6432 SCIPdebugPrintCons(scip, newcons, NULL); 6433 6434 SCIP_CALL( SCIPreleaseCons(scip, &newcons) ); 6435 6436 ++(*naddconss); 6437 } 6438 } 6439 } 6440 /* at least two solutions */ 6441 else 6442 { 6443 /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */ 6444 6445 /* only one variable in the second set, so we can bound this variables */ 6446 if( ninfcheckvars == 1 ) 6447 { 6448 SCIP_Bool tightened; 6449 SCIP_Real newlb; 6450 SCIP_Real newub; 6451 6452 assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0]))); 6453 6454 if( infcheckvals[0] < 0 ) 6455 { 6456 newlb = maxvalue/infcheckvals[0]; 6457 newub = minvalue/infcheckvals[0]; 6458 } 6459 else 6460 { 6461 newlb = minvalue/infcheckvals[0]; 6462 newub = maxvalue/infcheckvals[0]; 6463 } 6464 assert(newlb < newub); 6465 6466 if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) ) 6467 { 6468 /* update lower bound of variable */ 6469 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n", 6470 SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb); 6471 6472 /* tighten variable lower bound to minimal possible value */ 6473 SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons, 6474 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) ); 6475 6476 if( *cutoff ) 6477 { 6478 /* start conflict analysis */ 6479 /* @todo improve conflict analysis by adding relaxed bounds */ 6480 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) ); 6481 } 6482 6483 if( tightened ) 6484 ++(*nchgbds); 6485 } 6486 6487 if( newub < SCIPvarGetUbLocal(infcheckvars[0]) ) 6488 { 6489 /* update upper bound of variable */ 6490 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n", 6491 SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub); 6492 6493 /* tighten variable upper bound to maximal possible value */ 6494 SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons, 6495 getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) ); 6496 6497 if( *cutoff ) 6498 { 6499 /* start conflict analysis */ 6500 /* @todo improve conflict analysis by adding relaxed bounds */ 6501 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) ); 6502 } 6503 6504 if( tightened ) 6505 ++(*nchgbds); 6506 } 6507 } 6508 /* check if we have only one not infcheckvars, if so we can tighten this variable */ 6509 else if( ninfcheckvars == nunfixedvars - 1 ) 6510 { 6511 SCIP_Bool foundvar = FALSE; 6512 SCIP_Bool tightened; 6513 SCIP_Real newlb; 6514 SCIP_Real newub; 6515 int w = 0; 6516 6517 assert(ninfcheckvars > 0); 6518 assert(minvalue < maxvalue); 6519 6520 /* find variable which is not an infcheckvar and fix it */ 6521 for( v = 0; v < consdata->nvars - 1; ++v ) 6522 { 6523 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) ) 6524 { 6525 if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] ) 6526 { 6527 #ifndef NDEBUG 6528 int v2 = v + 1; 6529 int w2 = w; 6530 6531 assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE); 6532 6533 for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 ) 6534 { 6535 if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) ) 6536 continue; 6537 6538 assert(consdata->vars[v2] == infcheckvars[w2]); 6539 ++w2; 6540 } 6541 assert(w2 == ninfcheckvars); 6542 #endif 6543 6544 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v]))); 6545 foundvar = TRUE; 6546 6547 if( consdata->vals[v] < 0 ) 6548 { 6549 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]); 6550 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]); 6551 } 6552 else 6553 { 6554 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]); 6555 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]); 6556 } 6557 assert(SCIPisLE(scip, newlb, newub)); 6558 6559 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) ) 6560 { 6561 /* update lower bound of variable */ 6562 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n", 6563 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb); 6564 6565 /* tighten variable lower bound to minimal possible value */ 6566 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons, 6567 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) ); 6568 6569 if( *cutoff ) 6570 { 6571 /* start conflict analysis */ 6572 /* @todo improve conflict analysis by adding relaxed bounds */ 6573 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, 6574 consdata->vars[v], newlb) ); 6575 } 6576 6577 if( tightened ) 6578 ++(*nchgbds); 6579 } 6580 6581 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) ) 6582 { 6583 /* update upper bound of variable */ 6584 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n", 6585 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub); 6586 6587 /* tighten variable upper bound to maximal possible value */ 6588 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons, 6589 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) ); 6590 6591 if( *cutoff ) 6592 { 6593 /* start conflict analysis */ 6594 /* @todo improve conflict analysis by adding relaxed bounds */ 6595 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, 6596 consdata->vars[v], newub) ); 6597 } 6598 6599 if( tightened ) 6600 ++(*nchgbds); 6601 } 6602 6603 break; 6604 } 6605 6606 ++w; 6607 } 6608 } 6609 6610 /* maybe last variable was the not infcheckvar */ 6611 if( !foundvar ) 6612 { 6613 assert(v == consdata->nvars - 1); 6614 assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v]))); 6615 6616 if( consdata->vals[v] < 0 ) 6617 { 6618 newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]); 6619 newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]); 6620 } 6621 else 6622 { 6623 newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]); 6624 newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]); 6625 } 6626 assert(SCIPisLE(scip, newlb, newub)); 6627 6628 if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) ) 6629 { 6630 /* update lower bound of variable */ 6631 SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n", 6632 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb); 6633 6634 /* tighten variable lower bound to minimal possible value */ 6635 SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons, 6636 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) ); 6637 6638 if( *cutoff ) 6639 { 6640 /* start conflict analysis */ 6641 /* @todo improve conflict analysis by adding relaxed bounds */ 6642 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) ); 6643 } 6644 6645 if( tightened ) 6646 ++(*nchgbds); 6647 } 6648 6649 if( newub < SCIPvarGetUbLocal(consdata->vars[v]) ) 6650 { 6651 /* update upper bound of variable */ 6652 SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n", 6653 SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub); 6654 6655 /* tighten variable upper bound to maximal possible value */ 6656 SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons, 6657 getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) ); 6658 6659 if( *cutoff ) 6660 { 6661 /* start conflict analysis */ 6662 /* @todo improve conflict analysis by adding relaxed bounds */ 6663 SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) ); 6664 } 6665 6666 if( tightened ) 6667 ++(*nchgbds); 6668 } 6669 } 6670 } 6671 /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible 6672 * region for our infcheckvars, if possible 6673 */ 6674 else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) ) 6675 { 6676 SCIP_CONS* newcons; 6677 char name[SCIP_MAXSTRLEN]; 6678 SCIP_Real newlhs; 6679 SCIP_Real newrhs; 6680 6681 assert(maxvalue > minvalue); 6682 6683 if( SCIPisGT(scip, minvalue, minactinfvars) ) 6684 newlhs = minvalue; 6685 else 6686 newlhs = -SCIPinfinity(scip); 6687 6688 if( SCIPisLT(scip, maxvalue, maxactinfvars) ) 6689 newrhs = maxvalue; 6690 else 6691 newrhs = SCIPinfinity(scip); 6692 6693 if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) ) 6694 { 6695 /* create, add, and release new artificial constraint */ 6696 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss); 6697 ++conshdlrdata->naddconss; 6698 6699 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name); 6700 6701 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs, 6702 TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) ); 6703 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) ); 6704 6705 SCIPdebugPrintCons(scip, newcons, NULL); 6706 SCIP_CALL( SCIPreleaseCons(scip, &newcons) ); 6707 6708 ++(*naddconss); 6709 } 6710 /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs 6711 * should be maxvalue */ 6712 } 6713 } 6714 } 6715 } 6716 else if( addartconss && ncontvars < ninfcheckvars ) 6717 { 6718 SCIP_Real maxact = 0.0; 6719 SCIP_Real minact = 0.0; 6720 int w = 0; 6721 6722 /* compute activities of non-infcheckvars */ 6723 for( v = 0; v < consdata->nvars; ++v ) 6724 { 6725 if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] ) 6726 { 6727 ++w; 6728 continue; 6729 } 6730 6731 if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) ) 6732 { 6733 if( SCIPvarIsBinary(consdata->vars[v]) ) 6734 { 6735 if( consdata->vals[v] > 0.0 ) 6736 maxact += consdata->vals[v]; 6737 else 6738 minact += consdata->vals[v]; 6739 } 6740 else 6741 { 6742 SCIP_Real tmpval; 6743 6744 assert(SCIPvarIsIntegral(consdata->vars[v])); 6745 6746 if( consdata->vals[v] > 0.0 ) 6747 { 6748 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]); 6749 6750 if( SCIPisHugeValue(scip, -tmpval) ) 6751 break; 6752 6753 minact += tmpval; 6754 6755 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]); 6756 6757 if( SCIPisHugeValue(scip, tmpval) ) 6758 break; 6759 6760 maxact += tmpval; 6761 } 6762 else 6763 { 6764 tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]); 6765 6766 if( SCIPisHugeValue(scip, -tmpval) ) 6767 break; 6768 6769 minact += tmpval; 6770 6771 tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]); 6772 6773 if( SCIPisHugeValue(scip, tmpval) ) 6774 break; 6775 6776 maxact += tmpval; 6777 } 6778 } 6779 } 6780 } 6781 if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) ) 6782 { 6783 SCIP_CONS* newcons; 6784 char name[SCIP_MAXSTRLEN]; 6785 SCIP_Real newlhs; 6786 SCIP_Real newrhs; 6787 6788 assert(maxact > minact); 6789 assert(w == ninfcheckvars); 6790 6791 newlhs = lhs - maxact; 6792 newrhs = rhs - minact; 6793 assert(newlhs < newrhs); 6794 6795 /* create, add, and release new artificial constraint */ 6796 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss); 6797 ++conshdlrdata->naddconss; 6798 6799 SCIPdebugMsg(scip, "adding artificial constraint %s\n", name); 6800 6801 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs, 6802 TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) ); 6803 SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) ); 6804 6805 SCIPdebugPrintCons(scip, newcons, NULL); 6806 SCIP_CALL( SCIPreleaseCons(scip, &newcons) ); 6807 6808 ++(*naddconss); 6809 } 6810 } 6811 6812 TERMINATE: 6813 SCIPfreeBufferArray(scip, &infcheckvals); 6814 SCIPfreeBufferArray(scip, &infcheckvars); 6815 6816 return SCIP_OKAY; 6817 } 6818 6819 /** tightens bounds of a single variable due to activity bounds */ 6820 static 6821 SCIP_RETCODE tightenVarBounds( 6822 SCIP* scip, /**< SCIP data structure */ 6823 SCIP_CONS* cons, /**< linear constraint */ 6824 int pos, /**< position of the variable in the vars array */ 6825 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */ 6826 int* nchgbds, /**< pointer to count the total number of tightened bounds */ 6827 SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */ 6828 ) 6829 { 6830 SCIP_CONSDATA* consdata; 6831 SCIP_VAR* var; 6832 SCIP_Real val; 6833 SCIP_Real lb; 6834 SCIP_Real ub; 6835 SCIP_Real minresactivity; 6836 SCIP_Real maxresactivity; 6837 SCIP_Real lhs; 6838 SCIP_Real rhs; 6839 SCIP_Bool infeasible; 6840 SCIP_Bool tightened; 6841 SCIP_Bool minisrelax; 6842 SCIP_Bool maxisrelax; 6843 SCIP_Bool isminsettoinfinity; 6844 SCIP_Bool ismaxsettoinfinity; 6845 6846 assert(scip != NULL); 6847 assert(cons != NULL); 6848 assert(cutoff != NULL); 6849 assert(nchgbds != NULL); 6850 6851 /* we cannot tighten variables' bounds, if the constraint may be not complete */ 6852 if( SCIPconsIsModifiable(cons) ) 6853 return SCIP_OKAY; 6854 6855 consdata = SCIPconsGetData(cons); 6856 assert(consdata != NULL); 6857 assert(0 <= pos && pos < consdata->nvars); 6858 6859 *cutoff = FALSE; 6860 6861 var = consdata->vars[pos]; 6862 6863 /* we cannot tighten bounds of multi-aggregated variables */ 6864 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR ) 6865 return SCIP_OKAY; 6866 6867 val = consdata->vals[pos]; 6868 lhs = consdata->lhs; 6869 rhs = consdata->rhs; 6870 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity, 6871 &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity); 6872 assert(var != NULL); 6873 assert(!SCIPisZero(scip, val)); 6874 assert(!SCIPisInfinity(scip, lhs)); 6875 assert(!SCIPisInfinity(scip, -rhs)); 6876 6877 lb = SCIPvarGetLbLocal(var); 6878 ub = SCIPvarGetUbLocal(var); 6879 assert(SCIPisLE(scip, lb, ub)); 6880 6881 if( val > 0.0 ) 6882 { 6883 /* check, if we can tighten the variable's bounds */ 6884 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax ) 6885 { 6886 SCIP_Real newub; 6887 6888 newub = (rhs - minresactivity)/val; 6889 6890 if( !SCIPisInfinity(scip, newub) && 6891 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) ) 6892 { 6893 SCIP_Bool activityunreliable; 6894 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity); 6895 6896 /* check minresactivities for reliability */ 6897 if( activityunreliable ) 6898 { 6899 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE); 6900 newub = (rhs - minresactivity)/val; 6901 activityunreliable = SCIPisInfinity(scip, -minresactivity) || 6902 (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var)) 6903 && (!force || !SCIPisLT(scip, newub, ub))); 6904 } 6905 6906 if( !activityunreliable ) 6907 { 6908 /* tighten upper bound */ 6909 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n", 6910 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub); 6911 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force, 6912 &infeasible, &tightened) ); 6913 if( infeasible ) 6914 { 6915 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 6916 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub); 6917 6918 /* analyze conflict */ 6919 SCIP_CALL( analyzeConflict(scip, cons, TRUE) ); 6920 6921 *cutoff = TRUE; 6922 return SCIP_OKAY; 6923 } 6924 if( tightened ) 6925 { 6926 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */ 6927 assert(SCIPisFeasLE(scip, ub, newub)); 6928 (*nchgbds)++; 6929 6930 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n", 6931 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub); 6932 } 6933 } 6934 } 6935 } 6936 6937 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax ) 6938 { 6939 SCIP_Real newlb; 6940 6941 newlb = (lhs - maxresactivity)/val; 6942 if( !SCIPisInfinity(scip, -newlb) && 6943 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) ) 6944 { 6945 /* check maxresactivities for reliability */ 6946 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) ) 6947 { 6948 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE); 6949 newlb = (lhs - maxresactivity)/val; 6950 6951 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub) 6952 && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var)) 6953 && (!force || !SCIPisGT(scip, newlb, lb))) ) 6954 return SCIP_OKAY; 6955 } 6956 6957 /* tighten lower bound */ 6958 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n", 6959 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb); 6960 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force, 6961 &infeasible, &tightened) ); 6962 if( infeasible ) 6963 { 6964 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 6965 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub); 6966 6967 /* analyze conflict */ 6968 SCIP_CALL( analyzeConflict(scip, cons, FALSE) ); 6969 6970 *cutoff = TRUE; 6971 return SCIP_OKAY; 6972 } 6973 if( tightened ) 6974 { 6975 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */ 6976 assert(SCIPisFeasGE(scip, lb, newlb)); 6977 (*nchgbds)++; 6978 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n", 6979 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub); 6980 } 6981 } 6982 } 6983 } 6984 else 6985 { 6986 /* check, if we can tighten the variable's bounds */ 6987 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax ) 6988 { 6989 SCIP_Real newlb; 6990 6991 newlb = (rhs - minresactivity)/val; 6992 if( !SCIPisInfinity(scip, -newlb) && 6993 ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) ) 6994 { 6995 SCIP_Bool activityunreliable; 6996 activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity); 6997 /* check minresactivities for reliability */ 6998 if( activityunreliable ) 6999 { 7000 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE); 7001 newlb = (rhs - minresactivity)/val; 7002 7003 activityunreliable = SCIPisInfinity(scip, -minresactivity) 7004 || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var)) 7005 && (!force || !SCIPisGT(scip, newlb, lb))); 7006 } 7007 7008 if( !activityunreliable ) 7009 { 7010 /* tighten lower bound */ 7011 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n", 7012 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb); 7013 SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force, 7014 &infeasible, &tightened) ); 7015 if( infeasible ) 7016 { 7017 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 7018 SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub); 7019 7020 /* analyze conflict */ 7021 SCIP_CALL( analyzeConflict(scip, cons, TRUE) ); 7022 7023 *cutoff = TRUE; 7024 return SCIP_OKAY; 7025 } 7026 if( tightened ) 7027 { 7028 lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */ 7029 assert(SCIPisFeasGE(scip, lb, newlb)); 7030 (*nchgbds)++; 7031 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n", 7032 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub); 7033 } 7034 } 7035 } 7036 } 7037 7038 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax ) 7039 { 7040 SCIP_Real newub; 7041 7042 newub = (lhs - maxresactivity)/val; 7043 if( !SCIPisInfinity(scip, newub) && 7044 ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) ) 7045 { 7046 /* check maxresactivities for reliability */ 7047 if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) ) 7048 { 7049 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE); 7050 newub = (lhs - maxresactivity)/val; 7051 7052 if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub) 7053 && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var)) 7054 && (!force || !SCIPisLT(scip, newub, ub))) ) 7055 return SCIP_OKAY; 7056 } 7057 7058 /* tighten upper bound */ 7059 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n", 7060 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub); 7061 SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force, 7062 &infeasible, &tightened) ); 7063 if( infeasible ) 7064 { 7065 SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n", 7066 SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub); 7067 7068 /* analyze conflict */ 7069 SCIP_CALL( analyzeConflict(scip, cons, FALSE) ); 7070 7071 *cutoff = TRUE; 7072 return SCIP_OKAY; 7073 } 7074 if( tightened ) 7075 { 7076 ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */ 7077 assert(SCIPisFeasLE(scip, ub, newub)); 7078 (*nchgbds)++; 7079 SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n", 7080 SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub); 7081 } 7082 } 7083 } 7084 } 7085 7086 return SCIP_OKAY; 7087 } 7088 7089 #define MAXTIGHTENROUNDS 10 7090 7091 /** tightens bounds of variables in constraint due to activity bounds */ 7092 static 7093 SCIP_RETCODE tightenBounds( 7094 SCIP* scip, /**< SCIP data structure */ 7095 SCIP_CONS* cons, /**< linear constraint */ 7096 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */ 7097 SCIP_Bool sortvars, /**< should variables be used in sorted order? */ 7098 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */ 7099 int* nchgbds /**< pointer to count the total number of tightened bounds */ 7100 ) 7101 { 7102 SCIP_CONSDATA* consdata; 7103 unsigned int tightenmode; 7104 int nvars; 7105 int nrounds; 7106 int lastchange; 7107 int oldnchgbds; 7108 #ifndef SCIP_DEBUG 7109 int oldnchgbdstotal; 7110 #endif 7111 int v; 7112 SCIP_Bool force; 7113 SCIP_Bool easycase; 7114 7115 assert(scip != NULL); 7116 assert(cons != NULL); 7117 assert(nchgbds != NULL); 7118 assert(cutoff != NULL); 7119 7120 *cutoff = FALSE; 7121 7122 /* we cannot tighten variables' bounds, if the constraint may be not complete */ 7123 if( SCIPconsIsModifiable(cons) ) 7124 return SCIP_OKAY; 7125 7126 /* if a constraint was created after presolve, then it may hold fixed variables 7127 * if there are even multi-aggregated variables, then we cannot do bound tightening on these 7128 * thus, ensure here again that variable fixings have been applied 7129 */ 7130 SCIP_CALL( applyFixings(scip, cons, cutoff) ); 7131 if( *cutoff ) 7132 return SCIP_OKAY; 7133 7134 /* check if constraint has any chances of tightening bounds */ 7135 if( !canTightenBounds(cons) ) 7136 return SCIP_OKAY; 7137 7138 consdata = SCIPconsGetData(cons); 7139 assert(consdata != NULL); 7140 7141 nvars = consdata->nvars; 7142 force = (nvars == 1) && !SCIPconsIsModifiable(cons); 7143 7144 /* we are at the root node or during presolving */ 7145 if( SCIPgetDepth(scip) < 1 ) 7146 tightenmode = 2; 7147 else 7148 tightenmode = 1; 7149 7150 /* stop if we already tightened the constraint and the tightening is not forced */ 7151 if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/ 7152 return SCIP_OKAY; 7153 7154 /* ensure that the variables are properly sorted */ 7155 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted ) 7156 { 7157 SCIP_CALL( consdataSort(scip, consdata) ); 7158 assert(consdata->coefsorted); 7159 } 7160 7161 /* update maximal activity delta if necessary */ 7162 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/ 7163 consdataRecomputeMaxActivityDelta(scip, consdata); 7164 7165 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/ 7166 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta)); 7167 checkMaxActivityDelta(scip, consdata); 7168 7169 /* this may happen if all variables are fixed */ 7170 if( SCIPisFeasZero(scip, consdata->maxactdelta) ) 7171 return SCIP_OKAY; 7172 7173 if( !SCIPisInfinity(scip, consdata->maxactdelta) ) 7174 { 7175 SCIP_Real slack; 7176 SCIP_Real surplus; 7177 SCIP_Real minactivity; 7178 SCIP_Real maxactivity; 7179 SCIP_Bool minisrelax; 7180 SCIP_Bool maxisrelax; 7181 SCIP_Bool isminsettoinfinity; 7182 SCIP_Bool ismaxsettoinfinity; 7183 7184 /* use maximal activity delta to skip propagation (cannot deduce anything) */ 7185 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax, 7186 &isminsettoinfinity, &ismaxsettoinfinity); 7187 assert(!SCIPisInfinity(scip, minactivity)); 7188 assert(!SCIPisInfinity(scip, -maxactivity)); 7189 7190 slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity); 7191 surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs); 7192 7193 /* check if the constraint will propagate */ 7194 if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) ) 7195 return SCIP_OKAY; 7196 } 7197 7198 /* check if we can use fast implementation for easy and numerically well behaved cases */ 7199 easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta); 7200 7201 /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */ 7202 lastchange = -1; 7203 oldnchgbds = 0; 7204 7205 #ifndef SCIP_DEBUG 7206 oldnchgbdstotal = *nchgbds; 7207 #endif 7208 7209 for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/ 7210 { 7211 /* ensure that the variables are properly sorted 7212 * 7213 * note: it might happen that integer variables become binary during bound tightening at the root node 7214 */ 7215 if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted ) 7216 { 7217 SCIP_CALL( consdataSort(scip, consdata) ); 7218 assert(consdata->coefsorted); 7219 } 7220 7221 /* mark the constraint to have the variables' bounds tightened */ 7222 consdata->boundstightened = (unsigned int)tightenmode; 7223 7224 /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable 7225 * sorting enables skipping variables 7226 */ 7227 v = 0; 7228 while( v < nvars && v != lastchange && !(*cutoff) ) 7229 { 7230 oldnchgbds = *nchgbds; 7231 7232 if( easycase ) 7233 { 7234 SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) ); 7235 } 7236 else 7237 { 7238 SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) ); 7239 } 7240 7241 /* if there was no progress, skip the rest of the binary variables */ 7242 if( *nchgbds > oldnchgbds ) 7243 { 7244 lastchange = v; 7245 ++v; 7246 } 7247 else if( consdata->coefsorted && v < consdata->nbinvars - 1 7248 && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) ) 7249 v = consdata->nbinvars; 7250 else 7251 ++v; 7252 } 7253 7254 #ifndef SCIP_DEBUG 7255 SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons), 7256 *nchgbds - oldnchgbdstotal, nrounds); 7257 oldnchgbdstotal += oldnchgbds; 7258 #endif 7259 } 7260 7261 #ifndef NDEBUG 7262 if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) ) 7263 assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0]))); 7264 #endif 7265 7266 return SCIP_OKAY; 7267 } 7268 7269 /** checks linear constraint for feasibility of given solution or current solution */ 7270 static 7271 SCIP_RETCODE checkCons( 7272 SCIP* scip, /**< SCIP data structure */ 7273 SCIP_CONS* cons, /**< linear constraint */ 7274 SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */ 7275 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */ 7276 SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative 7277 * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */ 7278 SCIP_Bool* violated /**< pointer to store whether the constraint is violated */ 7279 ) 7280 { 7281 SCIP_CONSDATA* consdata; 7282 SCIP_Real activity; 7283 SCIP_Real absviol; 7284 SCIP_Real relviol; 7285 SCIP_Real lhsviol; 7286 SCIP_Real rhsviol; 7287 7288 assert(scip != NULL); 7289 assert(cons != NULL); 7290 assert(violated != NULL); 7291 7292 SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons)); 7293 SCIPdebugPrintCons(scip, cons, NULL); 7294 7295 consdata = SCIPconsGetData(cons); 7296 assert(consdata != NULL); 7297 7298 *violated = FALSE; 7299 7300 if( consdata->row != NULL ) 7301 { 7302 if( !checklprows && SCIProwIsInLP(consdata->row) ) 7303 return SCIP_OKAY; 7304 else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) ) 7305 activity = consdataComputePseudoActivity(scip, consdata); 7306 else 7307 activity = SCIPgetRowSolActivity(scip, consdata->row, sol); 7308 } 7309 else 7310 activity = consdataGetActivity(scip, consdata, sol); 7311 7312 SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n", 7313 activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows, 7314 consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol, 7315 consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip)); 7316 7317 /* calculate absolute and relative bound violations */ 7318 lhsviol = consdata->lhs - activity; 7319 rhsviol = activity - consdata->rhs; 7320 7321 absviol = 0.0; 7322 relviol = 0.0; 7323 if( (lhsviol > 0) && (lhsviol > rhsviol) ) 7324 { 7325 absviol = lhsviol; 7326 relviol = SCIPrelDiff(consdata->lhs, activity); 7327 } 7328 else if( rhsviol > 0 ) 7329 { 7330 absviol = rhsviol; 7331 relviol = SCIPrelDiff(activity, consdata->rhs); 7332 } 7333 7334 /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we 7335 * return infeasible for safety 7336 */ 7337 if( activity == SCIP_INVALID ) /*lint !e777*/ 7338 { 7339 assert(sol == NULL); 7340 *violated = TRUE; 7341 7342 /* set violation of invalid pseudo solutions */ 7343 absviol = SCIP_INVALID; 7344 relviol = SCIP_INVALID; 7345 7346 /* reset constraint age since we are in enforcement */ 7347 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7348 } 7349 /* check with relative tolerances (the default) */ 7350 else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) ) 7351 { 7352 /* the "normal" check: one of the two sides is violated */ 7353 if( !checkrelmaxabs ) 7354 { 7355 *violated = TRUE; 7356 7357 /* only reset constraint age if we are in enforcement */ 7358 if( sol == NULL ) 7359 { 7360 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7361 } 7362 } 7363 /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are 7364 * small compared to the absolute values occurring in the activity 7365 */ 7366 else 7367 { 7368 SCIP_Real maxabs; 7369 SCIP_Real coef; 7370 SCIP_Real absval; 7371 SCIP_Real solval; 7372 int v; 7373 7374 maxabs = 1.0; 7375 7376 /* compute maximum absolute value */ 7377 for( v = 0; v < consdata->nvars; ++v ) 7378 { 7379 if( consdata->vals != NULL ) 7380 { 7381 coef = consdata->vals[v]; 7382 } 7383 else 7384 coef = 1.0; 7385 7386 solval = SCIPgetSolVal(scip, sol, consdata->vars[v]); 7387 absval = REALABS( coef * solval ); 7388 maxabs = MAX( maxabs, absval ); 7389 } 7390 7391 /* regard left hand side, first */ 7392 if( SCIPisFeasLT(scip, activity, consdata->lhs) ) 7393 { 7394 /* check whether violation is random noise */ 7395 if( (consdata->lhs - activity) <= (1e-15 * maxabs) ) 7396 { 7397 SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n", 7398 consdata->lhs - activity, maxabs); 7399 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) ); 7400 7401 /* only increase constraint age if we are in enforcement */ 7402 if( sol == NULL ) 7403 { 7404 SCIP_CALL( SCIPincConsAge(scip, cons) ); 7405 } 7406 } 7407 /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */ 7408 else if( SCIPisZero(scip, consdata->lhs) ) 7409 { 7410 if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) ) 7411 { 7412 SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n", 7413 consdata->lhs - activity, maxabs); 7414 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) ); 7415 7416 /* only increase constraint age if we are in enforcement */ 7417 if( sol == NULL ) 7418 { 7419 SCIP_CALL( SCIPincConsAge(scip, cons) ); 7420 } 7421 } 7422 else 7423 { 7424 *violated = TRUE; 7425 7426 /* only reset constraint age if we are in enforcement */ 7427 if( sol == NULL ) 7428 { 7429 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7430 } 7431 } 7432 } 7433 else 7434 { 7435 *violated = TRUE; 7436 7437 /* only reset constraint age if we are in enforcement */ 7438 if( sol == NULL ) 7439 { 7440 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7441 } 7442 } 7443 } 7444 7445 /* now regard right hand side */ 7446 if( SCIPisFeasGT(scip, activity, consdata->rhs) ) 7447 { 7448 /* check whether violation is random noise */ 7449 if( (activity - consdata->rhs) <= (1e-15 * maxabs) ) 7450 { 7451 SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n", 7452 activity - consdata->rhs, maxabs); 7453 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) ); 7454 7455 /* only increase constraint age if we are in enforcement */ 7456 if( sol == NULL ) 7457 { 7458 SCIP_CALL( SCIPincConsAge(scip, cons) ); 7459 } 7460 } 7461 /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */ 7462 else if( SCIPisZero(scip, consdata->rhs) ) 7463 { 7464 if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) ) 7465 { 7466 SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n", 7467 activity - consdata->rhs, maxabs); 7468 SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) ); 7469 7470 /* only increase constraint age if we are in enforcement */ 7471 if( sol == NULL ) 7472 { 7473 SCIP_CALL( SCIPincConsAge(scip, cons) ); 7474 } 7475 } 7476 else 7477 { 7478 *violated = TRUE; 7479 7480 /* only reset constraint age if we are in enforcement */ 7481 if( sol == NULL ) 7482 { 7483 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7484 } 7485 } 7486 } 7487 else 7488 { 7489 *violated = TRUE; 7490 7491 /* only reset constraint age if we are in enforcement */ 7492 if( sol == NULL ) 7493 { 7494 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7495 } 7496 } 7497 } 7498 } 7499 } 7500 /* check with absolute tolerances */ 7501 else if( consdata->checkabsolute && 7502 ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) || 7503 (!SCIPisInfinity(scip, consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) ) 7504 { 7505 *violated = TRUE; 7506 7507 /* only reset constraint age if we are in enforcement */ 7508 if( sol == NULL ) 7509 { 7510 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7511 } 7512 } 7513 else 7514 { 7515 /* only increase constraint age if we are in enforcement */ 7516 if( sol == NULL ) 7517 { 7518 SCIP_CALL( SCIPincConsAge(scip, cons) ); 7519 } 7520 } 7521 7522 /* update absolute and relative violation of the solution */ 7523 if( sol != NULL ) 7524 SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol); 7525 7526 return SCIP_OKAY; 7527 } 7528 7529 /** creates an LP row in a linear constraint data */ 7530 static 7531 SCIP_RETCODE createRow( 7532 SCIP* scip, /**< SCIP data structure */ 7533 SCIP_CONS* cons /**< linear constraint */ 7534 ) 7535 { 7536 SCIP_CONSDATA* consdata; 7537 7538 assert(scip != NULL); 7539 assert(cons != NULL); 7540 7541 consdata = SCIPconsGetData(cons); 7542 assert(consdata != NULL); 7543 assert(consdata->row == NULL); 7544 7545 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs, 7546 SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsRemovable(cons)) ); 7547 7548 SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) ); 7549 7550 return SCIP_OKAY; 7551 } 7552 7553 /** adds linear constraint as cut to the LP */ 7554 static 7555 SCIP_RETCODE addRelaxation( 7556 SCIP* scip, /**< SCIP data structure */ 7557 SCIP_CONS* cons, /**< linear constraint */ 7558 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */ 7559 ) 7560 { 7561 SCIP_CONSDATA* consdata; 7562 7563 assert(scip != NULL); 7564 assert(cons != NULL); 7565 7566 consdata = SCIPconsGetData(cons); 7567 assert(consdata != NULL); 7568 7569 if( consdata->row == NULL ) 7570 { 7571 if( !SCIPconsIsModifiable(cons) ) 7572 { 7573 /* replace all fixed variables by active counterparts, as we have no chance to do this anymore after the row has been added to the LP 7574 * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03) 7575 */ 7576 SCIP_CALL( applyFixings(scip, cons, cutoff) ); 7577 if( *cutoff ) 7578 return SCIP_OKAY; 7579 } 7580 7581 /* convert consdata object into LP row */ 7582 SCIP_CALL( createRow(scip, cons) ); 7583 } 7584 assert(consdata->row != NULL); 7585 7586 if( consdata->nvars == 0 ) 7587 { 7588 SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons)); 7589 } 7590 7591 /* insert LP row as cut */ 7592 if( !SCIProwIsInLP(consdata->row) ) 7593 { 7594 SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons)); 7595 SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) ); 7596 /* if presolving is turned off, the row might be trivial */ 7597 if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) ) 7598 { 7599 SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) ); 7600 } 7601 #ifndef NDEBUG 7602 else 7603 { 7604 int pr; 7605 int cr; 7606 SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) ); 7607 SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) ); 7608 assert( pr == 0 || cr == 0 ); 7609 } 7610 #endif 7611 } 7612 7613 return SCIP_OKAY; 7614 } 7615 7616 /** adds linear constraint as row to the NLP, if not added yet */ 7617 static 7618 SCIP_RETCODE addNlrow( 7619 SCIP* scip, /**< SCIP data structure */ 7620 SCIP_CONS* cons /**< linear constraint */ 7621 ) 7622 { 7623 SCIP_CONSDATA* consdata; 7624 7625 assert(SCIPisNLPConstructed(scip)); 7626 7627 /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */ 7628 if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) ) 7629 return SCIP_OKAY; 7630 7631 consdata = SCIPconsGetData(cons); 7632 assert(consdata != NULL); 7633 7634 if( consdata->nlrow == NULL ) 7635 { 7636 assert(consdata->lhs <= consdata->rhs); 7637 7638 SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons), 7639 0.0, consdata->nvars, consdata->vars, consdata->vals, NULL, consdata->lhs, consdata->rhs, SCIP_EXPRCURV_LINEAR) ); 7640 7641 assert(consdata->nlrow != NULL); 7642 } 7643 7644 if( !SCIPnlrowIsInNLP(consdata->nlrow) ) 7645 { 7646 SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) ); 7647 } 7648 7649 return SCIP_OKAY; 7650 } 7651 7652 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */ 7653 static 7654 SCIP_RETCODE separateCons( 7655 SCIP* scip, /**< SCIP data structure */ 7656 SCIP_CONS* cons, /**< linear constraint */ 7657 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */ 7658 SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */ 7659 SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */ 7660 SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only 7661 * the ones with non-zero dual value? */ 7662 int* ncuts, /**< pointer to add up the number of found cuts */ 7663 SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */ 7664 ) 7665 { 7666 SCIP_CONSDATA* consdata; 7667 SCIP_Bool violated; 7668 int oldncuts; 7669 7670 assert(scip != NULL); 7671 assert(conshdlrdata != NULL); 7672 assert(cons != NULL); 7673 assert(cutoff != NULL); 7674 7675 consdata = SCIPconsGetData(cons); 7676 assert(ncuts != NULL); 7677 assert(consdata != NULL); 7678 7679 oldncuts = *ncuts; 7680 *cutoff = FALSE; 7681 7682 SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) ); 7683 7684 if( violated ) 7685 { 7686 /* insert LP row as cut */ 7687 SCIP_CALL( addRelaxation(scip, cons, cutoff) ); 7688 (*ncuts)++; 7689 } 7690 else if( !SCIPconsIsModifiable(cons) && separatecards ) 7691 { 7692 /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */ 7693 if( !separateall && sol == NULL ) 7694 { 7695 /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */ 7696 if( consdata->row != NULL && SCIProwIsInLP(consdata->row) ) 7697 { 7698 SCIP_Real dualsol; 7699 7700 dualsol = SCIProwGetDualsol(consdata->row); 7701 if( SCIPisFeasNegative(scip, dualsol) ) 7702 { 7703 if( !SCIPisInfinity(scip, consdata->rhs) ) 7704 { 7705 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars, 7706 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) ); 7707 } 7708 } 7709 else if( SCIPisFeasPositive(scip, dualsol) ) 7710 { 7711 if( !SCIPisInfinity(scip, -consdata->lhs) ) 7712 { 7713 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars, 7714 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) ); 7715 } 7716 } 7717 } 7718 } 7719 else 7720 { 7721 if( !SCIPisInfinity(scip, consdata->rhs) ) 7722 { 7723 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars, 7724 consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) ); 7725 } 7726 if( !SCIPisInfinity(scip, -consdata->lhs) ) 7727 { 7728 SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars, 7729 consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) ); 7730 } 7731 } 7732 } 7733 7734 if( *ncuts > oldncuts ) 7735 { 7736 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7737 } 7738 7739 return SCIP_OKAY; 7740 } 7741 7742 /** propagation method for linear constraints */ 7743 static 7744 SCIP_RETCODE propagateCons( 7745 SCIP* scip, /**< SCIP data structure */ 7746 SCIP_CONS* cons, /**< linear constraint */ 7747 SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */ 7748 SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */ 7749 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */ 7750 SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */ 7751 SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */ 7752 int* nchgbds /**< pointer to count the total number of tightened bounds */ 7753 ) 7754 { 7755 SCIP_CONSDATA* consdata; 7756 SCIP_Real minactivity; 7757 SCIP_Real maxactivity; 7758 SCIP_Bool minactisrelax; 7759 SCIP_Bool maxactisrelax; 7760 SCIP_Bool isminsettoinfinity; 7761 SCIP_Bool ismaxsettoinfinity; 7762 7763 assert(scip != NULL); 7764 assert(cons != NULL); 7765 assert(cutoff != NULL); 7766 assert(nchgbds != NULL); 7767 7768 /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/ 7769 7770 consdata = SCIPconsGetData(cons); 7771 assert(consdata != NULL); 7772 7773 if( consdata->eventdata == NULL ) 7774 { 7775 SCIP_CONSHDLR* conshdlr; 7776 SCIP_CONSHDLRDATA* conshdlrdata; 7777 7778 conshdlr = SCIPconsGetHdlr(cons); 7779 assert(conshdlr != NULL); 7780 7781 conshdlrdata = SCIPconshdlrGetData(conshdlr); 7782 assert(conshdlrdata != NULL); 7783 7784 /* catch bound change events of variables */ 7785 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) ); 7786 assert(consdata->eventdata != NULL); 7787 } 7788 7789 *cutoff = FALSE; 7790 7791 /* we can only infer activity bounds of the linear constraint, if it is not modifiable */ 7792 if( !SCIPconsIsModifiable(cons) ) 7793 { 7794 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */ 7795 if( !SCIPinRepropagation(scip) ) 7796 { 7797 SCIP_CALL( SCIPincConsAge(scip, cons) ); 7798 } 7799 7800 /* tighten the variable's bounds */ 7801 if( tightenbounds ) 7802 { 7803 int oldnchgbds; 7804 7805 oldnchgbds = *nchgbds; 7806 7807 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) ); 7808 7809 if( *nchgbds > oldnchgbds ) 7810 { 7811 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7812 } 7813 } 7814 7815 /* propagate ranged rows */ 7816 if( rangedrowpropagation && tightenbounds && !(*cutoff) ) 7817 { 7818 int nfixedvars; 7819 int naddconss; 7820 SCIPdebug( int oldnchgbds = *nchgbds; ) 7821 7822 nfixedvars = 0; 7823 naddconss = 0; 7824 7825 SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) ); 7826 7827 if( *cutoff ) 7828 { 7829 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons)); 7830 } 7831 else 7832 { 7833 SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); ) 7834 } 7835 7836 if( nfixedvars > 0 ) 7837 *nchgbds += 2*nfixedvars; 7838 } /*lint !e438*/ 7839 7840 /* check constraint for infeasibility and redundancy */ 7841 if( !(*cutoff) ) 7842 { 7843 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 7844 &isminsettoinfinity, &ismaxsettoinfinity); 7845 7846 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) ) 7847 { 7848 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n", 7849 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs); 7850 7851 /* analyze conflict */ 7852 SCIP_CALL( analyzeConflict(scip, cons, TRUE) ); 7853 7854 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7855 *cutoff = TRUE; 7856 } 7857 else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) ) 7858 { 7859 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n", 7860 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs); 7861 7862 /* analyze conflict */ 7863 SCIP_CALL( analyzeConflict(scip, cons, FALSE) ); 7864 7865 SCIP_CALL( SCIPresetConsAge(scip, cons) ); 7866 *cutoff = TRUE; 7867 } 7868 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) ) 7869 { 7870 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n", 7871 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs); 7872 7873 /* remove the constraint locally unless it has become empty, in which case it is removed globally */ 7874 if( consdata->nvars > 0 ) 7875 SCIP_CALL( SCIPdelConsLocal(scip, cons) ); 7876 else 7877 SCIP_CALL( SCIPdelCons(scip, cons) ); 7878 } 7879 } 7880 } 7881 7882 return SCIP_OKAY; 7883 } 7884 7885 7886 /* 7887 * Presolving methods 7888 */ 7889 7890 /** converts all variables with fixed domain into FIXED variables */ 7891 static 7892 SCIP_RETCODE fixVariables( 7893 SCIP* scip, /**< SCIP data structure */ 7894 SCIP_CONS* cons, /**< linear constraint */ 7895 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 7896 int* nfixedvars /**< pointer to count the total number of fixed variables */ 7897 ) 7898 { 7899 SCIP_CONSDATA* consdata; 7900 SCIP_VAR* var; 7901 SCIP_VARSTATUS varstatus; 7902 SCIP_Real lb; 7903 SCIP_Real ub; 7904 SCIP_Bool fixed; 7905 SCIP_Bool infeasible; 7906 int v; 7907 7908 assert(scip != NULL); 7909 assert(cons != NULL); 7910 assert(cutoff != NULL); 7911 assert(nfixedvars != NULL); 7912 7913 consdata = SCIPconsGetData(cons); 7914 assert(consdata != NULL); 7915 7916 for( v = 0; v < consdata->nvars; ++v ) 7917 { 7918 assert(consdata->vars != NULL); 7919 var = consdata->vars[v]; 7920 varstatus = SCIPvarGetStatus(var); 7921 7922 if( varstatus != SCIP_VARSTATUS_FIXED ) 7923 { 7924 lb = SCIPvarGetLbGlobal(var); 7925 ub = SCIPvarGetUbGlobal(var); 7926 if( SCIPisEQ(scip, lb, ub) ) 7927 { 7928 SCIP_Real fixval; 7929 7930 fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM); 7931 SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n", 7932 SCIPvarGetName(var), lb, ub, fixval); 7933 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) ); 7934 if( infeasible ) 7935 { 7936 SCIPdebugMsg(scip, " -> infeasible fixing\n"); 7937 *cutoff = TRUE; 7938 return SCIP_OKAY; 7939 } 7940 if( fixed ) 7941 (*nfixedvars)++; 7942 } 7943 } 7944 } 7945 7946 SCIP_CALL( applyFixings(scip, cons, &infeasible) ); 7947 7948 if( infeasible ) 7949 { 7950 SCIPdebugMsg(scip, " -> infeasible fixing\n"); 7951 *cutoff = TRUE; 7952 return SCIP_OKAY; 7953 } 7954 7955 assert(consdata->removedfixings); 7956 7957 return SCIP_OKAY; 7958 } 7959 7960 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000 7961 7962 /** extracts cliques of the constraint and adds them to SCIP 7963 * 7964 * The following clique extraction mechanism are implemeneted 7965 * 7966 * 1. collect binary variables and sort them in non increasing order, then 7967 * 7968 * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero 7969 * then add the variables as a clique for which all successive pairs of coefficients fullfill the following 7970 * condition 7971 * 7972 * minactivity + vals[i] + vals[i+1] > rhs 7973 * 7974 * and also add the binary to binary implication also for non-successive variables for which the same argument 7975 * holds 7976 * 7977 * minactivity + vals[i] + vals[j] > rhs 7978 * 7979 * e.g. 5.3 x1 + 3.6 x2 + 3.3 x3 + 2.1 x4 <= 5.5 (all x are binary) would lead to the clique (x1, x2, x3) and the 7980 * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0 7981 * 7982 * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero 7983 * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing 7984 * condition 7985 * 7986 * maxactivity + vals[i] + vals[i-1] < lhs 7987 * 7988 * and also add the binary to binary implication also for non-successive variables for which the same argument 7989 * holds 7990 * 7991 * maxactivity + vals[i] + vals[j] < lhs 7992 * 7993 * e.g. you could multiply the above example by -1 7994 * 7995 * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated 7996 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following 7997 * condition 7998 * 7999 * minactivity - vals[i] - vals[i-1] > rhs 8000 * 8001 * and also add the binary to binary implication also for non-successive variables for which the 8002 * same argument holds 8003 * 8004 * minactivity - vals[i] - vals[j] > rhs 8005 * 8006 * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary 8007 * implication x1 = 0 => x3 = 1 8008 * 8009 * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated 8010 * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following 8011 * condition 8012 * 8013 * maxactivity - vals[i] - vals[i+1] < lhs 8014 * 8015 * and also add the binary to binary implication also for non-successive variables for which the same argument 8016 * holds 8017 * 8018 * maxactivity - vals[i] - vals[j] < lhs 8019 * 8020 * e.g. you could multiply the above example by -1 8021 * 8022 * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added 8023 * as clique, (this part is done at the end of the method) 8024 * 8025 */ 8026 static 8027 SCIP_RETCODE extractCliques( 8028 SCIP* scip, /**< SCIP data structure */ 8029 SCIP_CONS* cons, /**< linear constraint */ 8030 SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */ 8031 SCIP_Bool sortvars, /**< should variables be used in sorted order? */ 8032 int* nfixedvars, /**< pointer to count number of fixed variables */ 8033 int* nchgbds, /**< pointer to count the total number of tightened bounds */ 8034 SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */ 8035 ) 8036 { 8037 SCIP_VAR** vars; 8038 SCIP_Real* vals; 8039 SCIP_CONSDATA* consdata; 8040 SCIP_Bool lhsclique; 8041 SCIP_Bool rhsclique; 8042 SCIP_Bool finitelhs; 8043 SCIP_Bool finiterhs; 8044 SCIP_Bool finiteminact; 8045 SCIP_Bool finitemaxact; 8046 SCIP_Bool finitenegminact; 8047 SCIP_Bool finitenegmaxact; 8048 SCIP_Bool finiteposminact; 8049 SCIP_Bool finiteposmaxact; 8050 SCIP_Bool infeasible; 8051 SCIP_Bool stopped; 8052 int cliquenonzerosadded; 8053 int v; 8054 int i; 8055 int nposcoefs; 8056 int nnegcoefs; 8057 int nvars; 8058 8059 assert(scip != NULL); 8060 assert(cons != NULL); 8061 assert(nfixedvars != NULL); 8062 assert(nchgbds != NULL); 8063 assert(cutoff != NULL); 8064 assert(!SCIPconsIsDeleted(cons)); 8065 8066 consdata = SCIPconsGetData(cons); 8067 assert(consdata != NULL); 8068 8069 if( consdata->nvars < 2 ) 8070 return SCIP_OKAY; 8071 8072 /* add implications if possible 8073 * 8074 * for now we only add binary to non-binary implications, and this is only done for the binary variable with the 8075 * maximal absolute contribution and also only if this variable would force all other variables to their bound 8076 * corresponding to the global minimal activity of the constraint 8077 */ 8078 if( !consdata->implsadded ) 8079 { 8080 /* sort variables by variable type */ 8081 SCIP_CALL( consdataSort(scip, consdata) ); 8082 8083 /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables 8084 * up front, might change sorting correspondingly 8085 */ 8086 /* fast abort if no binaries seem to exist 8087 * "seem to", because there are rare situations in which variables may actually not be sorted by type, even though consdataSort has been called 8088 * this situation can occur if, e.g., the type of consdata->vars[1] has been changed to binary, but the corresponding variable event has 8089 * not been executed yet, because it is the eventExecLinear() which marks the variables array as unsorted (set consdata->indexsorted to FALSE), 8090 * which is the requirement for consdataSort() to actually resort the variables 8091 * we assume that in this situation the below code may be executed in a future presolve round, after the variable events have been executed 8092 */ 8093 if( !SCIPvarIsBinary(consdata->vars[0]) ) 8094 return SCIP_OKAY; 8095 8096 nvars = consdata->nvars; 8097 vars = consdata->vars; 8098 vals = consdata->vals; 8099 8100 /* recompute activities if needed */ 8101 if( !consdata->validactivities ) 8102 consdataCalcActivities(scip, consdata); 8103 assert(consdata->validactivities); 8104 8105 finitelhs = !SCIPisInfinity(scip, -consdata->lhs); 8106 finiterhs = !SCIPisInfinity(scip, consdata->rhs); 8107 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0); 8108 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0); 8109 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0); 8110 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0); 8111 finiteminact = (finitenegminact && finiteposminact); 8112 finitemaxact = (finitenegmaxact && finiteposmaxact); 8113 8114 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) ) 8115 { 8116 SCIP_Real maxabscontrib = -1.0; 8117 SCIP_Bool posval = FALSE; 8118 SCIP_Bool allbinary = TRUE; 8119 int oldnchgbds = *nchgbds; 8120 int nbdchgs = 0; 8121 int nimpls = 0; 8122 int position = -1; 8123 8124 /* we need a valid minimal/maximal activity to add cliques */ 8125 if( (finitenegminact || finiteposminact) && !consdata->validglbminact ) 8126 { 8127 consdataRecomputeGlbMinactivity(scip, consdata); 8128 assert(consdata->validglbminact); 8129 } 8130 8131 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact ) 8132 { 8133 consdataRecomputeGlbMaxactivity(scip, consdata); 8134 assert(consdata->validglbmaxact); 8135 } 8136 assert(consdata->validglbminact || consdata->validglbmaxact); 8137 8138 /* @todo extend this to local/constraint probing */ 8139 8140 /* determine maximal contribution to the activity */ 8141 for( v = nvars - 1; v >= 0; --v ) 8142 { 8143 if( SCIPvarIsBinary(vars[v]) ) 8144 { 8145 if( vals[v] > 0 ) 8146 { 8147 SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]); 8148 8149 if( value > maxabscontrib ) 8150 { 8151 maxabscontrib = value; 8152 position = v; 8153 posval = TRUE; 8154 } 8155 } 8156 else 8157 { 8158 SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]); 8159 8160 value = REALABS(value); 8161 8162 if( value > maxabscontrib ) 8163 { 8164 maxabscontrib = value; 8165 position = v; 8166 posval = FALSE; 8167 } 8168 } 8169 } 8170 else 8171 allbinary = FALSE; 8172 } 8173 assert(0 <= position && position < nvars); 8174 8175 if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary ) 8176 { 8177 /* if the right hand side and the minimal activity are finite and changing the variable with the biggest 8178 * influence to their bound forces all other variables to be at their minimal contribution, we can add these 8179 * implications 8180 */ 8181 if( finiterhs && finiteminact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbminactivity), consdata->rhs - maxabscontrib) ) 8182 { 8183 for( v = nvars - 1; v >= 0; --v ) 8184 { 8185 /* binary to binary implications will be collected when extrating cliques */ 8186 if( !SCIPvarIsBinary(vars[v]) ) 8187 { 8188 if( v != position ) 8189 { 8190 if( vals[v] > 0 ) 8191 { 8192 /* add implications */ 8193 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) ); 8194 ++nimpls; 8195 *nchgbds += nbdchgs; 8196 } 8197 else 8198 { 8199 /* add implications */ 8200 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) ); 8201 ++nimpls; 8202 *nchgbds += nbdchgs; 8203 } 8204 8205 if( infeasible ) 8206 { 8207 *cutoff = TRUE; 8208 break; 8209 } 8210 } 8211 } 8212 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */ 8213 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY ) 8214 break; 8215 } 8216 } 8217 8218 /* if the left hand side and the maximal activity are finite and changing the variable with the biggest 8219 * influence to their bound forces all other variables to be at their minimal contribution, we can add these 8220 * implications 8221 */ 8222 if( finitelhs && finitemaxact && SCIPisEQ(scip, QUAD_TO_DBL(consdata->glbmaxactivity), consdata->lhs - maxabscontrib) ) 8223 { 8224 for( v = nvars - 1; v >= 0; --v ) 8225 { 8226 /* binary to binary implications will be collected when extrating cliques */ 8227 if( !SCIPvarIsBinary(vars[v]) ) 8228 { 8229 if( v != position ) 8230 { 8231 if( vals[v] > 0 ) 8232 { 8233 /* add implications */ 8234 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) ); 8235 ++nimpls; 8236 *nchgbds += nbdchgs; 8237 } 8238 else 8239 { 8240 /* add implications */ 8241 SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) ); 8242 ++nimpls; 8243 *nchgbds += nbdchgs; 8244 } 8245 8246 if( infeasible ) 8247 { 8248 *cutoff = TRUE; 8249 break; 8250 } 8251 } 8252 } 8253 /* stop when reaching a 'real' binary variable because the variables are sorted after their type */ 8254 else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY ) 8255 break; 8256 } 8257 } 8258 8259 /* did we find some implications */ 8260 if( nimpls > 0 ) 8261 { 8262 SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no "); 8263 8264 if( *cutoff ) 8265 return SCIP_OKAY; 8266 8267 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */ 8268 if( *nchgbds - oldnchgbds > 0 ) 8269 { 8270 /* check for fixed variables */ 8271 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8272 if( *cutoff ) 8273 return SCIP_OKAY; 8274 8275 /* tighten variable's bounds */ 8276 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) ); 8277 if( *cutoff ) 8278 return SCIP_OKAY; 8279 8280 /* check for fixed variables */ 8281 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8282 if( *cutoff ) 8283 return SCIP_OKAY; 8284 } 8285 } 8286 } 8287 } 8288 8289 consdata->implsadded = TRUE; 8290 } 8291 8292 /* check if we already added the cliques of this constraint */ 8293 if( consdata->cliquesadded ) 8294 return SCIP_OKAY; 8295 8296 consdata->cliquesadded = TRUE; 8297 cliquenonzerosadded = 0; 8298 stopped = FALSE; 8299 8300 /* sort variables by variable type */ 8301 SCIP_CALL( consdataSort(scip, consdata) ); 8302 8303 nvars = consdata->nvars; 8304 vars = consdata->vars; 8305 vals = consdata->vals; 8306 8307 /**@todo extract more cliques, implications and variable bounds from linear constraints */ 8308 8309 /* recompute activities if needed */ 8310 if( !consdata->validactivities ) 8311 consdataCalcActivities(scip, consdata); 8312 assert(consdata->validactivities); 8313 8314 finitelhs = !SCIPisInfinity(scip, -consdata->lhs); 8315 finiterhs = !SCIPisInfinity(scip, consdata->rhs); 8316 finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0); 8317 finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0); 8318 finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0); 8319 finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0); 8320 finiteminact = (finitenegminact && finiteposminact); 8321 finitemaxact = (finitenegmaxact && finiteposmaxact); 8322 8323 /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique 8324 * information 8325 */ 8326 if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) ) 8327 { 8328 SCIP_VAR** binvars; 8329 SCIP_Real* binvarvals; 8330 int nposbinvars = 0; 8331 int nnegbinvars = 0; 8332 int allonebinary = 0; 8333 8334 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) ); 8335 SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) ); 8336 8337 /* collect binary variables */ 8338 for( i = 0; i < nvars; ++i ) 8339 { 8340 if( SCIPvarIsBinary(vars[i]) ) 8341 { 8342 assert(!SCIPisZero(scip, vals[i])); 8343 8344 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) ) 8345 ++allonebinary; 8346 8347 binvars[nposbinvars + nnegbinvars] = vars[i]; 8348 binvarvals[nposbinvars + nnegbinvars] = vals[i]; 8349 8350 if( SCIPisPositive(scip, vals[i]) ) 8351 ++nposbinvars; 8352 else 8353 ++nnegbinvars; 8354 8355 assert(nposbinvars + nnegbinvars <= nvars); 8356 } 8357 /* stop searching for binary variables, because the constraint data is sorted */ 8358 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS ) 8359 break; 8360 } 8361 assert(nposbinvars + nnegbinvars <= nvars); 8362 8363 /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract 8364 * cliques 8365 */ 8366 if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) ) 8367 { 8368 SCIP_Real threshold; 8369 int oldnchgbds = *nchgbds; 8370 int nbdchgs; 8371 int jstart; 8372 int j; 8373 8374 /* we need a valid minimal/maximal activity to add cliques */ 8375 if( (finitenegminact || finiteposminact) && !consdata->validglbminact ) 8376 { 8377 consdataRecomputeGlbMinactivity(scip, consdata); 8378 assert(consdata->validglbminact); 8379 } 8380 8381 if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact ) 8382 { 8383 consdataRecomputeGlbMaxactivity(scip, consdata); 8384 assert(consdata->validglbmaxact); 8385 } 8386 assert(consdata->validglbminact || consdata->validglbmaxact); 8387 8388 /* sort coefficients non-increasing to be faster in the clique search */ 8389 SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars); 8390 8391 /* case a) */ 8392 if( finiterhs && finitenegminact && nposbinvars >= 2 ) 8393 { 8394 /* compute value that needs to be exceeded */ 8395 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity); 8396 8397 j = 1; 8398 #ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */ 8399 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */ 8400 assert(SCIPisFeasLE(scip, binvarvals[0], threshold)); 8401 #endif 8402 /* check if at least two variables are in a clique */ 8403 if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) ) 8404 { 8405 ++j; 8406 /* check for extending the clique */ 8407 while( j < nposbinvars ) 8408 { 8409 if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) ) 8410 break; 8411 ++j; 8412 } 8413 assert(j >= 2); 8414 8415 /* add clique with at least two variables */ 8416 SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) ); 8417 8418 if( infeasible ) 8419 *cutoff = TRUE; 8420 8421 *nchgbds += nbdchgs; 8422 8423 cliquenonzerosadded += j; 8424 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8425 stopped = TRUE; 8426 8427 /* exchange the last variable in the clique if possible and add all new ones */ 8428 if( !stopped && !(*cutoff) && j < nposbinvars ) 8429 { 8430 SCIP_VAR** clqvars; 8431 int lastfit = j - 2; 8432 assert(lastfit >= 0); 8433 8434 /* copy all 'main'-clique variables */ 8435 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) ); 8436 8437 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */ 8438 while( lastfit >= 0 && j < nposbinvars ) 8439 { 8440 /* check if two variables are in a clique */ 8441 if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) ) 8442 { 8443 clqvars[lastfit + 1] = binvars[j]; 8444 8445 /* add clique with at least two variables */ 8446 SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) ); 8447 8448 if( infeasible ) 8449 { 8450 *cutoff = TRUE; 8451 break; 8452 } 8453 8454 *nchgbds += nbdchgs; 8455 8456 cliquenonzerosadded += (lastfit + 2); 8457 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8458 { 8459 stopped = TRUE; 8460 break; 8461 } 8462 8463 ++j; 8464 } 8465 else 8466 --lastfit; 8467 } 8468 8469 SCIPfreeBufferArray(scip, &clqvars); 8470 } 8471 } 8472 } 8473 8474 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */ 8475 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 ) 8476 { 8477 /* check for fixed variables */ 8478 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8479 8480 if( !*cutoff ) 8481 { 8482 /* tighten variable's bounds */ 8483 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) ); 8484 8485 if( !*cutoff ) 8486 { 8487 /* check for fixed variables */ 8488 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8489 8490 if( !*cutoff ) 8491 { 8492 /* sort variables by variable type */ 8493 SCIP_CALL( consdataSort(scip, consdata) ); 8494 8495 /* recompute activities if needed */ 8496 if( !consdata->validactivities ) 8497 consdataCalcActivities(scip, consdata); 8498 assert(consdata->validactivities); 8499 8500 nvars = consdata->nvars; 8501 vars = consdata->vars; 8502 vals = consdata->vals; 8503 nposbinvars = 0; 8504 nnegbinvars = 0; 8505 allonebinary = 0; 8506 8507 /* update binary variables */ 8508 for( i = 0; i < nvars; ++i ) 8509 { 8510 if( SCIPvarIsBinary(vars[i]) ) 8511 { 8512 assert(!SCIPisZero(scip, vals[i])); 8513 8514 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) ) 8515 ++allonebinary; 8516 8517 binvars[nposbinvars + nnegbinvars] = vars[i]; 8518 binvarvals[nposbinvars + nnegbinvars] = vals[i]; 8519 8520 if( SCIPisPositive(scip, vals[i]) ) 8521 ++nposbinvars; 8522 else 8523 ++nnegbinvars; 8524 8525 assert(nposbinvars + nnegbinvars <= nvars); 8526 } 8527 /* stop searching for binary variables, because the constraint data is sorted */ 8528 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS ) 8529 break; 8530 } 8531 assert(nposbinvars + nnegbinvars <= nvars); 8532 } 8533 } 8534 } 8535 8536 oldnchgbds = *nchgbds; 8537 } 8538 8539 /* case b) */ 8540 if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 ) 8541 { 8542 /* compute value that needs to be deceeded */ 8543 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity); 8544 8545 i = nposbinvars + nnegbinvars - 1; 8546 j = i - 1; 8547 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */ 8548 /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */ 8549 assert(SCIPisFeasGE(scip, binvarvals[i], threshold)); 8550 #endif 8551 /* check if two variables are in a clique */ 8552 if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) ) 8553 { 8554 --j; 8555 /* check for extending the clique */ 8556 while( j >= nposbinvars ) 8557 { 8558 if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) ) 8559 break; 8560 --j; 8561 } 8562 jstart = j; 8563 8564 assert(i - j >= 2); 8565 /* add clique with at least two variables */ 8566 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) ); 8567 8568 if( infeasible ) 8569 *cutoff = TRUE; 8570 8571 *nchgbds += nbdchgs; 8572 8573 cliquenonzerosadded += (i - j); 8574 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8575 stopped = TRUE; 8576 8577 /* exchange the last variable in the clique if possible and add all new ones */ 8578 if( !stopped && !(*cutoff) && jstart >= nposbinvars ) 8579 { 8580 SCIP_VAR** clqvars; 8581 int lastfit = jstart + 1; 8582 assert(lastfit < i); 8583 8584 /* copy all 'main'-clique variables */ 8585 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) ); 8586 ++lastfit; 8587 8588 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */ 8589 while( lastfit <= i && j >= nposbinvars ) 8590 { 8591 /* check if two variables are in a clique */ 8592 if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) ) 8593 { 8594 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i); 8595 clqvars[lastfit - jstart - 2] = binvars[j]; 8596 8597 assert(i - lastfit + 2 >= 2); 8598 /* add clique with at least two variables */ 8599 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) ); 8600 8601 if( infeasible ) 8602 { 8603 *cutoff = TRUE; 8604 break; 8605 } 8606 8607 *nchgbds += nbdchgs; 8608 8609 cliquenonzerosadded += (i - lastfit + 2); 8610 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8611 { 8612 stopped = TRUE; 8613 break; 8614 } 8615 8616 --j; 8617 } 8618 else 8619 ++lastfit; 8620 } 8621 8622 SCIPfreeBufferArray(scip, &clqvars); 8623 } 8624 } 8625 } 8626 8627 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */ 8628 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 ) 8629 { 8630 /* check for fixed variables */ 8631 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8632 8633 if( !*cutoff ) 8634 { 8635 /* tighten variable's bounds */ 8636 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) ); 8637 8638 if( !*cutoff ) 8639 { 8640 /* check for fixed variables */ 8641 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8642 8643 if( !*cutoff ) 8644 { 8645 /* sort variables by variable type */ 8646 SCIP_CALL( consdataSort(scip, consdata) ); 8647 8648 /* recompute activities if needed */ 8649 if( !consdata->validactivities ) 8650 consdataCalcActivities(scip, consdata); 8651 assert(consdata->validactivities); 8652 8653 nvars = consdata->nvars; 8654 vars = consdata->vars; 8655 vals = consdata->vals; 8656 nposbinvars = 0; 8657 nnegbinvars = 0; 8658 allonebinary = 0; 8659 8660 /* update binary variables */ 8661 for( i = 0; i < nvars; ++i ) 8662 { 8663 if( SCIPvarIsBinary(vars[i]) ) 8664 { 8665 assert(!SCIPisZero(scip, vals[i])); 8666 8667 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) ) 8668 ++allonebinary; 8669 8670 binvars[nposbinvars + nnegbinvars] = vars[i]; 8671 binvarvals[nposbinvars + nnegbinvars] = vals[i]; 8672 8673 if( SCIPisPositive(scip, vals[i]) ) 8674 ++nposbinvars; 8675 else 8676 ++nnegbinvars; 8677 8678 assert(nposbinvars + nnegbinvars <= nvars); 8679 } 8680 /* stop searching for binary variables, because the constraint data is sorted */ 8681 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS ) 8682 break; 8683 } 8684 assert(nposbinvars + nnegbinvars <= nvars); 8685 } 8686 } 8687 } 8688 8689 oldnchgbds = *nchgbds; 8690 } 8691 8692 /* case c) */ 8693 if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 ) 8694 { 8695 SCIP_Bool* values; 8696 8697 /* initialize clique values array for adding a negated clique */ 8698 SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) ); 8699 BMSclearMemoryArray(values, nnegbinvars); 8700 8701 /* compute value that needs to be exceeded */ 8702 threshold = consdata->rhs - QUAD_TO_DBL(consdata->glbminactivity); 8703 8704 i = nposbinvars + nnegbinvars - 1; 8705 j = i - 1; 8706 8707 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */ 8708 /* check if the variable should not have already been fixed to one */ 8709 assert(!SCIPisFeasGT(scip, binvarvals[i], threshold)); 8710 #endif 8711 8712 if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) ) 8713 { 8714 --j; 8715 /* check for extending the clique */ 8716 while( j >= nposbinvars ) 8717 { 8718 if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) ) 8719 break; 8720 --j; 8721 } 8722 jstart = j; 8723 8724 assert(i - j >= 2); 8725 /* add negated clique with at least two variables */ 8726 SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) ); 8727 8728 if( infeasible ) 8729 *cutoff = TRUE; 8730 8731 *nchgbds += nbdchgs; 8732 8733 cliquenonzerosadded += (i - j); 8734 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8735 stopped = TRUE; 8736 8737 /* exchange the last variable in the clique if possible and add all new ones */ 8738 if( !stopped && !(*cutoff) && jstart >= nposbinvars ) 8739 { 8740 SCIP_VAR** clqvars; 8741 int lastfit = j + 1; 8742 assert(lastfit < i); 8743 8744 /* copy all 'main'-clique variables */ 8745 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) ); 8746 ++lastfit; 8747 8748 /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */ 8749 while( lastfit <= i && j >= nposbinvars ) 8750 { 8751 /* check if two variables are in a negated clique */ 8752 if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) ) 8753 { 8754 assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i); 8755 clqvars[lastfit - jstart - 2] = binvars[j]; 8756 8757 assert(i - lastfit + 2 >= 2); 8758 /* add clique with at least two variables */ 8759 SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) ); 8760 8761 if( infeasible ) 8762 { 8763 *cutoff = TRUE; 8764 break; 8765 } 8766 8767 *nchgbds += nbdchgs; 8768 8769 cliquenonzerosadded += (i - lastfit + 2); 8770 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8771 { 8772 stopped = TRUE; 8773 break; 8774 } 8775 8776 --j; 8777 } 8778 else 8779 ++lastfit; 8780 } 8781 8782 SCIPfreeBufferArray(scip, &clqvars); 8783 } 8784 } 8785 8786 SCIPfreeBufferArray(scip, &values); 8787 } 8788 8789 /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */ 8790 if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 ) 8791 { 8792 /* check for fixed variables */ 8793 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8794 8795 if( !*cutoff ) 8796 { 8797 /* tighten variable's bounds */ 8798 SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) ); 8799 8800 if( !*cutoff ) 8801 { 8802 /* check for fixed variables */ 8803 SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) ); 8804 8805 if( !*cutoff ) 8806 { 8807 /* sort variables by variable type */ 8808 SCIP_CALL( consdataSort(scip, consdata) ); 8809 8810 /* recompute activities if needed */ 8811 if( !consdata->validactivities ) 8812 consdataCalcActivities(scip, consdata); 8813 assert(consdata->validactivities); 8814 8815 nvars = consdata->nvars; 8816 vars = consdata->vars; 8817 vals = consdata->vals; 8818 nposbinvars = 0; 8819 nnegbinvars = 0; 8820 allonebinary = 0; 8821 8822 /* update binary variables */ 8823 for( i = 0; i < nvars; ++i ) 8824 { 8825 if( SCIPvarIsBinary(vars[i]) ) 8826 { 8827 assert(!SCIPisZero(scip, vals[i])); 8828 8829 if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) ) 8830 ++allonebinary; 8831 8832 binvars[nposbinvars + nnegbinvars] = vars[i]; 8833 binvarvals[nposbinvars + nnegbinvars] = vals[i]; 8834 8835 if( SCIPisPositive(scip, vals[i]) ) 8836 ++nposbinvars; 8837 else 8838 ++nnegbinvars; 8839 8840 assert(nposbinvars + nnegbinvars <= nvars); 8841 } 8842 /* stop searching for binary variables, because the constraint data is sorted */ 8843 else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS ) 8844 break; 8845 } 8846 assert(nposbinvars + nnegbinvars <= nvars); 8847 } 8848 } 8849 } 8850 } 8851 8852 /* case d) */ 8853 if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 ) 8854 { 8855 SCIP_Bool* values; 8856 8857 /* initialize clique values array for adding a negated clique */ 8858 SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) ); 8859 BMSclearMemoryArray(values, nposbinvars); 8860 8861 /* compute value that needs to be exceeded */ 8862 threshold = consdata->lhs - QUAD_TO_DBL(consdata->glbmaxactivity); 8863 8864 j = 1; 8865 8866 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */ 8867 /* check if the variable should not have already been fixed to one */ 8868 assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold)); 8869 #endif 8870 8871 if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) ) 8872 { 8873 ++j; 8874 /* check for extending the clique */ 8875 while( j < nposbinvars ) 8876 { 8877 if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) ) 8878 break; 8879 ++j; 8880 } 8881 assert(j >= 2); 8882 8883 /* add negated clique with at least two variables */ 8884 SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) ); 8885 8886 if( infeasible ) 8887 *cutoff = TRUE; 8888 8889 *nchgbds += nbdchgs; 8890 8891 cliquenonzerosadded += j; 8892 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8893 stopped = TRUE; 8894 8895 /* exchange the last variable in the clique if possible and add all new ones */ 8896 if( !stopped && !(*cutoff) && j < nposbinvars ) 8897 { 8898 SCIP_VAR** clqvars; 8899 int lastfit = j - 2; 8900 assert(lastfit >= 0); 8901 8902 /* copy all 'main'-clique variables */ 8903 SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) ); 8904 8905 /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */ 8906 while( lastfit >= 0 && j < nposbinvars ) 8907 { 8908 /* check if two variables are in a negated clique */ 8909 if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) ) 8910 { 8911 clqvars[lastfit + 1] = binvars[j]; 8912 8913 /* add clique with at least two variables */ 8914 SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) ); 8915 8916 if( infeasible ) 8917 { 8918 *cutoff = TRUE; 8919 break; 8920 } 8921 8922 *nchgbds += nbdchgs; 8923 8924 cliquenonzerosadded += lastfit + 2; 8925 if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS ) 8926 break; 8927 8928 ++j; 8929 } 8930 else 8931 --lastfit; 8932 } 8933 8934 SCIPfreeBufferArray(scip, &clqvars); 8935 } 8936 } 8937 8938 SCIPfreeBufferArray(scip, &values); 8939 } 8940 } 8941 8942 SCIPfreeBufferArray(scip, &binvarvals); 8943 SCIPfreeBufferArray(scip, &binvars); 8944 8945 if( *cutoff ) 8946 return SCIP_OKAY; 8947 } 8948 8949 /* 2. we only check if the constraint is a set packing / partitioning constraint */ 8950 8951 /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal 8952 * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1 8953 */ 8954 nposcoefs = 0; 8955 nnegcoefs = 0; 8956 for( i = 0; i < nvars; ++i ) 8957 { 8958 if( !SCIPvarIsBinary(vars[i]) ) 8959 return SCIP_OKAY; 8960 else if( SCIPisEQ(scip, vals[i], +1.0) ) 8961 nposcoefs++; 8962 else if( SCIPisEQ(scip, vals[i], -1.0) ) 8963 nnegcoefs++; 8964 else 8965 return SCIP_OKAY; 8966 } 8967 8968 lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0); 8969 rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs); 8970 8971 if( lhsclique || rhsclique ) 8972 { 8973 SCIP_Bool* values; 8974 int nbdchgs; 8975 8976 SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n", 8977 SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs); 8978 SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) ); 8979 8980 for( i = 0; i < nvars; ++i ) 8981 values[i] = (rhsclique == (vals[i] > 0.0)); 8982 8983 SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) ); 8984 8985 if( infeasible ) 8986 *cutoff = TRUE; 8987 8988 *nchgbds += nbdchgs; 8989 SCIPfreeBufferArray(scip, &values); 8990 } 8991 8992 return SCIP_OKAY; 8993 } 8994 8995 /** tightens left and right hand side of constraint due to integrality */ 8996 static 8997 SCIP_RETCODE tightenSides( 8998 SCIP* scip, /**< SCIP data structure */ 8999 SCIP_CONS* cons, /**< linear constraint */ 9000 int* nchgsides, /**< pointer to count number of side changes */ 9001 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */ 9002 ) 9003 { 9004 SCIP_CONSDATA* consdata; 9005 SCIP_Real newlhs; 9006 SCIP_Real newrhs; 9007 SCIP_Bool chglhs; 9008 SCIP_Bool chgrhs; 9009 SCIP_Bool integral; 9010 int i; 9011 9012 assert(scip != NULL); 9013 assert(cons != NULL); 9014 assert(nchgsides != NULL); 9015 assert(infeasible != NULL); 9016 9017 consdata = SCIPconsGetData(cons); 9018 assert(consdata != NULL); 9019 9020 *infeasible = FALSE; 9021 9022 chglhs = FALSE; 9023 chgrhs = FALSE; 9024 newlhs = -SCIPinfinity(scip); 9025 newrhs = SCIPinfinity(scip); 9026 9027 if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) ) 9028 { 9029 integral = TRUE; 9030 for( i = 0; i < consdata->nvars && integral; ++i ) 9031 { 9032 integral = SCIPisIntegral(scip, consdata->vals[i]) 9033 && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS); 9034 } 9035 if( integral ) 9036 { 9037 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) ) 9038 { 9039 newlhs = SCIPfeasCeil(scip, consdata->lhs); 9040 chglhs = TRUE; 9041 } 9042 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) ) 9043 { 9044 newrhs = SCIPfeasFloor(scip, consdata->rhs); 9045 chgrhs = TRUE; 9046 } 9047 9048 /* check whether rounding would lead to an unsatisfiable constraint */ 9049 if( SCIPisGT(scip, newlhs, newrhs) ) 9050 { 9051 SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only " 9052 "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons)); 9053 9054 *infeasible = TRUE; 9055 return SCIP_OKAY; 9056 } 9057 9058 SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n", 9059 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 9060 9061 if( chglhs ) 9062 { 9063 assert(!SCIPisInfinity(scip, -newlhs)); 9064 9065 SCIP_CALL( chgLhs(scip, cons, newlhs) ); 9066 if( !consdata->upgraded ) 9067 (*nchgsides)++; 9068 } 9069 if( chgrhs ) 9070 { 9071 assert(!SCIPisInfinity(scip, newrhs)); 9072 9073 SCIP_CALL( chgRhs(scip, cons, newrhs) ); 9074 if( !consdata->upgraded ) 9075 (*nchgsides)++; 9076 } 9077 SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n", 9078 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 9079 } 9080 } 9081 9082 return SCIP_OKAY; 9083 } 9084 9085 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving: 9086 * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui 9087 * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi} 9088 * (i) ai >= 0: 9089 * if minact + ai >= lhs and maxact - ai <= rhs: (**) 9090 * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant 9091 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for 9092 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation 9093 * - change coefficients: 9094 * ai' := max(lhs - minact, maxact - rhs) 9095 * lhs' := lhs - (ai - ai')*li 9096 * rhs' := rhs - (ai - ai')*ui 9097 * (ii) ai < 0: 9098 * if minact - ai >= lhs and maxact + ai <= rhs: (***) 9099 * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant 9100 * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for 9101 * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation 9102 * - change coefficients: 9103 * ai' := min(rhs - maxact, minact - lhs) 9104 * lhs' := lhs - (ai - ai')*ui 9105 * rhs' := rhs - (ai - ai')*li 9106 * 9107 * We further try to remove redundant variable from the constraint; 9108 * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables. 9109 * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other 9110 * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make 9111 * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint. 9112 * E.g., for binary variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one 9113 * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed. 9114 * 9115 * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see 9116 * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights() 9117 */ 9118 static 9119 SCIP_RETCODE consdataTightenCoefs( 9120 SCIP* scip, /**< SCIP data structure */ 9121 SCIP_CONS* cons, /**< linear constraint */ 9122 int* nchgcoefs, /**< pointer to count total number of changed coefficients */ 9123 int* nchgsides /**< pointer to count number of side changes */ 9124 ) 9125 { 9126 SCIP_CONSDATA* consdata; 9127 SCIP_VAR* var; 9128 SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's 9129 * activity, ignoring the coefficients contributing with infinite value */ 9130 SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's 9131 * activity, ignoring the coefficients contributing with infinite value */ 9132 SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */ 9133 SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */ 9134 SCIP_Bool isminsettoinfinity; 9135 SCIP_Bool ismaxsettoinfinity; 9136 SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */ 9137 SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */ 9138 SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */ 9139 SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */ 9140 SCIP_Real lval; /* candidate for new value arising from considering the left hand side */ 9141 SCIP_Real rval; /* candidate for new value arising from considering the left hand side */ 9142 SCIP_Real val; 9143 SCIP_Real newval; 9144 SCIP_Real newlhs; 9145 SCIP_Real newrhs; 9146 SCIP_Real lb; 9147 SCIP_Real ub; 9148 int i; 9149 9150 assert(scip != NULL); 9151 assert(cons != NULL); 9152 assert(nchgcoefs != NULL); 9153 assert(nchgsides != NULL); 9154 9155 consdata = SCIPconsGetData(cons); 9156 assert(consdata != NULL); 9157 9158 /* @todo Is this still needed with automatic recomputation of activities? */ 9159 /* if the maximal coefficient is too large, recompute the activities */ 9160 if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP) 9161 || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) ) 9162 { 9163 consdataRecomputeMinactivity(scip, consdata); 9164 consdataRecomputeMaxactivity(scip, consdata); 9165 } 9166 9167 /* get the minimal and maximal activity of the constraint */ 9168 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 9169 &isminsettoinfinity, &ismaxsettoinfinity); 9170 9171 minleftactivity = 0.0; 9172 maxleftactivity = 0.0; 9173 9174 /* try to tighten each coefficient */ 9175 i = 0; 9176 while( i < consdata->nvars ) 9177 { 9178 var = consdata->vars[i]; 9179 9180 /* get coefficient and variable's bounds */ 9181 lb = SCIPvarGetLbLocal(var); 9182 ub = SCIPvarGetUbLocal(var); 9183 val = consdata->vals[i]; 9184 assert(!SCIPisZero(scip, val)); 9185 9186 /* check sign of coefficient */ 9187 if( val >= 0.0 ) 9188 { 9189 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */ 9190 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && 9191 SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) ) 9192 { 9193 /* change coefficients: 9194 * ai' := max(lhs - minact, maxact - rhs) 9195 * lhs' := lhs - (ai - ai')*li 9196 * rhs' := rhs - (ai - ai')*ui 9197 */ 9198 9199 lval = consdata->lhs - minactivity; 9200 rval = maxactivity - consdata->rhs; 9201 9202 /* Try to avoid cancellation, if there are only two variables */ 9203 if( consdata->nvars == 2 ) 9204 { 9205 SCIP_Real otherval; 9206 otherval = consdata->vals[1-i]; 9207 9208 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity ) 9209 { 9210 lval = consdata->lhs - val*lb; 9211 lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]); 9212 } 9213 9214 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity ) 9215 { 9216 rval = val*ub - consdata->rhs; 9217 rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]); 9218 } 9219 } 9220 9221 newval = MAX(lval, rval); 9222 assert(SCIPisSumRelLE(scip, newval, val)); 9223 9224 /* Try to avoid cancellation in computation of lhs/rhs */ 9225 newlhs = consdata->lhs - val * lb; 9226 newlhs += newval * lb; 9227 newrhs = consdata->rhs - val * ub; 9228 newrhs += newval * ub; 9229 9230 if( !SCIPisSumRelEQ(scip, newval, val) ) 9231 { 9232 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n", 9233 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), 9234 minactivity, maxactivity, consdata->lhs, consdata->rhs); 9235 9236 /* update the coefficient and the activity bounds */ 9237 if( SCIPisZero(scip, newval) ) 9238 { 9239 SCIP_CALL( delCoefPos(scip, cons, i) ); 9240 i--; 9241 } 9242 else 9243 { 9244 SCIP_CALL( chgCoefPos(scip, cons, i, newval) ); 9245 } 9246 (*nchgcoefs)++; 9247 9248 /* get the new minimal and maximal activity of the constraint */ 9249 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 9250 &isminsettoinfinity, &ismaxsettoinfinity); 9251 9252 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) ) 9253 { 9254 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs); 9255 9256 SCIP_CALL( chgLhs(scip, cons, newlhs) ); 9257 (*nchgsides)++; 9258 assert(SCIPisEQ(scip, consdata->lhs, newlhs)); 9259 } 9260 9261 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) ) 9262 { 9263 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs); 9264 9265 SCIP_CALL( chgRhs(scip, cons, newrhs) ); 9266 (*nchgsides)++; 9267 assert(SCIPisEQ(scip, consdata->rhs, newrhs)); 9268 } 9269 } 9270 } 9271 else 9272 { 9273 if( !SCIPisInfinity(scip, -minleftactivity) ) 9274 { 9275 assert(!SCIPisInfinity(scip, val)); 9276 assert(!SCIPisInfinity(scip, lb)); 9277 if( SCIPisInfinity(scip, -lb) ) 9278 minleftactivity = -SCIPinfinity(scip); 9279 else 9280 minleftactivity += val * lb; 9281 } 9282 9283 if( !SCIPisInfinity(scip, maxleftactivity) ) 9284 { 9285 assert(!SCIPisInfinity(scip, val)); 9286 assert(!SCIPisInfinity(scip, -ub)); 9287 if( SCIPisInfinity(scip,ub) ) 9288 maxleftactivity = SCIPinfinity(scip); 9289 else 9290 maxleftactivity += val * ub; 9291 } 9292 } 9293 } 9294 else 9295 { 9296 /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */ 9297 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && 9298 SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) ) 9299 { 9300 /* change coefficients: 9301 * ai' := min(rhs - maxact, minact - lhs) 9302 * lhs' := lhs - (ai - ai')*ui 9303 * rhs' := rhs - (ai - ai')*li 9304 */ 9305 9306 lval = minactivity - consdata->lhs; 9307 rval = consdata->rhs - maxactivity; 9308 9309 /* Try to avoid cancellation, if there are only two variables */ 9310 if( consdata->nvars == 2 ) 9311 { 9312 SCIP_Real otherval; 9313 otherval = consdata->vals[1-i]; 9314 9315 if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity ) 9316 { 9317 lval = val*ub - consdata->lhs; 9318 lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]); 9319 } 9320 9321 if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity ) 9322 { 9323 rval = consdata->rhs - val*lb; 9324 rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]); 9325 } 9326 } 9327 9328 newval = MIN(lval, rval); 9329 assert(SCIPisSumRelGE(scip, newval, val)); 9330 9331 /* Try to avoid cancellation in computation of lhs/rhs */ 9332 newlhs = consdata->lhs - val * ub; 9333 newlhs += newval * ub; 9334 newrhs = consdata->rhs - val * lb; 9335 newrhs += newval * lb; 9336 9337 if( !SCIPisSumRelEQ(scip, newval, val) ) 9338 { 9339 SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n", 9340 SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var), 9341 minactivity, maxactivity, consdata->lhs, consdata->rhs); 9342 9343 /* update the coefficient and the activity bounds */ 9344 if( SCIPisZero(scip, newval) ) 9345 { 9346 SCIP_CALL( delCoefPos(scip, cons, i) ); 9347 i--; 9348 } 9349 else 9350 { 9351 SCIP_CALL( chgCoefPos(scip, cons, i, newval) ); 9352 } 9353 (*nchgcoefs)++; 9354 9355 /* get the new minimal and maximal activity of the constraint */ 9356 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 9357 &isminsettoinfinity, &ismaxsettoinfinity); 9358 9359 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) ) 9360 { 9361 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs); 9362 9363 SCIP_CALL( chgLhs(scip, cons, newlhs) ); 9364 (*nchgsides)++; 9365 assert(SCIPisEQ(scip, consdata->lhs, newlhs)); 9366 } 9367 9368 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) ) 9369 { 9370 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs); 9371 9372 SCIP_CALL( chgRhs(scip, cons, newrhs) ); 9373 (*nchgsides)++; 9374 assert(SCIPisEQ(scip, consdata->rhs, newrhs)); 9375 } 9376 } 9377 } 9378 else 9379 { 9380 if( !SCIPisInfinity(scip, -minleftactivity) ) 9381 { 9382 assert(!SCIPisInfinity(scip, -val)); 9383 assert(!SCIPisInfinity(scip, -ub)); 9384 if( SCIPisInfinity(scip, ub) ) 9385 minleftactivity = -SCIPinfinity(scip); 9386 else 9387 minleftactivity += val * ub; 9388 } 9389 9390 if( !SCIPisInfinity(scip, maxleftactivity) ) 9391 { 9392 assert(!SCIPisInfinity(scip, -val)); 9393 assert(!SCIPisInfinity(scip, lb)); 9394 if( SCIPisInfinity(scip, -lb) ) 9395 maxleftactivity = SCIPinfinity(scip); 9396 else 9397 maxleftactivity += val * lb; 9398 } 9399 } 9400 } 9401 ++i; 9402 } 9403 9404 SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n", 9405 minleftactivity, consdata->rhs); 9406 SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n", 9407 maxleftactivity, consdata->lhs); 9408 9409 /* minleft == \infty ==> minactivity == \infty */ 9410 assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity)); 9411 assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity)); 9412 9413 /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible; 9414 * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation) 9415 * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation 9416 * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following 9417 */ 9418 assert(!SCIPisInfinity(scip, minactivity)); 9419 if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) ) 9420 return SCIP_OKAY; 9421 9422 /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible; 9423 * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation) 9424 * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation 9425 * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following 9426 */ 9427 assert(!SCIPisInfinity(scip, -maxactivity)); 9428 if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) ) 9429 return SCIP_OKAY; 9430 9431 /* correct lhs and rhs by min/max activity of surely non-redundant variables 9432 * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant 9433 */ 9434 aggrlhs = consdata->lhs - minactivity + minleftactivity; 9435 aggrrhs = consdata->rhs - maxactivity + maxleftactivity; 9436 9437 /* check if the constraint contains variables which are redundant. The reasoning is the following: 9438 * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound. 9439 * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible, 9440 * they can be removed from the constraint. 9441 * aggrrhs may contain some near-infinity value, but only if rhs is infinity. 9442 */ 9443 if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs)) 9444 && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) ) 9445 { 9446 SCIP_Real minleftactivitypart; 9447 SCIP_Real maxleftactivitypart; 9448 9449 assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs)); 9450 9451 /* try to remove redundant variables from constraint */ 9452 i = 0; 9453 while( i < consdata->nvars ) 9454 { 9455 var = consdata->vars[i]; 9456 minleftactivitypart = 0.0; 9457 maxleftactivitypart = 0.0; 9458 lb = SCIPvarGetLbLocal(var); 9459 ub = SCIPvarGetUbLocal(var); 9460 9461 /* get coefficient and variable's bounds */ 9462 val = consdata->vals[i]; 9463 assert(!SCIPisZero(scip, val)); 9464 9465 /* check sign of coefficient */ 9466 if( val >= 0.0 ) 9467 { 9468 /* negation of condition above in case of positive val */ 9469 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || 9470 SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) ) 9471 { 9472 SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs); 9473 SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs); 9474 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n", 9475 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val); 9476 9477 minleftactivitypart = val * lb; 9478 maxleftactivitypart = val * ub; 9479 9480 SCIP_CALL( delCoefPos(scip, cons, i) ); 9481 i--; 9482 9483 /* get the new minimal and maximal activity of the constraint */ 9484 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 9485 &isminsettoinfinity, &ismaxsettoinfinity); 9486 9487 /* we return above if the condition does not hold and deleting a variable cannot increase the number of 9488 * huge contributions 9489 */ 9490 assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs)); 9491 assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs)); 9492 } 9493 } 9494 else 9495 { 9496 /* negation of condition above in case of negative val */ 9497 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || 9498 SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) ) 9499 { 9500 SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n", 9501 SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val); 9502 9503 minleftactivitypart = val * ub; 9504 maxleftactivitypart = val * lb; 9505 9506 SCIP_CALL( delCoefPos(scip, cons, i) ); 9507 i--; 9508 9509 /* get the new minimal and maximal activity of the constraint */ 9510 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 9511 &isminsettoinfinity, &ismaxsettoinfinity); 9512 9513 /* we return above if the condition does not hold and deleting a variable cannot increase the number of 9514 * huge contributions 9515 */ 9516 assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs)); 9517 assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs)); 9518 } 9519 } 9520 9521 /* the following update step is needed in every iteration cause otherwise it is possible that the surely none- 9522 * redundant variables could get deleted, 9523 * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that 9524 * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides 9525 * we would also delete y2 and as a result we would have gotten infeasibility */ 9526 /* adjust lhs and right hand side */ 9527 newlhs = consdata->lhs - minleftactivitypart; 9528 newrhs = consdata->rhs - maxleftactivitypart; 9529 9530 if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) ) 9531 { 9532 SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs); 9533 SCIP_CALL( chgLhs(scip, cons, newlhs) ); 9534 ++(*nchgsides); 9535 assert(SCIPisEQ(scip, consdata->lhs, newlhs)); 9536 } 9537 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) ) 9538 { 9539 SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs); 9540 SCIP_CALL( chgRhs(scip, cons, newrhs) ); 9541 ++(*nchgsides); 9542 assert(SCIPisEQ(scip, consdata->rhs, newrhs)); 9543 } 9544 ++i; 9545 } 9546 } 9547 9548 return SCIP_OKAY; 9549 } 9550 9551 /** processes equality with only one variable by fixing the variable and deleting the constraint */ 9552 static 9553 SCIP_RETCODE convertUnaryEquality( 9554 SCIP* scip, /**< SCIP data structure */ 9555 SCIP_CONS* cons, /**< linear constraint */ 9556 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 9557 int* nfixedvars, /**< pointer to count number of fixed variables */ 9558 int* ndelconss /**< pointer to count number of deleted constraints */ 9559 ) 9560 { 9561 SCIP_CONSDATA* consdata; 9562 SCIP_VAR* var; 9563 SCIP_Real val; 9564 SCIP_Real fixval; 9565 SCIP_Bool infeasible; 9566 SCIP_Bool fixed; 9567 9568 assert(scip != NULL); 9569 assert(cons != NULL); 9570 assert(cutoff != NULL); 9571 assert(nfixedvars != NULL); 9572 assert(ndelconss != NULL); 9573 9574 consdata = SCIPconsGetData(cons); 9575 assert(consdata != NULL); 9576 assert(consdata->nvars == 1); 9577 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs)); 9578 9579 /* calculate the value to fix the variable to */ 9580 var = consdata->vars[0]; 9581 val = consdata->vals[0]; 9582 assert(!SCIPisZero(scip, val)); 9583 fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip), 9584 consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM); 9585 SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n", 9586 SCIPconsGetName(cons), SCIPvarGetName(var), fixval); 9587 9588 /* fix variable */ 9589 SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) ); 9590 if( infeasible ) 9591 { 9592 SCIPdebugMsg(scip, " -> infeasible fixing\n"); 9593 *cutoff = TRUE; 9594 return SCIP_OKAY; 9595 } 9596 if( fixed ) 9597 (*nfixedvars)++; 9598 9599 /* disable constraint */ 9600 SCIP_CALL( SCIPdelCons(scip, cons) ); 9601 if( !consdata->upgraded ) 9602 (*ndelconss)++; 9603 9604 return SCIP_OKAY; 9605 } 9606 9607 /** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */ 9608 static 9609 SCIP_RETCODE convertBinaryEquality( 9610 SCIP* scip, /**< SCIP data structure */ 9611 SCIP_CONS* cons, /**< linear constraint */ 9612 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 9613 int* naggrvars, /**< pointer to count number of aggregated variables */ 9614 int* ndelconss /**< pointer to count number of deleted constraints */ 9615 ) 9616 { 9617 SCIP_CONSDATA* consdata; 9618 SCIP_Bool infeasible; 9619 SCIP_Bool redundant; 9620 SCIP_Bool aggregated; 9621 9622 assert(scip != NULL); 9623 assert(cons != NULL); 9624 assert(cutoff != NULL); 9625 assert(naggrvars != NULL); 9626 assert(ndelconss != NULL); 9627 9628 consdata = SCIPconsGetData(cons); 9629 assert(consdata != NULL); 9630 assert(consdata->nvars == 2); 9631 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs)); 9632 9633 SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n", 9634 SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]), 9635 consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs); 9636 9637 /* aggregate the equality */ 9638 SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1], 9639 consdata->rhs, &infeasible, &redundant, &aggregated) ); 9640 9641 /* check for infeasibility of aggregation */ 9642 if( infeasible ) 9643 { 9644 SCIPdebugMsg(scip, " -> infeasible aggregation\n"); 9645 *cutoff = TRUE; 9646 return SCIP_OKAY; 9647 } 9648 9649 /* count the aggregation */ 9650 if( aggregated ) 9651 (*naggrvars)++; 9652 9653 /* delete the constraint, if it is redundant */ 9654 if( redundant ) 9655 { 9656 SCIP_CALL( SCIPdelCons(scip, cons) ); 9657 9658 if( !consdata->upgraded ) 9659 (*ndelconss)++; 9660 } 9661 9662 return SCIP_OKAY; 9663 } 9664 9665 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */ 9666 static 9667 void getNewSidesAfterAggregation( 9668 SCIP* scip, /**< SCIP data structure */ 9669 SCIP_CONSDATA* consdata, /**< linear constraint data */ 9670 SCIP_VAR* slackvar, /**< variable to be aggregated out */ 9671 SCIP_Real slackcoef, /**< coefficient of variable in constraint */ 9672 SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */ 9673 SCIP_Real* newrhs /**< pointer to store new rhs of constraint */ 9674 ) 9675 { 9676 SCIP_Real slackvarlb; 9677 SCIP_Real slackvarub; 9678 9679 assert(scip != NULL); 9680 assert(consdata != NULL); 9681 assert(newlhs != NULL); 9682 assert(newrhs != NULL); 9683 assert(!SCIPisInfinity(scip, -consdata->lhs)); 9684 assert(!SCIPisInfinity(scip, consdata->rhs)); 9685 9686 slackvarlb = SCIPvarGetLbGlobal(slackvar); 9687 slackvarub = SCIPvarGetUbGlobal(slackvar); 9688 if( slackcoef > 0.0 ) 9689 { 9690 if( SCIPisInfinity(scip, -slackvarlb) ) 9691 *newrhs = SCIPinfinity(scip); 9692 else 9693 *newrhs = consdata->rhs - slackcoef * slackvarlb; 9694 if( SCIPisInfinity(scip, slackvarub) ) 9695 *newlhs = -SCIPinfinity(scip); 9696 else 9697 *newlhs = consdata->lhs - slackcoef * slackvarub; 9698 } 9699 else 9700 { 9701 if( SCIPisInfinity(scip, -slackvarlb) ) 9702 *newlhs = -SCIPinfinity(scip); 9703 else 9704 *newlhs = consdata->rhs - slackcoef * slackvarlb; 9705 if( SCIPisInfinity(scip, slackvarub) ) 9706 *newrhs = SCIPinfinity(scip); 9707 else 9708 *newrhs = consdata->lhs - slackcoef * slackvarub; 9709 } 9710 assert(SCIPisLE(scip, *newlhs, *newrhs)); 9711 } 9712 9713 /** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality 9714 * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that 9715 * is implicitly integral by this constraint 9716 * 9717 * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables 9718 * can help. 9719 */ 9720 static 9721 SCIP_RETCODE convertLongEquality( 9722 SCIP* scip, /**< SCIP data structure */ 9723 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */ 9724 SCIP_CONS* cons, /**< linear constraint */ 9725 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 9726 int* naggrvars, /**< pointer to count number of aggregated variables */ 9727 int* ndelconss /**< pointer to count number of deleted constraints */ 9728 ) 9729 { 9730 SCIP_CONSDATA* consdata; 9731 SCIP_VAR** vars; 9732 SCIP_Real* vals; 9733 SCIP_VARTYPE bestslacktype; 9734 SCIP_VARTYPE slacktype; 9735 SCIP_Real lhs; 9736 SCIP_Real rhs; 9737 SCIP_Real bestslackdomrng; 9738 SCIP_Real minabsval; 9739 SCIP_Real maxabsval; 9740 SCIP_Bool bestremovescons; 9741 SCIP_Bool coefszeroone; 9742 SCIP_Bool coefsintegral; 9743 SCIP_Bool varsintegral; 9744 SCIP_Bool infeasible; 9745 SCIP_Bool samevar; 9746 int supinf; /* counter for infinite contributions to the supremum of a possible 9747 * multi-aggregation 9748 */ 9749 int infinf; /* counter for infinite contributions to the infimum of a possible 9750 * multi-aggregation 9751 */ 9752 int maxnlocksstay; 9753 int maxnlocksremove; 9754 int bestslackpos; 9755 int bestnlocks; 9756 int ncontvars; 9757 int contvarpos; 9758 int nintvars; 9759 int nimplvars; 9760 int intvarpos; 9761 int v; 9762 9763 assert(scip != NULL); 9764 assert(cons != NULL); 9765 assert(cutoff != NULL); 9766 assert(naggrvars != NULL); 9767 9768 consdata = SCIPconsGetData(cons); 9769 assert(consdata != NULL); 9770 assert(consdata->nvars > 2); 9771 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs)); 9772 9773 SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons)); 9774 9775 /* We do not want to increase the total number of non-zeros due to the multi-aggregation. 9776 * Therefore, we have to restrict the number of locks of a variable that is aggregated out. 9777 * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation 9778 * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation 9779 */ 9780 lhs = consdata->lhs; 9781 rhs = consdata->rhs; 9782 maxnlocksstay = 0; 9783 if( consdata->nvars == 3 ) 9784 { 9785 /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each 9786 * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints. 9787 */ 9788 maxnlocksremove = 3; 9789 } 9790 else if( consdata->nvars == 4 ) 9791 { 9792 /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each 9793 * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints. 9794 */ 9795 maxnlocksremove = 2; 9796 } 9797 else 9798 { 9799 /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */ 9800 maxnlocksremove = 1; 9801 } 9802 9803 /* the locks on this constraint can be ignored */ 9804 if( SCIPconsIsChecked(cons) ) 9805 { 9806 if( !SCIPisInfinity(scip, -lhs) ) 9807 { 9808 maxnlocksstay++; 9809 maxnlocksremove++; 9810 } 9811 if( !SCIPisInfinity(scip, rhs) ) 9812 { 9813 maxnlocksstay++; 9814 maxnlocksremove++; 9815 } 9816 } 9817 9818 /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */ 9819 vars = consdata->vars; 9820 vals = consdata->vals; 9821 bestslackpos = -1; 9822 bestslacktype = SCIP_VARTYPE_BINARY; 9823 bestnlocks = INT_MAX; 9824 bestremovescons = FALSE; 9825 bestslackdomrng = 0.0; 9826 coefszeroone = TRUE; 9827 coefsintegral = TRUE; 9828 varsintegral = TRUE; 9829 ncontvars = 0; 9830 contvarpos = -1; 9831 nintvars = 0; 9832 nimplvars = 0; 9833 intvarpos = -1; 9834 minabsval = SCIPinfinity(scip); 9835 maxabsval = -1.0; 9836 for( v = 0; v < consdata->nvars; ++v ) 9837 { 9838 SCIP_VAR* var; 9839 SCIP_Real val; 9840 SCIP_Real absval; 9841 SCIP_Real varlb; 9842 SCIP_Real varub; 9843 SCIP_Bool iscont; 9844 int nlocks; 9845 9846 assert(vars != NULL); 9847 assert(vals != NULL); 9848 9849 var = vars[v]; 9850 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */ 9851 assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1); 9852 varlb = SCIPvarGetLbGlobal(var); 9853 varub = SCIPvarGetUbGlobal(var); 9854 9855 val = vals[v]; 9856 absval = REALABS(val); 9857 assert(SCIPisPositive(scip, absval)); 9858 9859 /* calculate minimal and maximal absolute value */ 9860 if( absval < minabsval ) 9861 minabsval = absval; 9862 if( absval > maxabsval ) 9863 maxabsval = absval; 9864 9865 /* do not try to multi aggregate, when numerical bad */ 9866 if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot ) 9867 return SCIP_OKAY; 9868 9869 slacktype = SCIPvarGetType(var); 9870 coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0); 9871 coefsintegral = coefsintegral && SCIPisIntegral(scip, val); 9872 varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS); 9873 iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT); 9874 9875 /* update candidates for continuous -> implint and integer -> implint conversion */ 9876 if( slacktype == SCIP_VARTYPE_CONTINUOUS ) 9877 { 9878 ncontvars++; 9879 contvarpos = v; 9880 } 9881 else if( slacktype == SCIP_VARTYPE_IMPLINT ) 9882 { 9883 ++nimplvars; 9884 } 9885 else if( slacktype == SCIP_VARTYPE_INTEGER ) 9886 { 9887 nintvars++; 9888 intvarpos = v; 9889 } 9890 9891 /* check, if variable is already fixed or aggregated */ 9892 if( !SCIPvarIsActive(var) ) 9893 continue; 9894 9895 /* check, if variable is used in too many other constraints, even if this constraint could be deleted */ 9896 nlocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) + SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL); 9897 9898 if( nlocks > maxnlocksremove ) 9899 continue; 9900 9901 /* check, if variable can be used as a slack variable */ 9902 if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) && 9903 !SCIPdoNotMultaggrVar(scip, var) ) 9904 { 9905 SCIP_Bool better; 9906 SCIP_Bool equal; 9907 SCIP_Real slackdomrng; 9908 9909 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) ) 9910 slackdomrng = SCIPinfinity(scip); 9911 /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */ 9912 else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) ) 9913 return SCIP_OKAY; 9914 else 9915 { 9916 slackdomrng = (varub - varlb)*absval; 9917 assert(!SCIPisInfinity(scip, slackdomrng)); 9918 } 9919 equal = FALSE; 9920 better = (slacktype > bestslacktype) || (bestslackpos == -1); 9921 if( !better && slacktype == bestslacktype ) 9922 { 9923 better = (nlocks < bestnlocks); 9924 if( nlocks == bestnlocks && !bestremovescons ) 9925 { 9926 better = SCIPisGT(scip, slackdomrng, bestslackdomrng); 9927 equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng); 9928 } 9929 } 9930 9931 if( better || equal ) 9932 { 9933 SCIP_Real minresactivity; 9934 SCIP_Real maxresactivity; 9935 SCIP_Real newlhs; 9936 SCIP_Real newrhs; 9937 SCIP_Bool removescons; 9938 SCIP_Bool minisrelax; 9939 SCIP_Bool maxisrelax; 9940 SCIP_Bool isminsettoinfinity; 9941 SCIP_Bool ismaxsettoinfinity; 9942 9943 /* check if the constraint becomes redundant after multi-aggregation */ 9944 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity, 9945 &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity); 9946 9947 /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual 9948 * activity 9949 */ 9950 if( minisrelax || maxisrelax ) 9951 continue; 9952 9953 getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs); 9954 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs)); 9955 9956 /* check resactivities for reliability */ 9957 if( removescons ) 9958 { 9959 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) ) 9960 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE); 9961 9962 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) 9963 && SCIPisFeasLE(scip, newlhs, minresactivity)) 9964 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE); 9965 9966 removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs)); 9967 } 9968 9969 /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */ 9970 if( conshdlrdata->multaggrremove && !removescons ) 9971 continue; 9972 9973 /* prefer variables that make the constraints redundant */ 9974 if( bestremovescons && !removescons ) 9975 continue; 9976 9977 /* if the constraint does not become redundant, only accept the variable if it does not appear in 9978 * other constraints 9979 */ 9980 if( !removescons && nlocks > maxnlocksstay ) 9981 continue; 9982 9983 better = better || (!bestremovescons && removescons); 9984 if( better ) 9985 { 9986 bestslackpos = v; 9987 bestslacktype = slacktype; 9988 bestnlocks = nlocks; 9989 bestslackdomrng = slackdomrng; 9990 bestremovescons = removescons; 9991 } 9992 } 9993 } 9994 } 9995 9996 /* if all coefficients and variables are integral, the right hand side must also be integral */ 9997 if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) ) 9998 { 9999 SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons)); 10000 SCIPdebugPrintCons(scip, cons, NULL); 10001 *cutoff = TRUE; 10002 return SCIP_OKAY; 10003 } 10004 10005 supinf = 0; 10006 infinf = 0; 10007 samevar = FALSE; 10008 10009 /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */ 10010 for( v = 0; v < consdata->nvars; ++v ) 10011 { 10012 if( v != bestslackpos ) 10013 { 10014 if( SCIPisPositive(scip, consdata->vals[v]) ) 10015 { 10016 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) ) 10017 { 10018 ++supinf; 10019 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) ) 10020 { 10021 ++infinf; 10022 samevar = TRUE; 10023 } 10024 } 10025 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) ) 10026 ++infinf; 10027 } 10028 else if( SCIPisNegative(scip, consdata->vals[v]) ) 10029 { 10030 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) ) 10031 { 10032 ++supinf; 10033 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) ) 10034 { 10035 ++infinf; 10036 samevar = TRUE; 10037 } 10038 } 10039 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) ) 10040 ++infinf; 10041 } 10042 } 10043 } 10044 assert(!samevar || (supinf > 0 && infinf > 0)); 10045 10046 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable. 10047 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */ 10048 if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) ) 10049 { 10050 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n"); 10051 return SCIP_OKAY; 10052 } 10053 10054 /* if the slack variable is of integer type, and the constraint itself may take fractional values, 10055 * we cannot aggregate the variable, because the integrality condition would get lost 10056 * Similarly, if there are implicitly integral variables we cannot aggregate, since we might 10057 * loose the integrality condition for this variable. 10058 */ 10059 if( bestslackpos >= 0 10060 && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT 10061 || (coefsintegral && varsintegral && nimplvars == 0)) ) 10062 { 10063 SCIP_VAR* slackvar; 10064 SCIP_Real* scalars; 10065 SCIP_Real slackcoef; 10066 SCIP_Real aggrconst; 10067 SCIP_Real newlhs; 10068 SCIP_Real newrhs; 10069 SCIP_Bool aggregated; 10070 10071 /* we found a slack variable that only occurs in at most one other constraint: 10072 * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k 10073 */ 10074 assert(bestslackpos < consdata->nvars); 10075 10076 /* do not multi aggregate binary variables */ 10077 if( SCIPvarIsBinary(vars[bestslackpos]) ) 10078 return SCIP_OKAY; 10079 10080 /* convert equality into inequality by deleting the slack variable: 10081 * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l 10082 */ 10083 slackvar = vars[bestslackpos]; 10084 slackcoef = vals[bestslackpos]; 10085 assert(!SCIPisZero(scip, slackcoef)); 10086 aggrconst = consdata->rhs/slackcoef; 10087 10088 getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs); 10089 assert(SCIPisLE(scip, newlhs, newrhs)); 10090 SCIP_CALL( chgLhs(scip, cons, newlhs) ); 10091 SCIP_CALL( chgRhs(scip, cons, newrhs) ); 10092 SCIP_CALL( delCoefPos(scip, cons, bestslackpos) ); 10093 10094 /* allocate temporary memory */ 10095 SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) ); 10096 10097 /* set up the multi-aggregation */ 10098 SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar)); 10099 for( v = 0; v < consdata->nvars; ++v ) 10100 { 10101 scalars[v] = -consdata->vals[v]/slackcoef; 10102 SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v])); 10103 } 10104 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n", 10105 aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar), 10106 bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons); 10107 10108 /* perform the multi-aggregation */ 10109 SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst, 10110 &infeasible, &aggregated) ); 10111 assert(aggregated); 10112 10113 /* free temporary memory */ 10114 SCIPfreeBufferArray(scip, &scalars); 10115 10116 /* check for infeasible aggregation */ 10117 if( infeasible ) 10118 { 10119 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons)); 10120 *cutoff = TRUE; 10121 return SCIP_OKAY; 10122 } 10123 10124 (*naggrvars)++; 10125 10126 /* delete the constraint if it became redundant */ 10127 if( bestremovescons ) 10128 { 10129 SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons)); 10130 SCIP_CALL( SCIPdelCons(scip, cons) ); 10131 10132 if( !consdata->upgraded ) 10133 (*ndelconss)++; 10134 } 10135 } 10136 else if( ncontvars == 1 ) 10137 { 10138 SCIP_VAR* var; 10139 10140 assert(0 <= contvarpos && contvarpos < consdata->nvars); 10141 var = vars[contvarpos]; 10142 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS); 10143 10144 if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) ) 10145 { 10146 /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */ 10147 if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) ) 10148 { 10149 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */ 10150 SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n", 10151 SCIPconsGetName(cons), SCIPvarGetName(var)); 10152 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) ); 10153 if( infeasible ) 10154 { 10155 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var)); 10156 *cutoff = TRUE; 10157 10158 return SCIP_OKAY; 10159 } 10160 } 10161 /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */ 10162 /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */ 10163 else if( !SCIPdoNotAggr(scip) ) 10164 { 10165 SCIP_VAR* newvar; 10166 SCIP_Real absval; 10167 char newvarname[SCIP_MAXSTRLEN]; 10168 SCIP_Bool redundant; 10169 SCIP_Bool aggregated; 10170 10171 absval = REALABS(vals[contvarpos]); 10172 10173 (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var)); 10174 10175 /* create new implicit variable for aggregation */ 10176 SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, 10177 SCIP_VARTYPE_IMPLINT, SCIPvarIsInitial(var), SCIPvarIsRemovable(var), NULL, NULL, NULL, NULL, NULL) ); 10178 10179 /* add new variable to problem */ 10180 SCIP_CALL( SCIPaddVar(scip, newvar) ); 10181 10182 #ifdef WITH_DEBUG_SOLUTION 10183 if( SCIPdebugIsMainscip(scip) ) 10184 { 10185 SCIP_Real varval; 10186 SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) ); 10187 SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) ); 10188 } 10189 #endif 10190 10191 /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */ 10192 SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n", 10193 SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval); 10194 10195 /* aggregate continuous and implicit variable */ 10196 SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) ); 10197 10198 if( infeasible ) 10199 { 10200 SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n", 10201 SCIPvarGetName(var), SCIPvarGetName(newvar)); 10202 *cutoff = TRUE; 10203 10204 /* release implicit variable */ 10205 SCIP_CALL( SCIPreleaseVar(scip, &newvar) ); 10206 10207 return SCIP_OKAY; 10208 } 10209 10210 /* release implicit variable */ 10211 SCIP_CALL( SCIPreleaseVar(scip, &newvar) ); 10212 10213 if( aggregated ) 10214 (*naggrvars)++; 10215 else 10216 return SCIP_OKAY; 10217 } 10218 10219 /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved 10220 * again 10221 */ 10222 consdata->boundstightened = 0; 10223 consdata->rangedrowpropagated = 0; 10224 consdata->presolved = FALSE; 10225 } 10226 } 10227 else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone ) 10228 { 10229 SCIP_VAR* var; 10230 10231 /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0) 10232 * -> we don't convert integers into implints if the row is a 0/1-row 10233 */ 10234 assert(varsintegral); 10235 assert(0 <= intvarpos && intvarpos < consdata->nvars); 10236 var = vars[intvarpos]; 10237 assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER); 10238 10239 if( coefsintegral 10240 && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0) 10241 && SCIPisFeasIntegral(scip, consdata->rhs) ) 10242 { 10243 /* convert the integer variable with coefficient 1.0 into an implicit integer variable */ 10244 SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n", 10245 SCIPconsGetName(cons), SCIPvarGetName(var)); 10246 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) ); 10247 if( infeasible ) 10248 { 10249 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var)); 10250 *cutoff = TRUE; 10251 10252 return SCIP_OKAY; 10253 } 10254 } 10255 } 10256 10257 return SCIP_OKAY; 10258 } 10259 10260 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */ 10261 static 10262 SCIP_Bool checkEqualObjective( 10263 SCIP* scip, /**< SCIP data structure */ 10264 SCIP_CONSDATA* consdata, /**< linear constraint data */ 10265 SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the 10266 * objective function */ 10267 SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by 10268 * this constraint */ 10269 ) 10270 { 10271 SCIP_VAR** vars; 10272 SCIP_VAR* var; 10273 SCIP_Real objval; 10274 SCIP_Bool negated; 10275 int nvars; 10276 int v; 10277 10278 vars = consdata->vars; 10279 nvars = consdata->nvars; 10280 10281 assert(vars != NULL); 10282 10283 for( v = 0; v < nvars; ++v ) 10284 { 10285 negated = FALSE; 10286 var = vars[v]; 10287 assert(var != NULL); 10288 10289 if( SCIPvarIsNegated(var) ) 10290 { 10291 negated = TRUE; 10292 var = SCIPvarGetNegatedVar(var); 10293 assert(var != NULL); 10294 } 10295 10296 objval = SCIPvarGetObj(var); 10297 10298 /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective 10299 * function 10300 */ 10301 if( SCIPisZero(scip, objval) ) 10302 return FALSE; 10303 else 10304 { 10305 SCIP_Real val; 10306 10307 val = consdata->vals[v]; 10308 10309 if( negated ) 10310 { 10311 if( v == 0 ) 10312 { 10313 /* the first variable defines the scale */ 10314 (*scale) = val / -objval; 10315 10316 (*offset) += val; 10317 } 10318 else if( SCIPisEQ(scip, -objval * (*scale), val) ) 10319 (*offset) += val; 10320 else 10321 return FALSE; 10322 } 10323 else if( v == 0 ) 10324 { 10325 /* the first variable defines the scale */ 10326 (*scale) = val / objval; 10327 } 10328 else if( !SCIPisEQ(scip, objval * (*scale), val) ) 10329 return FALSE; 10330 } 10331 } 10332 10333 return TRUE; 10334 } 10335 10336 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the 10337 * objective coefficients and add an objective offset 10338 */ 10339 static 10340 SCIP_RETCODE checkPartialObjective( 10341 SCIP* scip, /**< SCIP data structure */ 10342 SCIP_CONS* cons, /**< linear equation constraint */ 10343 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */ 10344 ) 10345 { 10346 SCIP_CONSDATA* consdata; 10347 SCIP_Real offset; 10348 SCIP_Real scale; 10349 SCIP_Bool applicable; 10350 int nobjvars; 10351 int nvars; 10352 int v; 10353 10354 assert(scip != NULL); 10355 assert(cons != NULL); 10356 assert(conshdlrdata != NULL); 10357 10358 consdata = SCIPconsGetData(cons); 10359 assert(consdata != NULL); 10360 assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs)); 10361 10362 nvars = consdata->nvars; 10363 nobjvars = SCIPgetNObjVars(scip); 10364 10365 /* check if the linear equality constraints does not have more variables than the objective function */ 10366 if( nvars > nobjvars || nvars == 0 ) 10367 return SCIP_OKAY; 10368 10369 /* check for allowance of algorithm */ 10370 if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) || 10371 (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) ) 10372 return SCIP_OKAY; 10373 10374 offset = consdata->rhs; 10375 scale = 1.0; 10376 10377 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */ 10378 applicable = checkEqualObjective(scip, consdata, &scale, &offset); 10379 10380 if( applicable ) 10381 { 10382 SCIP_VAR** vars; 10383 10384 vars = consdata->vars; 10385 assert(vars != NULL); 10386 10387 offset /= scale; 10388 10389 SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n", 10390 SCIPconsGetName(cons), consdata->rhs, offset); 10391 10392 /* make equality a model constraint to ensure optimality in this direction */ 10393 SCIP_CALL( SCIPsetConsChecked(scip, cons, TRUE) ); 10394 SCIP_CALL( SCIPsetConsEnforced(scip, cons, TRUE) ); 10395 10396 /* set all objective coefficient to zero */ 10397 for( v = 0; v < nvars; ++v ) 10398 { 10399 SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) ); 10400 } 10401 10402 /* add an objective offset */ 10403 SCIP_CALL( SCIPaddObjoffset(scip, offset) ); 10404 } 10405 10406 return SCIP_OKAY; 10407 } 10408 10409 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */ 10410 static 10411 SCIP_RETCODE updateCutoffbound( 10412 SCIP* scip, /**< SCIP data structure */ 10413 SCIP_CONS* cons, /**< constraint */ 10414 SCIP_Real primalbound /**< feasible primal bound */ 10415 ) 10416 { 10417 SCIP_Real cutoffbound; 10418 10419 /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still 10420 * accepted 10421 */ 10422 cutoffbound = primalbound + SCIPcutoffbounddelta(scip); 10423 10424 if( cutoffbound < SCIPgetCutoffbound(scip) ) 10425 { 10426 SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound); 10427 10428 SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) ); 10429 } 10430 else 10431 { 10432 SCIP_CONSDATA* consdata; 10433 10434 consdata = SCIPconsGetData(cons); 10435 assert(consdata != NULL); 10436 10437 /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have 10438 * resulted from one side 10439 */ 10440 if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) ) 10441 { 10442 /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and 10443 * propagation 10444 */ 10445 SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) ); 10446 SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) ); 10447 } 10448 } 10449 10450 return SCIP_OKAY; 10451 } 10452 10453 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the 10454 * constraint enters the LP by setting the initial and separated flag to FALSE 10455 */ 10456 static 10457 SCIP_RETCODE checkParallelObjective( 10458 SCIP* scip, /**< SCIP data structure */ 10459 SCIP_CONS* cons, /**< linear constraint */ 10460 SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */ 10461 ) 10462 { 10463 SCIP_CONSDATA* consdata; 10464 SCIP_Real offset; 10465 SCIP_Real scale; 10466 SCIP_Bool applicable; 10467 int nobjvars; 10468 int nvars; 10469 10470 assert(scip != NULL); 10471 assert(cons != NULL); 10472 assert(conshdlrdata != NULL); 10473 10474 consdata = SCIPconsGetData(cons); 10475 assert(consdata != NULL); 10476 10477 /* ignore equalities since these are covered by the method checkPartialObjective() */ 10478 if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) ) 10479 return SCIP_OKAY; 10480 10481 nvars = consdata->nvars; 10482 nobjvars = SCIPgetNObjVars(scip); 10483 10484 /* check if the linear inequality constraints has the same number of variables as the objective function and if the 10485 * initial and/or separated flag is set to FALSE 10486 */ 10487 if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) ) 10488 return SCIP_OKAY; 10489 10490 offset = 0.0; 10491 scale = 1.0; 10492 10493 /* There are no variables in the objective function and in the constraint. Thus, the constraint is redundant or proves 10494 * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound. 10495 */ 10496 if( nobjvars == 0 ) 10497 return SCIP_OKAY; 10498 10499 /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */ 10500 applicable = checkEqualObjective(scip, consdata, &scale, &offset); 10501 10502 if( applicable ) 10503 { 10504 SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs); 10505 SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs); 10506 10507 assert(scale != 0.0); 10508 10509 if( scale > 0.0 ) 10510 { 10511 if( conshdlrdata->detectcutoffbound && rhsfinite ) 10512 { 10513 SCIP_Real primalbound; 10514 10515 primalbound = (consdata->rhs - offset) / scale; 10516 10517 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n", 10518 SCIPconsGetName(cons), primalbound); 10519 10520 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) ); 10521 } 10522 10523 if( conshdlrdata->detectlowerbound && lhsfinite ) 10524 { 10525 SCIP_Real lowerbound; 10526 10527 lowerbound = (consdata->lhs - offset) / scale; 10528 10529 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n", 10530 SCIPconsGetName(cons), lowerbound); 10531 10532 SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) ); 10533 } 10534 10535 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) || 10536 (conshdlrdata->detectlowerbound && !rhsfinite) ) 10537 { 10538 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */ 10539 SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) ); 10540 SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) ); 10541 } 10542 } 10543 else 10544 { 10545 if( conshdlrdata->detectlowerbound && rhsfinite ) 10546 { 10547 SCIP_Real lowerbound; 10548 10549 lowerbound = (consdata->rhs - offset) / scale; 10550 10551 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n", 10552 SCIPconsGetName(cons), lowerbound); 10553 10554 SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) ); 10555 } 10556 10557 if( conshdlrdata->detectcutoffbound && lhsfinite ) 10558 { 10559 SCIP_Real primalbound; 10560 10561 primalbound = (consdata->lhs - offset) / scale; 10562 10563 SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n", 10564 SCIPconsGetName(cons), primalbound); 10565 10566 SCIP_CALL( updateCutoffbound(scip, cons, primalbound) ); 10567 } 10568 10569 if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) || 10570 (conshdlrdata->detectlowerbound && !lhsfinite) ) 10571 { 10572 /* avoid that the linear constraint enters the LP since it is parallel to the objective function */ 10573 SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) ); 10574 SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) ); 10575 } 10576 } 10577 } 10578 10579 return SCIP_OKAY; 10580 } 10581 10582 /** converts special equalities */ 10583 static 10584 SCIP_RETCODE convertEquality( 10585 SCIP* scip, /**< SCIP data structure */ 10586 SCIP_CONS* cons, /**< linear constraint */ 10587 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */ 10588 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 10589 int* nfixedvars, /**< pointer to count number of fixed variables */ 10590 int* naggrvars, /**< pointer to count number of aggregated variables */ 10591 int* ndelconss /**< pointer to count number of deleted constraints */ 10592 ) 10593 { 10594 SCIP_CONSDATA* consdata; 10595 10596 assert(scip != NULL); 10597 assert(cons != NULL); 10598 assert(conshdlrdata != NULL); 10599 assert(cutoff != NULL); 10600 assert(nfixedvars != NULL); 10601 assert(naggrvars != NULL); 10602 assert(ndelconss != NULL); 10603 10604 consdata = SCIPconsGetData(cons); 10605 assert(consdata != NULL); 10606 assert(consdata->removedfixings); 10607 10608 /* do nothing on inequalities */ 10609 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) ) 10610 return SCIP_OKAY; 10611 10612 /* depending on the number of variables, call a special conversion method */ 10613 if( consdata->nvars == 1 ) 10614 { 10615 /* fix variable */ 10616 SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) ); 10617 } 10618 else if( consdata->nvars == 2 ) 10619 { 10620 /* aggregate one of the variables */ 10621 SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) ); 10622 } 10623 else 10624 { 10625 /* check if the equality is part of the objective function */ 10626 SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) ); 10627 10628 /* try to multi-aggregate one of the variables */ 10629 SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) ); 10630 } 10631 10632 return SCIP_OKAY; 10633 } 10634 10635 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always 10636 * integral 10637 */ 10638 static 10639 SCIP_Bool consdataIsResidualIntegral( 10640 SCIP* scip, /**< SCIP data structure */ 10641 SCIP_CONSDATA* consdata, /**< linear constraint */ 10642 int pos, /**< position of variable to be left out */ 10643 SCIP_Real val /**< value to divide the coefficients by */ 10644 ) 10645 { 10646 int v; 10647 10648 assert(scip != NULL); 10649 assert(consdata != NULL); 10650 assert(0 <= pos && pos < consdata->nvars); 10651 10652 for( v = 0; v < consdata->nvars; ++v ) 10653 { 10654 if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) ) 10655 return FALSE; 10656 } 10657 10658 return TRUE; 10659 } 10660 10661 /** check if \f$lhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$, 10662 * check if \f$rhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$ 10663 */ 10664 static 10665 void calculateMinvalAndMaxval( 10666 SCIP* scip, /**< SCIP data structure */ 10667 SCIP_Real side, /**< lhs or rhs */ 10668 SCIP_Real val, /**< coefficient */ 10669 SCIP_Real minresactivity, /**< minimal residual activity */ 10670 SCIP_Real maxresactivity, /**< maximal residual activity */ 10671 SCIP_Real* minval, /**< pointer to store calculated minval */ 10672 SCIP_Real* maxval /**< pointer to store calculated maxval */ 10673 ) 10674 { 10675 assert(scip != NULL); 10676 assert(minval != NULL); 10677 assert(maxval != NULL); 10678 10679 if( val > 0.0 ) 10680 { 10681 if( SCIPisInfinity(scip, ABS(maxresactivity)) ) 10682 *minval = -maxresactivity; 10683 else 10684 *minval = (side - maxresactivity)/val; 10685 10686 if( SCIPisInfinity(scip, ABS(minresactivity)) ) 10687 *maxval = -minresactivity; 10688 else 10689 *maxval = (side - minresactivity)/val; 10690 } 10691 else 10692 { 10693 if( SCIPisInfinity(scip, ABS(minresactivity)) ) 10694 *minval = minresactivity; 10695 else 10696 *minval = (side - minresactivity)/val; 10697 10698 if( SCIPisInfinity(scip, ABS(maxresactivity)) ) 10699 *maxval = maxresactivity; 10700 else 10701 *maxval = (side - maxresactivity)/val; 10702 } 10703 } 10704 10705 10706 /** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a 10707 * linear inequality 10708 */ 10709 static 10710 SCIP_RETCODE dualPresolve( 10711 SCIP* scip, /**< SCIP data structure */ 10712 SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */ 10713 SCIP_CONS* cons, /**< linear constraint */ 10714 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 10715 int* nfixedvars, /**< pointer to count number of fixed variables */ 10716 int* naggrvars, /**< pointer to count number of aggregated variables */ 10717 int* ndelconss /**< pointer to count number of deleted constraints */ 10718 ) 10719 { 10720 SCIP_CONSDATA* consdata; 10721 SCIP_Bool lhsexists; 10722 SCIP_Bool rhsexists; 10723 SCIP_Bool bestisint; 10724 SCIP_Bool bestislhs; 10725 SCIP_Real minabsval; 10726 SCIP_Real maxabsval; 10727 int bestpos; 10728 int i; 10729 int maxotherlocks; 10730 10731 assert(scip != NULL); 10732 assert(cons != NULL); 10733 assert(cutoff != NULL); 10734 assert(nfixedvars != NULL); 10735 assert(naggrvars != NULL); 10736 assert(ndelconss != NULL); 10737 10738 /* only process checked constraints (for which the locks are increased); 10739 * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the 10740 * dualfix presolver 10741 */ 10742 if( !SCIPconsIsChecked(cons) ) 10743 return SCIP_OKAY; 10744 10745 consdata = SCIPconsGetData(cons); 10746 assert(consdata != NULL); 10747 10748 lhsexists = !SCIPisInfinity(scip, -consdata->lhs); 10749 rhsexists = !SCIPisInfinity(scip, consdata->rhs); 10750 10751 /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we 10752 * can use it safely for aggregation and break the search loop 10753 */ 10754 bestpos = -1; 10755 bestisint = TRUE; 10756 bestislhs = FALSE; 10757 10758 /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint, 10759 * everything else would produce fill-in. Exceptions: 10760 * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be 10761 * produced. 10762 * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove 10763 * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add 10764 * six nonzeros (two variables per substitution). 10765 * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove 10766 * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add 10767 * six nonzeros (three variables per substitution). God exists! 10768 */ 10769 if( consdata->nvars <= 2 ) 10770 maxotherlocks = INT_MAX; 10771 else if( consdata->nvars == 3 ) 10772 maxotherlocks = 3; 10773 else if( consdata->nvars == 4 ) 10774 maxotherlocks = 2; 10775 else 10776 maxotherlocks = 1; 10777 10778 /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */ 10779 if( lhsexists && rhsexists && maxotherlocks < INT_MAX ) 10780 maxotherlocks++; 10781 10782 minabsval = SCIPinfinity(scip); 10783 maxabsval = -1.0; 10784 for( i = 0; i < consdata->nvars && bestisint; ++i ) 10785 { 10786 SCIP_VAR* var; 10787 SCIP_Bool isint; 10788 SCIP_Real val; 10789 SCIP_Real absval; 10790 SCIP_Real obj; 10791 SCIP_Real lb; 10792 SCIP_Real ub; 10793 SCIP_Bool agglhs; 10794 SCIP_Bool aggrhs; 10795 10796 val = consdata->vals[i]; 10797 absval = REALABS(val); 10798 10799 /* calculate minimal and maximal absolute value */ 10800 if( absval < minabsval ) 10801 minabsval = absval; 10802 if( absval > maxabsval ) 10803 maxabsval = absval; 10804 10805 /* do not try to multi aggregate, when numerical bad */ 10806 if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot ) 10807 return SCIP_OKAY; 10808 10809 var = consdata->vars[i]; 10810 isint = (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER); 10811 10812 /* if we already found a candidate, skip integers */ 10813 if( bestpos >= 0 && isint ) 10814 continue; 10815 10816 /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either 10817 * active, fixed, or single-aggregated with another binary variable 10818 */ 10819 if( SCIPvarIsBinary(var) && consdata->nvars > 2 ) 10820 continue; 10821 10822 if ( SCIPdoNotMultaggrVar(scip, var) ) 10823 continue; 10824 10825 val = consdata->vals[i]; 10826 obj = SCIPvarGetObj(var); 10827 lb = SCIPvarGetLbGlobal(var); 10828 ub = SCIPvarGetUbGlobal(var); 10829 10830 /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs 10831 * 10832 * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1: 10833 * - constraint is the only one that forbids fixing the variable to its lower bound 10834 * - fix x_i to the smallest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j 10835 * 10836 * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1: 10837 * - constraint is the only one that forbids fixing the variable to its upper bound 10838 * - fix x_i to the largest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j 10839 * 10840 * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1: 10841 * - constraint is the only one that forbids fixing the variable to its upper bound 10842 * - fix x_i to the largest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j 10843 * 10844 * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1: 10845 * - constraint is the only one that forbids fixing the variable to its lower bound 10846 * - fix x_i to the smallest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j 10847 * 10848 * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values 10849 * of all x_j 10850 * furthermore: we only want to apply this, if no fill-in will be produced 10851 */ 10852 agglhs = lhsexists 10853 && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1 10854 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks) 10855 || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1 10856 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)); 10857 aggrhs = rhsexists 10858 && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1 10859 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks) 10860 || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1 10861 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)); 10862 if( agglhs || aggrhs ) 10863 { 10864 SCIP_Real minresactivity; 10865 SCIP_Real maxresactivity; 10866 SCIP_Real minval; 10867 SCIP_Real maxval; 10868 SCIP_Bool minisrelax; 10869 SCIP_Bool maxisrelax; 10870 SCIP_Bool isminsettoinfinity; 10871 SCIP_Bool ismaxsettoinfinity; 10872 10873 /* calculate bounds for \sum_{j \neq i} a_j * x_j */ 10874 consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity, 10875 &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity); 10876 assert(SCIPisLE(scip, minresactivity, maxresactivity)); 10877 10878 /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation, 10879 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity. 10880 * This is needed, because we do not want to rely on relaxed finite resactivities. 10881 */ 10882 assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity)); 10883 10884 if( agglhs ) 10885 { 10886 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */ 10887 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval); 10888 10889 assert(SCIPisLE(scip, minval, maxval)); 10890 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) && 10891 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) ) 10892 { 10893 SCIP_Real oldmaxresactivity; 10894 SCIP_Real oldminresactivity; 10895 SCIP_Bool recalculated; 10896 10897 recalculated = FALSE; 10898 oldmaxresactivity = maxresactivity; 10899 oldminresactivity = minresactivity; 10900 10901 /* check minresactivity for reliability */ 10902 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) ) 10903 { 10904 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE); 10905 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity); 10906 isminsettoinfinity = TRUE; /* here it means only that it was even calculated */ 10907 } 10908 10909 /* check maxresactivity for reliability */ 10910 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) ) 10911 { 10912 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE); 10913 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity); 10914 ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */ 10915 } 10916 10917 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/ 10918 if( recalculated ) 10919 { 10920 assert(SCIPisLE(scip, minresactivity, maxresactivity)); 10921 10922 /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */ 10923 calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval); 10924 10925 assert(SCIPisLE(scip, minval, maxval)); 10926 } 10927 10928 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) ) 10929 { 10930 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied 10931 * in the multi-aggregation 10932 */ 10933 if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) ) 10934 { 10935 bestpos = i; 10936 bestisint = isint; 10937 bestislhs = TRUE; 10938 continue; /* no need to also look at the right hand side */ 10939 } 10940 } 10941 } 10942 } 10943 10944 if( aggrhs ) 10945 { 10946 /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */ 10947 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval); 10948 10949 assert(SCIPisLE(scip,minval,maxval)); 10950 if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) && 10951 (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) ) 10952 { 10953 SCIP_Real oldmaxresactivity; 10954 SCIP_Real oldminresactivity; 10955 SCIP_Bool recalculated; 10956 10957 recalculated = FALSE; 10958 oldmaxresactivity = maxresactivity; 10959 oldminresactivity = minresactivity; 10960 10961 /* check minresactivity for reliability */ 10962 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) ) 10963 { 10964 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE); 10965 recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity); 10966 } 10967 10968 /* check maxresactivity for reliability */ 10969 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) ) 10970 { 10971 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE); 10972 recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity); 10973 } 10974 10975 /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/ 10976 if( recalculated ) 10977 { 10978 /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */ 10979 calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval); 10980 assert(SCIPisLE(scip,minval,maxval)); 10981 } 10982 10983 if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) ) 10984 { 10985 /* if the variable is integer, we have to check whether the integrality condition would always be satisfied 10986 * in the multi-aggregation 10987 */ 10988 if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) ) 10989 { 10990 bestpos = i; 10991 bestisint = isint; 10992 bestislhs = FALSE; 10993 } 10994 } 10995 } 10996 } 10997 } 10998 } 10999 11000 if( bestpos >= 0 ) 11001 { 11002 SCIP_VAR** aggrvars; 11003 SCIP_Real* aggrcoefs; 11004 SCIP_Real aggrconst; 11005 SCIP_VAR* bestvar; 11006 SCIP_Real bestval; 11007 SCIP_Real epsilon; 11008 int naggrs; 11009 int j; 11010 SCIP_Bool infeasible; 11011 SCIP_Bool aggregated; 11012 SCIP_Bool samevar; 11013 int supinf; /* counter for infinite contributions to the supremum of a possible 11014 * multi-aggregation 11015 */ 11016 int infinf; /* counter for infinite contributions to the infimum of a possible 11017 * multi-aggregation 11018 */ 11019 11020 assert(!bestislhs || lhsexists); 11021 assert(bestislhs || rhsexists); 11022 11023 bestvar = consdata->vars[bestpos]; 11024 bestval = consdata->vals[bestpos]; 11025 assert(bestisint == 11026 (SCIPvarGetType(bestvar) == SCIP_VARTYPE_BINARY || SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER)); 11027 11028 /* allocate temporary memory */ 11029 SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) ); 11030 SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) ); 11031 11032 /* set up the multi-aggregation */ 11033 SCIPdebugPrintCons(scip, cons, NULL); 11034 SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar)); 11035 naggrs = 0; 11036 supinf = 0; 11037 infinf = 0; 11038 samevar = FALSE; 11039 epsilon = SCIPepsilon(scip); 11040 11041 for( j = 0; j < consdata->nvars; ++j ) 11042 { 11043 if( j != bestpos ) 11044 { 11045 SCIP_Real absaggrcoef; 11046 11047 aggrvars[naggrs] = consdata->vars[j]; 11048 aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos]; 11049 SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs])); 11050 11051 absaggrcoef = REALABS(aggrcoefs[naggrs]); 11052 11053 /* do not try to multi aggregate, when numerical bad */ 11054 if( absaggrcoef < epsilon ) 11055 { 11056 SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n"); 11057 11058 /* free temporary memory */ 11059 SCIPfreeBufferArray(scip, &aggrcoefs); 11060 SCIPfreeBufferArray(scip, &aggrvars); 11061 11062 return SCIP_OKAY; 11063 } 11064 11065 if( bestisint ) 11066 { 11067 /* coefficient must be integral: round it to exact integral value */ 11068 assert(SCIPisIntegral(scip, aggrcoefs[naggrs])); 11069 aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5); 11070 } 11071 11072 if( SCIPisPositive(scip, aggrcoefs[naggrs]) ) 11073 { 11074 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) ) 11075 { 11076 ++supinf; 11077 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) ) 11078 { 11079 ++infinf; 11080 samevar = TRUE; 11081 } 11082 } 11083 else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) ) 11084 ++infinf; 11085 } 11086 else if( SCIPisNegative(scip, aggrcoefs[naggrs]) ) 11087 { 11088 if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) ) 11089 { 11090 ++supinf; 11091 if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) ) 11092 { 11093 ++infinf; 11094 samevar = TRUE; 11095 } 11096 } 11097 else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) ) 11098 ++infinf; 11099 } 11100 11101 naggrs++; 11102 } 11103 } 11104 assert(!samevar || (supinf > 0 && infinf > 0)); 11105 11106 aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval); 11107 SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar), 11108 SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar)); 11109 assert(naggrs == consdata->nvars-1); 11110 11111 /* right hand side must be integral: round it to exact integral value */ 11112 if( bestisint ) 11113 { 11114 assert(SCIPisIntegral(scip, aggrconst)); 11115 aggrconst = SCIPfloor(scip, aggrconst+0.5); 11116 } 11117 11118 aggregated = FALSE; 11119 infeasible = FALSE; 11120 11121 /* perform the multi-aggregation */ 11122 if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) ) 11123 { 11124 /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see 11125 * also convertLongEquality() early termination due to coefficients 11126 */ 11127 SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) ); 11128 11129 /* if the multi-aggregate bestvar is integer, we need to convert implicit integers to integers because 11130 * the implicitness might rely on the constraint and the integrality of bestvar 11131 */ 11132 if( !infeasible && aggregated && SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER ) 11133 { 11134 SCIP_Bool infeasiblevartypechg; 11135 11136 for( j = 0; j < naggrs; ++j) 11137 { 11138 /* If the multi-aggregation was not infeasible, then setting implicit integers to integers should not 11139 * lead to infeasibility 11140 */ 11141 if( SCIPvarGetType(aggrvars[j]) == SCIP_VARTYPE_IMPLINT ) 11142 { 11143 SCIP_CALL( SCIPchgVarType(scip, aggrvars[j], SCIP_VARTYPE_INTEGER, &infeasiblevartypechg) ); 11144 assert(!infeasiblevartypechg); 11145 } 11146 } 11147 } 11148 } 11149 else 11150 { 11151 /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable. 11152 * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */ 11153 SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n"); 11154 } 11155 /* free temporary memory */ 11156 SCIPfreeBufferArray(scip, &aggrcoefs); 11157 SCIPfreeBufferArray(scip, &aggrvars); 11158 11159 /* check for infeasible aggregation */ 11160 if( infeasible ) 11161 { 11162 SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons)); 11163 *cutoff = TRUE; 11164 return SCIP_OKAY; 11165 } 11166 11167 /* delete the constraint, if the aggregation was successful */ 11168 if( aggregated ) 11169 { 11170 SCIP_CALL( SCIPdelCons(scip, cons) ); 11171 11172 if( !consdata->upgraded ) 11173 (*ndelconss)++; 11174 (*naggrvars)++; 11175 } 11176 else 11177 { 11178 SCIPdebugMsg(scip, "aggregation non successful!\n"); 11179 } 11180 } 11181 11182 return SCIP_OKAY; 11183 } 11184 11185 #define BINWEIGHT 1 11186 #define INTWEIGHT 4 11187 #define CONTWEIGHT 8 11188 11189 /** gets weight for variable in a "weighted number of variables" sum */ 11190 static 11191 int getVarWeight( 11192 SCIP_VAR* var /**< variable to get weight for */ 11193 ) 11194 { 11195 switch( SCIPvarGetType(var) ) 11196 { 11197 case SCIP_VARTYPE_BINARY: 11198 return BINWEIGHT; 11199 case SCIP_VARTYPE_INTEGER: 11200 case SCIP_VARTYPE_IMPLINT: 11201 return INTWEIGHT; 11202 case SCIP_VARTYPE_CONTINUOUS: 11203 return CONTWEIGHT; 11204 default: 11205 SCIPerrorMessage("invalid variable type\n"); 11206 SCIPABORT(); 11207 return 0; /*lint !e527*/ 11208 } 11209 } 11210 11211 /** tries to aggregate variables in equations a^Tx = lhs 11212 * in case there are at most two binary variables with an odd coefficient and all other 11213 * variables are not continuous and have an even coefficient then: 11214 * - exactly one odd binary variables 11215 * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd 11216 * - lhs is odd -> y = 1 11217 * - lhs is even -> y = 0 11218 * - exactly two odd binary variables 11219 * aggregate the two binary variables with odd coefficient 11220 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1 11221 * - lhs is even -> both have to take the same value -> var1 - var2 = 0 11222 */ 11223 static 11224 SCIP_RETCODE aggregateVariables( 11225 SCIP* scip, /**< SCIP data structure */ 11226 SCIP_CONS* cons, /**< linear constraint */ 11227 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 11228 int* nfixedvars, /**< pointer to count number of fixed variables */ 11229 int* naggrvars /**< pointer to count number of aggregated variables */ 11230 ) 11231 { /*lint --e{715}*/ 11232 SCIP_CONSDATA* consdata; 11233 SCIP_Bool success; 11234 11235 assert( scip != NULL ); 11236 assert( cons != NULL ); 11237 11238 consdata = SCIPconsGetData(cons); 11239 assert( consdata != NULL ); 11240 11241 /* check if the linear constraint is an equation with integral right hand side */ 11242 if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) ) 11243 return SCIP_OKAY; 11244 11245 /* try to fix and aggregated variables until nothing is possible anymore */ 11246 do 11247 { 11248 int v; 11249 int nvars; 11250 SCIP_VAR** vars; 11251 SCIP_Real* vals; 11252 SCIP_Real lhs; 11253 SCIP_Bool lhsodd; 11254 11255 SCIP_Bool infeasible; 11256 SCIP_Bool fixed; 11257 SCIP_Bool aggregated; 11258 SCIP_Bool redundant; 11259 11260 SCIP_VAR* var1; 11261 SCIP_VAR* var2; 11262 int noddvars; 11263 11264 success = FALSE; 11265 11266 lhs = consdata->lhs; 11267 vars = consdata->vars; 11268 vals = consdata->vals; 11269 nvars = consdata->nvars; 11270 11271 assert( !SCIPisInfinity(scip, ABS(lhs)) ); 11272 11273 var1 = NULL; 11274 var2 = NULL; 11275 noddvars = 0; 11276 11277 /* search for binary variables with an odd coefficient */ 11278 for( v = 0; v < nvars && noddvars < 3; ++v ) 11279 { 11280 SCIP_Longint val; 11281 11282 /* all coefficients and variables have to be integral */ 11283 if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ) 11284 return SCIP_OKAY; 11285 11286 val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]); 11287 if( val % 2 != 0 ) 11288 { 11289 /* the odd values have to belong to binary variables */ 11290 if( !SCIPvarIsBinary(vars[v]) ) 11291 return SCIP_OKAY; 11292 11293 if( noddvars == 0 ) 11294 var1 = vars[v]; 11295 else 11296 var2 = vars[v]; 11297 11298 noddvars++; 11299 } 11300 } 11301 11302 /* check lhs is odd or even */ 11303 lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0); 11304 11305 if( noddvars == 1 ) 11306 { 11307 assert( var1 != NULL ); 11308 11309 SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n", 11310 SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0); 11311 11312 SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) ); 11313 11314 /* check for infeasibility of fixing */ 11315 if( infeasible ) 11316 { 11317 SCIPdebugMsg(scip, " -> infeasible fixing\n"); 11318 *cutoff = TRUE; 11319 return SCIP_OKAY; 11320 } 11321 11322 if( fixed ) 11323 { 11324 SCIPdebugMsg(scip, " -> feasible fixing\n"); 11325 (*nfixedvars)++; 11326 success = TRUE; 11327 } 11328 } 11329 else if( noddvars == 2 ) 11330 { 11331 assert( var1 != NULL ); 11332 assert( var2 != NULL ); 11333 11334 /* aggregate the two variables with odd coefficient 11335 * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1 11336 * - lhs is even -> both have to take the same value -> var1 - var2 = 0 11337 */ 11338 SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n", 11339 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2)); 11340 11341 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0, 11342 lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) ); 11343 11344 /* check for infeasibility of aggregation */ 11345 if( infeasible ) 11346 { 11347 SCIPdebugMsg(scip, " -> infeasible aggregation\n"); 11348 *cutoff = TRUE; 11349 return SCIP_OKAY; 11350 } 11351 11352 /* count the aggregation */ 11353 if( aggregated ) 11354 { 11355 SCIPdebugMsg(scip, " -> feasible aggregation\n"); 11356 (*naggrvars)++; 11357 success = TRUE; 11358 } 11359 } 11360 11361 if( success ) 11362 { 11363 /* apply fixings and aggregation to successfully rerun this presolving step */ 11364 SCIP_CALL( applyFixings(scip, cons, &infeasible) ); 11365 11366 if( infeasible ) 11367 { 11368 SCIPdebugMsg(scip, " -> infeasible fixing\n"); 11369 *cutoff = TRUE; 11370 return SCIP_OKAY; 11371 } 11372 11373 /* normalize constraint */ 11374 SCIP_CALL( normalizeCons(scip, cons, &infeasible) ); 11375 11376 if( infeasible ) 11377 { 11378 SCIPdebugMsg(scip, " -> infeasible normalization\n"); 11379 *cutoff = TRUE; 11380 return SCIP_OKAY; 11381 } 11382 } 11383 } 11384 while( success ); 11385 11386 return SCIP_OKAY; 11387 } 11388 11389 11390 11391 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to 11392 * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the 11393 * coefficients 11394 */ 11395 static 11396 SCIP_DECL_SORTINDCOMP(consdataCompSim) 11397 { /*lint --e{715}*/ 11398 SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr; 11399 SCIP_VARTYPE vartype1; 11400 SCIP_VARTYPE vartype2; 11401 SCIP_Real value; 11402 11403 assert(consdata != NULL); 11404 assert(0 <= ind1 && ind1 < consdata->nvars); 11405 assert(0 <= ind2 && ind2 < consdata->nvars); 11406 11407 vartype1 = SCIPvarGetType(consdata->vars[ind1]); 11408 vartype2 = SCIPvarGetType(consdata->vars[ind2]); 11409 11410 if( vartype1 == SCIP_VARTYPE_CONTINUOUS ) 11411 { 11412 /* continuous varibles will be sorted to the back */ 11413 if( vartype2 != vartype1 ) 11414 return +1; 11415 /* both variables are continuous */ 11416 else 11417 return 0; 11418 } 11419 /* continuous variables will be sorted to the back */ 11420 else if( vartype2 == SCIP_VARTYPE_CONTINUOUS ) 11421 return -1; 11422 11423 value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]); 11424 11425 /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */ 11426 return (value > 0 ? +1 : (value < 0 ? -1 : 0)); 11427 } 11428 11429 /** tries to simplify coefficients in ranged row of the form lhs <= a^Tx <= rhs 11430 * 11431 * 1. lhs <= a^Tx <= rhs, x binary, lhs > 0, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs, 11432 * then we can change this constraint to 1^Tx = 1 11433 */ 11434 static 11435 SCIP_RETCODE rangedRowSimplify( 11436 SCIP* scip, /**< SCIP data structure */ 11437 SCIP_CONS* cons, /**< linear constraint */ 11438 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */ 11439 int* nchgsides /**< pointer to store the amount of changed sides */ 11440 ) 11441 { 11442 SCIP_CONSDATA* consdata; 11443 SCIP_VAR** vars; 11444 SCIP_Real* vals; 11445 SCIP_Real minval; 11446 SCIP_Real secondminval; 11447 SCIP_Real maxval; 11448 SCIP_Real lhs; 11449 SCIP_Real rhs; 11450 int nvars; 11451 int v; 11452 11453 /* we must not change a modifiable constraint in any way */ 11454 if( SCIPconsIsModifiable(cons) ) 11455 return SCIP_OKAY; 11456 11457 if( SCIPconsIsDeleted(cons) ) 11458 return SCIP_OKAY; 11459 11460 consdata = SCIPconsGetData(cons); 11461 assert(consdata != NULL); 11462 11463 nvars = consdata->nvars; 11464 11465 /* do not check empty or bound-constraints */ 11466 if( nvars < 2 ) 11467 return SCIP_OKAY; 11468 11469 lhs = consdata->lhs; 11470 rhs = consdata->rhs; 11471 assert(!SCIPisInfinity(scip, -lhs)); 11472 assert(!SCIPisInfinity(scip, rhs)); 11473 assert(!SCIPisNegative(scip, rhs)); 11474 11475 /* sides must be positive and different to detect set partition */ 11476 if( !SCIPisPositive(scip, lhs) || !SCIPisLT(scip, lhs, rhs) ) 11477 return SCIP_OKAY; 11478 11479 vals = consdata->vals; 11480 vars = consdata->vars; 11481 assert(vars != NULL); 11482 assert(vals != NULL); 11483 11484 minval = SCIP_INVALID; 11485 secondminval = SCIP_INVALID; 11486 maxval = -SCIP_INVALID; 11487 11488 for( v = nvars - 1; v >= 0; --v ) 11489 { 11490 if( SCIPvarIsBinary(vars[v]) ) 11491 { 11492 if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/ 11493 { 11494 secondminval = minval; 11495 minval = vals[v]; 11496 } 11497 else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/ 11498 secondminval = vals[v]; 11499 11500 if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/ 11501 maxval = vals[v]; 11502 } 11503 else 11504 break; 11505 } 11506 11507 /* check if all variables are binary, we can choose one, and need to choose at most one */ 11508 if( v == -1 && SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) 11509 && SCIPisGT(scip, minval + secondminval, rhs) ) 11510 { 11511 /* change all coefficients to 1.0 */ 11512 for( v = nvars - 1; v >= 0; --v ) 11513 { 11514 SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) ); 11515 } 11516 (*nchgcoefs) += nvars; 11517 11518 /* replace old right and left hand side with 1.0 */ 11519 SCIP_CALL( chgRhs(scip, cons, 1.0) ); 11520 SCIP_CALL( chgLhs(scip, cons, 1.0) ); 11521 (*nchgsides) += 2; 11522 } 11523 11524 return SCIP_OKAY; 11525 } 11526 11527 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs 11528 * 11529 * for both-sided constraints only @see rangedRowSimplify() will be called 11530 * 11531 * for one-sided constraints there are several different coefficient reduction steps which will be applied 11532 * 11533 * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint 11534 * 11535 * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3 11536 * 11537 * 2. We try to remove redundant fractional parts in a constraint 11538 * 11539 * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary 11540 * 11541 * 3. We are using the greatest common divisor for further reductions 11542 * 11543 * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is 11544 * integral 11545 */ 11546 static 11547 SCIP_RETCODE simplifyInequalities( 11548 SCIP* scip, /**< SCIP data structure */ 11549 SCIP_CONS* cons, /**< linear constraint */ 11550 int* nchgcoefs, /**< pointer to store the amount of changed coefficients */ 11551 int* nchgsides, /**< pointer to store the amount of changed sides */ 11552 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */ 11553 ) 11554 { 11555 SCIP_CONSDATA* consdata; 11556 SCIP_VAR** vars; 11557 SCIP_Real* vals; 11558 int* perm; 11559 SCIP_Real minactsub; 11560 SCIP_Real maxactsub; 11561 SCIP_Real siderest; 11562 SCIP_Real feastol; 11563 SCIP_Real newcoef; 11564 SCIP_Real absval; 11565 SCIP_Real minact; 11566 SCIP_Real maxact; 11567 SCIP_Real side; 11568 SCIP_Real lhs; 11569 SCIP_Real rhs; 11570 SCIP_Real lb; 11571 SCIP_Real ub; 11572 SCIP_Longint restcoef; 11573 SCIP_Longint oldgcd; 11574 SCIP_Longint rest; 11575 SCIP_Longint gcd; 11576 SCIP_Bool isminsettoinfinity; 11577 SCIP_Bool ismaxsettoinfinity; 11578 SCIP_Bool isminrelax; 11579 SCIP_Bool ismaxrelax; 11580 SCIP_Bool allcoefintegral; 11581 SCIP_Bool onlybin; 11582 SCIP_Bool hasrhs; 11583 SCIP_Bool haslhs; 11584 int oldnchgcoefs; 11585 int oldnchgsides; 11586 int foundbin; 11587 int candpos; 11588 int candpos2; 11589 int offsetv; 11590 int nvars; 11591 int v; 11592 int w; 11593 11594 assert(scip != NULL); 11595 assert(cons != NULL); 11596 assert(nchgcoefs != NULL); 11597 assert(nchgsides != NULL); 11598 11599 *infeasible = FALSE; 11600 11601 /* we must not change a modifiable constraint in any way */ 11602 if( SCIPconsIsModifiable(cons) ) 11603 return SCIP_OKAY; 11604 11605 if( SCIPconsIsDeleted(cons) ) 11606 return SCIP_OKAY; 11607 11608 consdata = SCIPconsGetData(cons); 11609 assert(consdata != NULL); 11610 11611 nvars = consdata->nvars; 11612 11613 /* do not check empty or bound-constraints */ 11614 if( nvars <= 2 ) 11615 return SCIP_OKAY; 11616 11617 /* update maximal activity delta if necessary */ 11618 if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/ 11619 consdataRecomputeMaxActivityDelta(scip, consdata); 11620 11621 assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/ 11622 assert(!SCIPisFeasNegative(scip, consdata->maxactdelta)); 11623 checkMaxActivityDelta(scip, consdata); 11624 11625 /* @todo the following might be too hard, check which steps can be applied and what code must be corrected 11626 * accordingly 11627 */ 11628 /* can only work with valid non-infinity activities per variable */ 11629 if( SCIPisInfinity(scip, consdata->maxactdelta) ) 11630 return SCIP_OKAY; 11631 11632 /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event 11633 * but the eventsystem seems to be full 11634 */ 11635 consdata->normalized = FALSE; 11636 11637 /* normalize constraint */ 11638 SCIP_CALL( normalizeCons(scip, cons, infeasible) ); 11639 assert(nvars == consdata->nvars); 11640 11641 if( *infeasible ) 11642 return SCIP_OKAY; 11643 11644 if( !consdata->normalized ) 11645 return SCIP_OKAY; 11646 11647 lhs = consdata->lhs; 11648 rhs = consdata->rhs; 11649 assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs)); 11650 assert(!SCIPisNegative(scip, rhs)); 11651 11652 if( !SCIPisInfinity(scip, -lhs) ) 11653 haslhs = TRUE; 11654 else 11655 haslhs = FALSE; 11656 11657 if( !SCIPisInfinity(scip, rhs) ) 11658 hasrhs = TRUE; 11659 else 11660 hasrhs = FALSE; 11661 11662 SCIPdebug( oldnchgcoefs = *nchgcoefs; ) 11663 SCIPdebug( oldnchgsides = *nchgsides; ) 11664 11665 /* @todo extend both-sided simplification */ 11666 if( haslhs && hasrhs ) 11667 { 11668 SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) ); 11669 11670 return SCIP_OKAY; 11671 } 11672 assert(haslhs != hasrhs); 11673 11674 /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */ 11675 assert(!hasrhs || !SCIPisNegative(scip, rhs)); 11676 assert(!haslhs || !SCIPisNegative(scip, lhs)); 11677 11678 /* get temporary memory to store the sorted permutation */ 11679 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) ); 11680 11681 /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute 11682 * value of their coefficients 11683 */ 11684 SCIPsort(perm, consdataCompSim, (void*)consdata, nvars); 11685 11686 /* perform sorting after permutation array */ 11687 permSortConsdata(consdata, perm, nvars); 11688 consdata->indexsorted = FALSE; 11689 consdata->coefsorted = FALSE; 11690 11691 vars = consdata->vars; 11692 vals = consdata->vals; 11693 assert(vars != NULL); 11694 assert(vals != NULL); 11695 assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE); 11696 11697 /* free temporary memory */ 11698 SCIPfreeBufferArray(scip, &perm); 11699 11700 /* only check constraints with at least two non continuous variables */ 11701 if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS ) 11702 return SCIP_OKAY; 11703 11704 /* do not process constraints when all coefficients are 1.0 */ 11705 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) ) 11706 return SCIP_OKAY; 11707 11708 feastol = SCIPfeastol(scip); 11709 11710 SCIPdebugMsg(scip, "starting simplification of coefficients\n"); 11711 SCIPdebugPrintCons(scip, cons, NULL); 11712 11713 /* get global activities */ 11714 consdataGetGlbActivityBounds(scip, consdata, FALSE, &minact, &maxact, 11715 &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity); 11716 11717 /* cannot work with infinite activities */ 11718 if( isminsettoinfinity || ismaxsettoinfinity ) 11719 return SCIP_OKAY; 11720 11721 assert(!isminrelax); 11722 assert(!ismaxrelax); 11723 assert(maxact > minact); 11724 assert(!SCIPisInfinity(scip, -minact)); 11725 assert(!SCIPisInfinity(scip, maxact)); 11726 11727 v = 0; 11728 offsetv = -1; 11729 side = haslhs ? lhs : rhs; 11730 minactsub = minact; 11731 maxactsub = maxact; 11732 11733 /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we 11734 * do not need to look at the large coefficients 11735 * 11736 * e.g. all x are binary, z are positive integer 11737 * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint) 11738 * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3 11739 * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7 11740 * 11741 * can be changed to 11742 * 11743 * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2) 11744 * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2) 11745 * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4) 11746 */ 11747 11748 /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left 11749 * hand side, we cannot apply the extra reduction step and need to reset v 11750 * 11751 * e.g. 7x1 + 7x2 - 4x3 - 4x4 >= 7 => xi = 1 for all i is not a solution, but if we would do a change on the 11752 * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1 11753 * for all i is a solution 11754 * 11755 * also redundancy of variables would not be correctly determined in such a case 11756 */ 11757 if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) ) 11758 { 11759 v = 1; 11760 11761 while( v < nvars && SCIPisEQ(scip, side, vals[v]) ) 11762 { 11763 /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this 11764 * extra step, which might have worked 11765 */ 11766 if( SCIPvarGetLbGlobal(vars[v]) > 0.5 ) 11767 { 11768 v = 0; 11769 break; 11770 } 11771 11772 ++v; 11773 } 11774 11775 /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */ 11776 /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */ 11777 if( v == nvars ) 11778 return SCIP_OKAY; 11779 11780 /* cannot work with continuous variables which have a big coefficient */ 11781 if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS ) 11782 return SCIP_OKAY; 11783 11784 /* big negative coefficient, do not try to use the extra coefficient reduction step */ 11785 if( SCIPisEQ(scip, side, -vals[v]) ) 11786 v = 0; 11787 11788 /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient 11789 * reduction 11790 */ 11791 if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ) 11792 v = 0; 11793 11794 if( v > 0 ) 11795 { 11796 assert(v < nvars); 11797 11798 offsetv = v - 1; 11799 11800 for( w = 0; w < v; ++w ) 11801 { 11802 lb = SCIPvarGetLbGlobal(vars[w]); 11803 ub = SCIPvarGetUbGlobal(vars[w]); 11804 11805 assert(vals[w] > 0); 11806 11807 /* update residual activities */ 11808 maxactsub -= ub * vals[w]; 11809 minactsub -= lb * vals[w]; 11810 assert(maxactsub > minactsub); 11811 } 11812 } 11813 } 11814 11815 /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint 11816 * 11817 * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce 11818 * 11819 * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26 11820 * to 11821 * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1 11822 */ 11823 if( nvars > 2 && SCIPisIntegral(scip, vals[v]) ) 11824 { 11825 SCIP_Bool redundant = FALSE; 11826 SCIP_Bool numericsok; 11827 SCIP_Bool rredundant; 11828 SCIP_Bool lredundant; 11829 11830 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol); 11831 assert(gcd >= 1); 11832 11833 if( v == 0 ) 11834 { 11835 lb = SCIPvarGetLbGlobal(vars[0]); 11836 ub = SCIPvarGetUbGlobal(vars[0]); 11837 11838 /* update residual activities */ 11839 if( vals[0] > 0 ) 11840 { 11841 maxactsub -= ub * vals[0]; 11842 minactsub -= lb * vals[0]; 11843 } 11844 else 11845 { 11846 maxactsub -= lb * vals[0]; 11847 minactsub -= ub * vals[0]; 11848 } 11849 assert(maxactsub > minactsub); 11850 ++v; 11851 } 11852 11853 siderest = -SCIP_INVALID; 11854 allcoefintegral = TRUE; 11855 11856 /* check if some variables always fit into the given constraint */ 11857 for( ; v < nvars - 1; ++v ) 11858 { 11859 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ) 11860 break; 11861 11862 if( !SCIPisIntegral(scip, vals[v]) ) 11863 { 11864 allcoefintegral = FALSE; 11865 break; 11866 } 11867 11868 /* calculate greatest common divisor for all general and binary variables */ 11869 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol)); 11870 11871 if( gcd == 1 ) 11872 break; 11873 11874 lb = SCIPvarGetLbGlobal(vars[v]); 11875 ub = SCIPvarGetUbGlobal(vars[v]); 11876 11877 assert(!SCIPisInfinity(scip, -lb)); 11878 assert(!SCIPisInfinity(scip, ub)); 11879 11880 /* update residual activities */ 11881 if( vals[v] > 0 ) 11882 { 11883 maxactsub -= ub * vals[v]; 11884 minactsub -= lb * vals[v]; 11885 } 11886 else 11887 { 11888 maxactsub -= lb * vals[v]; 11889 minactsub -= ub * vals[v]; 11890 } 11891 assert(SCIPisGE(scip, maxactsub, minactsub)); 11892 11893 if( hasrhs ) 11894 { 11895 /* determine the remainder of the right hand side and the gcd */ 11896 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd; 11897 } 11898 else 11899 { 11900 /* determine the remainder of the left hand side and the gcd */ 11901 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd; 11902 if( SCIPisZero(scip, siderest) ) 11903 siderest = gcd; 11904 } 11905 11906 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd); 11907 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd; 11908 11909 /* early termination if the activities deceed the gcd */ 11910 if( offsetv == -1 && (rredundant || lredundant) ) 11911 { 11912 redundant = TRUE; 11913 break; 11914 } 11915 } 11916 assert(v < nvars || (offsetv >= 0 && gcd > 1)); 11917 11918 if( !redundant ) 11919 { 11920 if( hasrhs ) 11921 { 11922 /* determine the remainder of the right hand side and the gcd */ 11923 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd; 11924 } 11925 else 11926 { 11927 /* determine the remainder of the left hand side and the gcd */ 11928 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd; 11929 if( SCIPisZero(scip, siderest) ) 11930 siderest = gcd; 11931 } 11932 } 11933 else 11934 ++v; 11935 11936 SCIPdebugMsg(scip, "stopped at pos %d (of %d), subactivities [%g, %g], redundant = %u, hasrhs = %u, siderest = %g, gcd = %" SCIP_LONGINT_FORMAT ", offset position for 'side' coefficients = %d\n", 11937 v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv); 11938 11939 /* to avoid inconsistencies due to numerics, check that the full and partial activities have 11940 * reasonable absolute values */ 11941 numericsok = REALABS(maxact) < MAXACTVAL && REALABS(maxactsub) < MAXACTVAL && REALABS(minact) < MAXACTVAL && 11942 REALABS(minactsub) < MAXACTVAL; 11943 11944 rredundant = hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd); 11945 lredundant = haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd; 11946 11947 /* check if we can remove redundant variables */ 11948 if( v < nvars && numericsok && (redundant || (offsetv == -1 && (rredundant || lredundant))) ) 11949 { 11950 SCIP_Real oldcoef; 11951 11952 /* double check the redundancy */ 11953 #ifndef NDEBUG 11954 SCIP_Real tmpminactsub = 0.0; 11955 SCIP_Real tmpmaxactsub = 0.0; 11956 11957 /* recompute residual activities */ 11958 for( w = v; w < nvars; ++w ) 11959 { 11960 lb = SCIPvarGetLbGlobal(vars[w]); 11961 ub = SCIPvarGetUbGlobal(vars[w]); 11962 11963 assert(!SCIPisInfinity(scip, -lb)); 11964 assert(!SCIPisInfinity(scip, ub)); 11965 11966 /* update residual activities */ 11967 if( vals[w] > 0 ) 11968 { 11969 tmpmaxactsub += ub * vals[w]; 11970 tmpminactsub += lb * vals[w]; 11971 } 11972 else 11973 { 11974 tmpmaxactsub += lb * vals[w]; 11975 tmpminactsub += ub * vals[w]; 11976 } 11977 assert(tmpmaxactsub >= tmpminactsub); 11978 } 11979 11980 if( hasrhs ) 11981 { 11982 assert(offsetv == -1); 11983 11984 /* determine the remainder of the right hand side and the gcd */ 11985 siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd; 11986 } 11987 else 11988 { 11989 /* determine the remainder of the left hand side and the gcd */ 11990 siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd; 11991 if( SCIPisZero(scip, siderest) ) 11992 siderest = gcd; 11993 } 11994 11995 /* is the redundancy really fulfilled */ 11996 assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || 11997 (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd))); 11998 #endif 11999 12000 SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n", 12001 nvars - v, SCIPconsGetName(cons)); 12002 12003 /* remove redundant variables */ 12004 for( w = nvars - 1; w >= v; --w ) 12005 { 12006 SCIP_CALL( delCoefPos(scip, cons, w) ); 12007 } 12008 (*nchgcoefs) += (nvars - v); 12009 12010 assert(w >= 0); 12011 12012 oldcoef = vals[w]; 12013 12014 /* normalize constraint */ 12015 SCIP_CALL( normalizeCons(scip, cons, infeasible) ); 12016 assert(vars == consdata->vars); 12017 assert(vals == consdata->vals); 12018 assert(w < consdata->nvars); 12019 12020 if( *infeasible ) 12021 return SCIP_OKAY; 12022 12023 /* compute new greatest common divisor due to normalization */ 12024 gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol); 12025 assert(gcd >= 1); 12026 12027 /* update side */ 12028 if( hasrhs ) 12029 { 12030 /* replace old with new right hand side */ 12031 SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) ); 12032 rhs = consdata->rhs; 12033 } 12034 else 12035 { 12036 if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) ) 12037 { 12038 SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) ); 12039 lhs = consdata->lhs; 12040 } 12041 else 12042 assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs)); 12043 } 12044 ++(*nchgsides); 12045 12046 assert(!hasrhs || !SCIPisNegative(scip, rhs)); 12047 assert(!haslhs || !SCIPisNegative(scip, lhs)); 12048 12049 /* get new constraint data */ 12050 nvars = consdata->nvars; 12051 assert(nvars > 0); 12052 12053 allcoefintegral = TRUE; 12054 12055 #ifndef NDEBUG 12056 /* check integrality */ 12057 for( w = offsetv + 1; w < nvars; ++w ) 12058 { 12059 assert(SCIPisIntegral(scip, vals[w])); 12060 } 12061 #endif 12062 SCIPdebugPrintCons(scip, cons, NULL); 12063 } 12064 12065 /* try to find a better gcd, when having large coefficients */ 12066 if( offsetv >= 0 && gcd == 1 ) 12067 { 12068 /* calculate greatest common divisor for all general variables */ 12069 gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol); 12070 12071 if( gcd > 1 ) 12072 { 12073 gcd = -1; 12074 candpos = -1; 12075 12076 for( v = nvars - 1; v > offsetv; --v ) 12077 { 12078 assert(!SCIPisZero(scip, vals[v])); 12079 if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ) 12080 break; 12081 12082 if( !SCIPisIntegral(scip, vals[v]) ) 12083 { 12084 allcoefintegral = FALSE; 12085 break; 12086 } 12087 12088 oldgcd = gcd; 12089 12090 if( gcd == -1 ) 12091 { 12092 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol); 12093 assert(gcd >= 1); 12094 } 12095 else 12096 { 12097 /* calculate greatest common divisor for all general and binary variables */ 12098 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol)); 12099 } 12100 12101 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we 12102 * can stop searching 12103 */ 12104 if( gcd == 1 ) 12105 { 12106 if( !SCIPvarIsBinary(vars[v]) ) 12107 break; 12108 12109 /* found candidate */ 12110 if( candpos == -1 ) 12111 { 12112 gcd = oldgcd; 12113 candpos = v; 12114 } 12115 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */ 12116 else 12117 break; 12118 } 12119 } 12120 assert(v > offsetv || candpos > offsetv); 12121 } 12122 else 12123 candpos = -1; 12124 } 12125 else 12126 candpos = nvars - 1; 12127 12128 /* check last coefficient for integrality */ 12129 if( gcd > 1 && allcoefintegral && !redundant ) 12130 { 12131 if( !SCIPisIntegral(scip, vals[nvars - 1]) ) 12132 allcoefintegral = FALSE; 12133 } 12134 12135 /* check for further necessary coefficient adjustments */ 12136 if( offsetv >= 0 && gcd > 1 && allcoefintegral ) 12137 { 12138 assert(offsetv + 1 < nvars); 12139 assert(0 <= candpos && candpos < nvars); 12140 12141 if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS ) 12142 { 12143 SCIP_Bool notchangable = FALSE; 12144 12145 #ifndef NDEBUG 12146 /* check integrality */ 12147 for( w = offsetv + 1; w < nvars; ++w ) 12148 { 12149 assert(SCIPisIntegral(scip, vals[w])); 12150 } 12151 #endif 12152 12153 if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) && 12154 SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd ) 12155 { 12156 /* determine the remainder of the side and the gcd */ 12157 if( hasrhs ) 12158 rest = ((SCIP_Longint)(rhs + feastol)) % gcd; 12159 else 12160 rest = ((SCIP_Longint)(lhs + feastol)) % gcd; 12161 assert(rest >= 0); 12162 assert(rest < gcd); 12163 12164 /* determine the remainder of the coefficient candidate and the gcd */ 12165 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd; 12166 assert(restcoef >= 1); 12167 assert(restcoef < gcd); 12168 12169 if( hasrhs ) 12170 { 12171 /* calculate new coefficient */ 12172 if( restcoef > rest ) 12173 newcoef = vals[candpos] - restcoef + gcd; 12174 else 12175 newcoef = vals[candpos] - restcoef; 12176 } 12177 else 12178 { 12179 /* calculate new coefficient */ 12180 if( rest == 0 || restcoef < rest ) 12181 newcoef = vals[candpos] - restcoef; 12182 else 12183 newcoef = vals[candpos] - restcoef + gcd; 12184 } 12185 12186 /* done */ 12187 12188 /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if 12189 * another with the big coefficient was set to 1 12190 */ 12191 if( hasrhs && SCIPisZero(scip, newcoef) ) 12192 { 12193 notchangable = TRUE; 12194 } 12195 else if( SCIPisZero(scip, newcoef) ) 12196 { 12197 /* delete old redundant coefficient */ 12198 SCIP_CALL( delCoefPos(scip, cons, candpos) ); 12199 ++(*nchgcoefs); 12200 } 12201 else 12202 { 12203 /* replace old with new coefficient */ 12204 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) ); 12205 ++(*nchgcoefs); 12206 } 12207 } 12208 else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) ) 12209 { 12210 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)); 12211 } 12212 12213 /* correct side and big coefficients */ 12214 if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) || 12215 ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) ) 12216 { 12217 if( haslhs ) 12218 { 12219 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol)); 12220 12221 SCIP_CALL( chgLhs(scip, cons, newcoef) ); 12222 ++(*nchgsides); 12223 } 12224 else 12225 { 12226 assert(hasrhs); 12227 newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol)); 12228 12229 SCIP_CALL( chgRhs(scip, cons, newcoef) ); 12230 ++(*nchgsides); 12231 } 12232 12233 /* correct coefficients up front */ 12234 for( w = offsetv; w >= 0; --w ) 12235 { 12236 assert(vals[w] > 0); 12237 12238 SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) ); 12239 } 12240 (*nchgcoefs) += (offsetv + 1); 12241 } 12242 12243 if( !notchangable ) 12244 { 12245 /* normalize constraint */ 12246 SCIP_CALL( normalizeCons(scip, cons, infeasible) ); 12247 assert(vars == consdata->vars); 12248 assert(vals == consdata->vals); 12249 12250 if( *infeasible ) 12251 return SCIP_OKAY; 12252 12253 /* get new constraint data */ 12254 nvars = consdata->nvars; 12255 assert(nvars >= 2); 12256 12257 SCIPdebugPrintCons(scip, cons, NULL); 12258 12259 lhs = consdata->lhs; 12260 rhs = consdata->rhs; 12261 assert(!hasrhs || !SCIPisNegative(scip, rhs)); 12262 assert(!haslhs || !SCIPisNegative(scip, lhs)); 12263 } 12264 } 12265 } 12266 } 12267 12268 /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */ 12269 /* no continuous variables are left over */ 12270 if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS ) 12271 return SCIP_OKAY; 12272 12273 onlybin = TRUE; 12274 allcoefintegral = TRUE; 12275 /* check if all variables are of binary type */ 12276 for( v = nvars - 1; v >= 0; --v ) 12277 { 12278 if( !SCIPvarIsBinary(vars[v]) ) 12279 onlybin = FALSE; 12280 if( !SCIPisIntegral(scip, vals[v]) ) 12281 allcoefintegral = FALSE; 12282 } 12283 12284 /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right 12285 * hand side or bigger than the left hand side respectively, so we can make all of them integral 12286 * 12287 * @todo there are some steps missing .... 12288 */ 12289 if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) ) 12290 { 12291 SCIP_Real val; 12292 SCIP_Real newval; 12293 SCIP_Real frac = 0.0; 12294 SCIP_Bool found = FALSE; 12295 12296 if( hasrhs ) 12297 { 12298 if( allcoefintegral ) 12299 { 12300 /* replace old with new right hand side */ 12301 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) ); 12302 ++(*nchgsides); 12303 } 12304 else 12305 { 12306 siderest = rhs - SCIPfloor(scip, rhs); 12307 12308 /* try to round down all non-integral coefficients */ 12309 for( v = nvars - 1; v >= 0; --v ) 12310 { 12311 val = vals[v]; 12312 12313 /* add up all possible fractional parts */ 12314 if( !SCIPisIntegral(scip, val) ) 12315 { 12316 lb = SCIPvarGetLbGlobal(vars[v]); 12317 ub = SCIPvarGetUbGlobal(vars[v]); 12318 12319 /* at least one bound need to be at zero */ 12320 if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) ) 12321 return SCIP_OKAY; 12322 12323 /* swap bounds for 'standard' form */ 12324 if( !SCIPisFeasZero(scip, lb) ) 12325 { 12326 ub = lb; 12327 val *= -1; 12328 } 12329 12330 found = TRUE; 12331 12332 frac += (val - SCIPfloor(scip, val)) * ub; 12333 12334 /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients 12335 * 12336 * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because 12337 * x3, x4 set to 1 would be infeasible but feasible after flooring 12338 */ 12339 if( SCIPisGT(scip, frac, siderest) ) 12340 return SCIP_OKAY; 12341 } 12342 } 12343 assert(v == -1); 12344 12345 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n"); 12346 12347 /* round rhs and coefficients to integral values */ 12348 if( found ) 12349 { 12350 for( v = nvars - 1; v >= 0; --v ) 12351 { 12352 val = vals[v]; 12353 12354 /* add the whole fractional part */ 12355 if( !SCIPisIntegral(scip, val) ) 12356 { 12357 lb = SCIPvarGetLbGlobal(vars[v]); 12358 12359 if( SCIPisFeasZero(scip, lb) ) 12360 newval = SCIPfloor(scip, val); 12361 else 12362 newval = SCIPceil(scip, val); 12363 12364 if( SCIPisZero(scip, newval) ) 12365 { 12366 /* delete old redundant coefficient */ 12367 SCIP_CALL( delCoefPos(scip, cons, v) ); 12368 ++(*nchgcoefs); 12369 } 12370 else 12371 { 12372 /* replace old with new coefficient */ 12373 SCIP_CALL( chgCoefPos(scip, cons, v, newval) ); 12374 ++(*nchgcoefs); 12375 } 12376 } 12377 } 12378 } 12379 12380 /* replace old with new right hand side */ 12381 SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) ); 12382 ++(*nchgsides); 12383 } 12384 } 12385 else 12386 { 12387 if( allcoefintegral ) 12388 { 12389 /* replace old with new left hand side */ 12390 SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) ); 12391 ++(*nchgsides); 12392 } 12393 else 12394 { 12395 /* cannot floor left hand side to zero */ 12396 if( SCIPisLT(scip, lhs, 1.0) ) 12397 return SCIP_OKAY; 12398 12399 siderest = lhs - SCIPfloor(scip, lhs); 12400 12401 /* try to round down all non-integral coefficients */ 12402 for( v = nvars - 1; v >= 0; --v ) 12403 { 12404 val = vals[v]; 12405 12406 /* add up all possible fractional parts */ 12407 if( !SCIPisIntegral(scip, val) ) 12408 { 12409 lb = SCIPvarGetLbGlobal(vars[v]); 12410 ub = SCIPvarGetUbGlobal(vars[v]); 12411 12412 /* at least one bound need to be at zero */ 12413 if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) ) 12414 return SCIP_OKAY; 12415 12416 /* swap bounds for 'standard' form */ 12417 if( !SCIPisFeasZero(scip, lb) ) 12418 { 12419 ub = lb; 12420 val *= -1; 12421 } 12422 12423 /* cannot floor to zero */ 12424 if( SCIPisLT(scip, val, 1.0) ) 12425 return SCIP_OKAY; 12426 12427 /* the fractional part on each variable need to exceed the fractional part on the left hand side */ 12428 if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) ) 12429 return SCIP_OKAY; 12430 12431 found = TRUE; 12432 12433 frac += (val - SCIPfloor(scip, val)) * ub; 12434 12435 /* if we exceed the fractional part of the left hand side plus one by summing up all maximal 12436 * fractional parts of the variables, we cannot tighten the coefficients 12437 * 12438 * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because 12439 * x2-x4 set to 1 would be feasible but not after flooring 12440 */ 12441 if( SCIPisGE(scip, frac, 1 + siderest) ) 12442 return SCIP_OKAY; 12443 } 12444 /* all coefficients need to be integral, otherwise we might do an invalid reduction */ 12445 else 12446 return SCIP_OKAY; 12447 } 12448 assert(v == -1); 12449 12450 SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n"); 12451 12452 /* round lhs and coefficients to integral values */ 12453 if( found ) 12454 { 12455 for( v = nvars - 1; v >= 0; --v ) 12456 { 12457 val = vals[v]; 12458 12459 /* add the whole fractional part */ 12460 if( !SCIPisIntegral(scip, val) ) 12461 { 12462 lb = SCIPvarGetLbGlobal(vars[v]); 12463 12464 if( SCIPisFeasZero(scip, lb) ) 12465 newval = SCIPfloor(scip, val); 12466 else 12467 newval = SCIPceil(scip, val); 12468 12469 if( SCIPisZero(scip, newval) ) 12470 { 12471 /* delete old redundant coefficient */ 12472 SCIP_CALL( delCoefPos(scip, cons, v) ); 12473 ++(*nchgcoefs); 12474 } 12475 else 12476 { 12477 /* replace old with new coefficient */ 12478 SCIP_CALL( chgCoefPos(scip, cons, v, newval) ); 12479 ++(*nchgcoefs); 12480 } 12481 } 12482 } 12483 } 12484 12485 /* replace old with new left hand side */ 12486 SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) ); 12487 ++(*nchgsides); 12488 } 12489 } 12490 12491 /* normalize constraint */ 12492 SCIP_CALL( normalizeCons(scip, cons, infeasible) ); 12493 assert(vars == consdata->vars); 12494 assert(vals == consdata->vals); 12495 12496 if( *infeasible ) 12497 return SCIP_OKAY; 12498 12499 rhs = consdata->rhs; 12500 lhs = consdata->lhs; 12501 12502 assert(!hasrhs || !SCIPisNegative(scip, rhs)); 12503 assert(!haslhs || !SCIPisNegative(scip, lhs)); 12504 12505 SCIPdebugPrintCons(scip, cons, NULL); 12506 12507 nvars = consdata->nvars; 12508 if( nvars < 2 ) 12509 return SCIP_OKAY; 12510 12511 allcoefintegral = TRUE; 12512 #ifndef NDEBUG 12513 /* debug check if all coefficients are really integral */ 12514 for( v = nvars - 1; v >= 0; --v ) 12515 assert(SCIPisIntegral(scip, vals[v])); 12516 #endif 12517 } 12518 12519 /* @todo following can also work on non integral coefficients, need more investigation */ 12520 /* only check constraints with integral coefficients on all integral variables */ 12521 if( !allcoefintegral ) 12522 return SCIP_OKAY; 12523 12524 /* we want to avoid numerical troubles, therefore we do not change non-integral sides */ 12525 if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) ) 12526 return SCIP_OKAY; 12527 12528 /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */ 12529 if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) ) 12530 return SCIP_OKAY; 12531 12532 /* stop if the last coeffcients is one in absolute value and the variable is not binary */ 12533 if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) ) 12534 return SCIP_OKAY; 12535 12536 assert(nvars >= 2); 12537 12538 /* start gcd procedure for all variables */ 12539 do 12540 { 12541 SCIPdebug( oldnchgcoefs = *nchgcoefs; ) 12542 SCIPdebug( oldnchgsides = *nchgsides; ) 12543 12544 /* stop if we have two coeffcients which are one in absolute value */ 12545 if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) ) 12546 return SCIP_OKAY; 12547 12548 gcd = -1; 12549 12550 /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed 12551 * because coefficients of non-binary variables might have changed to zero */ 12552 if( !onlybin ) 12553 { 12554 foundbin = -1; 12555 onlybin = TRUE; 12556 12557 for( v = nvars - 1; v >= 0; --v ) 12558 { 12559 assert(!SCIPisZero(scip, vals[v])); 12560 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS); 12561 12562 if( SCIPvarIsBinary(vars[v]) ) 12563 { 12564 if( foundbin == -1 ) 12565 foundbin = v; 12566 continue; 12567 } 12568 else 12569 onlybin = FALSE; 12570 12571 absval = REALABS(vals[v]); 12572 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance, 12573 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough 12574 */ 12575 assert(SCIPisFeasIntegral(scip, absval)); 12576 12577 if( gcd == -1 ) 12578 { 12579 gcd = (SCIP_Longint)(absval + feastol); 12580 assert(gcd >= 1); 12581 } 12582 else 12583 { 12584 /* calculate greatest common divisor for all general variables */ 12585 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol)); 12586 } 12587 if( gcd == 1 ) 12588 break; 12589 } 12590 } 12591 else 12592 foundbin = nvars - 1; 12593 12594 /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */ 12595 if( gcd == 1 || foundbin == -1) 12596 return SCIP_OKAY; 12597 12598 assert((onlybin && gcd == -1) || (!onlybin && gcd > 1)); 12599 12600 candpos = -1; 12601 candpos2 = -1; 12602 12603 /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might 12604 * change the coefficient 12605 */ 12606 for( v = foundbin; v >= 0; --v ) 12607 { 12608 if( onlybin || SCIPvarIsBinary(vars[v]) ) 12609 { 12610 absval = REALABS(vals[v]); 12611 /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance, 12612 * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough 12613 */ 12614 assert(SCIPisFeasIntegral(scip, absval)); 12615 12616 oldgcd = gcd; 12617 12618 if( gcd == -1 ) 12619 { 12620 gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol); 12621 assert(gcd >= 1); 12622 } 12623 else 12624 { 12625 /* calculate greatest common divisor for all general and binary variables */ 12626 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol)); 12627 } 12628 12629 /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we 12630 * can terminate 12631 */ 12632 if( gcd == 1 ) 12633 { 12634 /* found candidate */ 12635 if( candpos == -1 ) 12636 { 12637 gcd = oldgcd; 12638 candpos = v; 12639 12640 /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for 12641 * the coefficient change 12642 */ 12643 if( onlybin && v == foundbin - 1 ) 12644 candpos2 = foundbin; 12645 } 12646 /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */ 12647 else 12648 { 12649 if( onlybin && candpos == v + 1 && candpos2 == v + 2 ) 12650 { 12651 assert(candpos2 == nvars - 1); 12652 12653 /* take new candidates */ 12654 candpos = candpos2; 12655 12656 /* recalculate gcd from scratch */ 12657 gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol); 12658 assert(gcd >= 1); 12659 12660 /* calculate greatest common divisor for all general and binary variables */ 12661 gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol)); 12662 if( gcd == 1 ) 12663 return SCIP_OKAY; 12664 } 12665 else 12666 /* cannot determine a possible coefficient for reduction */ 12667 return SCIP_OKAY; 12668 } 12669 } 12670 } 12671 } 12672 assert(gcd >= 2); 12673 12674 /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint 12675 * further 12676 */ 12677 assert(candpos >= 0 && candpos < nvars); 12678 12679 /* all variables and all coefficients are integral, so the side should be too */ 12680 assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))); 12681 12682 /* check again, if we have a normalized inequality (not ranged) the one side should be positive, 12683 * @see normalizeCons() 12684 */ 12685 assert(!hasrhs || !SCIPisNegative(scip, rhs)); 12686 assert(!haslhs || !SCIPisNegative(scip, lhs)); 12687 12688 /* determine the remainder of the side and the gcd */ 12689 if( hasrhs ) 12690 rest = ((SCIP_Longint)(rhs + feastol)) % gcd; 12691 else 12692 rest = ((SCIP_Longint)(lhs + feastol)) % gcd; 12693 assert(rest >= 0); 12694 assert(rest < gcd); 12695 12696 /* determine the remainder of the coefficient candidate and the gcd */ 12697 if( vals[candpos] < 0 ) 12698 { 12699 restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd; 12700 assert(restcoef <= -1); 12701 restcoef += gcd; 12702 } 12703 else 12704 restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd; 12705 assert(restcoef >= 1); 12706 assert(restcoef < gcd); 12707 12708 if( hasrhs ) 12709 { 12710 if( rest > 0 ) 12711 { 12712 /* replace old with new right hand side */ 12713 SCIP_CALL( chgRhs(scip, cons, rhs - rest) ); 12714 ++(*nchgsides); 12715 } 12716 12717 /* calculate new coefficient */ 12718 if( restcoef > rest ) 12719 newcoef = vals[candpos] - restcoef + gcd; 12720 else 12721 newcoef = vals[candpos] - restcoef; 12722 } 12723 else 12724 { 12725 if( rest > 0 ) 12726 { 12727 /* replace old with new left hand side */ 12728 SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) ); 12729 ++(*nchgsides); 12730 } 12731 12732 /* calculate new coefficient */ 12733 if( rest == 0 || restcoef < rest ) 12734 newcoef = vals[candpos] - restcoef; 12735 else 12736 newcoef = vals[candpos] - restcoef + gcd; 12737 } 12738 assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd); 12739 12740 SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0)); 12741 12742 if( SCIPisZero(scip, newcoef) ) 12743 { 12744 /* delete redundant coefficient */ 12745 SCIP_CALL( delCoefPos(scip, cons, candpos) ); 12746 } 12747 else 12748 { 12749 /* replace old with new coefficient */ 12750 SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) ); 12751 } 12752 ++(*nchgcoefs); 12753 12754 /* now constraint can be normalized, might be directly done by dividing it by the gcd */ 12755 SCIP_CALL( normalizeCons(scip, cons, infeasible) ); 12756 assert(vars == consdata->vars); 12757 assert(vals == consdata->vals); 12758 12759 if( *infeasible ) 12760 return SCIP_OKAY; 12761 12762 SCIPdebugPrintCons(scip, cons, NULL); 12763 12764 rhs = consdata->rhs; 12765 lhs = consdata->lhs; 12766 assert(!hasrhs || !SCIPisNegative(scip, rhs)); 12767 assert(!haslhs || !SCIPisNegative(scip, lhs)); 12768 12769 nvars = consdata->nvars; 12770 12771 SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons)); 12772 } 12773 while( nvars >= 2 ); 12774 12775 return SCIP_OKAY; 12776 } 12777 12778 12779 /** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality: 12780 * cons0 := a * cons0 + b * cons1, 12781 * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight; 12782 * for numerical stability, we will only accept integral a and b; 12783 * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT, 12784 * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT 12785 */ 12786 static 12787 SCIP_RETCODE aggregateConstraints( 12788 SCIP* scip, /**< SCIP data structure */ 12789 SCIP_CONS* cons0, /**< (in)equality to modify */ 12790 SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */ 12791 int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */ 12792 int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */ 12793 int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */ 12794 int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */ 12795 int nvarscommon, /**< number of variables, that appear in both constraints */ 12796 int commonidxweight, /**< variable weight sum of common variables */ 12797 int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */ 12798 int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */ 12799 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */ 12800 int* nchgcoefs, /**< pointer to count the number of changed coefficients */ 12801 SCIP_Bool* aggregated, /**< pointer to store whether an aggregation was made */ 12802 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */ 12803 ) 12804 { 12805 SCIP_CONSDATA* consdata0; 12806 SCIP_CONSDATA* consdata1; 12807 SCIP_Real a; 12808 SCIP_Real b; 12809 SCIP_Real aggrcoef; 12810 SCIP_Real scalarsum; 12811 SCIP_Real bestscalarsum; 12812 SCIP_Bool betterscalarsum; 12813 SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */ 12814 int varweight; 12815 int nvars; 12816 int bestvarweight; 12817 int bestnvars; 12818 int bestv; 12819 int v; 12820 int i; 12821 12822 assert(scip != NULL); 12823 assert(cons0 != NULL); 12824 assert(cons1 != NULL); 12825 assert(commonidx0 != NULL); 12826 assert(commonidx1 != NULL); 12827 assert(diffidx0minus1 != NULL); 12828 assert(diffidx1minus0 != NULL); 12829 assert(nvarscommon >= 1); 12830 assert(commonidxweight >= nvarscommon); 12831 assert(nchgcoefs != NULL); 12832 assert(aggregated != NULL); 12833 12834 assert(SCIPconsIsActive(cons0)); 12835 assert(SCIPconsIsActive(cons1)); 12836 12837 *infeasible = FALSE; 12838 12839 SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1)); 12840 12841 /* cons0 is an (in)equality */ 12842 consdata0 = SCIPconsGetData(cons0); 12843 assert(consdata0 != NULL); 12844 assert(consdata0->nvars >= 1); 12845 assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs)); 12846 assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon); 12847 12848 /* cons1 is an equality */ 12849 consdata1 = SCIPconsGetData(cons1); 12850 assert(consdata1 != NULL); 12851 assert(consdata1->nvars >= 1); 12852 assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs)); 12853 assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon); 12854 12855 *aggregated = FALSE; 12856 12857 /* search for the best common variable such that 12858 * val1[var] * consdata0 - val0[var] * consdata1 12859 * has least weighted number of variables 12860 */ 12861 bestvarweight = commonidxweight + diffidx0minus1weight; 12862 bestnvars = consdata0->nvars; 12863 bestv = -1; 12864 bestscalarsum = 0.0; 12865 commonvarlindependent = TRUE; 12866 for( v = 0; v < nvarscommon; ++v ) 12867 { 12868 assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]); 12869 a = consdata1->vals[commonidx1[v]]; 12870 b = -consdata0->vals[commonidx0[v]]; 12871 12872 /* only try aggregation, if coefficients are integral (numerical stability) */ 12873 if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) ) 12874 { 12875 /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */ 12876 varweight = diffidx0minus1weight + diffidx1minus0weight; 12877 nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon; 12878 scalarsum = REALABS(a) + REALABS(b); 12879 betterscalarsum = (scalarsum < bestscalarsum); 12880 for( i = 0; i < nvarscommon 12881 && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i ) 12882 { 12883 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]]; 12884 if( !SCIPisZero(scip, aggrcoef) ) 12885 { 12886 varweight += getVarWeight(consdata0->vars[commonidx0[i]]); 12887 nvars++; 12888 } 12889 } 12890 if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) ) 12891 { 12892 bestv = v; 12893 bestvarweight = varweight; 12894 bestnvars = nvars; 12895 bestscalarsum = scalarsum; 12896 } 12897 } 12898 12899 /* update commonvarlindependent flag, if still TRUE: 12900 * v's common coefficient in cons1 / v's common coefficient in cons0 should be constant, i.e., equal 0's common coefficient in cons1 / 0's common coefficient in cons0 12901 */ 12902 if( commonvarlindependent && v > 0 ) 12903 commonvarlindependent = SCIPisEQ(scip, 12904 consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]], 12905 consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]); 12906 } 12907 12908 /* if better aggregation was found, create new constraint and delete old one */ 12909 if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 ) 12910 { 12911 SCIP_CONS* newcons; 12912 SCIP_CONSDATA* newconsdata; 12913 SCIP_VAR** newvars; 12914 SCIP_Real* newvals; 12915 SCIP_Real newlhs; 12916 SCIP_Real newrhs; 12917 int newnvars; 12918 12919 if( bestv != -1 ) 12920 { 12921 /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */ 12922 if( consdata1->vals[commonidx1[bestv]] > 0.0 ) 12923 { 12924 a = consdata1->vals[commonidx1[bestv]]; 12925 b = -consdata0->vals[commonidx0[bestv]]; 12926 } 12927 else 12928 { 12929 a = -consdata1->vals[commonidx1[bestv]]; 12930 b = consdata0->vals[commonidx0[bestv]]; 12931 } 12932 assert(SCIPisIntegral(scip, a)); 12933 assert(SCIPisPositive(scip, a)); 12934 assert(SCIPisIntegral(scip, b)); 12935 assert(!SCIPisZero(scip, b)); 12936 } 12937 else 12938 { 12939 assert(commonvarlindependent); 12940 if( consdata1->vals[commonidx1[0]] > 0.0 ) 12941 { 12942 a = consdata1->vals[commonidx1[0]]; 12943 b = -consdata0->vals[commonidx0[0]]; 12944 } 12945 else 12946 { 12947 a = -consdata1->vals[commonidx1[0]]; 12948 b = consdata0->vals[commonidx0[0]]; 12949 } 12950 assert(SCIPisPositive(scip, a)); 12951 assert(!SCIPisZero(scip, b)); 12952 12953 /* if a/b is integral, then we can easily choose integer multipliers */ 12954 if( SCIPisIntegral(scip, a/b) ) 12955 { 12956 if( a/b > 0 ) 12957 { 12958 a /= b; 12959 b = 1.0; 12960 } 12961 else 12962 { 12963 a /= -b; 12964 b = -1.0; 12965 } 12966 } 12967 12968 /* setup best* variables that were not setup above because we are in the commonvarlindependent case */ 12969 SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; ) 12970 bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon; 12971 } 12972 12973 SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n", 12974 SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1), 12975 consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight); 12976 SCIPdebugPrintCons(scip, cons0, NULL); 12977 SCIPdebugPrintCons(scip, cons1, NULL); 12978 12979 /* get temporary memory for creating the new linear constraint */ 12980 SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) ); 12981 SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) ); 12982 12983 /* calculate the common coefficients, if we have not recognized linear dependency */ 12984 newnvars = 0; 12985 if( !commonvarlindependent ) 12986 { 12987 for( i = 0; i < nvarscommon; ++i ) 12988 { 12989 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars); 12990 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars); 12991 12992 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]]; 12993 if( !SCIPisZero(scip, aggrcoef) ) 12994 { 12995 assert(newnvars < bestnvars); 12996 newvars[newnvars] = consdata0->vars[commonidx0[i]]; 12997 newvals[newnvars] = aggrcoef; 12998 newnvars++; 12999 } 13000 } 13001 } 13002 else 13003 { 13004 /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */ 13005 #ifndef NDEBUG 13006 for( i = 0; i < nvarscommon; ++i ) 13007 { 13008 assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars); 13009 assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars); 13010 13011 aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]]; 13012 assert(SCIPisZero(scip, aggrcoef)); 13013 } 13014 #endif 13015 } 13016 13017 /* calculate the coefficients appearing in cons0 but not in cons1 */ 13018 for( i = 0; i < consdata0->nvars - nvarscommon; ++i ) 13019 { 13020 assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars); 13021 13022 aggrcoef = a * consdata0->vals[diffidx0minus1[i]]; 13023 assert(!SCIPisZero(scip, aggrcoef)); 13024 assert(newnvars < bestnvars); 13025 newvars[newnvars] = consdata0->vars[diffidx0minus1[i]]; 13026 newvals[newnvars] = aggrcoef; 13027 newnvars++; 13028 } 13029 13030 /* calculate the coefficients appearing in cons1 but not in cons0 */ 13031 for( i = 0; i < consdata1->nvars - nvarscommon; ++i ) 13032 { 13033 assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars); 13034 13035 aggrcoef = b * consdata1->vals[diffidx1minus0[i]]; 13036 assert(!SCIPisZero(scip, aggrcoef)); 13037 assert(newnvars < bestnvars); 13038 newvars[newnvars] = consdata1->vars[diffidx1minus0[i]]; 13039 newvals[newnvars] = aggrcoef; 13040 newnvars++; 13041 } 13042 assert(newnvars == bestnvars); 13043 13044 /* calculate the new left and right hand side of the (in)equality */ 13045 assert(!SCIPisInfinity(scip, -consdata1->lhs)); 13046 assert(!SCIPisInfinity(scip, consdata1->rhs)); 13047 if( SCIPisInfinity(scip, -consdata0->lhs) ) 13048 newlhs = -SCIPinfinity(scip); 13049 else 13050 newlhs = a * consdata0->lhs + b * consdata1->lhs; 13051 if( SCIPisInfinity(scip, consdata0->rhs) ) 13052 newrhs = SCIPinfinity(scip); 13053 else 13054 newrhs = a * consdata0->rhs + b * consdata1->rhs; 13055 13056 /* create the new linear constraint */ 13057 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs, 13058 SCIPconsIsInitial(cons0), SCIPconsIsSeparated(cons0), SCIPconsIsEnforced(cons0), 13059 SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0), 13060 SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0), 13061 SCIPconsIsDynamic(cons0), SCIPconsIsRemovable(cons0), SCIPconsIsStickingAtNode(cons0)) ); 13062 13063 newconsdata = SCIPconsGetData(newcons); 13064 assert(newconsdata != NULL); 13065 13066 /* copy the upgraded flag from the old cons0 to the new constraint */ 13067 newconsdata->upgraded = consdata0->upgraded; 13068 13069 /* normalize the new constraint */ 13070 SCIP_CALL( normalizeCons(scip, newcons, infeasible) ); 13071 13072 if( *infeasible ) 13073 goto TERMINATE; 13074 13075 /* check, if we really want to use the new constraint instead of the old one: 13076 * use the new one, if the maximum norm doesn't grow too much 13077 */ 13078 if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) ) 13079 { 13080 SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons)); 13081 SCIPdebugPrintCons(scip, newcons, NULL); 13082 13083 /* update the statistics: we changed all coefficients */ 13084 if( !consdata0->upgraded ) 13085 (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon; 13086 *aggregated = TRUE; 13087 13088 /* delete the old constraint, and add the new linear constraint to the problem */ 13089 SCIP_CALL( SCIPdelCons(scip, cons0) ); 13090 SCIP_CALL( SCIPaddCons(scip, newcons) ); 13091 } 13092 13093 TERMINATE: 13094 /* release the new constraint */ 13095 SCIP_CALL( SCIPreleaseCons(scip, &newcons) ); 13096 13097 /* free temporary memory */ 13098 SCIPfreeBufferArray(scip, &newvals); 13099 SCIPfreeBufferArray(scip, &newvars); 13100 } 13101 13102 return SCIP_OKAY; 13103 } 13104 13105 /** gets the key of the given element */ 13106 static 13107 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons) 13108 { /*lint --e{715}*/ 13109 /* the key is the element itself */ 13110 return elem; 13111 } 13112 13113 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the 13114 * coefficients are either equal or negated 13115 */ 13116 static 13117 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons) 13118 { 13119 SCIP* scip; 13120 SCIP_CONSDATA* consdata1; 13121 SCIP_CONSDATA* consdata2; 13122 SCIP_Real cons1scale; 13123 SCIP_Real cons2scale; 13124 int i; 13125 13126 assert(key1 != NULL); 13127 assert(key2 != NULL); 13128 consdata1 = SCIPconsGetData((SCIP_CONS*)key1); 13129 consdata2 = SCIPconsGetData((SCIP_CONS*)key2); 13130 assert(consdata1->indexsorted); 13131 assert(consdata2->indexsorted); 13132 13133 scip = (SCIP*)userptr; 13134 assert(scip != NULL); 13135 13136 /* if it is the same constraint we dont need to check anything */ 13137 if( key1 == key2 ) 13138 return TRUE; 13139 13140 /* checks trivial case */ 13141 if( consdata1->nvars != consdata2->nvars ) 13142 return FALSE; 13143 13144 /* tests if variables are equal */ 13145 for( i = 0; i < consdata1->nvars; ++i ) 13146 { 13147 if( consdata1->vars[i] != consdata2->vars[i] ) 13148 { 13149 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 || 13150 SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1); 13151 return FALSE; 13152 } 13153 assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0); 13154 } 13155 13156 /* compute scale before comparing coefficients of constraints */ 13157 cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]); 13158 cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]); 13159 13160 /* tests if coefficients are equal with the computed scale */ 13161 for( i = 0; i < consdata1->nvars; ++i ) 13162 { 13163 SCIP_Real val1; 13164 SCIP_Real val2; 13165 13166 val1 = consdata1->vals[i] * cons1scale; 13167 val2 = consdata2->vals[i] * cons2scale; 13168 13169 if( !SCIPisEQ(scip, val1, val2) ) 13170 return FALSE; 13171 } 13172 13173 return TRUE; 13174 } 13175 13176 /** returns the hash value of the key */ 13177 static 13178 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons) 13179 { 13180 SCIP_CONSDATA* consdata; 13181 int minidx; 13182 int mididx; 13183 int maxidx; 13184 SCIP_Real scale; 13185 #ifndef NDEBUG 13186 SCIP* scip; 13187 13188 scip = (SCIP*)userptr; 13189 assert(scip != NULL); 13190 #endif 13191 13192 assert(key != NULL); 13193 consdata = SCIPconsGetData((SCIP_CONS*)key); 13194 assert(consdata != NULL); 13195 assert(consdata->nvars > 0); 13196 13197 assert(consdata->indexsorted); 13198 13199 minidx = SCIPvarGetIndex(consdata->vars[0]); 13200 mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]); 13201 maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]); 13202 scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]); 13203 13204 /* using only the variable indices as hash, since the values are compared by epsilon */ 13205 return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale), 13206 mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale), 13207 maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale)); 13208 } 13209 13210 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept); 13211 * prefers non-upgraded constraints and as second criterion the constraint with the smallest position 13212 */ 13213 static 13214 unsigned int getParallelConsKey( 13215 SCIP_CONS* cons /**< linear constraint */ 13216 ) 13217 { 13218 SCIP_CONSDATA* consdata; 13219 13220 assert(cons != NULL); 13221 13222 consdata = SCIPconsGetData(cons); 13223 assert(consdata != NULL); 13224 13225 return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/ 13226 } 13227 13228 /** updates the hashtable such that out of all constraints in the hashtable that are detected 13229 * to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons, 13230 * and all others are removed from the hashtable and stored in the given array 13231 */ 13232 static 13233 SCIP_RETCODE retrieveParallelConstraints( 13234 SCIP_HASHTABLE* hashtable, /**< hashtable containing linear constraints */ 13235 SCIP_CONS** querycons, /**< pointer to linear constraint used to look for duplicates in the hash table; 13236 * upon return will contain the constraint that should be kept */ 13237 SCIP_CONS** parallelconss, /**< array to return constraints that are parallel to the given; 13238 * these constraints where removed from the hashtable */ 13239 int* nparallelconss /**< pointer to return number of parallel constraints */ 13240 ) 13241 { 13242 SCIP_CONS* parallelcons; 13243 unsigned int querykey; 13244 13245 *nparallelconss = 0; 13246 querykey = getParallelConsKey(*querycons); 13247 13248 while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL ) 13249 { 13250 unsigned int conskey = getParallelConsKey(parallelcons); 13251 13252 if( conskey < querykey ) 13253 { 13254 parallelconss[(*nparallelconss)++] = *querycons; 13255 *querycons = parallelcons; 13256 querykey = conskey; 13257 } 13258 else 13259 { 13260 parallelconss[(*nparallelconss)++] = parallelcons; 13261 } 13262 13263 /* if the constraint that just came out of the hash table is the one that is kept, 13264 * we do not need to look into the hashtable again, since the invariant is that 13265 * in the hashtable only pair-wise non-parallel constraints are contained. 13266 * For the original querycons, however, multiple constraints that compare equal (=parallel) 13267 * could be contained due to non-transitivity of the equality comparison. 13268 * Also we can return immediately, since parallelcons is already contained in the 13269 * hashtable and we do not need to remove and reinsert it. 13270 */ 13271 if( *querycons == parallelcons ) 13272 return SCIP_OKAY; 13273 13274 /* remove parallelcons from the hashtable, since it will be replaced by querycons */ 13275 SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) ); 13276 } 13277 13278 /* in debug mode we make sure, that the hashtable cannot contain a constraint that 13279 * comnpares equal to querycons at this point 13280 */ 13281 #ifndef NDEBUG 13282 SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) ); 13283 #else 13284 SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) ); 13285 #endif 13286 13287 return SCIP_OKAY; 13288 } 13289 13290 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint 13291 * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table 13292 */ 13293 static 13294 SCIP_RETCODE detectRedundantConstraints( 13295 SCIP* scip, /**< SCIP data structure */ 13296 BMS_BLKMEM* blkmem, /**< block memory */ 13297 SCIP_CONS** conss, /**< constraint set */ 13298 int nconss, /**< number of constraints in constraint set */ 13299 int* firstchange, /**< pointer to store first changed constraint */ 13300 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 13301 int* ndelconss, /**< pointer to count number of deleted constraints */ 13302 int* nchgsides /**< pointer to count number of changed left/right hand sides */ 13303 ) 13304 { 13305 SCIP_HASHTABLE* hashtable; 13306 SCIP_CONS** parallelconss; 13307 int nparallelconss; 13308 int hashtablesize; 13309 int c; 13310 13311 assert(scip != NULL); 13312 assert(blkmem != NULL); 13313 assert(conss != NULL); 13314 assert(firstchange != NULL); 13315 assert(cutoff != NULL); 13316 assert(ndelconss != NULL); 13317 assert(nchgsides != NULL); 13318 13319 /* create a hash table for the constraint set */ 13320 hashtablesize = nconss; 13321 SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize, 13322 hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) ); 13323 13324 SCIP_CALL( SCIPallocBufferArray(scip, ¶llelconss, nconss) ); 13325 13326 /* check all constraints in the given set for redundancy */ 13327 for( c = 0; c < nconss; ++c ) 13328 { 13329 SCIP_CONS* cons0; 13330 SCIP_CONSDATA* consdata0; 13331 13332 cons0 = conss[c]; 13333 13334 if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) ) 13335 continue; 13336 13337 /* do not check for parallel constraints if they should not be upgraded */ 13338 if ( SCIPconsGetNUpgradeLocks(cons0) > 0 ) 13339 continue; 13340 13341 /* check for interuption */ 13342 if( c % 1000 == 0 && SCIPisStopped(scip) ) 13343 break; 13344 13345 /* sorts the constraint */ 13346 consdata0 = SCIPconsGetData(cons0); 13347 assert(consdata0 != NULL); 13348 SCIP_CALL( consdataSort(scip, consdata0) ); 13349 assert(consdata0->indexsorted); 13350 13351 /* get constraints from current hash table with same variables as cons0 and with coefficients equal 13352 * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the 13353 * first variable is positive 13354 * Also inserts cons0 into the hashtable. 13355 */ 13356 SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) ); 13357 13358 if( nparallelconss != 0 ) 13359 { 13360 SCIP_Real lhs; 13361 SCIP_Real rhs; 13362 13363 int i; 13364 13365 /* cons0 may have been changed in retrieveParallelConstraints() */ 13366 consdata0 = SCIPconsGetData(cons0); 13367 13368 lhs = consdata0->lhs; 13369 rhs = consdata0->rhs; 13370 13371 for( i = 0; i < nparallelconss; ++i ) 13372 { 13373 SCIP_CONS* consdel; 13374 SCIP_CONSDATA* consdatadel; 13375 SCIP_Real scale; 13376 13377 consdel = parallelconss[i]; 13378 consdatadel = SCIPconsGetData(consdel); 13379 13380 /* do not delete constraint if it should not be upgraded */ 13381 if ( SCIPconsGetNUpgradeLocks(consdel) > 0 ) 13382 continue; 13383 13384 assert(SCIPconsIsActive(consdel)); 13385 assert(!SCIPconsIsModifiable(consdel)); 13386 13387 /* constraint found: create a new constraint with same coefficients and best left and right hand side; 13388 * delete old constraints afterwards 13389 */ 13390 assert(consdatadel != NULL); 13391 assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars); 13392 13393 assert(consdatadel->indexsorted); 13394 assert(consdata0->vars[0] == consdatadel->vars[0]); 13395 13396 scale = consdata0->vals[0] / consdatadel->vals[0]; 13397 assert(scale != 0.0); 13398 13399 /* in debug mode, check that all coefficients are equal with respect to epsilon 13400 * if the constraints are in equilibrium scale 13401 */ 13402 #ifndef NDEBUG 13403 { 13404 int k; 13405 SCIP_Real scale0 = 1.0 / consdata0->maxabsval; 13406 SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale); 13407 13408 for( k = 0; k < consdata0->nvars; ++k ) 13409 { 13410 assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k])); 13411 } 13412 } 13413 #endif 13414 13415 if( scale > 0.0 ) 13416 { 13417 /* the coefficients of both constraints are parallel with a positive scale */ 13418 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n", 13419 SCIPconsGetName(cons0), SCIPconsGetName(consdel)); 13420 SCIPdebugPrintCons(scip, cons0, NULL); 13421 SCIPdebugPrintCons(scip, consdel, NULL); 13422 13423 if( ! SCIPisInfinity(scip, -consdatadel->lhs) ) 13424 lhs = MAX(scale * consdatadel->lhs, lhs); 13425 13426 if( ! SCIPisInfinity(scip, consdatadel->rhs) ) 13427 rhs = MIN(scale * consdatadel->rhs, rhs); 13428 } 13429 else 13430 { 13431 /* the coefficients of both rows are negations */ 13432 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n", 13433 SCIPconsGetName(cons0), SCIPconsGetName(consdel)); 13434 SCIPdebugPrintCons(scip, cons0, NULL); 13435 SCIPdebugPrintCons(scip, consdel, NULL); 13436 13437 if( ! SCIPisInfinity(scip, consdatadel->rhs) ) 13438 lhs = MAX(scale * consdatadel->rhs, lhs); 13439 13440 if( ! SCIPisInfinity(scip, -consdatadel->lhs) ) 13441 rhs = MIN(scale * consdatadel->lhs, rhs); 13442 } 13443 13444 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 13445 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) ); 13446 13447 /* delete consdel */ 13448 assert( ! consdata0->upgraded || consdatadel->upgraded ); 13449 SCIP_CALL( SCIPdelCons(scip, consdel) ); 13450 if( !consdatadel->upgraded ) 13451 (*ndelconss)++; 13452 } 13453 13454 if( SCIPisFeasLT(scip, rhs, lhs) ) 13455 { 13456 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0)); 13457 *cutoff = TRUE; 13458 break; 13459 } 13460 13461 /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */ 13462 if( lhs > rhs ) 13463 { 13464 rhs = (lhs + rhs)/2; 13465 lhs = rhs; 13466 } 13467 13468 /* update lhs and rhs of cons0 */ 13469 SCIP_CALL( chgLhs(scip, cons0, lhs) ); 13470 SCIP_CALL( chgRhs(scip, cons0, rhs) ); 13471 13472 /* update the first changed constraint to begin the next aggregation round with */ 13473 if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange ) 13474 *firstchange = SCIPconsGetPos(cons0); 13475 13476 assert(SCIPconsIsActive(cons0)); 13477 } 13478 } 13479 #ifdef SCIP_MORE_DEBUG 13480 SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n"); 13481 SCIPhashtablePrintStatistics(hashtable, SCIPgetMessagehdlr(scip)); 13482 #endif 13483 13484 SCIPfreeBufferArray(scip, ¶llelconss); 13485 13486 /* free hash table */ 13487 SCIPhashtableFree(&hashtable); 13488 13489 return SCIP_OKAY; 13490 } 13491 13492 /** compares constraint with all prior constraints for possible redundancy or aggregation, 13493 * and removes or changes constraint accordingly 13494 */ 13495 static 13496 SCIP_RETCODE preprocessConstraintPairs( 13497 SCIP* scip, /**< SCIP data structure */ 13498 SCIP_CONS** conss, /**< constraint set */ 13499 int firstchange, /**< first constraint that changed since last pair preprocessing round */ 13500 int chkind, /**< index of constraint to check against all prior indices upto startind */ 13501 SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */ 13502 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 13503 int* ndelconss, /**< pointer to count number of deleted constraints */ 13504 int* nchgsides, /**< pointer to count number of changed left/right hand sides */ 13505 int* nchgcoefs /**< pointer to count number of changed coefficients */ 13506 ) 13507 { 13508 SCIP_CONS* cons0; 13509 SCIP_CONSDATA* consdata0; 13510 int* commonidx0; 13511 int* commonidx1; 13512 int* diffidx0minus1; 13513 int* diffidx1minus0; 13514 uint64_t possignature0; 13515 uint64_t negsignature0; 13516 SCIP_Bool cons0changed; 13517 SCIP_Bool cons0isequality; 13518 int diffidx1minus0size; 13519 int c; 13520 SCIP_Real cons0lhs; 13521 SCIP_Real cons0rhs; 13522 SCIP_Bool cons0upgraded; 13523 13524 assert(scip != NULL); 13525 assert(conss != NULL); 13526 assert(firstchange <= chkind); 13527 assert(cutoff != NULL); 13528 assert(ndelconss != NULL); 13529 assert(nchgsides != NULL); 13530 assert(nchgcoefs != NULL); 13531 13532 /* get the constraint to be checked against all prior constraints */ 13533 cons0 = conss[chkind]; 13534 assert(cons0 != NULL); 13535 assert(SCIPconsIsActive(cons0)); 13536 assert(!SCIPconsIsModifiable(cons0)); 13537 13538 consdata0 = SCIPconsGetData(cons0); 13539 assert(consdata0 != NULL); 13540 assert(consdata0->nvars >= 1); 13541 cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs); 13542 13543 /* sort the constraint */ 13544 SCIP_CALL( consdataSort(scip, consdata0) ); 13545 13546 /* calculate bit signatures of cons0 for potentially positive and negative coefficients */ 13547 consdataCalcSignatures(consdata0); 13548 possignature0 = consdata0->possignature; 13549 negsignature0 = consdata0->negsignature; 13550 13551 /* get temporary memory for indices of common variables */ 13552 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) ); 13553 SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) ); 13554 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) ); 13555 SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) ); 13556 diffidx1minus0size = consdata0->nvars; 13557 13558 cons0lhs = consdata0->lhs; 13559 cons0rhs = consdata0->rhs; 13560 cons0upgraded = consdata0->upgraded; 13561 13562 /* check constraint against all prior constraints */ 13563 cons0changed = consdata0->changed; 13564 consdata0->changed = FALSE; 13565 for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c ) 13566 { 13567 SCIP_CONS* cons1; 13568 SCIP_CONSDATA* consdata1; 13569 uint64_t possignature1; 13570 uint64_t negsignature1; 13571 SCIP_Bool cons0dominateslhs; 13572 SCIP_Bool cons1dominateslhs; 13573 SCIP_Bool cons0dominatesrhs; 13574 SCIP_Bool cons1dominatesrhs; 13575 SCIP_Bool cons1isequality; 13576 SCIP_Bool coefsequal; 13577 SCIP_Bool coefsnegated; 13578 SCIP_Bool tryaggregation; 13579 int nvarscommon; 13580 int nvars0minus1; 13581 int nvars1minus0; 13582 int commonidxweight; 13583 int diffidx0minus1weight; 13584 int diffidx1minus0weight; 13585 int v0; 13586 int v1; 13587 13588 assert(cons0lhs == consdata0->lhs); /*lint !e777*/ 13589 assert(cons0rhs == consdata0->rhs); /*lint !e777*/ 13590 assert(cons0upgraded == consdata0->upgraded); 13591 13592 cons1 = conss[c]; 13593 13594 /* cons1 has become inactive during presolving of constraint pairs */ 13595 if( cons1 == NULL ) 13596 continue; 13597 13598 assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0)); 13599 assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1)); 13600 13601 consdata1 = SCIPconsGetData(cons1); 13602 assert(consdata1 != NULL); 13603 13604 /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n", 13605 SCIPconsGetName(cons0), cons0changed, cons0upgraded, 13606 SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */ 13607 13608 /* if both constraints didn't change since last pair processing, we can ignore the pair */ 13609 if( !cons0changed && !consdata1->changed ) 13610 continue; 13611 13612 /* if both constraints are already upgraded, skip the pair; 13613 * because changes on these constraints cannot be applied to the instance anymore */ 13614 if( cons0upgraded && consdata1->upgraded ) 13615 continue; 13616 13617 assert(consdata1->nvars >= 1); 13618 13619 /* sort the constraint */ 13620 SCIP_CALL( consdataSort(scip, consdata1) ); 13621 13622 /* calculate bit signatures of cons1 for potentially positive and negative coefficients */ 13623 consdataCalcSignatures(consdata1); 13624 possignature1 = consdata1->possignature; 13625 negsignature1 = consdata1->negsignature; 13626 13627 /* the signatures give a quick test to check for domination and equality of coefficients */ 13628 coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1); 13629 coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1); 13630 cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs) 13631 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */ 13632 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */ 13633 cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs) 13634 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */ 13635 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */ 13636 cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs) 13637 && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */ 13638 && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */ 13639 cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs) 13640 && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */ 13641 && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */ 13642 cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs); 13643 tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0); 13644 if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs 13645 && !coefsequal && !coefsnegated && !tryaggregation ) 13646 continue; 13647 13648 /* make sure, we have enough memory for the index set of V_1 \ V_0 */ 13649 if( tryaggregation && consdata1->nvars > diffidx1minus0size ) 13650 { 13651 SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) ); 13652 diffidx1minus0size = consdata1->nvars; 13653 } 13654 13655 /* check consdata0 against consdata1: 13656 * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v, 13657 * consdata0 dominates consdata1 w.r.t. left hand side 13658 * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v, 13659 * consdata0 dominates consdata1 w.r.t. right hand side 13660 * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single 13661 * ranged row (or equality) 13662 * - if at least one constraint is an equality, count the weighted number of common variables W_c 13663 * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0), 13664 * where the weight of each variable depends on its type, such that aggregations in order to remove the 13665 * number of continuous and integer variables are preferred: 13666 * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the 13667 * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to 13668 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has 13669 * to be positive to not switch the sense of the (in)equality cons0 13670 * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the 13671 * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to 13672 * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has 13673 * to be positive to not switch the sense of the (in)equality cons1 13674 */ 13675 13676 /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */ 13677 nvarscommon = 0; 13678 commonidxweight = 0; 13679 nvars0minus1 = 0; 13680 diffidx0minus1weight = 0; 13681 nvars1minus0 = 0; 13682 diffidx1minus0weight = 0; 13683 v0 = 0; 13684 v1 = 0; 13685 while( (v0 < consdata0->nvars || v1 < consdata1->nvars) 13686 && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs 13687 || coefsequal || coefsnegated || tryaggregation) ) 13688 { 13689 SCIP_VAR* var; 13690 SCIP_Real val0; 13691 SCIP_Real val1; 13692 int varcmp; 13693 13694 /* test, if variable appears in only one or in both constraints */ 13695 if( v0 < consdata0->nvars && v1 < consdata1->nvars ) 13696 varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]); 13697 else if( v0 < consdata0->nvars ) 13698 varcmp = -1; 13699 else 13700 varcmp = +1; 13701 13702 switch( varcmp ) 13703 { 13704 case -1: 13705 /* variable doesn't appear in consdata1 */ 13706 var = consdata0->vars[v0]; 13707 val0 = consdata0->vals[v0]; 13708 val1 = 0.0; 13709 if( tryaggregation ) 13710 { 13711 diffidx0minus1[nvars0minus1] = v0; 13712 nvars0minus1++; 13713 diffidx0minus1weight += getVarWeight(var); 13714 } 13715 v0++; 13716 coefsequal = FALSE; 13717 coefsnegated = FALSE; 13718 break; 13719 13720 case +1: 13721 /* variable doesn't appear in consdata0 */ 13722 var = consdata1->vars[v1]; 13723 val0 = 0.0; 13724 val1 = consdata1->vals[v1]; 13725 if( tryaggregation ) 13726 { 13727 diffidx1minus0[nvars1minus0] = v1; 13728 nvars1minus0++; 13729 diffidx1minus0weight += getVarWeight(var); 13730 } 13731 v1++; 13732 coefsequal = FALSE; 13733 coefsnegated = FALSE; 13734 break; 13735 13736 case 0: 13737 /* variable appears in both constraints */ 13738 assert(consdata0->vars[v0] == consdata1->vars[v1]); 13739 var = consdata0->vars[v0]; 13740 val0 = consdata0->vals[v0]; 13741 val1 = consdata1->vals[v1]; 13742 if( tryaggregation ) 13743 { 13744 commonidx0[nvarscommon] = v0; 13745 commonidx1[nvarscommon] = v1; 13746 nvarscommon++; 13747 commonidxweight += getVarWeight(var); 13748 } 13749 v0++; 13750 v1++; 13751 coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1)); 13752 coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1)); 13753 break; 13754 13755 default: 13756 SCIPerrorMessage("invalid comparison result\n"); 13757 SCIPABORT(); 13758 var = NULL; 13759 val0 = 0.0; 13760 val1 = 0.0; 13761 } 13762 assert(var != NULL); 13763 13764 /* update domination criteria w.r.t. the coefficient and the variable's bounds */ 13765 if( SCIPisGT(scip, val0, val1) ) 13766 { 13767 if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) ) 13768 { 13769 cons0dominatesrhs = FALSE; 13770 cons1dominateslhs = FALSE; 13771 } 13772 if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) ) 13773 { 13774 cons0dominateslhs = FALSE; 13775 cons1dominatesrhs = FALSE; 13776 } 13777 } 13778 else if( SCIPisLT(scip, val0, val1) ) 13779 { 13780 if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) ) 13781 { 13782 cons0dominateslhs = FALSE; 13783 cons1dominatesrhs = FALSE; 13784 } 13785 if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) ) 13786 { 13787 cons0dominatesrhs = FALSE; 13788 cons1dominateslhs = FALSE; 13789 } 13790 } 13791 } 13792 13793 /* check for disaggregated ranged rows */ 13794 if( coefsequal || coefsnegated ) 13795 { 13796 SCIP_CONS* consstay; 13797 SCIP_CONS* consdel; 13798 #ifndef NDEBUG 13799 SCIP_CONSDATA* consdatastay; 13800 #endif 13801 SCIP_CONSDATA* consdatadel; 13802 SCIP_Real lhs; 13803 SCIP_Real rhs; 13804 int consinddel; 13805 13806 /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and 13807 * best left and right hand sides; delete the old constraints afterwards 13808 */ 13809 SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n", 13810 SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated"); 13811 SCIPdebugPrintCons(scip, cons0, NULL); 13812 SCIPdebugPrintCons(scip, cons1, NULL); 13813 13814 if( coefsequal ) 13815 { 13816 /* the coefficients of both rows are equal */ 13817 lhs = MAX(consdata0->lhs, consdata1->lhs); 13818 rhs = MIN(consdata0->rhs, consdata1->rhs); 13819 } 13820 else 13821 { 13822 /* the coefficients of both rows are negations */ 13823 lhs = MAX(consdata0->lhs, -consdata1->rhs); 13824 rhs = MIN(consdata0->rhs, -consdata1->lhs); 13825 } 13826 if( SCIPisFeasLT(scip, rhs, lhs) ) 13827 { 13828 SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0)); 13829 *cutoff = TRUE; 13830 break; 13831 } 13832 13833 /* check which constraint has to stay; 13834 * changes applied to an upgraded constraint will not be considered in the instance */ 13835 if( consdata0->upgraded ) 13836 { 13837 assert(!consdata1->upgraded); 13838 consstay = cons1; 13839 #ifndef NDEBUG 13840 consdatastay = consdata1; 13841 #endif 13842 13843 consdel = cons0; 13844 consdatadel = consdata0; 13845 consinddel = chkind; 13846 } 13847 else 13848 { 13849 consstay = cons0; 13850 #ifndef NDEBUG 13851 consdatastay = consdata0; 13852 #endif 13853 13854 consdel = cons1; 13855 consdatadel = consdata1; 13856 consinddel = c; 13857 } 13858 13859 /* update the sides of consstay */ 13860 SCIP_CALL( chgLhs(scip, consstay, lhs) ); 13861 SCIP_CALL( chgRhs(scip, consstay, rhs) ); 13862 if( !consdata0->upgraded ) 13863 { 13864 assert(consstay == cons0); 13865 cons0lhs = consdata0->lhs; 13866 cons0rhs = consdata0->rhs; 13867 } 13868 13869 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 13870 SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) ); 13871 13872 assert( !consdatastay->upgraded ); 13873 /* delete consdel */ 13874 SCIP_CALL( SCIPdelCons(scip, consdel) ); 13875 conss[consinddel] = NULL; 13876 if( !consdatadel->upgraded ) 13877 (*ndelconss)++; 13878 continue; 13879 } 13880 13881 /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally 13882 * redundant 13883 */ 13884 if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) ) 13885 { 13886 /* left hand side is dominated by consdata1: delete left hand side of consdata0 */ 13887 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n", 13888 SCIPconsGetName(cons0), SCIPconsGetName(cons1)); 13889 SCIPdebugPrintCons(scip, cons0, NULL); 13890 SCIPdebugPrintCons(scip, cons1, NULL); 13891 13892 /* check for infeasibility */ 13893 if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) ) 13894 { 13895 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1)); 13896 *cutoff = TRUE; 13897 break; 13898 } 13899 13900 /* remove redundant left hand side */ 13901 if( !SCIPisInfinity(scip, -consdata0->lhs) ) 13902 { 13903 SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) ); 13904 cons0lhs = consdata0->lhs; 13905 cons0isequality = FALSE; 13906 if( !consdata0->upgraded ) 13907 { 13908 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 13909 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) ); 13910 13911 (*nchgsides)++; 13912 } 13913 } 13914 } 13915 else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) ) 13916 { 13917 /* left hand side is dominated by consdata0: delete left hand side of consdata1 */ 13918 SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n", 13919 SCIPconsGetName(cons1), SCIPconsGetName(cons0)); 13920 SCIPdebugPrintCons(scip, cons1, NULL); 13921 SCIPdebugPrintCons(scip, cons0, NULL); 13922 13923 /* check for infeasibility */ 13924 if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) ) 13925 { 13926 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1)); 13927 *cutoff = TRUE; 13928 break; 13929 } 13930 13931 /* remove redundant left hand side */ 13932 if( !SCIPisInfinity(scip, -consdata1->lhs) ) 13933 { 13934 SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) ); 13935 cons1isequality = FALSE; 13936 if( !consdata1->upgraded ) 13937 { 13938 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 13939 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) ); 13940 13941 (*nchgsides)++; 13942 } 13943 } 13944 } 13945 if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) ) 13946 { 13947 /* right hand side is dominated by consdata1: delete right hand side of consdata0 */ 13948 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n", 13949 SCIPconsGetName(cons0), SCIPconsGetName(cons1)); 13950 SCIPdebugPrintCons(scip, cons0, NULL); 13951 SCIPdebugPrintCons(scip, cons1, NULL); 13952 13953 /* check for infeasibility */ 13954 if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) ) 13955 { 13956 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1)); 13957 *cutoff = TRUE; 13958 break; 13959 } 13960 13961 /* remove redundant right hand side */ 13962 if( !SCIPisInfinity(scip, consdata0->rhs) ) 13963 { 13964 SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) ); 13965 cons0rhs = consdata0->rhs; 13966 cons0isequality = FALSE; 13967 if( !consdata0->upgraded ) 13968 { 13969 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 13970 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) ); 13971 13972 (*nchgsides)++; 13973 } 13974 } 13975 } 13976 else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) ) 13977 { 13978 /* right hand side is dominated by consdata0: delete right hand side of consdata1 */ 13979 SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n", 13980 SCIPconsGetName(cons1), SCIPconsGetName(cons0)); 13981 SCIPdebugPrintCons(scip, cons1, NULL); 13982 SCIPdebugPrintCons(scip, cons0, NULL); 13983 13984 /* check for infeasibility */ 13985 if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) ) 13986 { 13987 SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1)); 13988 *cutoff = TRUE; 13989 break; 13990 } 13991 13992 /* remove redundant right hand side */ 13993 if( !SCIPisInfinity(scip, consdata1->rhs) ) 13994 { 13995 SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) ); 13996 cons1isequality = FALSE; 13997 if( !consdata1->upgraded ) 13998 { 13999 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 14000 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) ); 14001 14002 (*nchgsides)++; 14003 } 14004 } 14005 } 14006 14007 /* check for now redundant constraints */ 14008 if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) ) 14009 { 14010 /* consdata0 became redundant */ 14011 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0)); 14012 SCIP_CALL( SCIPdelCons(scip, cons0) ); 14013 conss[chkind] = NULL; 14014 if( !consdata0->upgraded ) 14015 { 14016 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 14017 SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) ); 14018 14019 (*ndelconss)++; 14020 } 14021 continue; 14022 } 14023 if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) ) 14024 { 14025 /* consdata1 became redundant */ 14026 SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1)); 14027 SCIP_CALL( SCIPdelCons(scip, cons1) ); 14028 conss[c] = NULL; 14029 if( !consdata1->upgraded ) 14030 { 14031 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */ 14032 SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) ); 14033 14034 (*ndelconss)++; 14035 } 14036 continue; 14037 } 14038 14039 /* check, if we want to aggregate an (in)equality with an equality: 14040 * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0 14041 */ 14042 if( tryaggregation ) 14043 { 14044 SCIP_Bool aggregated; 14045 14046 assert(consdata0->nvars == nvarscommon + nvars0minus1); 14047 assert(consdata1->nvars == nvarscommon + nvars1minus0); 14048 14049 aggregated = FALSE; 14050 if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight ) 14051 { 14052 /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */ 14053 SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0, 14054 nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale, 14055 nchgcoefs, &aggregated, cutoff) ); 14056 14057 if( *cutoff ) 14058 break; 14059 14060 /* update array of active constraints */ 14061 if( aggregated ) 14062 { 14063 assert(!SCIPconsIsActive(cons0)); 14064 assert(SCIPconsIsActive(cons1)); 14065 conss[chkind] = NULL; 14066 } 14067 } 14068 if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight ) 14069 { 14070 /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */ 14071 SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1, 14072 nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale, 14073 nchgcoefs, &aggregated, cutoff) ); 14074 14075 if( *cutoff ) 14076 break; 14077 14078 /* update array of active constraints */ 14079 if( aggregated ) 14080 { 14081 assert(!SCIPconsIsActive(cons1)); 14082 assert(SCIPconsIsActive(cons0)); 14083 conss[c] = NULL; 14084 } 14085 } 14086 } 14087 } 14088 14089 /* free temporary memory */ 14090 SCIPfreeBufferArray(scip, &diffidx1minus0); 14091 SCIPfreeBufferArray(scip, &diffidx0minus1); 14092 SCIPfreeBufferArray(scip, &commonidx1); 14093 SCIPfreeBufferArray(scip, &commonidx0); 14094 14095 return SCIP_OKAY; 14096 } 14097 14098 /** do stuffing presolving on a single constraint */ 14099 static 14100 SCIP_RETCODE presolStuffing( 14101 SCIP* scip, /**< SCIP data structure */ 14102 SCIP_CONS* cons, /**< linear constraint */ 14103 SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */ 14104 SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill 14105 * constraints using the cheapest variable? */ 14106 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 14107 int* nfixedvars, /**< pointer to count the total number of fixed variables */ 14108 int* nchgbds /**< pointer to count the total number of tightened bounds */ 14109 ) 14110 { 14111 SCIP_CONSDATA* consdata; 14112 SCIP_Real* ratios; 14113 int* varpos; 14114 SCIP_Bool* swapped; 14115 SCIP_VAR** vars; 14116 SCIP_Real* vals; 14117 SCIP_VAR* var; 14118 SCIP_Real lb; 14119 SCIP_Real ub; 14120 SCIP_Real minactivity; 14121 SCIP_Real maxactivity; 14122 SCIP_Real maxcondactivity; 14123 SCIP_Real mincondactivity; 14124 SCIP_Real rhs; 14125 SCIP_Real val; 14126 SCIP_Real obj; 14127 SCIP_Real factor; 14128 SCIP_Bool minactisrelax; 14129 SCIP_Bool maxactisrelax; 14130 SCIP_Bool isminsettoinfinity; 14131 SCIP_Bool ismaxsettoinfinity; 14132 SCIP_Bool tryfixing; 14133 int nsingletons; 14134 int idx; 14135 int v; 14136 int nvars; 14137 14138 assert(scip != NULL); 14139 assert(cons != NULL); 14140 assert(nfixedvars != NULL); 14141 14142 consdata = SCIPconsGetData(cons); 14143 14144 /* we only want to run for inequalities */ 14145 if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) ) 14146 return SCIP_OKAY; 14147 14148 if( singlevarstuffing ) 14149 { 14150 consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 14151 &isminsettoinfinity, &ismaxsettoinfinity); 14152 } 14153 else 14154 { 14155 minactivity = SCIP_INVALID; 14156 maxactivity = SCIP_INVALID; 14157 isminsettoinfinity = FALSE; 14158 ismaxsettoinfinity = FALSE; 14159 } 14160 14161 /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1, 14162 * the new maxactivity is minus the old minactivity then 14163 */ 14164 if( SCIPisInfinity(scip, consdata->rhs) ) 14165 { 14166 rhs = -consdata->lhs; 14167 factor = -1.0; 14168 maxactivity = -minactivity; 14169 ismaxsettoinfinity = isminsettoinfinity; 14170 } 14171 else 14172 { 14173 assert(SCIPisInfinity(scip, -consdata->lhs)); 14174 rhs = consdata->rhs; 14175 factor = 1.0; 14176 } 14177 14178 nvars = consdata->nvars; 14179 vars = consdata->vars; 14180 vals = consdata->vals; 14181 14182 /* check for continuous singletons */ 14183 if( singletonstuffing ) 14184 { 14185 for( v = 0; v < nvars; ++v ) 14186 { 14187 var = vars[v]; 14188 14189 if( (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) + SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL)) == 1 14190 && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ) 14191 break; 14192 } 14193 } 14194 else 14195 /* we don't want to go into the next block */ 14196 v = nvars; 14197 14198 /* a singleton was found -> perform singleton variable stuffing */ 14199 if( v < nvars ) 14200 { 14201 assert(singletonstuffing); 14202 14203 SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) ); 14204 SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) ); 14205 SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) ); 14206 14207 tryfixing = TRUE; 14208 nsingletons = 0; 14209 mincondactivity = 0.0; 14210 maxcondactivity = 0.0; 14211 14212 for( v = 0; v < nvars; ++v ) 14213 { 14214 var = vars[v]; 14215 lb = SCIPvarGetLbGlobal(var); 14216 ub = SCIPvarGetUbGlobal(var); 14217 obj = SCIPvarGetObj(var); 14218 val = factor * vals[v]; 14219 14220 assert(!SCIPisZero(scip, val)); 14221 14222 /* the variable is a singleton and continuous */ 14223 if( (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) + SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL)) == 1 14224 && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ) 14225 { 14226 if( SCIPisNegative(scip, obj) && val > 0 ) 14227 { 14228 /* case 1: obj < 0 and coef > 0 */ 14229 if( SCIPisInfinity(scip, -lb) ) 14230 { 14231 tryfixing = FALSE; 14232 break; 14233 } 14234 14235 maxcondactivity += val * lb; 14236 mincondactivity += val * lb; 14237 swapped[v] = FALSE; 14238 ratios[nsingletons] = obj / val; 14239 varpos[nsingletons] = v; 14240 nsingletons++; 14241 } 14242 else if( SCIPisPositive(scip, obj) && val < 0 ) 14243 { 14244 /* case 2: obj > 0 and coef < 0 */ 14245 if( SCIPisInfinity(scip, ub) ) 14246 { 14247 tryfixing = FALSE; 14248 break; 14249 } 14250 /* multiply column by (-1) to become case 1. 14251 * now bounds are swapped: ub := -lb, lb := -ub 14252 */ 14253 14254 maxcondactivity += val * ub; 14255 mincondactivity += val * ub; 14256 swapped[v] = TRUE; 14257 ratios[nsingletons] = obj / val; 14258 varpos[nsingletons] = v; 14259 nsingletons++; 14260 } 14261 else if( val > 0 ) 14262 { 14263 /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing. 14264 * we only consider the lower bound for the constants 14265 */ 14266 assert(!SCIPisNegative(scip, obj)); 14267 14268 if( SCIPisInfinity(scip, -lb) ) 14269 { 14270 /* maybe unbounded */ 14271 tryfixing = FALSE; 14272 break; 14273 } 14274 14275 maxcondactivity += val * lb; 14276 mincondactivity += val * lb; 14277 } 14278 else 14279 { 14280 /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing. 14281 * we only consider the upper bound for the constants 14282 */ 14283 assert(!SCIPisPositive(scip, obj)); 14284 assert(val < 0); 14285 14286 if( SCIPisInfinity(scip, ub) ) 14287 { 14288 /* maybe unbounded */ 14289 tryfixing = FALSE; 14290 break; 14291 } 14292 14293 maxcondactivity += val * ub; 14294 mincondactivity += val * ub; 14295 } 14296 } 14297 else 14298 { 14299 /* consider contribution of discrete variables, non-singleton 14300 * continuous variables and variables with more than one lock 14301 */ 14302 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) ) 14303 { 14304 tryfixing = FALSE; 14305 break; 14306 } 14307 14308 if( val > 0 ) 14309 { 14310 maxcondactivity += val * ub; 14311 mincondactivity += val * lb; 14312 } 14313 else 14314 { 14315 maxcondactivity += val * lb; 14316 mincondactivity += val * ub; 14317 } 14318 } 14319 } 14320 if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) ) 14321 { 14322 SCIP_Real delta; 14323 SCIP_Bool tightened; 14324 #ifdef SCIP_DEBUG 14325 int oldnfixedvars = *nfixedvars; 14326 int oldnchgbds = *nchgbds; 14327 #endif 14328 14329 SCIPsortRealInt(ratios, varpos, nsingletons); 14330 14331 /* verify which singleton continuous variables can be fixed */ 14332 for( v = 0; v < nsingletons; ++v ) 14333 { 14334 idx = varpos[v]; 14335 var = vars[idx]; 14336 val = factor * vals[idx]; 14337 lb = SCIPvarGetLbGlobal(var); 14338 ub = SCIPvarGetUbGlobal(var); 14339 14340 assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var))); 14341 assert((val < 0) == swapped[idx]); 14342 val = REALABS(val); 14343 14344 /* stop fixing if variable bounds are not finite */ 14345 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) ) 14346 break; 14347 14348 assert((SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) 14349 + SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL)) == 1); 14350 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS); 14351 14352 /* calculate the change in the row activities if this variable changes 14353 * its value from its worst to its best bound 14354 */ 14355 if( swapped[idx] ) 14356 delta = -(lb - ub) * val; 14357 else 14358 delta = (ub - lb) * val; 14359 14360 assert(!SCIPisNegative(scip, delta)); 14361 14362 if( SCIPisLE(scip, delta, rhs - maxcondactivity) ) 14363 { 14364 if( swapped[idx] ) 14365 { 14366 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb); 14367 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) ); 14368 } 14369 else 14370 { 14371 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub); 14372 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) ); 14373 } 14374 14375 if( *cutoff ) 14376 break; 14377 if( tightened ) 14378 { 14379 (*nfixedvars)++; 14380 } 14381 } 14382 /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case, 14383 * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening 14384 * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical 14385 * troubles in case of large bounds. 14386 */ 14387 else if( SCIPisLE(scip, rhs, mincondactivity) ) 14388 { 14389 if( swapped[idx] ) 14390 { 14391 SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub); 14392 SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) ); 14393 } 14394 else 14395 { 14396 SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb); 14397 SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) ); 14398 } 14399 14400 if( *cutoff ) 14401 break; 14402 if( tightened ) 14403 { 14404 (*nfixedvars)++; 14405 } 14406 } 14407 14408 maxcondactivity += delta; 14409 mincondactivity += delta; 14410 } 14411 14412 #ifdef SCIP_DEBUG 14413 if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 ) 14414 { 14415 SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); 14416 } 14417 #endif 14418 } 14419 14420 SCIPfreeBufferArray(scip, &swapped); 14421 SCIPfreeBufferArray(scip, &ratios); 14422 SCIPfreeBufferArray(scip, &varpos); 14423 } 14424 14425 /* perform single-variable stuffing: 14426 * for a linear inequality 14427 * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b 14428 * with a_i > 0 and objective coefficients c_i < 0, 14429 * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t. 14430 * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the 14431 * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint 14432 * is redundant. 14433 * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so 14434 * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest 14435 * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to 14436 * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint, 14437 * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their 14438 * upper bound. 14439 * Note that the others variables may have downlocks from other constraints, which we do not need to care 14440 * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the 14441 * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach 14442 * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method. 14443 * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral, 14444 * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure. 14445 * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to 14446 * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and 14447 * filling the remaining gap in the constraint with the next-best variable. For this, we check that 14448 * c_k * ceil((maxactivity - rhs)/val) is still better than 14449 * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j. 14450 * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs). 14451 * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same 14452 * sign of coefficients in constraint and objective prevent the use of this method. 14453 */ 14454 if( singlevarstuffing && !ismaxsettoinfinity ) 14455 { 14456 SCIP_Real bestratio = -SCIPinfinity(scip); 14457 SCIP_Real secondbestratio = -SCIPinfinity(scip); 14458 SCIP_Real ratio; 14459 int bestindex = -1; 14460 int bestuplocks = 0; 14461 int bestdownlocks = 1; 14462 int downlocks; 14463 int uplocks; 14464 SCIPdebug( int oldnfixedvars = *nfixedvars; ) 14465 SCIPdebug( int oldnchgbds = *nchgbds; ) 14466 14467 /* loop over all variables to identify the best and second-best ratio */ 14468 for( v = 0; v < nvars; ++v ) 14469 { 14470 var = vars[v]; 14471 obj = SCIPvarGetObj(var); 14472 val = factor * vals[v]; 14473 14474 assert(!SCIPisZero(scip, val)); 14475 14476 ratio = obj / val; 14477 14478 /* if both objective and constraint push the variable to the same direction, we can do nothing here */ 14479 if( !SCIPisNegative(scip, ratio) ) 14480 { 14481 bestindex = -1; 14482 break; 14483 } 14484 14485 if( val > 0 ) 14486 { 14487 downlocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL); 14488 uplocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL); 14489 } 14490 else 14491 { 14492 downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL); 14493 uplocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL); 14494 } 14495 14496 /* better ratio, update best candidate 14497 * @todo use some tolerance 14498 * @todo check size of domain and updated ratio for integer variables already? 14499 */ 14500 if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/ 14501 || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS 14502 && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) ) 14503 { 14504 /* best index becomes second-best*/ 14505 if( bestindex != -1 ) 14506 { 14507 /* second-best index must not have more than 1 uplock */ 14508 if( bestuplocks > 1 ) 14509 { 14510 bestindex = -1; 14511 break; 14512 } 14513 else 14514 { 14515 secondbestratio = bestratio; 14516 } 14517 } 14518 bestdownlocks = downlocks; 14519 bestuplocks = uplocks; 14520 bestratio = ratio; 14521 bestindex = v; 14522 14523 /* if this variable is the best in the end, we cannot do reductions since it has a downlocks, 14524 * if it is not the best, it has too many uplocks -> not applicable 14525 */ 14526 if( bestdownlocks > 0 && bestuplocks > 1 ) 14527 { 14528 bestindex = -1; 14529 break; 14530 } 14531 } 14532 else 14533 { 14534 /* non-best index must not have more than 1 uplock */ 14535 if( uplocks > 1 ) 14536 { 14537 bestindex = -1; 14538 break; 14539 } 14540 /* update second-best ratio */ 14541 if( ratio > secondbestratio ) 14542 { 14543 secondbestratio = ratio; 14544 } 14545 } 14546 } 14547 14548 /* check if we can apply single variable stuffing */ 14549 if( bestindex != -1 && bestdownlocks == 0 ) 14550 { 14551 SCIP_Bool tightened = FALSE; 14552 SCIP_Real bounddelta; 14553 14554 var = vars[bestindex]; 14555 obj = SCIPvarGetObj(var); 14556 val = factor * vals[bestindex]; 14557 lb = SCIPvarGetLbGlobal(var); 14558 ub = SCIPvarGetUbGlobal(var); 14559 tryfixing = TRUE; 14560 14561 if( val < 0 ) 14562 { 14563 assert(!SCIPisNegative(scip, obj)); 14564 14565 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */ 14566 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) ) 14567 { 14568 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val); 14569 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val); 14570 assert(SCIPisPositive(scip, activitydelta)); 14571 14572 tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio); 14573 14574 bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val); 14575 assert(SCIPisPositive(scip, bounddelta)); 14576 } 14577 else 14578 bounddelta = (maxactivity - rhs)/-val; 14579 14580 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb); 14581 14582 if( tryfixing ) 14583 { 14584 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0); 14585 14586 if( SCIPisEQ(scip, lb + bounddelta, ub) ) 14587 { 14588 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta); 14589 SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) ); 14590 } 14591 else 14592 { 14593 SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub); 14594 SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) ); 14595 } 14596 } 14597 } 14598 else 14599 { 14600 assert(!SCIPisPositive(scip, obj)); 14601 14602 /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */ 14603 if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val)) 14604 { 14605 SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val); 14606 SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val); 14607 assert(SCIPisPositive(scip, activitydelta)); 14608 14609 tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio); 14610 14611 bounddelta = SCIPceil(scip, (maxactivity - rhs)/val); 14612 assert(SCIPisPositive(scip, bounddelta)); 14613 } 14614 else 14615 bounddelta = (maxactivity - rhs)/val; 14616 14617 tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb); 14618 14619 if( tryfixing ) 14620 { 14621 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0); 14622 14623 if( SCIPisEQ(scip, ub - bounddelta, lb) ) 14624 { 14625 SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta); 14626 SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) ); 14627 } 14628 else 14629 { 14630 SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb); 14631 SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) ); 14632 } 14633 } 14634 } 14635 14636 if( *cutoff ) 14637 return SCIP_OKAY; 14638 if( tightened ) 14639 { 14640 if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) ) 14641 ++(*nfixedvars); 14642 else 14643 ++(*nchgbds); 14644 14645 SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs); 14646 for( v = 0; v < nvars; ++v ) 14647 { 14648 SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]), 14649 SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]), 14650 SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL), 14651 SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL), 14652 SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I"); 14653 } 14654 SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs); 14655 14656 for( v = 0; v < nvars; ++v ) 14657 { 14658 if( v == bestindex ) 14659 continue; 14660 14661 if( factor * vals[v] < 0 ) 14662 { 14663 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1); 14664 SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n", 14665 SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v])); 14666 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) ); 14667 } 14668 else 14669 { 14670 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1); 14671 SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n", 14672 SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v])); 14673 SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) ); 14674 } 14675 14676 if( *cutoff ) 14677 return SCIP_OKAY; 14678 if( tightened ) 14679 ++(*nfixedvars); 14680 } 14681 SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); ) 14682 } 14683 } 14684 } 14685 14686 return SCIP_OKAY; 14687 } 14688 14689 /** applies full dual presolving on variables that only appear in linear constraints */ 14690 static 14691 SCIP_RETCODE fullDualPresolve( 14692 SCIP* scip, /**< SCIP data structure */ 14693 SCIP_CONS** conss, /**< constraint set */ 14694 int nconss, /**< number of constraints */ 14695 SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */ 14696 int* nchgbds /**< pointer to count the number of bound changes */ 14697 ) 14698 { 14699 SCIP_Real* redlb; 14700 SCIP_Real* redub; 14701 int* nlocksdown; 14702 int* nlocksup; 14703 SCIP_Bool* isimplint; 14704 SCIP_VAR** origvars; 14705 SCIP_VAR** vars; 14706 SCIP_VAR** conscontvars; 14707 int nvars; 14708 int nbinvars; 14709 int nintvars; 14710 int ncontvars; 14711 int v; 14712 int c; 14713 14714 /* we calculate redundancy bounds with the following meaning: 14715 * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint 14716 * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint 14717 * then: 14718 * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality 14719 * c_v <= 0 : x_v >= redub[v] is feasible due to optimality 14720 */ 14721 14722 /* Additionally, we detect continuous variables that are implicitly integral. 14723 * A continuous variable j is implicit integral if it only has only +/-1 coefficients, 14724 * and all constraints (including the bounds as trivial constraints) in which: 14725 * c_j > 0: the variable is down-locked, 14726 * c_j < 0: the variable is up-locked, 14727 * c_j = 0: the variable appears 14728 * have, apart from j, only integer variables with integral coefficients and integral sides. 14729 * This is because then, the value of the variable is either determined by one of its bounds or 14730 * by one of these constraints, and in all cases, the value of the variable is integral. 14731 */ 14732 14733 assert(scip != NULL); 14734 assert(nconss == 0 || conss != NULL); 14735 assert(nchgbds != NULL); 14736 assert(!SCIPinProbing(scip)); 14737 14738 /* get active variables */ 14739 nvars = SCIPgetNVars(scip); 14740 origvars = SCIPgetVars(scip); 14741 14742 /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */ 14743 nbinvars = SCIPgetNBinVars(scip); 14744 if( nbinvars == nvars ) 14745 return SCIP_OKAY; 14746 14747 /* get number of continuous variables */ 14748 ncontvars = SCIPgetNContVars(scip); 14749 nintvars = nvars - ncontvars; 14750 14751 /* copy the variable array since this array might change during the curse of this algorithm */ 14752 nvars = nvars - nbinvars; 14753 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) ); 14754 14755 /* allocate temporary memory */ 14756 SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) ); 14757 SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) ); 14758 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) ); 14759 SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) ); 14760 SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) ); 14761 SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) ); 14762 14763 /* initialize redundancy bounds */ 14764 for( v = 0; v < nvars; ++v ) 14765 { 14766 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY); 14767 redlb[v] = SCIPvarGetLbGlobal(vars[v]); 14768 redub[v] = SCIPvarGetUbGlobal(vars[v]); 14769 } 14770 BMSclearMemoryArray(nlocksdown, nvars); 14771 BMSclearMemoryArray(nlocksup, nvars); 14772 14773 /* Initialize isimplint array: variable may be implicit integer if rounded to their best bound they are integral. 14774 * We better not use SCIPisFeasIntegral() in these checks. 14775 */ 14776 for( v = 0; v < ncontvars; v++ ) 14777 { 14778 SCIP_VAR* var; 14779 SCIP_Real obj; 14780 SCIP_Real lb; 14781 SCIP_Real ub; 14782 14783 var = vars[v + nintvars - nbinvars]; 14784 lb = SCIPvarGetLbGlobal(var); 14785 ub = SCIPvarGetUbGlobal(var); 14786 14787 obj = SCIPvarGetObj(var); 14788 if( SCIPisZero(scip, obj) ) 14789 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub)); 14790 else 14791 { 14792 if( SCIPisPositive(scip, obj) ) 14793 isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)); 14794 else 14795 { 14796 assert(SCIPisNegative(scip, obj)); 14797 isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub)); 14798 } 14799 } 14800 } 14801 14802 /* scan all constraints */ 14803 for( c = 0; c < nconss; ++c ) 14804 { 14805 /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are 14806 * part of checked disjunctions) 14807 */ 14808 if( SCIPconsIsLocked(conss[c]) ) 14809 { 14810 SCIP_CONSDATA* consdata; 14811 SCIP_Bool lhsexists; 14812 SCIP_Bool rhsexists; 14813 SCIP_Bool hasimpliedpotential; 14814 SCIP_Bool integralcoefs; 14815 int nlockspos; 14816 int contvarpos; 14817 int nconscontvars; 14818 int i; 14819 14820 consdata = SCIPconsGetData(conss[c]); 14821 assert(consdata != NULL); 14822 14823 /* get number of times the constraint was locked */ 14824 nlockspos = SCIPconsGetNLocksPos(conss[c]); 14825 14826 /* we do not want to include constraints with locked negation (this would be too weird) */ 14827 if( SCIPconsGetNLocksNeg(conss[c]) > 0 ) 14828 { 14829 /* mark all continuous variables as not being implicit integral */ 14830 for( i = 0; i < consdata->nvars; ++i ) 14831 { 14832 SCIP_VAR* var; 14833 14834 var = consdata->vars[i]; 14835 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ) 14836 { 14837 int contv; 14838 contv = SCIPvarGetProbindex(var) - nintvars; 14839 assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */ 14840 isimplint[contv] = FALSE; 14841 } 14842 } 14843 continue; 14844 } 14845 14846 /* check for existing sides */ 14847 lhsexists = !SCIPisInfinity(scip, -consdata->lhs); 14848 rhsexists = !SCIPisInfinity(scip, consdata->rhs); 14849 14850 /* count locks and update redundancy bounds */ 14851 contvarpos = -1; 14852 nconscontvars = 0; 14853 hasimpliedpotential = FALSE; 14854 integralcoefs = !SCIPconsIsModifiable(conss[c]); 14855 14856 for( i = 0; i < consdata->nvars; ++i ) 14857 { 14858 SCIP_VAR* var; 14859 SCIP_Real val; 14860 SCIP_Real minresactivity; 14861 SCIP_Real maxresactivity; 14862 SCIP_Real newredlb; 14863 SCIP_Real newredub; 14864 SCIP_Bool minisrelax; 14865 SCIP_Bool maxisrelax; 14866 SCIP_Bool isminsettoinfinity; 14867 SCIP_Bool ismaxsettoinfinity; 14868 int arrayindex; 14869 14870 var = consdata->vars[i]; 14871 val = consdata->vals[i]; 14872 14873 /* check if still all integer variables have integral coefficients */ 14874 if( SCIPvarIsIntegral(var) ) 14875 integralcoefs = integralcoefs && SCIPisIntegral(scip, val); 14876 14877 /* we do not need to process binary variables */ 14878 if( SCIPvarIsBinary(var) ) 14879 continue; 14880 14881 if( SCIPconsIsModifiable(conss[c]) ) 14882 { 14883 minresactivity = -SCIPinfinity(scip); 14884 maxresactivity = SCIPinfinity(scip); 14885 isminsettoinfinity = TRUE; 14886 ismaxsettoinfinity = TRUE; 14887 } 14888 else 14889 { 14890 /* calculate residual activity bounds if variable would be fixed to zero */ 14891 consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity, 14892 &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity); 14893 14894 /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation, 14895 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity. 14896 * This is needed, because we do not want to rely on relaxed finite resactivities. 14897 */ 14898 assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity)); 14899 14900 /* check minresactivity for reliability */ 14901 if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) ) 14902 consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE); 14903 14904 /* check maxresactivity for reliability */ 14905 if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) ) 14906 consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE); 14907 } 14908 14909 arrayindex = SCIPvarGetProbindex(var) - nbinvars; 14910 14911 assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */ 14912 14913 newredlb = redlb[arrayindex]; 14914 newredub = redub[arrayindex]; 14915 if( val > 0.0 ) 14916 { 14917 if( lhsexists ) 14918 { 14919 /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */ 14920 nlocksdown[arrayindex] += nlockspos; 14921 newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val); 14922 } 14923 if( rhsexists ) 14924 { 14925 /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */ 14926 nlocksup[arrayindex] += nlockspos; 14927 newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val); 14928 } 14929 } 14930 else 14931 { 14932 if( lhsexists ) 14933 { 14934 /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */ 14935 nlocksup[arrayindex] += nlockspos; 14936 newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val); 14937 } 14938 if( rhsexists ) 14939 { 14940 /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */ 14941 nlocksdown[arrayindex] += nlockspos; 14942 newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val); 14943 } 14944 } 14945 14946 /* if the variable is integer, we have to round the value to the next integral value */ 14947 if( SCIPvarIsIntegral(var) ) 14948 { 14949 if( !SCIPisInfinity(scip, newredlb) ) 14950 newredlb = SCIPceil(scip, newredlb); 14951 if( !SCIPisInfinity(scip, -newredub) ) 14952 newredub = SCIPfloor(scip, newredub); 14953 } 14954 14955 /* update redundancy bounds */ 14956 redlb[arrayindex] = MAX(redlb[arrayindex], newredlb); 14957 redub[arrayindex] = MIN(redub[arrayindex], newredub); 14958 14959 /* collect the continuous variables of the constraint */ 14960 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ) 14961 { 14962 int contv; 14963 14964 assert(nconscontvars < ncontvars); 14965 contvarpos = i; 14966 conscontvars[nconscontvars] = var; 14967 nconscontvars++; 14968 14969 contv = SCIPvarGetProbindex(var) - nintvars; 14970 assert(0 <= contv && contv < ncontvars); 14971 hasimpliedpotential = hasimpliedpotential || isimplint[contv]; 14972 } 14973 } 14974 14975 /* update implicit integer status of continuous variables */ 14976 if( hasimpliedpotential ) 14977 { 14978 if( nconscontvars > 1 || !integralcoefs ) 14979 { 14980 /* there is more than one continuous variable or the integer variables have fractional coefficients: 14981 * none of the continuous variables is implicit integer 14982 */ 14983 for( i = 0; i < nconscontvars; i++ ) 14984 { 14985 int contv; 14986 contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars; 14987 assert(0 <= contv && contv < ncontvars); 14988 isimplint[contv] = FALSE; 14989 } 14990 } 14991 else 14992 { 14993 SCIP_VAR* var; 14994 SCIP_Real val; 14995 SCIP_Real absval; 14996 int contv; 14997 14998 /* there is exactly one continuous variable and the integer variables have integral coefficients: 14999 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding 15000 * side(s) of the constraint is integral 15001 */ 15002 assert(nconscontvars == 1); 15003 assert(0 <= contvarpos && contvarpos < consdata->nvars); 15004 var = consdata->vars[contvarpos]; 15005 val = consdata->vals[contvarpos]; 15006 contv = SCIPvarGetProbindex(var) - nintvars; 15007 assert(0 <= contv && contv < ncontvars); 15008 assert(isimplint[contv]); 15009 15010 absval = REALABS(val); 15011 if( !SCIPisEQ(scip, absval, 1.0) ) 15012 isimplint[contv] = FALSE; 15013 else 15014 { 15015 SCIP_Real obj; 15016 15017 obj = SCIPvarGetObj(var); 15018 if( obj * val >= 0.0 && lhsexists ) 15019 { 15020 /* the variable may be blocked by the constraint's left hand side */ 15021 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs); 15022 } 15023 if( obj * val <= 0.0 && rhsexists ) 15024 { 15025 /* the variable may be blocked by the constraint's left hand side */ 15026 isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs); 15027 } 15028 } 15029 } 15030 } 15031 } 15032 } 15033 15034 /* check if any bounds can be tightened due to optimality */ 15035 for( v = 0; v < nvars; ++v ) 15036 { 15037 SCIP_VAR* var; 15038 SCIP_Real obj; 15039 SCIP_Bool infeasible; 15040 SCIP_Bool tightened; 15041 15042 assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY); 15043 assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]); 15044 assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]); 15045 15046 var = vars[v]; 15047 obj = SCIPvarGetObj(var); 15048 if( !SCIPisPositive(scip, -obj) ) 15049 { 15050 /* making the variable as small as possible does not increase the objective: 15051 * check if all down locks of the variables are due to linear constraints; 15052 * if variable is cost neutral and only upper bounded non-positively or negative largest bound to make 15053 * constraints redundant is huge, we better do nothing for numerical reasons 15054 */ 15055 if( ( SCIPisPositive(scip, obj) || SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) || !SCIPisInfinity(scip, -SCIPvarGetLbGlobal(var)) ) 15056 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v] 15057 && !SCIPisHugeValue(scip, -redlb[v]) 15058 && redlb[v] < SCIPvarGetUbGlobal(var) ) 15059 { 15060 SCIP_Real ub; 15061 15062 /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint 15063 * -> tighten upper bound to x_v <= redlb[v] 15064 */ 15065 SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n", 15066 SCIPvarGetName(var), SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), 15067 redlb[v]); 15068 SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) ); 15069 assert(!infeasible); 15070 15071 ub = SCIPvarGetUbGlobal(var); 15072 redub[v] = MIN(redub[v], ub); 15073 if( tightened ) 15074 (*nchgbds)++; 15075 } 15076 } 15077 if( !SCIPisPositive(scip, obj) ) 15078 { 15079 /* making the variable as large as possible does not increase the objective: 15080 * check if all up locks of the variables are due to linear constraints; 15081 * if variable is cost neutral and only lower bounded non-negatively or positive smallest bound to make 15082 * constraints redundant is huge, we better do nothing for numerical reasons 15083 */ 15084 if( ( SCIPisPositive(scip, -obj) || SCIPisPositive(scip, -SCIPvarGetLbGlobal(var)) || !SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) ) 15085 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] 15086 && !SCIPisHugeValue(scip, redub[v]) 15087 && redub[v] > SCIPvarGetLbGlobal(var) ) 15088 { 15089 SCIP_Real lb; 15090 15091 /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint 15092 * -> tighten lower bound to x_v >= redub[v] 15093 */ 15094 SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n", 15095 SCIPvarGetName(var), SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), 15096 redub[v]); 15097 SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) ); 15098 assert(!infeasible); 15099 15100 lb = SCIPvarGetLbGlobal(var); 15101 redlb[v] = MAX(redlb[v], lb); 15102 if( tightened ) 15103 (*nchgbds)++; 15104 } 15105 } 15106 } 15107 15108 /* upgrade continuous variables to implicit integers */ 15109 for( v = nintvars - nbinvars; v < nvars; ++v ) 15110 { 15111 SCIP_VAR* var; 15112 SCIP_Bool infeasible; 15113 15114 var = vars[v]; 15115 assert(var != NULL); 15116 15117 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS); 15118 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]); 15119 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]); 15120 assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars); 15121 15122 /* we can only conclude implicit integrality if the variable appears in no other constraint */ 15123 if( isimplint[v - nintvars + nbinvars] 15124 && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v] 15125 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] ) 15126 { 15127 /* since we locally copied the variable array we can change the variable type immediately */ 15128 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) ); 15129 15130 if( infeasible ) 15131 { 15132 SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var)); 15133 *cutoff = TRUE; 15134 15135 break; 15136 } 15137 15138 SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n", 15139 SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)); 15140 } 15141 } 15142 15143 /* free temporary memory */ 15144 SCIPfreeBufferArray(scip, &conscontvars); 15145 SCIPfreeBufferArray(scip, &isimplint); 15146 SCIPfreeBufferArray(scip, &nlocksup); 15147 SCIPfreeBufferArray(scip, &nlocksdown); 15148 SCIPfreeBufferArray(scip, &redub); 15149 SCIPfreeBufferArray(scip, &redlb); 15150 15151 SCIPfreeBufferArray(scip, &vars); 15152 15153 return SCIP_OKAY; 15154 } 15155 15156 /** helper function to enforce constraints */ 15157 static 15158 SCIP_RETCODE enforceConstraint( 15159 SCIP* scip, /**< SCIP data structure */ 15160 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 15161 SCIP_CONS** conss, /**< constraints to process */ 15162 int nconss, /**< number of constraints */ 15163 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */ 15164 SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */ 15165 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */ 15166 ) 15167 { 15168 SCIP_CONSHDLRDATA* conshdlrdata; 15169 SCIP_Bool checkrelmaxabs; 15170 SCIP_Bool violated; 15171 SCIP_Bool cutoff = FALSE; 15172 int c; 15173 15174 assert(scip != NULL); 15175 assert(conshdlr != NULL); 15176 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 15177 assert(result != NULL); 15178 15179 conshdlrdata = SCIPconshdlrGetData(conshdlr); 15180 assert(conshdlrdata != NULL); 15181 15182 checkrelmaxabs = conshdlrdata->checkrelmaxabs; 15183 15184 SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation"); 15185 15186 /* check for violated constraints 15187 * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP 15188 */ 15189 *result = SCIP_FEASIBLE; 15190 15191 /* check all useful linear constraints for feasibility */ 15192 for( c = 0; c < nusefulconss; ++c ) 15193 { 15194 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) ); 15195 15196 if( violated ) 15197 { 15198 /* insert LP row as cut */ 15199 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) ); 15200 if ( cutoff ) 15201 *result = SCIP_CUTOFF; 15202 else 15203 *result = SCIP_SEPARATED; 15204 } 15205 } 15206 15207 /* check all obsolete linear constraints for feasibility */ 15208 for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c ) 15209 { 15210 SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) ); 15211 15212 if( violated ) 15213 { 15214 /* insert LP row as cut */ 15215 SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) ); 15216 if ( cutoff ) 15217 *result = SCIP_CUTOFF; 15218 else 15219 *result = SCIP_SEPARATED; 15220 } 15221 } 15222 15223 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected"); 15224 15225 return SCIP_OKAY; 15226 } 15227 15228 /** adds symmetry information of constraint to a symmetry detection graph */ 15229 static 15230 SCIP_RETCODE addSymmetryInformation( 15231 SCIP* scip, /**< SCIP pointer */ 15232 SYM_SYMTYPE symtype, /**< type of symmetries that need to be added */ 15233 SCIP_CONS* cons, /**< constraint */ 15234 SYM_GRAPH* graph, /**< symmetry detection graph */ 15235 SCIP_Bool* success /**< pointer to store whether symmetry information could be added */ 15236 ) 15237 { 15238 SCIP_CONSDATA* consdata; 15239 SCIP_VAR** vars; 15240 SCIP_Real* vals; 15241 SCIP_Real constant = 0.0; 15242 SCIP_Real lhs; 15243 SCIP_Real rhs; 15244 int nlocvars; 15245 int nvars; 15246 int i; 15247 15248 assert(scip != NULL); 15249 assert(cons != NULL); 15250 assert(graph != NULL); 15251 assert(success != NULL); 15252 15253 consdata = SCIPconsGetData(cons); 15254 assert(consdata != NULL); 15255 15256 /* get active variables of the constraint */ 15257 nvars = SCIPgetNVars(scip); 15258 nlocvars = consdata->nvars; 15259 15260 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) ); 15261 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) ); 15262 15263 for( i = 0; i < nlocvars; ++i ) 15264 { 15265 vars[i] = consdata->vars[i]; 15266 vals[i] = consdata->vals[i]; 15267 } 15268 15269 SCIP_CALL( SCIPgetActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) ); 15270 lhs = consdata->lhs - constant; 15271 rhs = consdata->rhs - constant; 15272 15273 /* if rhs is infinite, normalize rhs to be finite to make sure that different encodings 15274 * of the same constraint are rated as equal 15275 */ 15276 if ( SCIPisInfinity(scip, rhs) ) 15277 { 15278 SCIP_Real tmp; 15279 assert(!SCIPisInfinity(scip, -lhs)); 15280 15281 for( i = 0; i < nlocvars; ++i ) 15282 vals[i] *= -1; 15283 tmp = rhs; 15284 rhs = -lhs; 15285 lhs = -tmp; 15286 } 15287 15288 SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars, 15289 cons, lhs, rhs, success) ); 15290 15291 SCIPfreeBufferArray(scip, &vals); 15292 SCIPfreeBufferArray(scip, &vars); 15293 15294 return SCIP_OKAY; 15295 } 15296 15297 /* 15298 * Callback methods of constraint handler 15299 */ 15300 15301 /** copy method for constraint handler plugins (called when SCIP copies plugins) */ 15302 static 15303 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear) 15304 { /*lint --e{715}*/ 15305 assert(scip != NULL); 15306 assert(conshdlr != NULL); 15307 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 15308 15309 /* call inclusion method of constraint handler */ 15310 SCIP_CALL( SCIPincludeConshdlrLinear(scip) ); 15311 15312 *valid = TRUE; 15313 15314 return SCIP_OKAY; 15315 } 15316 15317 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */ 15318 static 15319 SCIP_DECL_CONSFREE(consFreeLinear) 15320 { /*lint --e{715}*/ 15321 SCIP_CONSHDLRDATA* conshdlrdata; 15322 15323 assert(scip != NULL); 15324 assert(conshdlr != NULL); 15325 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 15326 15327 /* free constraint handler data */ 15328 conshdlrdata = SCIPconshdlrGetData(conshdlr); 15329 assert(conshdlrdata != NULL); 15330 15331 conshdlrdataFree(scip, &conshdlrdata); 15332 15333 SCIPconshdlrSetData(conshdlr, NULL); 15334 15335 return SCIP_OKAY; 15336 } 15337 15338 15339 /** initialization method of constraint handler (called after problem was transformed) */ 15340 static 15341 SCIP_DECL_CONSINIT(consInitLinear) 15342 { 15343 SCIP_CONSHDLRDATA* conshdlrdata; 15344 int c; 15345 15346 assert(scip != NULL); 15347 15348 /* check for event handler */ 15349 conshdlrdata = SCIPconshdlrGetData(conshdlr); 15350 assert(conshdlrdata != NULL); 15351 assert(conshdlrdata->eventhdlr != NULL); 15352 assert(nconss == 0 || conss != NULL); 15353 15354 conshdlrdata->naddconss = 0; 15355 15356 /* catch events for the constraints */ 15357 for( c = 0; c < nconss; ++c ) 15358 { 15359 /* catch all events */ 15360 SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) ); 15361 } 15362 15363 return SCIP_OKAY; 15364 } 15365 15366 15367 /** deinitialization method of constraint handler (called before transformed problem is freed) */ 15368 static 15369 SCIP_DECL_CONSEXIT(consExitLinear) 15370 { 15371 SCIP_CONSHDLRDATA* conshdlrdata; 15372 int c; 15373 15374 assert(scip != NULL); 15375 15376 /* check for event handler */ 15377 conshdlrdata = SCIPconshdlrGetData(conshdlr); 15378 assert(conshdlrdata != NULL); 15379 assert(conshdlrdata->eventhdlr != NULL); 15380 15381 /* drop events for the constraints */ 15382 for( c = nconss - 1; c >= 0; --c ) 15383 { 15384 SCIP_CONSDATA* consdata; 15385 15386 consdata = SCIPconsGetData(conss[c]); 15387 assert(consdata != NULL); 15388 15389 if( consdata->eventdata != NULL ) 15390 { 15391 /* drop all events */ 15392 SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) ); 15393 assert(consdata->eventdata == NULL); 15394 } 15395 } 15396 15397 return SCIP_OKAY; 15398 } 15399 15400 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */ 15401 static 15402 SCIP_Bool isRangedRow( 15403 SCIP* scip, /**< SCIP data structure */ 15404 SCIP_Real lhs, /**< left hand side */ 15405 SCIP_Real rhs /**< right hand side */ 15406 ) 15407 { 15408 assert(scip != NULL); 15409 15410 return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) ); 15411 } 15412 15413 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */ 15414 static 15415 SCIP_Bool isFiniteNonnegativeIntegral( 15416 SCIP* scip, /**< SCIP data structure */ 15417 SCIP_Real x /**< value */ 15418 ) 15419 { 15420 assert(scip != NULL); 15421 15422 return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x)); 15423 } 15424 15425 /** performs linear constraint type classification as used for MIPLIB 15426 * 15427 * iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats. 15428 * 15429 * @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already, 15430 * constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore. 15431 * Similarly, if specialized constraints were created through the API, these are currently not present. 15432 */ 15433 SCIP_RETCODE SCIPclassifyConstraintTypesLinear( 15434 SCIP* scip, /**< SCIP data structure */ 15435 SCIP_LINCONSSTATS* linconsstats /**< linear constraint type classification */ 15436 ) 15437 { 15438 int c; 15439 SCIP_CONSHDLR* conshdlr; 15440 SCIP_CONS** conss; 15441 int nconss; 15442 15443 assert(scip != NULL); 15444 assert(linconsstats != NULL); 15445 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME); 15446 assert(conshdlr != NULL); 15447 15448 if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM ) 15449 { 15450 conss = SCIPgetConss(scip); 15451 nconss = SCIPgetNConss(scip); 15452 } 15453 else 15454 { 15455 conss = SCIPconshdlrGetConss(conshdlr); 15456 nconss = SCIPconshdlrGetNConss(conshdlr); 15457 } 15458 15459 /* reset linear constraint type classification */ 15460 SCIPlinConsStatsReset(linconsstats); 15461 15462 /* loop through all constraints */ 15463 for( c = 0; c < nconss; c++ ) 15464 { 15465 SCIP_CONS* cons; 15466 SCIP_CONSDATA* consdata; 15467 SCIP_Real lhs; 15468 SCIP_Real rhs; 15469 int i; 15470 15471 /* get constraint */ 15472 cons = conss[c]; 15473 assert(cons != NULL); 15474 15475 /* skip constraints that are not handled by the constraint handler */ 15476 if( SCIPconsGetHdlr(cons) != conshdlr ) 15477 continue; 15478 15479 /* get constraint data */ 15480 consdata = SCIPconsGetData(cons); 15481 assert(consdata != NULL); 15482 rhs = consdata->rhs; 15483 lhs = consdata->lhs; 15484 15485 /* merge multiples and delete variables with zero coefficient */ 15486 SCIP_CALL( mergeMultiples(scip, cons) ); 15487 for( i = 0; i < consdata->nvars; i++ ) 15488 { 15489 assert(!SCIPisZero(scip, consdata->vals[i])); 15490 } 15491 15492 /* is constraint of type SCIP_CONSTYPE_EMPTY? */ 15493 if( consdata->nvars == 0 ) 15494 { 15495 SCIPdebugMsg(scip, "classified as EMPTY: "); 15496 SCIPdebugPrintCons(scip, cons, NULL); 15497 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_EMPTY, 1); 15498 15499 continue; 15500 } 15501 15502 /* is constraint of type SCIP_CONSTYPE_FREE? */ 15503 if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) ) 15504 { 15505 SCIPdebugMsg(scip, "classified as FREE: "); 15506 SCIPdebugPrintCons(scip, cons, NULL); 15507 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_FREE, 1); 15508 15509 continue; 15510 } 15511 15512 /* is constraint of type SCIP_CONSTYPE_SINGLETON? */ 15513 if( consdata->nvars == 1 ) 15514 { 15515 SCIPdebugMsg(scip, "classified as SINGLETON: "); 15516 SCIPdebugPrintCons(scip, cons, NULL); 15517 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1); 15518 15519 continue; 15520 } 15521 15522 /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */ 15523 if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) ) 15524 { 15525 SCIPdebugMsg(scip, "classified as AGGREGATION: "); 15526 SCIPdebugPrintCons(scip, cons, NULL); 15527 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_AGGREGATION, 1); 15528 15529 continue; 15530 } 15531 15532 /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */ 15533 if( consdata->nvars == 2 ) 15534 { 15535 SCIP_LINCONSTYPE constype; 15536 15537 /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */ 15538 if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1]) 15539 && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1])) 15540 { 15541 constype = SCIP_LINCONSTYPE_PRECEDENCE; 15542 SCIPdebugMsg(scip, "classified as PRECEDENCE: "); 15543 } 15544 else 15545 { 15546 constype = SCIP_LINCONSTYPE_VARBOUND; 15547 SCIPdebugMsg(scip, "classified as VARBOUND: "); 15548 } 15549 SCIPdebugPrintCons(scip, cons, NULL); 15550 15551 SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1); 15552 15553 continue; 15554 } 15555 15556 /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */ 15557 { 15558 SCIP_Real scale; 15559 SCIP_Real b; 15560 SCIP_Bool unmatched; 15561 int nnegbinvars; 15562 15563 unmatched = FALSE; 15564 nnegbinvars = 0; 15565 15566 scale = REALABS(consdata->vals[0]); 15567 15568 /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */ 15569 for( i = 0; i < consdata->nvars && !unmatched; i++ ) 15570 { 15571 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS; 15572 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0); 15573 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0); 15574 unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale); 15575 15576 if( consdata->vals[i] < 0.0 ) 15577 nnegbinvars++; 15578 } 15579 15580 if( !unmatched ) 15581 { 15582 if( SCIPisEQ(scip, lhs, rhs) ) 15583 { 15584 b = rhs/scale + nnegbinvars; 15585 if( SCIPisEQ(scip, 1.0, b) ) 15586 { 15587 SCIPdebugMsg(scip, "classified as SETPARTITION: "); 15588 SCIPdebugPrintCons(scip, cons, NULL); 15589 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPARTITION, 1); 15590 15591 continue; 15592 } 15593 else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) ) 15594 { 15595 SCIPdebugMsg(scip, "classified as CARDINALITY: "); 15596 SCIPdebugPrintCons(scip, cons, NULL); 15597 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_CARDINALITY, 1); 15598 15599 continue; 15600 } 15601 } 15602 15603 /* compute right hand side divided by scale */ 15604 if( !SCIPisInfinity(scip, rhs) ) 15605 b = rhs/scale + nnegbinvars; 15606 else 15607 b = SCIPinfinity(scip); 15608 15609 if( SCIPisEQ(scip, 1.0, b) ) 15610 { 15611 SCIPdebugMsg(scip, "classified as SETPACKING: "); 15612 SCIPdebugPrintCons(scip, cons, NULL); 15613 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPACKING, 1); 15614 15615 /* relax right hand side to prevent further classifications */ 15616 rhs = SCIPinfinity(scip); 15617 } 15618 else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) ) 15619 { 15620 SCIPdebugMsg(scip, "classified as INVKNAPSACK: "); 15621 SCIPdebugPrintCons(scip, cons, NULL); 15622 15623 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_INVKNAPSACK, 1);; 15624 15625 /* relax right hand side to prevent further classifications */ 15626 rhs = SCIPinfinity(scip); 15627 } 15628 15629 if( !SCIPisInfinity(scip, lhs) ) 15630 b = lhs/scale + nnegbinvars; 15631 else 15632 b = SCIPinfinity(scip); 15633 15634 if( SCIPisEQ(scip, 1.0, b) ) 15635 { 15636 SCIPdebugMsg(scip, "classified as SETCOVERING: "); 15637 SCIPdebugPrintCons(scip, cons, NULL); 15638 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SETCOVERING, 1); 15639 15640 /* relax left hand side to prevent further classifications */ 15641 lhs = -SCIPinfinity(scip); 15642 } 15643 15644 /* if both sides are infinite at this point, no further classification is necessary for this constraint */ 15645 if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) ) 15646 continue; 15647 } 15648 } 15649 15650 /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */ 15651 /* @todo If coefficients or rhs are not integral, we currently do not check 15652 * if the constraint could be scaled (finitely), such that they are. 15653 */ 15654 { 15655 SCIP_Real b; 15656 SCIP_Bool unmatched; 15657 15658 b = rhs; 15659 unmatched = FALSE; 15660 for( i = 0; i < consdata->nvars && !unmatched; i++ ) 15661 { 15662 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS; 15663 unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0); 15664 unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0); 15665 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]); 15666 15667 if( SCIPisNegative(scip, consdata->vals[i]) ) 15668 b -= consdata->vals[i]; 15669 } 15670 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b); 15671 15672 if( !unmatched ) 15673 { 15674 if( SCIPisEQ(scip, lhs, rhs) ) 15675 { 15676 SCIPdebugMsg(scip, "classified as EQKNAPSACK: "); 15677 SCIPdebugPrintCons(scip, cons, NULL); 15678 15679 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_EQKNAPSACK, 1); 15680 15681 continue; 15682 } 15683 else 15684 { 15685 SCIP_Bool matched; 15686 15687 matched = FALSE; 15688 for( i = 0; i < consdata->nvars && !matched; i++ ) 15689 { 15690 matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i])); 15691 } 15692 15693 SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK"); 15694 SCIPdebugPrintCons(scip, cons, NULL); 15695 SCIPlinConsStatsIncTypeCount(linconsstats, matched ? SCIP_LINCONSTYPE_BINPACKING : SCIP_LINCONSTYPE_KNAPSACK, 1); 15696 } 15697 15698 /* check if finite left hand side allows for a second classification, relax already used right hand side */ 15699 if( SCIPisInfinity(scip, -lhs) ) 15700 continue; 15701 else 15702 rhs = SCIPinfinity(scip); 15703 } 15704 } 15705 15706 /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */ 15707 { 15708 SCIP_Real b; 15709 SCIP_Bool unmatched; 15710 15711 unmatched = FALSE; 15712 15713 b = rhs; 15714 unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b); 15715 15716 for( i = 0; i < consdata->nvars && !unmatched; i++ ) 15717 { 15718 unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS; 15719 unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i])); 15720 unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]); 15721 unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]); 15722 } 15723 15724 if( !unmatched ) 15725 { 15726 SCIPdebugMsg(scip, "classified as INTKNAPSACK: "); 15727 SCIPdebugPrintCons(scip, cons, NULL); 15728 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_INTKNAPSACK, 1); 15729 15730 /* check if finite left hand side allows for a second classification, relax already used right hand side */ 15731 if( SCIPisInfinity(scip, -lhs) ) 15732 continue; 15733 else 15734 rhs = SCIPinfinity(scip); 15735 } 15736 } 15737 15738 /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */ 15739 { 15740 SCIP_Bool unmatched; 15741 15742 unmatched = FALSE; 15743 for( i = 0; i < consdata->nvars && !unmatched; i++ ) 15744 { 15745 if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS 15746 && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0) 15747 || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) ) 15748 unmatched = TRUE; 15749 } 15750 15751 if( !unmatched ) 15752 { 15753 SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1); 15754 SCIPdebugPrintCons(scip, cons, NULL); 15755 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1); 15756 15757 continue; 15758 } 15759 } 15760 15761 /* no special structure detected */ 15762 SCIPdebugMsg(scip, "classified as GENERAL: "); 15763 SCIPdebugPrintCons(scip, cons, NULL); 15764 SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1); 15765 } 15766 15767 return SCIP_OKAY; 15768 } 15769 15770 15771 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */ 15772 static 15773 SCIP_DECL_CONSEXITPRE(consExitpreLinear) 15774 { /*lint --e{715}*/ 15775 int c; 15776 #ifdef SCIP_STATISTIC 15777 SCIP_CONSHDLRDATA* conshdlrdata; 15778 int ngoodconss; 15779 int nallconss; 15780 #endif 15781 15782 /* delete all linear constraints that were upgraded to a more specific constraint type; 15783 * make sure, only active variables remain in the remaining constraints 15784 */ 15785 assert(scip != NULL); 15786 15787 #ifdef SCIP_STATISTIC 15788 /* count number of well behaved linear constraints */ 15789 conshdlrdata = SCIPconshdlrGetData(conshdlr); 15790 assert(conshdlrdata != NULL); 15791 15792 ngoodconss = 0; 15793 nallconss = 0; 15794 15795 for( c = 0; c < nconss; ++c ) 15796 { 15797 SCIP_CONSDATA* consdata; 15798 15799 if( SCIPconsIsDeleted(conss[c]) ) 15800 continue; 15801 15802 consdata = SCIPconsGetData(conss[c]); 15803 assert(consdata != NULL); 15804 15805 if( consdata->upgraded ) 15806 continue; 15807 15808 nallconss++; 15809 15810 consdataRecomputeMaxActivityDelta(scip, consdata); 15811 15812 if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) ) 15813 ngoodconss++; 15814 } 15815 if( nallconss ) 15816 { 15817 SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss)); 15818 } 15819 #endif 15820 15821 for( c = 0; c < nconss; ++c ) 15822 { 15823 SCIP_CONSDATA* consdata; 15824 15825 if( SCIPconsIsDeleted(conss[c]) ) 15826 continue; 15827 15828 consdata = SCIPconsGetData(conss[c]); 15829 assert(consdata != NULL); 15830 15831 if( consdata->upgraded ) 15832 { 15833 /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the 15834 * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler 15835 */ 15836 SCIP_CALL( SCIPdelCons(scip, conss[c]) ); 15837 } 15838 else 15839 { 15840 /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */ 15841 SCIP_CALL( applyFixings(scip, conss[c], NULL) ); 15842 } 15843 } 15844 15845 return SCIP_OKAY; 15846 } 15847 15848 /** solving process initialization method of constraint handler */ 15849 static 15850 SCIP_DECL_CONSINITSOL(consInitsolLinear) 15851 { /*lint --e{715}*/ 15852 /* add nlrow representation to NLP, if NLP had been constructed */ 15853 if( SCIPisNLPConstructed(scip) ) 15854 { 15855 int c; 15856 for( c = 0; c < nconss; ++c ) 15857 { 15858 SCIP_CALL( addNlrow(scip, conss[c]) ); 15859 } 15860 } 15861 15862 return SCIP_OKAY; 15863 } 15864 15865 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */ 15866 static 15867 SCIP_DECL_CONSEXITSOL(consExitsolLinear) 15868 { /*lint --e{715}*/ 15869 int c; 15870 15871 assert(scip != NULL); 15872 15873 /* release the rows and nlrows of all constraints */ 15874 for( c = 0; c < nconss; ++c ) 15875 { 15876 SCIP_CONSDATA* consdata; 15877 15878 consdata = SCIPconsGetData(conss[c]); 15879 assert(consdata != NULL); 15880 15881 if( consdata->row != NULL ) 15882 { 15883 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) ); 15884 } 15885 15886 if( consdata->nlrow != NULL ) 15887 { 15888 SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) ); 15889 } 15890 } 15891 15892 /* if this is a restart, convert cutpool rows into linear constraints */ 15893 if( restart ) 15894 { 15895 int ncutsadded; 15896 15897 ncutsadded = 0; 15898 15899 /* create out of all active cuts in cutpool linear constraints */ 15900 SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) ); 15901 15902 if( ncutsadded > 0 ) 15903 { 15904 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, 15905 "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded); 15906 /* an extra blank line should be printed separately since the buffer message handler only handles up to one 15907 * line correctly 15908 */ 15909 SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "\n"); 15910 } 15911 } 15912 15913 return SCIP_OKAY; 15914 } 15915 15916 15917 /** constraint activation notification method of constraint handler */ 15918 static 15919 SCIP_DECL_CONSACTIVE(consActiveLinear) 15920 { /*lint --e{715}*/ 15921 assert(cons != NULL); 15922 15923 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) ) 15924 { 15925 SCIP_CALL( addNlrow(scip, cons) ); 15926 } 15927 15928 return SCIP_OKAY; 15929 } 15930 15931 /** constraint deactivation notification method of constraint handler */ 15932 static 15933 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear) 15934 { /*lint --e{715}*/ 15935 SCIP_CONSDATA* consdata; 15936 15937 assert(scip != NULL); 15938 assert(conshdlr != NULL); 15939 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 15940 assert(cons != NULL ); 15941 15942 /* get constraint data */ 15943 consdata = SCIPconsGetData(cons); 15944 assert(consdata != NULL); 15945 15946 if( SCIPconsIsDeleted(cons) ) 15947 { 15948 SCIP_CONSHDLRDATA* conshdlrdata; 15949 15950 /* check for event handler */ 15951 conshdlrdata = SCIPconshdlrGetData(conshdlr); 15952 assert(conshdlrdata != NULL); 15953 assert(conshdlrdata->eventhdlr != NULL); 15954 15955 /* free event data */ 15956 if( consdata->eventdata != NULL ) 15957 { 15958 /* drop bound change events of variables */ 15959 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) ); 15960 } 15961 assert(consdata->eventdata == NULL); 15962 } 15963 15964 /* remove row from NLP, if still in solving 15965 * if we are in exitsolve, the whole NLP will be freed anyway 15966 */ 15967 if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL ) 15968 { 15969 SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) ); 15970 } 15971 15972 return SCIP_OKAY; 15973 } 15974 15975 15976 /** frees specific constraint data */ 15977 static 15978 SCIP_DECL_CONSDELETE(consDeleteLinear) 15979 { /*lint --e{715}*/ 15980 assert(scip != NULL); 15981 assert(conshdlr != NULL); 15982 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 15983 15984 if( (*consdata)->eventdata != NULL ) 15985 { 15986 SCIP_CONSHDLRDATA* conshdlrdata; 15987 15988 conshdlrdata = SCIPconshdlrGetData(conshdlr); 15989 assert(conshdlrdata != NULL); 15990 15991 /* drop all events */ 15992 SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) ); 15993 assert((*consdata)->eventdata == NULL); 15994 } 15995 15996 /* free linear constraint */ 15997 SCIP_CALL( consdataFree(scip, consdata) ); 15998 15999 return SCIP_OKAY; 16000 } 16001 16002 16003 /** transforms constraint data into data belonging to the transformed problem */ 16004 static 16005 SCIP_DECL_CONSTRANS(consTransLinear) 16006 { /*lint --e{715}*/ 16007 SCIP_CONSDATA* sourcedata; 16008 SCIP_CONSDATA* targetdata; 16009 16010 /*debugMsg(scip, "Trans method of linear constraints\n");*/ 16011 16012 assert(scip != NULL); 16013 assert(conshdlr != NULL); 16014 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16015 assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING); 16016 assert(sourcecons != NULL); 16017 assert(targetcons != NULL); 16018 16019 sourcedata = SCIPconsGetData(sourcecons); 16020 assert(sourcedata != NULL); 16021 assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */ 16022 16023 /* create linear constraint data for target constraint */ 16024 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) ); 16025 16026 #ifndef NDEBUG 16027 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */ 16028 if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) ) 16029 { 16030 int n; 16031 for(n = targetdata->nvars - 1; n >= 0; --n ) 16032 assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n])); 16033 } 16034 #endif 16035 16036 /* create target constraint */ 16037 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata, 16038 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons), 16039 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons), 16040 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons), 16041 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) ); 16042 16043 return SCIP_OKAY; 16044 } 16045 16046 16047 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */ 16048 static 16049 SCIP_DECL_CONSINITLP(consInitlpLinear) 16050 { /*lint --e{715}*/ 16051 int c; 16052 16053 assert(scip != NULL); 16054 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16055 16056 *infeasible = FALSE; 16057 16058 for( c = 0; c < nconss && !(*infeasible); ++c ) 16059 { 16060 assert(SCIPconsIsInitial(conss[c])); 16061 SCIP_CALL( addRelaxation(scip, conss[c], infeasible) ); 16062 } 16063 16064 return SCIP_OKAY; 16065 } 16066 16067 16068 /** separation method of constraint handler for LP solutions */ 16069 static 16070 SCIP_DECL_CONSSEPALP(consSepalpLinear) 16071 { /*lint --e{715}*/ 16072 SCIP_CONSHDLRDATA* conshdlrdata; 16073 SCIP_Real loclowerbound; 16074 SCIP_Real glblowerbound; 16075 SCIP_Real cutoffbound; 16076 SCIP_Real maxbound; 16077 SCIP_Bool separatecards; 16078 SCIP_Bool cutoff; 16079 int c; 16080 int depth; 16081 int nrounds; 16082 int maxsepacuts; 16083 int ncuts; 16084 16085 assert(scip != NULL); 16086 assert(conshdlr != NULL); 16087 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16088 assert(result != NULL); 16089 16090 conshdlrdata = SCIPconshdlrGetData(conshdlr); 16091 assert(conshdlrdata != NULL); 16092 depth = SCIPgetDepth(scip); 16093 nrounds = SCIPgetNSepaRounds(scip); 16094 16095 /*debugMsg(scip, "Sepa method of linear constraints\n");*/ 16096 16097 *result = SCIP_DIDNOTRUN; 16098 16099 /* only call the separator a given number of times at each node */ 16100 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot) 16101 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) ) 16102 return SCIP_OKAY; 16103 16104 /* get the maximal number of cuts allowed in a separation round */ 16105 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts); 16106 16107 /* check if we want to produce knapsack cardinality cuts at this node */ 16108 loclowerbound = SCIPgetLocalLowerbound(scip); 16109 glblowerbound = SCIPgetLowerbound(scip); 16110 cutoffbound = SCIPgetCutoffbound(scip); 16111 maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound); 16112 separatecards = SCIPisLE(scip, loclowerbound, maxbound); 16113 separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0); 16114 16115 *result = SCIP_DIDNOTFIND; 16116 ncuts = 0; 16117 cutoff = FALSE; 16118 16119 /* check all useful linear constraints for feasibility */ 16120 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c ) 16121 { 16122 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/ 16123 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) ); 16124 } 16125 16126 /* adjust return value */ 16127 if( cutoff ) 16128 *result = SCIP_CUTOFF; 16129 else if( ncuts > 0 ) 16130 *result = SCIP_SEPARATED; 16131 16132 /* combine linear constraints to get more cuts */ 16133 /**@todo further cuts of linear constraints */ 16134 16135 return SCIP_OKAY; 16136 } 16137 16138 16139 /** separation method of constraint handler for arbitrary primal solutions */ 16140 static 16141 SCIP_DECL_CONSSEPASOL(consSepasolLinear) 16142 { /*lint --e{715}*/ 16143 SCIP_CONSHDLRDATA* conshdlrdata; 16144 int c; 16145 int depth; 16146 int nrounds; 16147 int maxsepacuts; 16148 int ncuts; 16149 SCIP_Bool cutoff; 16150 16151 assert(scip != NULL); 16152 assert(conshdlr != NULL); 16153 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16154 assert(result != NULL); 16155 16156 conshdlrdata = SCIPconshdlrGetData(conshdlr); 16157 assert(conshdlrdata != NULL); 16158 depth = SCIPgetDepth(scip); 16159 nrounds = SCIPgetNSepaRounds(scip); 16160 16161 /*debugMsg(scip, "Sepa method of linear constraints\n");*/ 16162 16163 *result = SCIP_DIDNOTRUN; 16164 16165 /* only call the separator a given number of times at each node */ 16166 if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot) 16167 || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) ) 16168 return SCIP_OKAY; 16169 16170 /* get the maximal number of cuts allowed in a separation round */ 16171 maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts); 16172 16173 *result = SCIP_DIDNOTFIND; 16174 ncuts = 0; 16175 cutoff = FALSE; 16176 16177 /* check all useful linear constraints for feasibility */ 16178 for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c ) 16179 { 16180 /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/ 16181 SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) ); 16182 } 16183 16184 /* adjust return value */ 16185 if( cutoff ) 16186 *result = SCIP_CUTOFF; 16187 else if( ncuts > 0 ) 16188 *result = SCIP_SEPARATED; 16189 16190 /* combine linear constraints to get more cuts */ 16191 /**@todo further cuts of linear constraints */ 16192 16193 return SCIP_OKAY; 16194 } 16195 16196 16197 /** constraint enforcing method of constraint handler for LP solutions */ 16198 static 16199 SCIP_DECL_CONSENFOLP(consEnfolpLinear) 16200 { /*lint --e{715}*/ 16201 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) ); 16202 16203 return SCIP_OKAY; 16204 } 16205 16206 /** constraint enforcing method of constraint handler for relaxation solutions */ 16207 static 16208 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear) 16209 { /*lint --e{715}*/ 16210 SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) ); 16211 16212 return SCIP_OKAY; 16213 } 16214 16215 /** constraint enforcing method of constraint handler for pseudo solutions */ 16216 static 16217 SCIP_DECL_CONSENFOPS(consEnfopsLinear) 16218 { /*lint --e{715}*/ 16219 SCIP_CONSHDLRDATA* conshdlrdata; 16220 SCIP_Bool checkrelmaxabs; 16221 SCIP_Bool violated; 16222 int c; 16223 16224 assert(scip != NULL); 16225 assert(conshdlr != NULL); 16226 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16227 assert(result != NULL); 16228 16229 conshdlrdata = SCIPconshdlrGetData(conshdlr); 16230 assert(conshdlrdata != NULL); 16231 16232 checkrelmaxabs = conshdlrdata->checkrelmaxabs; 16233 16234 SCIPdebugMsg(scip, "Enfops method of linear constraints\n"); 16235 16236 /* if the solution is infeasible anyway due to objective value, skip the enforcement */ 16237 if( objinfeasible ) 16238 { 16239 SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n"); 16240 16241 *result = SCIP_DIDNOTRUN; 16242 return SCIP_OKAY; 16243 } 16244 16245 /* check all linear constraints for feasibility */ 16246 violated = FALSE; 16247 for( c = 0; c < nconss && !violated; ++c ) 16248 { 16249 SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) ); 16250 } 16251 16252 if( violated ) 16253 *result = SCIP_INFEASIBLE; 16254 else 16255 *result = SCIP_FEASIBLE; 16256 16257 SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected"); 16258 16259 return SCIP_OKAY; 16260 } 16261 16262 16263 /** feasibility check method of constraint handler for integral solutions */ 16264 static 16265 SCIP_DECL_CONSCHECK(consCheckLinear) 16266 { /*lint --e{715}*/ 16267 SCIP_CONSHDLRDATA* conshdlrdata; 16268 SCIP_Bool checkrelmaxabs; 16269 int c; 16270 16271 assert(scip != NULL); 16272 assert(conshdlr != NULL); 16273 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16274 assert(result != NULL); 16275 16276 *result = SCIP_FEASIBLE; 16277 16278 conshdlrdata = SCIPconshdlrGetData(conshdlr); 16279 assert(conshdlrdata != NULL); 16280 16281 checkrelmaxabs = conshdlrdata->checkrelmaxabs; 16282 16283 /*debugMsg(scip, "Check method of linear constraints\n");*/ 16284 16285 /* check all linear constraints for feasibility */ 16286 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c ) 16287 { 16288 SCIP_Bool violated = FALSE; 16289 SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) ); 16290 16291 if( violated ) 16292 { 16293 *result = SCIP_INFEASIBLE; 16294 16295 if( printreason ) 16296 { 16297 SCIP_CONSDATA* consdata; 16298 SCIP_Real activity; 16299 16300 consdata = SCIPconsGetData(conss[c]); 16301 assert( consdata != NULL); 16302 16303 activity = consdataGetActivity(scip, consdata, sol); 16304 16305 SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) ); 16306 SCIPinfoMessage(scip, NULL, ";\n"); 16307 16308 if( activity == SCIP_INVALID ) /*lint !e777*/ 16309 SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n"); 16310 else if( SCIPisFeasLT(scip, activity, consdata->lhs) ) 16311 SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity); 16312 else if( SCIPisFeasGT(scip, activity, consdata->rhs) ) 16313 SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs); 16314 } 16315 } 16316 } 16317 16318 return SCIP_OKAY; 16319 } 16320 16321 16322 /** domain propagation method of constraint handler */ 16323 static 16324 SCIP_DECL_CONSPROP(consPropLinear) 16325 { /*lint --e{715}*/ 16326 SCIP_CONSHDLRDATA* conshdlrdata; 16327 SCIP_Bool rangedrowpropagation = FALSE; 16328 SCIP_Bool tightenbounds; 16329 SCIP_Bool cutoff; 16330 16331 int nchgbds; 16332 int i; 16333 16334 assert(scip != NULL); 16335 assert(conshdlr != NULL); 16336 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16337 assert(result != NULL); 16338 16339 conshdlrdata = SCIPconshdlrGetData(conshdlr); 16340 assert(conshdlrdata != NULL); 16341 16342 /*debugMsg(scip, "Prop method of linear constraints\n");*/ 16343 16344 /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */ 16345 if( SCIPinProbing(scip) ) 16346 tightenbounds = TRUE; 16347 else 16348 { 16349 int depth; 16350 int propfreq; 16351 int tightenboundsfreq; 16352 int rangedrowfreq; 16353 16354 depth = SCIPgetDepth(scip); 16355 propfreq = SCIPconshdlrGetPropFreq(conshdlr); 16356 tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq; 16357 tightenbounds = (conshdlrdata->tightenboundsfreq >= 0) 16358 && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0))); 16359 16360 /* check if we want to do ranged row propagation */ 16361 rangedrowpropagation = conshdlrdata->rangedrowpropagation; 16362 rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip); 16363 rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth); 16364 rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq; 16365 rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0) 16366 && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0))); 16367 } 16368 16369 cutoff = FALSE; 16370 nchgbds = 0; 16371 16372 /* process constraints marked for propagation */ 16373 for( i = 0; i < nmarkedconss && !cutoff; i++ ) 16374 { 16375 SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) ); 16376 SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation, 16377 conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) ); 16378 } 16379 16380 /* adjust result code */ 16381 if( cutoff ) 16382 *result = SCIP_CUTOFF; 16383 else if( nchgbds > 0 ) 16384 *result = SCIP_REDUCEDDOM; 16385 else 16386 *result = SCIP_DIDNOTFIND; 16387 16388 return SCIP_OKAY; 16389 } 16390 16391 16392 #define MAXCONSPRESOLROUNDS 10 16393 /** presolving method of constraint handler */ 16394 static 16395 SCIP_DECL_CONSPRESOL(consPresolLinear) 16396 { /*lint --e{715}*/ 16397 SCIP_CONSHDLRDATA* conshdlrdata; 16398 SCIP_CONS* cons; 16399 SCIP_CONSDATA* consdata; 16400 SCIP_Real minactivity; 16401 SCIP_Real maxactivity; 16402 SCIP_Bool minactisrelax; 16403 SCIP_Bool maxactisrelax; 16404 SCIP_Bool isminsettoinfinity; 16405 SCIP_Bool ismaxsettoinfinity; 16406 SCIP_Bool cutoff; 16407 int oldnfixedvars; 16408 int oldnaggrvars; 16409 int oldnchgbds; 16410 int oldndelconss; 16411 int oldnupgdconss; 16412 int oldnchgcoefs; 16413 int oldnchgsides; 16414 int firstchange; 16415 int firstupgradetry; 16416 int c; 16417 16418 assert(scip != NULL); 16419 assert(conshdlr != NULL); 16420 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); 16421 assert(result != NULL); 16422 16423 /*debugMsg(scip, "Presol method of linear constraints\n");*/ 16424 16425 /* remember old preprocessing counters */ 16426 cutoff = FALSE; 16427 oldnfixedvars = *nfixedvars; 16428 oldnaggrvars = *naggrvars; 16429 oldnchgbds = *nchgbds; 16430 oldndelconss = *ndelconss; 16431 oldnupgdconss = *nupgdconss; 16432 oldnchgcoefs = *nchgcoefs; 16433 oldnchgsides = *nchgsides; 16434 16435 /* get constraint handler data */ 16436 conshdlrdata = SCIPconshdlrGetData(conshdlr); 16437 assert(conshdlrdata != NULL); 16438 16439 /* process single constraints */ 16440 firstchange = INT_MAX; 16441 firstupgradetry = INT_MAX; 16442 for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c ) 16443 { 16444 int npresolrounds; 16445 SCIP_Bool infeasible; 16446 16447 infeasible = FALSE; 16448 16449 cons = conss[c]; 16450 assert(SCIPconsIsActive(cons)); 16451 consdata = SCIPconsGetData(cons); 16452 assert(consdata != NULL); 16453 16454 /* ensure that rhs >= lhs is satisfied without numerical tolerance */ 16455 if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) ) 16456 { 16457 consdata->lhs = consdata->rhs; 16458 assert(consdata->row == NULL); 16459 } 16460 16461 if( consdata->eventdata == NULL ) 16462 { 16463 /* catch bound change events of variables */ 16464 SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) ); 16465 assert(consdata->eventdata != NULL); 16466 } 16467 16468 /* constraint should not be already presolved in the initial round */ 16469 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons)); 16470 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0); 16471 assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved); 16472 assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved); 16473 16474 /* incorporate fixings and aggregations in constraint */ 16475 SCIP_CALL( applyFixings(scip, cons, &infeasible) ); 16476 16477 if( infeasible ) 16478 { 16479 SCIPdebugMsg(scip, " -> infeasible fixing\n"); 16480 cutoff = TRUE; 16481 break; 16482 } 16483 16484 assert(consdata->removedfixings); 16485 16486 /* we can only presolve linear constraints, that are not modifiable */ 16487 if( SCIPconsIsModifiable(cons) ) 16488 continue; 16489 16490 /* remember the first changed constraint to begin the next aggregation round with */ 16491 if( firstchange == INT_MAX && consdata->changed ) 16492 firstchange = c; 16493 16494 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */ 16495 if( firstupgradetry == INT_MAX && !consdata->upgradetried ) 16496 firstupgradetry = c; 16497 16498 /* check, if constraint is already preprocessed */ 16499 if( consdata->presolved ) 16500 continue; 16501 16502 assert(SCIPconsIsActive(cons)); 16503 16504 SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons)); 16505 SCIPdebugPrintCons(scip, cons, NULL); 16506 16507 /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds 16508 * to avoid nearly infinite cycling due to very small bound changes) 16509 */ 16510 npresolrounds = 0; 16511 while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) ) 16512 { 16513 assert(!cutoff); 16514 npresolrounds++; 16515 16516 /* mark constraint being presolved and propagated */ 16517 consdata->presolved = TRUE; 16518 SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) ); 16519 16520 /* normalize constraint */ 16521 SCIP_CALL( normalizeCons(scip, cons, &infeasible) ); 16522 16523 if( infeasible ) 16524 { 16525 SCIPdebugMsg(scip, " -> infeasible normalization\n"); 16526 cutoff = TRUE; 16527 break; 16528 } 16529 16530 /* tighten left and right hand side due to integrality */ 16531 SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) ); 16532 16533 if( infeasible ) 16534 { 16535 SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n"); 16536 cutoff = TRUE; 16537 break; 16538 } 16539 16540 /* check bounds */ 16541 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) ) 16542 { 16543 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n", 16544 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 16545 cutoff = TRUE; 16546 break; 16547 } 16548 16549 /* tighten variable's bounds */ 16550 SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) ); 16551 if( cutoff ) 16552 break; 16553 16554 /* check for fixed variables */ 16555 SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) ); 16556 if( cutoff ) 16557 break; 16558 16559 /* check constraint for infeasibility and redundancy */ 16560 consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax, 16561 &isminsettoinfinity, &ismaxsettoinfinity); 16562 if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) ) 16563 { 16564 SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n", 16565 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs); 16566 cutoff = TRUE; 16567 break; 16568 } 16569 else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) ) 16570 { 16571 SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n", 16572 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs); 16573 SCIP_CALL( SCIPdelCons(scip, cons) ); 16574 assert(!SCIPconsIsActive(cons)); 16575 16576 if( !consdata->upgraded ) 16577 (*ndelconss)++; 16578 break; 16579 } 16580 else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisGE(scip, minactivity, consdata->lhs) ) 16581 { 16582 SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n", 16583 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs); 16584 SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) ); 16585 if( !consdata->upgraded ) 16586 (*nchgsides)++; 16587 } 16588 else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisLE(scip, maxactivity, consdata->rhs) ) 16589 { 16590 SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n", 16591 SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs); 16592 SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) ); 16593 if( !consdata->upgraded ) 16594 (*nchgsides)++; 16595 } 16596 16597 /* handle empty constraint */ 16598 if( consdata->nvars == 0 ) 16599 { 16600 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) ) 16601 { 16602 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n", 16603 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 16604 cutoff = TRUE; 16605 } 16606 else 16607 { 16608 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n", 16609 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 16610 SCIP_CALL( SCIPdelCons(scip, cons) ); 16611 assert(!SCIPconsIsActive(cons)); 16612 16613 if( !consdata->upgraded ) 16614 (*ndelconss)++; 16615 } 16616 break; 16617 } 16618 16619 /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */ 16620 SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) ); 16621 16622 /* try to simplify inequalities */ 16623 if( conshdlrdata->simplifyinequalities ) 16624 { 16625 SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) ); 16626 16627 if( cutoff ) 16628 break; 16629 } 16630 16631 /* aggregation variable in equations */ 16632 if( conshdlrdata->aggregatevariables ) 16633 { 16634 SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) ); 16635 if( cutoff ) 16636 break; 16637 } 16638 } 16639 16640 if( !cutoff && !SCIPisStopped(scip) ) 16641 { 16642 /* perform ranged row propagation */ 16643 if( conshdlrdata->rangedrowpropagation ) 16644 { 16645 int lastnfixedvars; 16646 16647 lastnfixedvars = *nfixedvars; 16648 16649 SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) ); 16650 if( !cutoff ) 16651 { 16652 if( lastnfixedvars < *nfixedvars ) 16653 { 16654 SCIP_CALL( applyFixings(scip, cons, &cutoff) ); 16655 } 16656 } 16657 } 16658 16659 /* extract cliques from constraint */ 16660 if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) ) 16661 { 16662 SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, 16663 nfixedvars, nchgbds, &cutoff) ); 16664 16665 /* check if the constraint got redundant or infeasible */ 16666 if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 ) 16667 { 16668 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) ) 16669 { 16670 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n", 16671 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 16672 cutoff = TRUE; 16673 } 16674 else 16675 { 16676 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n", 16677 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 16678 SCIP_CALL( SCIPdelCons(scip, cons) ); 16679 assert(!SCIPconsIsActive(cons)); 16680 16681 if( !consdata->upgraded ) 16682 (*ndelconss)++; 16683 } 16684 } 16685 } 16686 16687 /* convert special equalities */ 16688 if( !cutoff && SCIPconsIsActive(cons) ) 16689 { 16690 SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) ); 16691 } 16692 16693 /* apply dual presolving for variables that appear in only one constraint */ 16694 if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) ) 16695 { 16696 SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) ); 16697 } 16698 16699 /* check if an inequality is parallel to the objective function */ 16700 if( !cutoff && SCIPconsIsActive(cons) ) 16701 { 16702 SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) ); 16703 } 16704 16705 /* remember the first changed constraint to begin the next aggregation round with */ 16706 if( firstchange == INT_MAX && consdata->changed ) 16707 firstchange = c; 16708 16709 /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */ 16710 if( firstupgradetry == INT_MAX && !consdata->upgradetried ) 16711 firstupgradetry = c; 16712 } 16713 16714 /* singleton column stuffing */ 16715 if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) && 16716 (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) ) 16717 { 16718 SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing, 16719 conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) ); 16720 16721 /* handle empty constraint */ 16722 if( consdata->nvars == 0 ) 16723 { 16724 if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) ) 16725 { 16726 SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n", 16727 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 16728 cutoff = TRUE; 16729 } 16730 else 16731 { 16732 SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n", 16733 SCIPconsGetName(cons), consdata->lhs, consdata->rhs); 16734 SCIP_CALL( SCIPdelCons(scip, cons) ); 16735 assert(!SCIPconsIsActive(cons)); 16736 16737 if( !consdata->upgraded ) 16738 (*ndelconss)++; 16739 } 16740 break; 16741 } 16742 } 16743 } 16744 16745 /* process pairs of constraints: check them for redundancy and try to aggregate them; 16746 * only apply this expensive procedure in exhaustive presolving timing 16747 */ 16748 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) ) 16749 { 16750 assert(firstchange >= 0); 16751 16752 if( firstchange < nconss && conshdlrdata->presolusehashing ) 16753 { 16754 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */ 16755 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff, 16756 ndelconss, nchgsides) ); 16757 } 16758 16759 if( firstchange < nconss && conshdlrdata->presolpairwise ) 16760 { 16761 SCIP_CONS** usefulconss; 16762 int nusefulconss; 16763 int firstchangenew; 16764 SCIP_Longint npaircomparisons; 16765 16766 npaircomparisons = 0; 16767 oldndelconss = *ndelconss; 16768 oldnchgsides = *nchgsides; 16769 oldnchgcoefs = *nchgcoefs; 16770 16771 /* allocate temporary memory */ 16772 SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) ); 16773 16774 nusefulconss = 0; 16775 firstchangenew = -1; 16776 for( c = 0; c < nconss; ++c ) 16777 { 16778 /* update firstchange */ 16779 if( c == firstchange ) 16780 firstchangenew = nusefulconss; 16781 16782 /* ignore inactive and modifiable constraints */ 16783 if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) ) 16784 continue; 16785 16786 usefulconss[nusefulconss] = conss[c]; 16787 ++nusefulconss; 16788 } 16789 firstchange = firstchangenew; 16790 assert(firstchangenew >= 0 && firstchangenew <= nusefulconss); 16791 16792 for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c ) 16793 { 16794 /* constraint has become inactive or modifiable during pairwise presolving */ 16795 if( usefulconss[c] == NULL ) 16796 continue; 16797 16798 npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/ 16799 16800 assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c])); 16801 SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale, 16802 &cutoff, ndelconss, nchgsides, nchgcoefs) ); 16803 16804 if( npaircomparisons > conshdlrdata->nmincomparisons ) 16805 { 16806 assert(npaircomparisons > 0); 16807 if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp ) 16808 break; 16809 oldndelconss = *ndelconss; 16810 oldnchgsides = *nchgsides; 16811 oldnchgcoefs = *nchgcoefs; 16812 npaircomparisons = 0; 16813 } 16814 } 16815 /* free temporary memory */ 16816 SCIPfreeBufferArray(scip, &usefulconss); 16817 } 16818 } 16819 16820 /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears 16821 * in linear constraints and we therefore have full information about it 16822 */ 16823 if( !cutoff && firstupgradetry < nconss 16824 && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss 16825 && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides 16826 ) 16827 { 16828 if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) ) 16829 { 16830 SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) ); 16831 } 16832 } 16833 16834 /* try to upgrade constraints into a more specific constraint type; 16835 * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler 16836 * may find additional reductions before giving control away to other (less intelligent?) constraint handlers) 16837 */ 16838 if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) ) 16839 { 16840 for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c ) 16841 { 16842 cons = conss[c]; 16843 16844 /* don't upgrade modifiable constraints */ 16845 if( SCIPconsIsModifiable(cons) ) 16846 continue; 16847 16848 consdata = SCIPconsGetData(cons); 16849 assert(consdata != NULL); 16850 16851 /* only upgrade completely presolved constraints, that changed since the last upgrading call */ 16852 if( consdata->upgradetried ) 16853 continue; 16854 /* @todo force that upgrade will be performed later? */ 16855 if( !consdata->presolved ) 16856 continue; 16857 16858 consdata->upgradetried = TRUE; 16859 if( SCIPconsIsActive(cons) ) 16860 { 16861 SCIP_CONS* upgdcons; 16862 16863 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) ); 16864 if( upgdcons != NULL ) 16865 { 16866 /* add the upgraded constraint to the problem */ 16867 SCIP_CALL( SCIPaddCons(scip, upgdcons) ); 16868 SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) ); 16869 (*nupgdconss)++; 16870 16871 /* mark the linear constraint being upgraded and to be removed after presolving; 16872 * don't delete it directly, because it may help to preprocess other linear constraints 16873 */ 16874 assert(!consdata->upgraded); 16875 consdata->upgraded = TRUE; 16876 16877 /* delete upgraded inequalities immediately; 16878 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking 16879 */ 16880 if( SCIPisLT(scip, consdata->lhs, consdata->rhs) 16881 || !conshdlrdata->presolpairwise 16882 || (conshdlrdata->maxaggrnormscale == 0.0) ) 16883 { 16884 SCIP_CALL( SCIPdelCons(scip, cons) ); 16885 } 16886 } 16887 } 16888 } 16889 } 16890 16891 /* return the correct result code */ 16892 if( cutoff ) 16893 *result = SCIP_CUTOFF; 16894 else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss 16895 || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides ) 16896 *result = SCIP_SUCCESS; 16897 else 16898 *result = SCIP_DIDNOTFIND; 16899 16900 return SCIP_OKAY; 16901 } 16902 16903 16904 /** propagation conflict resolving method of constraint handler */ 16905 static 16906 SCIP_DECL_CONSRESPROP(consRespropLinear) 16907 { /*lint --e{715}*/ 16908 assert(scip != NULL); 16909 assert(cons != NULL); 16910 assert(result != NULL); 16911 16912 SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) ); 16913 16914 return SCIP_OKAY; 16915 } 16916 16917 16918 /** variable rounding lock method of constraint handler */ 16919 static 16920 SCIP_DECL_CONSLOCK(consLockLinear) 16921 { /*lint --e{715}*/ 16922 SCIP_CONSDATA* consdata; 16923 SCIP_Bool haslhs; 16924 SCIP_Bool hasrhs; 16925 int i; 16926 16927 assert(scip != NULL); 16928 assert(cons != NULL); 16929 consdata = SCIPconsGetData(cons); 16930 assert(consdata != NULL); 16931 16932 haslhs = !SCIPisInfinity(scip, -consdata->lhs); 16933 hasrhs = !SCIPisInfinity(scip, consdata->rhs); 16934 16935 /* update rounding locks of every single variable */ 16936 for( i = 0; i < consdata->nvars; ++i ) 16937 { 16938 if( SCIPisPositive(scip, consdata->vals[i]) ) 16939 { 16940 if( haslhs ) 16941 { 16942 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) ); 16943 } 16944 if( hasrhs ) 16945 { 16946 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) ); 16947 } 16948 } 16949 else 16950 { 16951 if( haslhs ) 16952 { 16953 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) ); 16954 } 16955 if( hasrhs ) 16956 { 16957 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) ); 16958 } 16959 } 16960 } 16961 16962 return SCIP_OKAY; 16963 } 16964 16965 16966 /** variable deletion method of constraint handler */ 16967 static 16968 SCIP_DECL_CONSDELVARS(consDelvarsLinear) 16969 { 16970 assert(scip != NULL); 16971 assert(conshdlr != NULL); 16972 assert(conss != NULL || nconss == 0); 16973 16974 if( nconss > 0 ) 16975 { 16976 SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) ); 16977 } 16978 16979 return SCIP_OKAY; 16980 } 16981 16982 /** constraint display method of constraint handler */ 16983 static 16984 SCIP_DECL_CONSPRINT(consPrintLinear) 16985 { /*lint --e{715}*/ 16986 assert(scip != NULL); 16987 assert(conshdlr != NULL); 16988 assert(cons != NULL); 16989 16990 SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) ); 16991 16992 return SCIP_OKAY; 16993 } 16994 16995 /** constraint copying method of constraint handler */ 16996 static 16997 SCIP_DECL_CONSCOPY(consCopyLinear) 16998 { /*lint --e{715}*/ 16999 SCIP_VAR** sourcevars; 17000 SCIP_Real* sourcecoefs; 17001 const char* consname; 17002 int nvars; 17003 17004 assert(scip != NULL); 17005 assert(sourcescip != NULL); 17006 assert(sourcecons != NULL); 17007 17008 /* get variables and coefficients of the source constraint */ 17009 sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons); 17010 sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons); 17011 nvars = SCIPgetNVarsLinear(sourcescip, sourcecons); 17012 17013 if( name != NULL ) 17014 consname = name; 17015 else 17016 consname = SCIPconsGetName(sourcecons); 17017 17018 SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs, 17019 SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap, 17020 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) ); 17021 assert(cons != NULL || *valid == FALSE); 17022 17023 /* @todo should also the checkabsolute flag of the constraint be copied? */ 17024 17025 return SCIP_OKAY; 17026 } 17027 17028 /** find operators '<=', '==', '>=', [free] in input string and return those places 17029 * 17030 * There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present. 17031 */ 17032 static 17033 void findOperators( 17034 const char* str, /**< null terminated input string */ 17035 char** firstoperator, /**< pointer to store the string starting at the first operator */ 17036 char** secondoperator, /**< pointer to store the string starting at the second operator */ 17037 SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */ 17038 ) 17039 { 17040 char* curr; 17041 17042 assert(str != NULL); 17043 assert(firstoperator != NULL); 17044 assert(secondoperator != NULL); 17045 17046 *firstoperator = NULL; 17047 *secondoperator = NULL; 17048 17049 curr = (char*)str; 17050 *success = TRUE; 17051 17052 /* loop over the input string to find all operators */ 17053 while( *curr && *success ) 17054 { 17055 SCIP_Bool found = FALSE; 17056 int increment = 1; 17057 17058 /* try if we found a possible operator */ 17059 switch( *curr ) 17060 { 17061 case '<': 17062 case '=': 17063 case '>': 17064 17065 /* check if the two characters curr[0,1] form an operator together */ 17066 if( curr[1] == '=' ) 17067 { 17068 found = TRUE; 17069 17070 /* update increment to continue after this operator */ 17071 increment = 2; 17072 } 17073 break; 17074 case '[': 17075 if( strncmp(curr, "[free]", 6) == 0 ) 17076 { 17077 found = TRUE; 17078 17079 /* update increment to continue after this operator */ 17080 increment = 6; 17081 } 17082 break; 17083 default: 17084 break; 17085 } 17086 17087 /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */ 17088 if( found ) 17089 { 17090 if( *firstoperator == NULL ) 17091 { 17092 *firstoperator = curr; 17093 } 17094 else 17095 { 17096 if( *secondoperator != NULL ) 17097 { 17098 SCIPerrorMessage("Found more than two operators in line %s\n", str); 17099 *success = FALSE; 17100 } 17101 else if( strncmp(*firstoperator, "<=", 2) != 0 ) 17102 { 17103 SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str); 17104 *success = FALSE; 17105 } 17106 else if( strncmp(curr, "<=", 2) != 0 ) 17107 { 17108 SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str); 17109 *success = FALSE; 17110 } 17111 17112 *secondoperator = curr; 17113 } 17114 } 17115 17116 curr += increment; 17117 } 17118 17119 /* check if we did find at least one operator */ 17120 if( *success ) 17121 { 17122 if( *firstoperator == NULL ) 17123 { 17124 SCIPerrorMessage("Could not find any operator in line %s\n", str); 17125 *success = FALSE; 17126 } 17127 } 17128 } 17129 17130 /** constraint parsing method of constraint handler */ 17131 static 17132 SCIP_DECL_CONSPARSE(consParseLinear) 17133 { /*lint --e{715}*/ 17134 SCIP_VAR** vars; 17135 SCIP_Real* coefs; 17136 int nvars; 17137 int coefssize; 17138 int requsize; 17139 SCIP_Real lhs; 17140 SCIP_Real rhs; 17141 char* endptr; 17142 char* firstop; 17143 char* secondop; 17144 SCIP_Bool operatorsuccess; 17145 char* lhsstrptr; 17146 char* rhsstrptr; 17147 char* varstrptr; 17148 17149 assert(scip != NULL); 17150 assert(success != NULL); 17151 assert(str != NULL); 17152 assert(name != NULL); 17153 assert(cons != NULL); 17154 17155 /* set left and right hand side to their default values */ 17156 lhs = -SCIPinfinity(scip); 17157 rhs = SCIPinfinity(scip); 17158 17159 (*success) = FALSE; 17160 17161 /* return of string empty */ 17162 if( !*str ) 17163 return SCIP_OKAY; 17164 17165 /* ignore whitespace */ 17166 SCIP_CALL( SCIPskipSpace((char**)&str) ); 17167 17168 /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==', 17169 * and the special word [free] 17170 */ 17171 findOperators(str, &firstop, &secondop, &operatorsuccess); 17172 17173 /* if the grammar is not valid for parsing a linear constraint, return */ 17174 if( ! operatorsuccess ) 17175 return SCIP_OKAY; 17176 17177 varstrptr = (char *)str; 17178 lhsstrptr = rhsstrptr = NULL; 17179 assert(firstop != NULL); 17180 17181 /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */ 17182 switch( *firstop ) 17183 { 17184 case '<': 17185 assert(firstop[1] == '='); 17186 /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */ 17187 if( secondop != NULL ) 17188 { 17189 assert(secondop[0] == '<' && secondop[1] == '='); 17190 lhsstrptr = (char *)str; 17191 varstrptr = firstop + 2; 17192 rhsstrptr = secondop + 2; 17193 } 17194 else 17195 { 17196 /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */ 17197 lhsstrptr = NULL; 17198 varstrptr = (char *)str; 17199 rhsstrptr = firstop + 2; 17200 } 17201 break; 17202 case '>': 17203 assert(firstop[1] == '='); 17204 assert(secondop == NULL); 17205 /* we have a_1 x_1 + ... + a_n x_n >= lhs */ 17206 lhsstrptr = firstop + 2; 17207 break; 17208 case '=': 17209 assert(firstop[1] == '='); 17210 assert(secondop == NULL); 17211 /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */ 17212 rhsstrptr = firstop + 2; 17213 lhsstrptr = firstop + 2; 17214 break; 17215 case '[': 17216 assert(strncmp(firstop, "[free]", 6) == 0); 17217 assert(secondop == NULL); 17218 /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */ 17219 break; 17220 default: 17221 /* it should not be possible that a different character appears in that position */ 17222 SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop); 17223 return SCIP_READERROR; 17224 } 17225 17226 /* parse left hand side, if necessary */ 17227 if( lhsstrptr != NULL ) 17228 { 17229 if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) ) 17230 { 17231 SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr); 17232 return SCIP_OKAY; 17233 } 17234 17235 /* in case of an equation, assign the left also to the right hand side */ 17236 if( rhsstrptr == lhsstrptr ) 17237 rhs = lhs; 17238 } 17239 17240 /* parse right hand side, if different from left hand side */ 17241 if( rhsstrptr != NULL && rhsstrptr != lhsstrptr ) 17242 { 17243 if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) ) 17244 { 17245 SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr); 17246 return SCIP_OKAY; 17247 } 17248 } 17249 17250 /* initialize buffers for storing the variables and coefficients */ 17251 coefssize = 100; 17252 SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) ); 17253 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) ); 17254 17255 assert(varstrptr != NULL); 17256 17257 /* parse linear sum to get variables and coefficients */ 17258 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) ); 17259 17260 if( *success && requsize > coefssize ) 17261 { 17262 /* realloc buffers and try again */ 17263 coefssize = requsize; 17264 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) ); 17265 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) ); 17266 17267 SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) ); 17268 assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */ 17269 } 17270 17271 if( !*success ) 17272 { 17273 SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr); 17274 } 17275 else 17276 { 17277 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs, 17278 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) ); 17279 } 17280 17281 SCIPfreeBufferArray(scip, &coefs); 17282 SCIPfreeBufferArray(scip, &vars); 17283 17284 return SCIP_OKAY; 17285 } 17286 17287 17288 /** constraint method of constraint handler which returns the variables (if possible) */ 17289 static 17290 SCIP_DECL_CONSGETVARS(consGetVarsLinear) 17291 { /*lint --e{715}*/ 17292 SCIP_CONSDATA* consdata; 17293 17294 consdata = SCIPconsGetData(cons); 17295 assert(consdata != NULL); 17296 17297 if( varssize < consdata->nvars ) 17298 (*success) = FALSE; 17299 else 17300 { 17301 assert(vars != NULL); 17302 17303 BMScopyMemoryArray(vars, consdata->vars, consdata->nvars); 17304 (*success) = TRUE; 17305 } 17306 17307 return SCIP_OKAY; 17308 } 17309 17310 /**! [Callback for the number of variables]*/ 17311 /** constraint method of constraint handler which returns the number of variables (if possible) */ 17312 static 17313 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear) 17314 { /*lint --e{715}*/ 17315 SCIP_CONSDATA* consdata; 17316 17317 consdata = SCIPconsGetData(cons); 17318 assert(consdata != NULL); 17319 17320 (*nvars) = consdata->nvars; 17321 (*success) = TRUE; 17322 17323 return SCIP_OKAY; 17324 } 17325 /**! [Callback for the number of variables]*/ 17326 17327 /** constraint handler method which returns the permutation symmetry detection graph of a constraint */ 17328 static 17329 SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphLinear) 17330 { /*lint --e{715}*/ 17331 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) ); 17332 17333 return SCIP_OKAY; 17334 } 17335 17336 /** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */ 17337 static 17338 SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphLinear) 17339 { /*lint --e{715}*/ 17340 SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) ); 17341 17342 return SCIP_OKAY; 17343 } 17344 17345 /* 17346 * Callback methods of event handler 17347 */ 17348 17349 /** execution method of event handler */ 17350 static 17351 SCIP_DECL_EVENTEXEC(eventExecLinear) 17352 { /*lint --e{715}*/ 17353 SCIP_CONS* cons; 17354 SCIP_CONSDATA* consdata; 17355 SCIP_VAR* var; 17356 SCIP_EVENTTYPE eventtype; 17357 17358 assert(scip != NULL); 17359 assert(eventhdlr != NULL); 17360 assert(eventdata != NULL); 17361 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0); 17362 assert(event != NULL); 17363 17364 cons = eventdata->cons; 17365 assert(cons != NULL); 17366 consdata = SCIPconsGetData(cons); 17367 assert(consdata != NULL); 17368 17369 /* we can skip events droped for deleted constraints */ 17370 if( SCIPconsIsDeleted(cons) ) 17371 return SCIP_OKAY; 17372 17373 eventtype = SCIPeventGetType(event); 17374 var = SCIPeventGetVar(event); 17375 17376 if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 ) 17377 { 17378 SCIP_Real oldbound; 17379 SCIP_Real newbound; 17380 SCIP_Real val; 17381 int varpos; 17382 17383 varpos = eventdata->varpos; 17384 assert(0 <= varpos && varpos < consdata->nvars); 17385 oldbound = SCIPeventGetOldbound(event); 17386 newbound = SCIPeventGetNewbound(event); 17387 assert(var != NULL); 17388 assert(consdata->vars[varpos] == var); 17389 val = consdata->vals[varpos]; 17390 17391 /* we only need to update the activities if the constraint is active, 17392 * otherwise we mark them to be invalid 17393 */ 17394 if( SCIPconsIsActive(cons) ) 17395 { 17396 /* update the activity values */ 17397 if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 ) 17398 consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE); 17399 else 17400 { 17401 assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0); 17402 consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE); 17403 } 17404 } 17405 else 17406 consdataInvalidateActivities(consdata); 17407 17408 consdata->presolved = FALSE; 17409 consdata->rangedrowpropagated = 0; 17410 17411 /* bound change can turn the constraint infeasible or redundant only if it was a tightening */ 17412 if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 ) 17413 { 17414 SCIP_CALL( SCIPmarkConsPropagate(scip, cons) ); 17415 17416 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */ 17417 if( consdata->maxactdeltavar == var ) 17418 { 17419 consdata->maxactdelta = SCIP_INVALID; 17420 consdata->maxactdeltavar = NULL; 17421 } 17422 17423 /* check whether bound tightening might now be successful */ 17424 if( consdata->boundstightened > 0) 17425 { 17426 switch( eventtype ) 17427 { 17428 case SCIP_EVENTTYPE_LBTIGHTENED: 17429 if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) ) 17430 consdata->boundstightened = 0; 17431 break; 17432 case SCIP_EVENTTYPE_UBTIGHTENED: 17433 if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) ) 17434 consdata->boundstightened = 0; 17435 break; 17436 default: 17437 SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", eventtype); 17438 return SCIP_INVALIDDATA; 17439 } 17440 } 17441 } 17442 /* update maximal activity delta if a bound was relaxed */ 17443 else if( !SCIPisInfinity(scip, consdata->maxactdelta) ) 17444 { 17445 SCIP_Real lb; 17446 SCIP_Real ub; 17447 SCIP_Real domain; 17448 SCIP_Real delta; 17449 17450 assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0); 17451 17452 lb = SCIPvarGetLbLocal(var); 17453 ub = SCIPvarGetUbLocal(var); 17454 17455 domain = ub - lb; 17456 delta = REALABS(val) * domain; 17457 17458 if( delta > consdata->maxactdelta ) 17459 { 17460 consdata->maxactdelta = delta; 17461 consdata->maxactdeltavar = var; 17462 } 17463 } 17464 } 17465 else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 ) 17466 { 17467 /* we want to remove the fixed variable */ 17468 consdata->presolved = FALSE; 17469 consdata->removedfixings = FALSE; 17470 consdata->rangedrowpropagated = 0; 17471 17472 /* reset maximal activity delta, so that it will be recalculated on the next real propagation */ 17473 if( consdata->maxactdeltavar == var ) 17474 { 17475 consdata->maxactdelta = SCIP_INVALID; 17476 consdata->maxactdeltavar = NULL; 17477 } 17478 } 17479 else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 ) 17480 { 17481 /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */ 17482 assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1); 17483 assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1); 17484 consdata->presolved = FALSE; 17485 } 17486 else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 ) 17487 { 17488 SCIP_Real oldbound; 17489 SCIP_Real newbound; 17490 SCIP_Real val; 17491 int varpos; 17492 17493 varpos = eventdata->varpos; 17494 assert(0 <= varpos && varpos < consdata->nvars); 17495 oldbound = SCIPeventGetOldbound(event); 17496 newbound = SCIPeventGetNewbound(event); 17497 assert(var != NULL); 17498 assert(consdata->vars[varpos] == var); 17499 val = consdata->vals[varpos]; 17500 17501 consdata->rangedrowpropagated = 0; 17502 17503 /* update the activity values */ 17504 if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 ) 17505 consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE); 17506 else 17507 { 17508 assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0); 17509 consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE); 17510 } 17511 17512 /* if the variable is binary but not fixed it had to become binary due to this global change */ 17513 if( SCIPvarIsBinary(var) && SCIPisGT(scip, SCIPvarGetUbGlobal(var), SCIPvarGetLbGlobal(var)) ) 17514 { 17515 if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE ) 17516 consdata->indexsorted = FALSE; 17517 else 17518 consdata->coefsorted = FALSE; 17519 } 17520 } 17521 else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 ) 17522 { 17523 assert(SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED); 17524 17525 /* for presolving it only matters if a variable type changed from continuous to some kind of integer */ 17526 consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS); 17527 17528 /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */ 17529 consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var)); 17530 } 17531 else 17532 { 17533 assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0); 17534 consdata->varsdeleted = TRUE; 17535 } 17536 17537 return SCIP_OKAY; 17538 } 17539 17540 17541 /* 17542 * Callback methods of conflict handler 17543 */ 17544 17545 /** conflict processing method of conflict handler (called when conflict was found) */ 17546 static 17547 SCIP_DECL_CONFLICTEXEC(conflictExecLinear) 17548 { /*lint --e{715}*/ 17549 SCIP_VAR** vars; 17550 SCIP_Real* vals; 17551 SCIP_Real lhs; 17552 int i; 17553 17554 assert(scip != NULL); 17555 assert(conflicthdlr != NULL); 17556 assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0); 17557 assert(bdchginfos != NULL || nbdchginfos == 0); 17558 assert(result != NULL); 17559 17560 /* don't process already resolved conflicts */ 17561 if( resolved ) 17562 { 17563 *result = SCIP_DIDNOTRUN; 17564 return SCIP_OKAY; 17565 } 17566 17567 *result = SCIP_DIDNOTFIND; 17568 17569 /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */ 17570 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) ); 17571 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) ); 17572 lhs = 1.0; 17573 for( i = 0; i < nbdchginfos; ++i ) 17574 { 17575 assert(bdchginfos != NULL); 17576 17577 vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]); 17578 17579 /* we can only treat binary variables */ 17580 /**@todo extend linear conflict constraints to some non-binary cases */ 17581 if( !SCIPvarIsBinary(vars[i]) ) 17582 break; 17583 17584 /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */ 17585 if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 ) 17586 vals[i] = 1.0; 17587 else 17588 { 17589 vals[i] = -1.0; 17590 lhs -= 1.0; 17591 } 17592 } 17593 17594 if( i == nbdchginfos ) 17595 { 17596 SCIP_CONS* cons; 17597 SCIP_CONS* upgdcons; 17598 char consname[SCIP_MAXSTRLEN]; 17599 17600 /* create a constraint out of the conflict set */ 17601 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip)); 17602 SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip), 17603 FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) ); 17604 17605 /* try to automatically convert a linear constraint into a more specific and more specialized constraint */ 17606 SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) ); 17607 if( upgdcons != NULL ) 17608 { 17609 SCIP_CALL( SCIPreleaseCons(scip, &cons) ); 17610 cons = upgdcons; 17611 } 17612 17613 /* add conflict to SCIP */ 17614 SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) ); 17615 17616 *result = SCIP_CONSADDED; 17617 } 17618 17619 /* free temporary memory */ 17620 SCIPfreeBufferArray(scip, &vals); 17621 SCIPfreeBufferArray(scip, &vars); 17622 17623 return SCIP_OKAY; 17624 } 17625 17626 17627 /* 17628 * Nonlinear constraint upgrading 17629 */ 17630 17631 /** tries to upgrade a nonlinear constraint into a linear constraint */ 17632 static 17633 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear) 17634 { 17635 SCIP_CONSDATA* consdata; 17636 SCIP_EXPR* expr; 17637 SCIP_Real lhs; 17638 SCIP_Real rhs; 17639 int i; 17640 17641 assert(nupgdconss != NULL); 17642 assert(upgdconss != NULL); 17643 assert(upgdconsssize > 0); 17644 17645 expr = SCIPgetExprNonlinear(cons); 17646 assert(expr != NULL); 17647 17648 /* not a linear constraint if the expression is not a sum 17649 * (unless the expression is a variable or a constant or a constant*variable, but these are simplified away in cons_nonlinear) 17650 */ 17651 if( !SCIPisExprSum(scip, expr) ) 17652 return SCIP_OKAY; 17653 17654 /* if at least one child is not a variable, then not a linear constraint */ 17655 for( i = 0; i < SCIPexprGetNChildren(expr); ++i ) 17656 if( !SCIPisExprVar(scip, SCIPexprGetChildren(expr)[i]) ) 17657 return SCIP_OKAY; 17658 17659 /* consider constant part of the sum expression */ 17660 lhs = SCIPisInfinity(scip, -SCIPgetLhsNonlinear(cons)) ? -SCIPinfinity(scip) : (SCIPgetLhsNonlinear(cons) - SCIPgetConstantExprSum(expr)); 17661 rhs = SCIPisInfinity(scip, SCIPgetRhsNonlinear(cons)) ? SCIPinfinity(scip) : (SCIPgetRhsNonlinear(cons) - SCIPgetConstantExprSum(expr)); 17662 17663 SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons), 17664 0, NULL, NULL, lhs, rhs, 17665 SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), 17666 SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), 17667 SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), 17668 SCIPconsIsStickingAtNode(cons)) ); 17669 assert(upgdconss[0] != NULL); 17670 17671 consdata = SCIPconsGetData(upgdconss[0]); 17672 17673 /* add linear terms */ 17674 SCIP_CALL( consdataEnsureVarsSize(scip, consdata, SCIPexprGetNChildren(expr)) ); 17675 for( i = 0; i < SCIPexprGetNChildren(expr); ++i ) 17676 { 17677 SCIP_CALL( addCoef(scip, upgdconss[0], SCIPgetVarExprVar(SCIPexprGetChildren(expr)[i]), SCIPgetCoefsExprSum(expr)[i]) ); 17678 } 17679 17680 /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */ 17681 consdata->checkabsolute = TRUE; 17682 17683 *nupgdconss = 1; 17684 17685 SCIPdebugMsg(scip, "created linear constraint:\n"); 17686 SCIPdebugPrintCons(scip, upgdconss[0], NULL); 17687 17688 return SCIP_OKAY; 17689 } /*lint !e715*/ 17690 17691 /* 17692 * constraint specific interface methods 17693 */ 17694 17695 /** creates the handler for linear constraints and includes it in SCIP */ 17696 SCIP_RETCODE SCIPincludeConshdlrLinear( 17697 SCIP* scip /**< SCIP data structure */ 17698 ) 17699 { 17700 SCIP_CONSHDLRDATA* conshdlrdata; 17701 SCIP_CONSHDLR* conshdlr; 17702 SCIP_EVENTHDLR* eventhdlr; 17703 SCIP_CONFLICTHDLR* conflicthdlr; 17704 17705 assert(scip != NULL); 17706 17707 /* create event handler for bound change events */ 17708 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, 17709 eventExecLinear, NULL) ); 17710 17711 /* create conflict handler for linear constraints */ 17712 SCIP_CALL( SCIPincludeConflicthdlrBasic(scip, &conflicthdlr, CONFLICTHDLR_NAME, CONFLICTHDLR_DESC, CONFLICTHDLR_PRIORITY, 17713 conflictExecLinear, NULL) ); 17714 17715 /* create constraint handler data */ 17716 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) ); 17717 17718 /* include constraint handler */ 17719 SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC, 17720 CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY, CONSHDLR_EAGERFREQ, CONSHDLR_NEEDSCONS, 17721 consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear, 17722 conshdlrdata) ); 17723 17724 assert(conshdlr != NULL); 17725 17726 /* set non-fundamental callbacks via specific setter functions */ 17727 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) ); 17728 SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveLinear) ); 17729 SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) ); 17730 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) ); 17731 SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) ); 17732 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) ); 17733 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) ); 17734 SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolLinear) ); 17735 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) ); 17736 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) ); 17737 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) ); 17738 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) ); 17739 SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) ); 17740 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) ); 17741 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) ); 17742 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) ); 17743 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) ); 17744 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP, 17745 CONSHDLR_PROP_TIMING) ); 17746 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) ); 17747 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ, 17748 CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) ); 17749 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) ); 17750 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) ); 17751 SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphLinear) ); 17752 SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphLinear) ); 17753 17754 if( SCIPfindConshdlr(scip, "nonlinear") != NULL ) 17755 { 17756 /* include the linear constraint upgrade in the nonlinear constraint handler */ 17757 SCIP_CALL( SCIPincludeConsUpgradeNonlinear(scip, upgradeConsNonlinear, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) ); 17758 } 17759 17760 /* add linear constraint handler parameters */ 17761 SCIP_CALL( SCIPaddIntParam(scip, 17762 "constraints/" CONSHDLR_NAME "/tightenboundsfreq", 17763 "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)", 17764 &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) ); 17765 SCIP_CALL( SCIPaddIntParam(scip, 17766 "constraints/" CONSHDLR_NAME "/maxrounds", 17767 "maximal number of separation rounds per node (-1: unlimited)", 17768 &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) ); 17769 SCIP_CALL( SCIPaddIntParam(scip, 17770 "constraints/" CONSHDLR_NAME "/maxroundsroot", 17771 "maximal number of separation rounds per node in the root node (-1: unlimited)", 17772 &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) ); 17773 SCIP_CALL( SCIPaddIntParam(scip, 17774 "constraints/" CONSHDLR_NAME "/maxsepacuts", 17775 "maximal number of cuts separated per separation round", 17776 &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) ); 17777 SCIP_CALL( SCIPaddIntParam(scip, 17778 "constraints/" CONSHDLR_NAME "/maxsepacutsroot", 17779 "maximal number of cuts separated per separation round in the root node", 17780 &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) ); 17781 SCIP_CALL( SCIPaddBoolParam(scip, 17782 "constraints/" CONSHDLR_NAME "/presolpairwise", 17783 "should pairwise constraint comparison be performed in presolving?", 17784 &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) ); 17785 SCIP_CALL( SCIPaddBoolParam(scip, 17786 "constraints/" CONSHDLR_NAME "/presolusehashing", 17787 "should hash table be used for detecting redundant constraints in advance", 17788 &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) ); 17789 SCIP_CALL( SCIPaddIntParam(scip, 17790 "constraints/" CONSHDLR_NAME "/nmincomparisons", 17791 "number for minimal pairwise presolve comparisons", 17792 &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) ); 17793 SCIP_CALL( SCIPaddRealParam(scip, 17794 "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons", 17795 "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round", 17796 &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) ); 17797 SCIP_CALL( SCIPaddRealParam(scip, 17798 "constraints/" CONSHDLR_NAME "/maxaggrnormscale", 17799 "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)", 17800 &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) ); 17801 SCIP_CALL( SCIPaddRealParam(scip, 17802 "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta", 17803 "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)", 17804 &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) ); 17805 SCIP_CALL( SCIPaddRealParam(scip, 17806 "constraints/" CONSHDLR_NAME "/maxcardbounddist", 17807 "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts", 17808 &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) ); 17809 SCIP_CALL( SCIPaddBoolParam(scip, 17810 "constraints/" CONSHDLR_NAME "/separateall", 17811 "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?", 17812 &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) ); 17813 SCIP_CALL( SCIPaddBoolParam(scip, 17814 "constraints/" CONSHDLR_NAME "/aggregatevariables", 17815 "should presolving search for aggregations in equations", 17816 &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) ); 17817 SCIP_CALL( SCIPaddBoolParam(scip, 17818 "constraints/" CONSHDLR_NAME "/simplifyinequalities", 17819 "should presolving try to simplify inequalities", 17820 &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) ); 17821 SCIP_CALL( SCIPaddBoolParam(scip, 17822 "constraints/" CONSHDLR_NAME "/dualpresolving", 17823 "should dual presolving steps be performed?", 17824 &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) ); 17825 SCIP_CALL( SCIPaddBoolParam(scip, 17826 "constraints/" CONSHDLR_NAME "/singletonstuffing", 17827 "should stuffing of singleton continuous variables be performed?", 17828 &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) ); 17829 SCIP_CALL( SCIPaddBoolParam(scip, 17830 "constraints/" CONSHDLR_NAME "/singlevarstuffing", 17831 "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?", 17832 &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) ); 17833 SCIP_CALL( SCIPaddBoolParam(scip, 17834 "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?", 17835 &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) ); 17836 SCIP_CALL( SCIPaddBoolParam(scip, 17837 "constraints/" CONSHDLR_NAME "/checkrelmaxabs", 17838 "should the violation for a constraint with side 0.0 be checked relative to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)?", 17839 &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) ); 17840 SCIP_CALL( SCIPaddBoolParam(scip, 17841 "constraints/" CONSHDLR_NAME "/detectcutoffbound", 17842 "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?", 17843 &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) ); 17844 SCIP_CALL( SCIPaddBoolParam(scip, 17845 "constraints/" CONSHDLR_NAME "/detectlowerbound", 17846 "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?", 17847 &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) ); 17848 SCIP_CALL( SCIPaddBoolParam(scip, 17849 "constraints/" CONSHDLR_NAME "/detectpartialobjective", 17850 "should presolving try to detect subsets of constraints parallel to the objective function?", 17851 &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) ); 17852 SCIP_CALL( SCIPaddBoolParam(scip, 17853 "constraints/" CONSHDLR_NAME "/rangedrowpropagation", 17854 "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?", 17855 &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) ); 17856 SCIP_CALL( SCIPaddBoolParam(scip, 17857 "constraints/" CONSHDLR_NAME "/rangedrowartcons", 17858 "should presolving and propagation extract sub-constraints from ranged rows and equations?", 17859 &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) ); 17860 SCIP_CALL( SCIPaddIntParam(scip, 17861 "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth", 17862 "maximum depth to apply ranged row propagation", 17863 &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) ); 17864 SCIP_CALL( SCIPaddIntParam(scip, 17865 "constraints/" CONSHDLR_NAME "/rangedrowfreq", 17866 "frequency for applying ranged row propagation", 17867 &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) ); 17868 SCIP_CALL( SCIPaddBoolParam(scip, 17869 "constraints/" CONSHDLR_NAME "/multaggrremove", 17870 "should multi-aggregations only be performed if the constraint can be removed afterwards?", 17871 &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) ); 17872 SCIP_CALL( SCIPaddRealParam(scip, 17873 "constraints/" CONSHDLR_NAME "/maxmultaggrquot", 17874 "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation", 17875 &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) ); 17876 SCIP_CALL( SCIPaddRealParam(scip, 17877 "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot", 17878 "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation", 17879 &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) ); 17880 SCIP_CALL( SCIPaddBoolParam(scip, 17881 "constraints/" CONSHDLR_NAME "/extractcliques", 17882 "should Cliques be extracted?", 17883 &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) ); 17884 17885 return SCIP_OKAY; 17886 } 17887 17888 /** includes a linear constraint update method into the linear constraint handler */ 17889 SCIP_RETCODE SCIPincludeLinconsUpgrade( 17890 SCIP* scip, /**< SCIP data structure */ 17891 SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */ 17892 int priority, /**< priority of upgrading method */ 17893 const char* conshdlrname /**< name of the constraint handler */ 17894 ) 17895 { 17896 SCIP_CONSHDLR* conshdlr; 17897 SCIP_CONSHDLRDATA* conshdlrdata; 17898 SCIP_LINCONSUPGRADE* linconsupgrade; 17899 char paramname[SCIP_MAXSTRLEN]; 17900 char paramdesc[SCIP_MAXSTRLEN]; 17901 17902 assert(scip != NULL); 17903 assert(linconsupgd != NULL); 17904 assert(conshdlrname != NULL ); 17905 17906 /* find the linear constraint handler */ 17907 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME); 17908 if( conshdlr == NULL ) 17909 { 17910 SCIPerrorMessage("linear constraint handler not found\n"); 17911 return SCIP_PLUGINNOTFOUND; 17912 } 17913 17914 conshdlrdata = SCIPconshdlrGetData(conshdlr); 17915 assert(conshdlrdata != NULL); 17916 17917 /* check if linear constraint update method already exists in constraint handler data */ 17918 if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) ) 17919 { 17920 /* create a linear constraint upgrade data object */ 17921 SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) ); 17922 17923 /* insert linear constraint update method into constraint handler data */ 17924 SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) ); 17925 17926 /* adds parameter to turn on and off the upgrading step */ 17927 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname); 17928 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname); 17929 SCIP_CALL( SCIPaddBoolParam(scip, 17930 paramname, paramdesc, 17931 &linconsupgrade->active, FALSE, TRUE, NULL, NULL) ); 17932 } 17933 17934 return SCIP_OKAY; 17935 } 17936 17937 /** creates and captures a linear constraint 17938 * 17939 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons() 17940 */ 17941 SCIP_RETCODE SCIPcreateConsLinear( 17942 SCIP* scip, /**< SCIP data structure */ 17943 SCIP_CONS** cons, /**< pointer to hold the created constraint */ 17944 const char* name, /**< name of constraint */ 17945 int nvars, /**< number of nonzeros in the constraint */ 17946 SCIP_VAR** vars, /**< array with variables of constraint entries */ 17947 SCIP_Real* vals, /**< array with coefficients of constraint entries */ 17948 SCIP_Real lhs, /**< left hand side of constraint */ 17949 SCIP_Real rhs, /**< right hand side of constraint */ 17950 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? 17951 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */ 17952 SCIP_Bool separate, /**< should the constraint be separated during LP processing? 17953 * Usually set to TRUE. */ 17954 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? 17955 * TRUE for model constraints, FALSE for additional, redundant constraints. */ 17956 SCIP_Bool check, /**< should the constraint be checked for feasibility? 17957 * TRUE for model constraints, FALSE for additional, redundant constraints. */ 17958 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? 17959 * Usually set to TRUE. */ 17960 SCIP_Bool local, /**< is constraint only valid locally? 17961 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */ 17962 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? 17963 * Usually set to FALSE. In column generation applications, set to TRUE if pricing 17964 * adds coefficients to this constraint. */ 17965 SCIP_Bool dynamic, /**< is constraint subject to aging? 17966 * Usually set to FALSE. Set to TRUE for own cuts which 17967 * are separated as constraints. */ 17968 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? 17969 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */ 17970 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even 17971 * if it may be moved to a more global node? 17972 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */ 17973 ) 17974 { 17975 SCIP_CONSHDLR* conshdlr; 17976 SCIP_CONSDATA* consdata; 17977 int j; 17978 17979 assert(scip != NULL); 17980 assert(cons != NULL); 17981 17982 /* find the linear constraint handler */ 17983 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME); 17984 if( conshdlr == NULL ) 17985 { 17986 SCIPerrorMessage("linear constraint handler not found\n"); 17987 return SCIP_PLUGINNOTFOUND; 17988 } 17989 17990 for( j = 0; j < nvars; ++j ) 17991 { 17992 if( SCIPisInfinity(scip, REALABS(vals[j])) ) 17993 { 17994 SCIPerrorMessage("coefficient of variable <%s> is infinite.\n", SCIPvarGetName(vars[j])); 17995 SCIPABORT(); 17996 return SCIP_INVALIDDATA; 17997 } 17998 } 17999 18000 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear 18001 * constraint after presolving we have to ensure that it holds active variables 18002 */ 18003 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 ) 18004 { 18005 SCIP_VAR** consvars; 18006 SCIP_Real* consvals; 18007 SCIP_Real constant = 0.0; 18008 int nconsvars; 18009 int requiredsize; 18010 18011 nconsvars = nvars; 18012 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) ); 18013 SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) ); 18014 18015 /* get active variables for new constraint */ 18016 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) ); 18017 18018 /* if space was not enough we need to resize the buffers */ 18019 if( requiredsize > nconsvars ) 18020 { 18021 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); 18022 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); 18023 18024 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); 18025 assert(requiredsize <= nconsvars); 18026 } 18027 18028 /* adjust sides and check that we do not subtract infinity values */ 18029 if( SCIPisInfinity(scip, REALABS(constant)) ) 18030 { 18031 if( constant < 0.0 ) 18032 { 18033 if( SCIPisInfinity(scip, lhs) ) 18034 { 18035 SCIPfreeBufferArray(scip, &consvals); 18036 SCIPfreeBufferArray(scip, &consvars); 18037 18038 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", name); 18039 18040 SCIPABORT(); 18041 return SCIP_INVALIDDATA; /*lint !e527*/ 18042 } 18043 if( SCIPisInfinity(scip, rhs) ) 18044 { 18045 SCIPfreeBufferArray(scip, &consvals); 18046 SCIPfreeBufferArray(scip, &consvars); 18047 18048 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name); 18049 18050 SCIPABORT(); 18051 return SCIP_INVALIDDATA; /*lint !e527*/ 18052 } 18053 18054 lhs = -SCIPinfinity(scip); 18055 rhs = -SCIPinfinity(scip); 18056 } 18057 else 18058 { 18059 if( SCIPisInfinity(scip, -lhs) ) 18060 { 18061 SCIPfreeBufferArray(scip, &consvals); 18062 SCIPfreeBufferArray(scip, &consvars); 18063 18064 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", name); 18065 18066 SCIPABORT(); 18067 return SCIP_INVALIDDATA; /*lint !e527*/ 18068 } 18069 if( SCIPisInfinity(scip, -rhs) ) 18070 { 18071 SCIPfreeBufferArray(scip, &consvals); 18072 SCIPfreeBufferArray(scip, &consvars); 18073 18074 SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name); 18075 18076 SCIPABORT(); 18077 return SCIP_INVALIDDATA; /*lint !e527*/ 18078 } 18079 18080 lhs = SCIPinfinity(scip); 18081 rhs = SCIPinfinity(scip); 18082 } 18083 } 18084 else 18085 { 18086 if( !SCIPisInfinity(scip, REALABS(lhs)) ) 18087 lhs -= constant; 18088 if( !SCIPisInfinity(scip, REALABS(rhs)) ) 18089 rhs -= constant; 18090 18091 if( SCIPisInfinity(scip, -lhs) ) 18092 lhs = -SCIPinfinity(scip); 18093 else if( SCIPisInfinity(scip, lhs) ) 18094 lhs = SCIPinfinity(scip); 18095 18096 if( SCIPisInfinity(scip, rhs) ) 18097 rhs = SCIPinfinity(scip); 18098 else if( SCIPisInfinity(scip, -rhs) ) 18099 rhs = -SCIPinfinity(scip); 18100 } 18101 18102 /* create constraint data */ 18103 SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) ); 18104 assert(consdata != NULL); 18105 18106 SCIPfreeBufferArray(scip, &consvals); 18107 SCIPfreeBufferArray(scip, &consvars); 18108 } 18109 else 18110 { 18111 /* create constraint data */ 18112 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) ); 18113 assert(consdata != NULL); 18114 } 18115 18116 #ifndef NDEBUG 18117 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */ 18118 if( check || enforce ) 18119 { 18120 int n; 18121 for(n = consdata->nvars - 1; n >= 0; --n ) 18122 assert(!SCIPvarIsRelaxationOnly(consdata->vars[n])); 18123 } 18124 #endif 18125 18126 /* create constraint */ 18127 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate, 18128 local, modifiable, dynamic, removable, stickingatnode) ); 18129 18130 return SCIP_OKAY; 18131 } 18132 18133 /** creates and captures a linear constraint 18134 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the 18135 * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h 18136 * 18137 * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration 18138 * 18139 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons() 18140 */ 18141 SCIP_RETCODE SCIPcreateConsBasicLinear( 18142 SCIP* scip, /**< SCIP data structure */ 18143 SCIP_CONS** cons, /**< pointer to hold the created constraint */ 18144 const char* name, /**< name of constraint */ 18145 int nvars, /**< number of nonzeros in the constraint */ 18146 SCIP_VAR** vars, /**< array with variables of constraint entries */ 18147 SCIP_Real* vals, /**< array with coefficients of constraint entries */ 18148 SCIP_Real lhs, /**< left hand side of constraint */ 18149 SCIP_Real rhs /**< right hand side of constraint */ 18150 ) 18151 { 18152 assert(scip != NULL); 18153 18154 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs, 18155 TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 18156 18157 return SCIP_OKAY; 18158 } 18159 18160 /** creates by copying and captures a linear constraint */ 18161 SCIP_RETCODE SCIPcopyConsLinear( 18162 SCIP* scip, /**< target SCIP data structure */ 18163 SCIP_CONS** cons, /**< pointer to store the created target constraint */ 18164 SCIP* sourcescip, /**< source SCIP data structure */ 18165 const char* name, /**< name of constraint */ 18166 int nvars, /**< number of variables in source variable array */ 18167 SCIP_VAR** sourcevars, /**< source variables of the linear constraints */ 18168 SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */ 18169 SCIP_Real lhs, /**< left hand side of the linear constraint */ 18170 SCIP_Real rhs, /**< right hand side of the linear constraint */ 18171 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding 18172 * variables of the target SCIP */ 18173 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding 18174 * target constraints */ 18175 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */ 18176 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */ 18177 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */ 18178 SCIP_Bool check, /**< should the constraint be checked for feasibility? */ 18179 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */ 18180 SCIP_Bool local, /**< is constraint only valid locally? */ 18181 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */ 18182 SCIP_Bool dynamic, /**< is constraint subject to aging? */ 18183 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */ 18184 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even 18185 * if it may be moved to a more global node? */ 18186 SCIP_Bool global, /**< create a global or a local copy? */ 18187 SCIP_Bool* valid /**< pointer to store if the copying was valid */ 18188 ) 18189 { 18190 SCIP_VAR** vars; 18191 SCIP_Real* coefs; 18192 18193 SCIP_Real constant; 18194 int requiredsize; 18195 int v; 18196 SCIP_Bool success; 18197 18198 if( SCIPisGT(scip, lhs, rhs) ) 18199 { 18200 *valid = FALSE; 18201 return SCIP_OKAY; 18202 } 18203 18204 (*valid) = TRUE; 18205 18206 if( nvars == 0 ) 18207 { 18208 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs, 18209 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) ); 18210 return SCIP_OKAY; 18211 } 18212 18213 /* duplicate variable array */ 18214 SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) ); 18215 18216 /* duplicate coefficient array */ 18217 if( sourcecoefs != NULL ) 18218 { 18219 SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) ); 18220 } 18221 else 18222 { 18223 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) ); 18224 for( v = 0; v < nvars; ++v ) 18225 coefs[v] = 1.0; 18226 } 18227 18228 constant = 0.0; 18229 18230 /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of 18231 * the target SCIP 18232 */ 18233 if( !SCIPvarIsOriginal(vars[0]) ) 18234 { 18235 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) ); 18236 18237 if( requiredsize > nvars ) 18238 { 18239 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) ); 18240 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) ); 18241 18242 SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) ); 18243 assert(requiredsize <= nvars); 18244 } 18245 } 18246 else 18247 { 18248 for( v = 0; v < nvars; ++v ) 18249 { 18250 assert(SCIPvarIsOriginal(vars[v])); 18251 SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) ); 18252 assert(vars[v] != NULL); 18253 } 18254 } 18255 18256 success = TRUE; 18257 /* map variables of the source constraint to variables of the target SCIP */ 18258 for( v = 0; v < nvars && success; ++v ) 18259 { 18260 SCIP_VAR* var; 18261 var = vars[v]; 18262 18263 /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */ 18264 assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce)); 18265 18266 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) ); 18267 assert(!(success) || vars[v] != NULL); 18268 } 18269 18270 /* only create the target constraint, if all variables could be copied */ 18271 if( success ) 18272 { 18273 if( !SCIPisInfinity(scip, -lhs) ) 18274 lhs -= constant; 18275 18276 if( !SCIPisInfinity(scip, rhs) ) 18277 rhs -= constant; 18278 18279 SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs, 18280 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) ); 18281 } 18282 else 18283 *valid = FALSE; 18284 18285 /* free buffer array */ 18286 SCIPfreeBufferArray(scip, &coefs); 18287 SCIPfreeBufferArray(scip, &vars); 18288 18289 return SCIP_OKAY; 18290 } 18291 18292 /** adds coefficient to linear constraint (if it is not zero) */ 18293 SCIP_RETCODE SCIPaddCoefLinear( 18294 SCIP* scip, /**< SCIP data structure */ 18295 SCIP_CONS* cons, /**< constraint data */ 18296 SCIP_VAR* var, /**< variable of constraint entry */ 18297 SCIP_Real val /**< coefficient of constraint entry */ 18298 ) 18299 { 18300 assert(scip != NULL); 18301 assert(cons != NULL); 18302 assert(var != NULL); 18303 18304 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18305 { 18306 SCIPerrorMessage("constraint is not linear\n"); 18307 return SCIP_INVALIDDATA; 18308 } 18309 18310 /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear 18311 * constraint after presolving we have to ensure that it holds active variables 18312 */ 18313 if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE ) 18314 { 18315 SCIP_CONSDATA* consdata; 18316 SCIP_VAR** consvars; 18317 SCIP_Real* consvals; 18318 SCIP_Real constant = 0.0; 18319 SCIP_Real rhs; 18320 SCIP_Real lhs; 18321 int nconsvars; 18322 int requiredsize; 18323 int v; 18324 18325 nconsvars = 1; 18326 SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) ); 18327 SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) ); 18328 consvars[0] = var; 18329 consvals[0] = val; 18330 18331 /* get active variables for new constraint */ 18332 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) ); 18333 18334 /* if space was not enough we need to resize the buffers */ 18335 if( requiredsize > nconsvars ) 18336 { 18337 SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) ); 18338 SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) ); 18339 18340 SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) ); 18341 assert(requiredsize <= nconsvars); 18342 } 18343 18344 consdata = SCIPconsGetData(cons); 18345 assert(consdata != NULL); 18346 18347 lhs = consdata->lhs; 18348 rhs = consdata->rhs; 18349 18350 /* adjust sides and check that we do not subtract infinity values */ 18351 /* constant is infinite */ 18352 if( SCIPisInfinity(scip, REALABS(constant)) ) 18353 { 18354 if( constant < 0.0 ) 18355 { 18356 if( SCIPisInfinity(scip, lhs) ) 18357 { 18358 SCIPfreeBufferArray(scip, &consvals); 18359 SCIPfreeBufferArray(scip, &consvars); 18360 18361 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons)); 18362 18363 SCIPABORT(); 18364 return SCIP_INVALIDDATA; /*lint !e527*/ 18365 } 18366 if( SCIPisInfinity(scip, rhs) ) 18367 { 18368 SCIPfreeBufferArray(scip, &consvals); 18369 SCIPfreeBufferArray(scip, &consvars); 18370 18371 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons)); 18372 18373 SCIPABORT(); 18374 return SCIP_INVALIDDATA; /*lint !e527*/ 18375 } 18376 18377 lhs = -SCIPinfinity(scip); 18378 rhs = -SCIPinfinity(scip); 18379 } 18380 else 18381 { 18382 if( SCIPisInfinity(scip, -lhs) ) 18383 { 18384 SCIPfreeBufferArray(scip, &consvals); 18385 SCIPfreeBufferArray(scip, &consvars); 18386 18387 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons)); 18388 18389 SCIPABORT(); 18390 return SCIP_INVALIDDATA; /*lint !e527*/ 18391 } 18392 if( SCIPisInfinity(scip, -rhs) ) 18393 { 18394 SCIPfreeBufferArray(scip, &consvals); 18395 SCIPfreeBufferArray(scip, &consvars); 18396 18397 SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons)); 18398 18399 SCIPABORT(); 18400 return SCIP_INVALIDDATA; /*lint !e527*/ 18401 } 18402 18403 lhs = SCIPinfinity(scip); 18404 rhs = SCIPinfinity(scip); 18405 } 18406 } 18407 /* constant is not infinite */ 18408 else 18409 { 18410 if( !SCIPisInfinity(scip, REALABS(lhs)) ) 18411 lhs -= constant; 18412 if( !SCIPisInfinity(scip, REALABS(rhs)) ) 18413 rhs -= constant; 18414 18415 if( SCIPisInfinity(scip, -lhs) ) 18416 lhs = -SCIPinfinity(scip); 18417 else if( SCIPisInfinity(scip, lhs) ) 18418 lhs = SCIPinfinity(scip); 18419 18420 if( SCIPisInfinity(scip, rhs) ) 18421 rhs = SCIPinfinity(scip); 18422 else if( SCIPisInfinity(scip, -rhs) ) 18423 rhs = -SCIPinfinity(scip); 18424 } 18425 18426 /* add all active variables to constraint */ 18427 for( v = nconsvars - 1; v >= 0; --v ) 18428 { 18429 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) ); 18430 } 18431 18432 /* update left and right hand sides */ 18433 SCIP_CALL( chgLhs(scip, cons, lhs)); 18434 SCIP_CALL( chgRhs(scip, cons, rhs)); 18435 18436 SCIPfreeBufferArray(scip, &consvals); 18437 SCIPfreeBufferArray(scip, &consvars); 18438 } 18439 else 18440 { 18441 SCIP_CALL( addCoef(scip, cons, var, val) ); 18442 } 18443 18444 return SCIP_OKAY; 18445 } 18446 18447 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if 18448 * not yet contained in the constraint 18449 * 18450 * @note This method may only be called during problem creation stage for an original constraint and variable. 18451 * 18452 * @note This method requires linear time to search for occurences of the variable in the constraint data. 18453 */ 18454 SCIP_RETCODE SCIPchgCoefLinear( 18455 SCIP* scip, /**< SCIP data structure */ 18456 SCIP_CONS* cons, /**< constraint data */ 18457 SCIP_VAR* var, /**< variable of constraint entry */ 18458 SCIP_Real val /**< new coefficient of constraint entry */ 18459 ) 18460 { 18461 SCIP_CONSDATA* consdata; 18462 SCIP_VAR** vars; 18463 SCIP_Bool found; 18464 int i; 18465 18466 assert(scip != NULL); 18467 assert(cons != NULL); 18468 assert(var != NULL); 18469 18470 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18471 { 18472 SCIPerrorMessage("constraint is not linear\n"); 18473 return SCIP_INVALIDDATA; 18474 } 18475 18476 if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) ) 18477 { 18478 SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n"); 18479 return SCIP_INVALIDDATA; 18480 } 18481 18482 consdata = SCIPconsGetData(cons); 18483 assert(consdata != NULL); 18484 18485 vars = consdata->vars; 18486 found = FALSE; 18487 i = 0; 18488 while( i < consdata->nvars ) 18489 { 18490 if( vars[i] == var ) 18491 { 18492 if( found || SCIPisZero(scip, val) ) 18493 { 18494 SCIP_CALL( delCoefPos(scip, cons, i) ); 18495 18496 /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */ 18497 i--; 18498 } 18499 else 18500 { 18501 SCIP_CALL( chgCoefPos(scip, cons, i, val) ); 18502 } 18503 found = TRUE; 18504 } 18505 i++; 18506 } 18507 18508 if( !found && !SCIPisZero(scip, val) ) 18509 { 18510 SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) ); 18511 } 18512 18513 return SCIP_OKAY; 18514 } 18515 18516 /** deletes variable from linear constraint 18517 * 18518 * @note This method may only be called during problem creation stage for an original constraint and variable. 18519 * 18520 * @note This method requires linear time to search for occurences of the variable in the constraint data. 18521 */ 18522 SCIP_RETCODE SCIPdelCoefLinear( 18523 SCIP* scip, /**< SCIP data structure */ 18524 SCIP_CONS* cons, /**< constraint data */ 18525 SCIP_VAR* var /**< variable of constraint entry */ 18526 ) 18527 { 18528 assert(scip != NULL); 18529 assert(cons != NULL); 18530 assert(var != NULL); 18531 18532 SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) ); 18533 18534 return SCIP_OKAY; 18535 } 18536 18537 /** gets left hand side of linear constraint */ 18538 SCIP_Real SCIPgetLhsLinear( 18539 SCIP* scip, /**< SCIP data structure */ 18540 SCIP_CONS* cons /**< constraint data */ 18541 ) 18542 { 18543 SCIP_CONSDATA* consdata; 18544 18545 assert(scip != NULL); 18546 assert(cons != NULL); 18547 18548 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18549 { 18550 SCIPerrorMessage("constraint is not linear\n"); 18551 SCIPABORT(); 18552 return SCIP_INVALID; /*lint !e527*/ 18553 } 18554 18555 consdata = SCIPconsGetData(cons); 18556 assert(consdata != NULL); 18557 18558 return consdata->lhs; 18559 } 18560 18561 /** gets right hand side of linear constraint */ 18562 SCIP_Real SCIPgetRhsLinear( 18563 SCIP* scip, /**< SCIP data structure */ 18564 SCIP_CONS* cons /**< constraint data */ 18565 ) 18566 { 18567 SCIP_CONSDATA* consdata; 18568 18569 assert(scip != NULL); 18570 assert(cons != NULL); 18571 18572 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18573 { 18574 SCIPerrorMessage("constraint is not linear\n"); 18575 SCIPABORT(); 18576 return SCIP_INVALID; /*lint !e527*/ 18577 } 18578 18579 consdata = SCIPconsGetData(cons); 18580 assert(consdata != NULL); 18581 18582 return consdata->rhs; 18583 } 18584 18585 /** changes left hand side of linear constraint */ 18586 SCIP_RETCODE SCIPchgLhsLinear( 18587 SCIP* scip, /**< SCIP data structure */ 18588 SCIP_CONS* cons, /**< constraint data */ 18589 SCIP_Real lhs /**< new left hand side */ 18590 ) 18591 { 18592 assert(scip != NULL); 18593 assert(cons != NULL); 18594 18595 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18596 { 18597 SCIPerrorMessage("constraint is not linear\n"); 18598 return SCIP_INVALIDDATA; 18599 } 18600 18601 SCIP_CALL( chgLhs(scip, cons, lhs) ); 18602 18603 return SCIP_OKAY; 18604 } 18605 18606 /** changes right hand side of linear constraint */ 18607 SCIP_RETCODE SCIPchgRhsLinear( 18608 SCIP* scip, /**< SCIP data structure */ 18609 SCIP_CONS* cons, /**< constraint data */ 18610 SCIP_Real rhs /**< new right hand side */ 18611 ) 18612 { 18613 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18614 { 18615 SCIPerrorMessage("constraint is not linear\n"); 18616 return SCIP_INVALIDDATA; 18617 } 18618 18619 SCIP_CALL( chgRhs(scip, cons, rhs) ); 18620 18621 return SCIP_OKAY; 18622 } 18623 18624 /** gets the number of variables in the linear constraint */ 18625 int SCIPgetNVarsLinear( 18626 SCIP* scip, /**< SCIP data structure */ 18627 SCIP_CONS* cons /**< constraint data */ 18628 ) 18629 { 18630 SCIP_CONSDATA* consdata; 18631 18632 assert(scip != NULL); 18633 assert(cons != NULL); 18634 18635 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18636 { 18637 SCIPerrorMessage("constraint is not linear\n"); 18638 SCIPABORT(); 18639 return -1; /*lint !e527*/ 18640 } 18641 18642 consdata = SCIPconsGetData(cons); 18643 assert(consdata != NULL); 18644 18645 return consdata->nvars; 18646 } 18647 18648 /** gets the array of variables in the linear constraint; the user must not modify this array! */ 18649 SCIP_VAR** SCIPgetVarsLinear( 18650 SCIP* scip, /**< SCIP data structure */ 18651 SCIP_CONS* cons /**< constraint data */ 18652 ) 18653 { 18654 SCIP_CONSDATA* consdata; 18655 18656 assert(scip != NULL); 18657 assert(cons != NULL); 18658 18659 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18660 { 18661 SCIPerrorMessage("constraint is not linear\n"); 18662 SCIPABORT(); 18663 return NULL; /*lint !e527*/ 18664 } 18665 18666 consdata = SCIPconsGetData(cons); 18667 assert(consdata != NULL); 18668 18669 return consdata->vars; 18670 } 18671 18672 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */ 18673 SCIP_Real* SCIPgetValsLinear( 18674 SCIP* scip, /**< SCIP data structure */ 18675 SCIP_CONS* cons /**< constraint data */ 18676 ) 18677 { 18678 SCIP_CONSDATA* consdata; 18679 18680 assert(scip != NULL); 18681 assert(cons != NULL); 18682 18683 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18684 { 18685 SCIPerrorMessage("constraint is not linear\n"); 18686 SCIPABORT(); 18687 return NULL; /*lint !e527*/ 18688 } 18689 18690 consdata = SCIPconsGetData(cons); 18691 assert(consdata != NULL); 18692 18693 return consdata->vals; 18694 } 18695 18696 /** gets the activity of the linear constraint in the given solution 18697 * 18698 * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity 18699 * comprises positive and negative infinity contributions 18700 */ 18701 SCIP_Real SCIPgetActivityLinear( 18702 SCIP* scip, /**< SCIP data structure */ 18703 SCIP_CONS* cons, /**< constraint data */ 18704 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */ 18705 ) 18706 { 18707 SCIP_CONSDATA* consdata; 18708 18709 assert(scip != NULL); 18710 assert(cons != NULL); 18711 18712 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18713 { 18714 SCIPerrorMessage("constraint is not linear\n"); 18715 SCIPABORT(); 18716 return SCIP_INVALID; /*lint !e527*/ 18717 } 18718 18719 consdata = SCIPconsGetData(cons); 18720 assert(consdata != NULL); 18721 18722 if( consdata->row != NULL ) 18723 return SCIPgetRowSolActivity(scip, consdata->row, sol); 18724 else 18725 return consdataGetActivity(scip, consdata, sol); 18726 } 18727 18728 /** gets the feasibility of the linear constraint in the given solution */ 18729 SCIP_Real SCIPgetFeasibilityLinear( 18730 SCIP* scip, /**< SCIP data structure */ 18731 SCIP_CONS* cons, /**< constraint data */ 18732 SCIP_SOL* sol /**< solution, or NULL to use current node's solution */ 18733 ) 18734 { 18735 SCIP_CONSDATA* consdata; 18736 18737 assert(scip != NULL); 18738 assert(cons != NULL); 18739 18740 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18741 { 18742 SCIPerrorMessage("constraint is not linear\n"); 18743 SCIPABORT(); 18744 return SCIP_INVALID; /*lint !e527*/ 18745 } 18746 18747 consdata = SCIPconsGetData(cons); 18748 assert(consdata != NULL); 18749 18750 if( consdata->row != NULL ) 18751 return SCIPgetRowSolFeasibility(scip, consdata->row, sol); 18752 else 18753 return consdataGetFeasibility(scip, consdata, sol); 18754 } 18755 18756 /** gets the dual solution of the linear constraint in the current LP */ 18757 SCIP_Real SCIPgetDualsolLinear( 18758 SCIP* scip, /**< SCIP data structure */ 18759 SCIP_CONS* cons /**< constraint data */ 18760 ) 18761 { 18762 SCIP_CONSDATA* consdata; 18763 18764 assert(scip != NULL); 18765 assert(cons != NULL); 18766 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */ 18767 18768 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18769 { 18770 SCIPerrorMessage("constraint is not linear\n"); 18771 SCIPABORT(); 18772 return SCIP_INVALID; /*lint !e527*/ 18773 } 18774 18775 consdata = SCIPconsGetData(cons); 18776 assert(consdata != NULL); 18777 18778 if( consdata->row != NULL ) 18779 return SCIProwGetDualsol(consdata->row); 18780 else 18781 return 0.0; 18782 } 18783 18784 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */ 18785 SCIP_Real SCIPgetDualfarkasLinear( 18786 SCIP* scip, /**< SCIP data structure */ 18787 SCIP_CONS* cons /**< constraint data */ 18788 ) 18789 { 18790 SCIP_CONSDATA* consdata; 18791 18792 assert(scip != NULL); 18793 assert(cons != NULL); 18794 assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */ 18795 18796 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18797 { 18798 SCIPerrorMessage("constraint is not linear\n"); 18799 SCIPABORT(); 18800 return SCIP_INVALID; /*lint !e527*/ 18801 } 18802 18803 consdata = SCIPconsGetData(cons); 18804 assert(consdata != NULL); 18805 18806 if( consdata->row != NULL ) 18807 return SCIProwGetDualfarkas(consdata->row); 18808 else 18809 return 0.0; 18810 } 18811 18812 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created; 18813 * the user must not modify the row! 18814 */ 18815 SCIP_ROW* SCIPgetRowLinear( 18816 SCIP* scip, /**< SCIP data structure */ 18817 SCIP_CONS* cons /**< constraint data */ 18818 ) 18819 { 18820 SCIP_CONSDATA* consdata; 18821 18822 assert(scip != NULL); 18823 assert(cons != NULL); 18824 18825 if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 ) 18826 { 18827 SCIPerrorMessage("constraint is not linear\n"); 18828 SCIPABORT(); 18829 return NULL; /*lint !e527*/ 18830 } 18831 18832 consdata = SCIPconsGetData(cons); 18833 assert(consdata != NULL); 18834 18835 return consdata->row; 18836 } 18837 18838 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */ 18839 SCIP_RETCODE SCIPupgradeConsLinear( 18840 SCIP* scip, /**< SCIP data structure */ 18841 SCIP_CONS* cons, /**< source constraint to try to convert */ 18842 SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */ 18843 ) 18844 { 18845 SCIP_CONSHDLR* conshdlr; 18846 SCIP_CONSHDLRDATA* conshdlrdata; 18847 SCIP_CONSDATA* consdata; 18848 SCIP_VAR* var; 18849 SCIP_Real val; 18850 SCIP_Real lb; 18851 SCIP_Real ub; 18852 SCIP_Real poscoeffsum; 18853 SCIP_Real negcoeffsum; 18854 SCIP_Bool infeasible; 18855 SCIP_Bool integral; 18856 int nchgsides = 0; 18857 int nposbin; 18858 int nnegbin; 18859 int nposint; 18860 int nnegint; 18861 int nposimpl; 18862 int nnegimpl; 18863 int nposimplbin; 18864 int nnegimplbin; 18865 int nposcont; 18866 int nnegcont; 18867 int ncoeffspone; 18868 int ncoeffsnone; 18869 int ncoeffspint; 18870 int ncoeffsnint; 18871 int ncoeffspfrac; 18872 int ncoeffsnfrac; 18873 int i; 18874 18875 assert(scip != NULL); 18876 assert(cons != NULL); 18877 assert(upgdcons != NULL); 18878 18879 *upgdcons = NULL; 18880 18881 /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */ 18882 if( SCIPconsIsModifiable(cons) ) 18883 return SCIP_OKAY; 18884 18885 /* check for upgradability */ 18886 if( SCIPconsGetNUpgradeLocks(cons) > 0 ) 18887 return SCIP_OKAY; 18888 18889 /* get the constraint handler and check, if it's really a linear constraint */ 18890 conshdlr = SCIPconsGetHdlr(cons); 18891 if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 ) 18892 { 18893 SCIPerrorMessage("constraint is not linear\n"); 18894 return SCIP_INVALIDDATA; 18895 } 18896 18897 /* get constraint handler data and constraint data */ 18898 conshdlrdata = SCIPconshdlrGetData(conshdlr); 18899 assert(conshdlrdata != NULL); 18900 consdata = SCIPconsGetData(cons); 18901 assert(consdata != NULL); 18902 18903 /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */ 18904 if( consdata->upgraded ) 18905 return SCIP_OKAY; 18906 18907 /* check, if the constraint is already stored as LP row */ 18908 if( consdata->row != NULL ) 18909 { 18910 if( SCIProwIsInLP(consdata->row) ) 18911 { 18912 SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n"); 18913 return SCIP_INVALIDDATA; 18914 } 18915 else 18916 { 18917 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) ); 18918 } 18919 } 18920 18921 /* normalize constraint */ 18922 SCIP_CALL( normalizeCons(scip, cons, &infeasible) ); 18923 18924 /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was 18925 * skipped and we hope that the infeasibility gets detected later again. 18926 * 18927 * TODO: do we want to try to upgrade the constraint anyway? 18928 * 18929 * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is 18930 * proven to be infeasible. 18931 */ 18932 if( infeasible ) /*lint !e774*/ 18933 return SCIP_OKAY; 18934 18935 /* tighten sides */ 18936 SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) ); 18937 18938 if( infeasible ) /*lint !e774*/ 18939 return SCIP_OKAY; 18940 18941 /* 18942 * calculate some statistics on linear constraint 18943 */ 18944 18945 nposbin = 0; 18946 nnegbin = 0; 18947 nposint = 0; 18948 nnegint = 0; 18949 nposimpl = 0; 18950 nnegimpl = 0; 18951 nposimplbin = 0; 18952 nnegimplbin = 0; 18953 nposcont = 0; 18954 nnegcont = 0; 18955 ncoeffspone = 0; 18956 ncoeffsnone = 0; 18957 ncoeffspint = 0; 18958 ncoeffsnint = 0; 18959 ncoeffspfrac = 0; 18960 ncoeffsnfrac = 0; 18961 integral = TRUE; 18962 poscoeffsum = 0.0; 18963 negcoeffsum = 0.0; 18964 18965 for( i = 0; i < consdata->nvars; ++i ) 18966 { 18967 var = consdata->vars[i]; 18968 val = consdata->vals[i]; 18969 lb = SCIPvarGetLbLocal(var); 18970 ub = SCIPvarGetUbLocal(var); 18971 assert(!SCIPisZero(scip, val)); 18972 18973 switch( SCIPvarGetType(var) ) 18974 { 18975 case SCIP_VARTYPE_BINARY: 18976 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) ) 18977 integral = integral && SCIPisIntegral(scip, val); 18978 if( val >= 0.0 ) 18979 nposbin++; 18980 else 18981 nnegbin++; 18982 break; 18983 case SCIP_VARTYPE_INTEGER: 18984 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) ) 18985 integral = integral && SCIPisIntegral(scip, val); 18986 if( val >= 0.0 ) 18987 nposint++; 18988 else 18989 nnegint++; 18990 break; 18991 case SCIP_VARTYPE_IMPLINT: 18992 if( SCIPvarIsBinary(var) ) 18993 { 18994 if( val >= 0.0 ) 18995 nposimplbin++; 18996 else 18997 nnegimplbin++; 18998 } 18999 if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) ) 19000 integral = integral && SCIPisIntegral(scip, val); 19001 if( val >= 0.0 ) 19002 nposimpl++; 19003 else 19004 nnegimpl++; 19005 break; 19006 case SCIP_VARTYPE_CONTINUOUS: 19007 integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb); 19008 if( val >= 0.0 ) 19009 nposcont++; 19010 else 19011 nnegcont++; 19012 break; 19013 default: 19014 SCIPerrorMessage("unknown variable type\n"); 19015 return SCIP_INVALIDDATA; 19016 } 19017 if( SCIPisEQ(scip, val, 1.0) ) 19018 ncoeffspone++; 19019 else if( SCIPisEQ(scip, val, -1.0) ) 19020 ncoeffsnone++; 19021 else if( SCIPisIntegral(scip, val) ) 19022 { 19023 if( SCIPisPositive(scip, val) ) 19024 ncoeffspint++; 19025 else 19026 ncoeffsnint++; 19027 } 19028 else 19029 { 19030 if( SCIPisPositive(scip, val) ) 19031 ncoeffspfrac++; 19032 else 19033 ncoeffsnfrac++; 19034 } 19035 if( SCIPisPositive(scip, val) ) 19036 poscoeffsum += val; 19037 else 19038 negcoeffsum += val; 19039 } 19040 19041 /* 19042 * call the upgrading methods 19043 */ 19044 19045 SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n", 19046 SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades); 19047 SCIPdebugMsg(scip, " +bin=%d -bin=%d +int=%d -int=%d +impl=%d -impl=%d +cont=%d -cont=%d +1=%d -1=%d +I=%d -I=%d +F=%d -F=%d possum=%.15g negsum=%.15g integral=%u\n", 19048 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont, 19049 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac, 19050 poscoeffsum, negcoeffsum, integral); 19051 19052 /* try all upgrading methods in priority order in case the upgrading step is enable */ 19053 for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i ) 19054 { 19055 if( conshdlrdata->linconsupgrades[i]->active ) 19056 { 19057 SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars, 19058 consdata->vars, consdata->vals, consdata->lhs, consdata->rhs, 19059 nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont, 19060 ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac, 19061 poscoeffsum, negcoeffsum, integral, 19062 upgdcons) ); 19063 } 19064 } 19065 19066 #ifdef SCIP_DEBUG 19067 if( *upgdcons != NULL ) 19068 { 19069 SCIPdebugPrintCons(scip, cons, NULL); 19070 SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons))); 19071 SCIPdebugPrintCons(scip, *upgdcons, NULL); 19072 } 19073 #endif 19074 19075 return SCIP_OKAY; /*lint !e438*/ 19076 } 19077 19078 /** cleans up (multi-)aggregations and fixings from linear constraints */ 19079 SCIP_RETCODE SCIPcleanupConssLinear( 19080 SCIP* scip, /**< SCIP data structure */ 19081 SCIP_Bool onlychecked, /**< should only checked constraints be cleaned up? */ 19082 SCIP_Bool* infeasible /**< pointer to return whether the problem was detected to be infeasible */ 19083 ) 19084 { 19085 SCIP_CONSHDLR* conshdlr; 19086 SCIP_CONS** conss; 19087 int nconss; 19088 int i; 19089 19090 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME); 19091 if( conshdlr == NULL ) 19092 return SCIP_OKAY; 19093 19094 assert(infeasible != NULL); 19095 *infeasible = FALSE; 19096 19097 nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr); 19098 conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr); 19099 19100 for( i = 0; i < nconss; ++i ) 19101 { 19102 SCIP_CALL( applyFixings(scip, conss[i], infeasible) ); 19103 19104 if( *infeasible ) 19105 break; 19106 } 19107 19108 return SCIP_OKAY; 19109 } 19110