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 scip_var.c 26 * @ingroup OTHER_CFILES 27 * @brief public methods for SCIP variables 28 * @author Tobias Achterberg 29 * @author Timo Berthold 30 * @author Gerald Gamrath 31 * @author Leona Gottwald 32 * @author Stefan Heinz 33 * @author Gregor Hendel 34 * @author Thorsten Koch 35 * @author Alexander Martin 36 * @author Marc Pfetsch 37 * @author Michael Winkler 38 * @author Kati Wolter 39 * 40 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE 41 */ 42 43 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 44 45 #include <ctype.h> 46 #include "blockmemshell/memory.h" 47 #include "lpi/lpi.h" 48 #include "scip/branch.h" 49 #include "scip/clock.h" 50 #include "scip/conflict.h" 51 #include "scip/debug.h" 52 #include "scip/history.h" 53 #include "scip/implics.h" 54 #include "scip/lp.h" 55 #include "scip/prob.h" 56 #include "scip/pub_cons.h" 57 #include "scip/pub_implics.h" 58 #include "scip/pub_lp.h" 59 #include "scip/pub_message.h" 60 #include "scip/pub_misc.h" 61 #include "scip/pub_tree.h" 62 #include "scip/pub_var.h" 63 #include "scip/relax.h" 64 #include "scip/scip_general.h" 65 #include "scip/scip_lp.h" 66 #include "scip/scip_mem.h" 67 #include "scip/scip_message.h" 68 #include "scip/scip_numerics.h" 69 #include "scip/scip_prob.h" 70 #include "scip/scip_probing.h" 71 #include "scip/scip_sol.h" 72 #include "scip/scip_solvingstats.h" 73 #include "scip/scip_tree.h" 74 #include "scip/scip_var.h" 75 #include "scip/set.h" 76 #include "scip/sol.h" 77 #include "scip/solve.h" 78 #include "scip/stat.h" 79 #include "scip/struct_lp.h" 80 #include "scip/struct_mem.h" 81 #include "scip/struct_primal.h" 82 #include "scip/struct_prob.h" 83 #include "scip/struct_scip.h" 84 #include "scip/struct_set.h" 85 #include "scip/struct_stat.h" 86 #include "scip/struct_tree.h" 87 #include "scip/struct_var.h" 88 #include "scip/tree.h" 89 #include "scip/var.h" 90 91 92 /** creates and captures problem variable; if variable is of integral type, fractional bounds are automatically rounded; 93 * an integer variable with bounds zero and one is automatically converted into a binary variable; 94 * 95 * @warning When doing column generation and the original problem is a maximization problem, notice that SCIP will 96 * transform the problem into a minimization problem by multiplying the objective function by -1. Thus, the 97 * original objective function value of variables created during the solving process has to be multiplied by 98 * -1, too. 99 * 100 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 101 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 102 * 103 * @pre This method can be called if @p scip is in one of the following stages: 104 * - \ref SCIP_STAGE_PROBLEM 105 * - \ref SCIP_STAGE_TRANSFORMING 106 * - \ref SCIP_STAGE_INITPRESOLVE 107 * - \ref SCIP_STAGE_PRESOLVING 108 * - \ref SCIP_STAGE_EXITPRESOLVE 109 * - \ref SCIP_STAGE_PRESOLVED 110 * - \ref SCIP_STAGE_SOLVING 111 * 112 * @note the variable gets captured, hence at one point you have to release it using the method SCIPreleaseVar() 113 */ 114 SCIP_RETCODE SCIPcreateVar( 115 SCIP* scip, /**< SCIP data structure */ 116 SCIP_VAR** var, /**< pointer to variable object */ 117 const char* name, /**< name of variable, or NULL for automatic name creation */ 118 SCIP_Real lb, /**< lower bound of variable */ 119 SCIP_Real ub, /**< upper bound of variable */ 120 SCIP_Real obj, /**< objective function value */ 121 SCIP_VARTYPE vartype, /**< type of variable */ 122 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */ 123 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */ 124 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */ 125 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */ 126 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */ 127 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */ 128 SCIP_VARDATA* vardata /**< user data for this specific variable */ 129 ) 130 { 131 assert(var != NULL); 132 assert(lb <= ub); 133 134 SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateVar", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 135 136 /* forbid infinite objective function values */ 137 if( SCIPisInfinity(scip, REALABS(obj)) ) 138 { 139 SCIPerrorMessage("invalid objective function value: value is infinite\n"); 140 return SCIP_INVALIDDATA; 141 } 142 143 switch( scip->set->stage ) 144 { 145 case SCIP_STAGE_PROBLEM: 146 SCIP_CALL( SCIPvarCreateOriginal(var, scip->mem->probmem, scip->set, scip->stat, 147 name, lb, ub, obj, vartype, initial, removable, vardelorig, vartrans, vardeltrans, varcopy, vardata) ); 148 break; 149 150 case SCIP_STAGE_TRANSFORMING: 151 case SCIP_STAGE_INITPRESOLVE: 152 case SCIP_STAGE_PRESOLVING: 153 case SCIP_STAGE_EXITPRESOLVE: 154 case SCIP_STAGE_PRESOLVED: 155 case SCIP_STAGE_SOLVING: 156 SCIP_CALL( SCIPvarCreateTransformed(var, scip->mem->probmem, scip->set, scip->stat, 157 name, lb, ub, obj, vartype, initial, removable, vardelorig, vartrans, vardeltrans, varcopy, vardata) ); 158 break; 159 160 default: 161 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 162 return SCIP_INVALIDCALL; 163 } /*lint !e788*/ 164 165 return SCIP_OKAY; 166 } 167 168 /** creates and captures problem variable with optional callbacks and variable data set to NULL, which can be set 169 * afterwards using SCIPvarSetDelorigData(), SCIPvarSetTransData(), 170 * SCIPvarSetDeltransData(), SCIPvarSetCopy(), and SCIPvarSetData(); sets variable flags initial=TRUE 171 * and removable = FALSE, which can be adjusted by using SCIPvarSetInitial() and SCIPvarSetRemovable(), resp.; 172 * if variable is of integral type, fractional bounds are automatically rounded; 173 * an integer variable with bounds zero and one is automatically converted into a binary variable; 174 * 175 * @warning When doing column generation and the original problem is a maximization problem, notice that SCIP will 176 * transform the problem into a minimization problem by multiplying the objective function by -1. Thus, the 177 * original objective function value of variables created during the solving process has to be multiplied by 178 * -1, too. 179 * 180 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 181 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 182 * 183 * @pre This method can be called if @p scip is in one of the following stages: 184 * - \ref SCIP_STAGE_PROBLEM 185 * - \ref SCIP_STAGE_TRANSFORMING 186 * - \ref SCIP_STAGE_INITPRESOLVE 187 * - \ref SCIP_STAGE_PRESOLVING 188 * - \ref SCIP_STAGE_EXITPRESOLVE 189 * - \ref SCIP_STAGE_PRESOLVED 190 * - \ref SCIP_STAGE_SOLVING 191 * 192 * @note the variable gets captured, hence at one point you have to release it using the method SCIPreleaseVar() 193 */ 194 SCIP_RETCODE SCIPcreateVarBasic( 195 SCIP* scip, /**< SCIP data structure */ 196 SCIP_VAR** var, /**< pointer to variable object */ 197 const char* name, /**< name of variable, or NULL for automatic name creation */ 198 SCIP_Real lb, /**< lower bound of variable */ 199 SCIP_Real ub, /**< upper bound of variable */ 200 SCIP_Real obj, /**< objective function value */ 201 SCIP_VARTYPE vartype /**< type of variable */ 202 ) 203 { 204 SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateVarBasic", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 205 206 SCIP_CALL( SCIPcreateVar(scip, var, name, lb, ub, obj, vartype, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) ); 207 208 return SCIP_OKAY; 209 } 210 211 /** outputs the variable name to the file stream 212 * 213 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 214 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 215 * 216 * @pre This method can be called if @p scip is in one of the following stages: 217 * - \ref SCIP_STAGE_PROBLEM 218 * - \ref SCIP_STAGE_TRANSFORMING 219 * - \ref SCIP_STAGE_TRANSFORMED 220 * - \ref SCIP_STAGE_INITPRESOLVE 221 * - \ref SCIP_STAGE_PRESOLVING 222 * - \ref SCIP_STAGE_EXITPRESOLVE 223 * - \ref SCIP_STAGE_PRESOLVED 224 * - \ref SCIP_STAGE_INITSOLVE 225 * - \ref SCIP_STAGE_SOLVING 226 * - \ref SCIP_STAGE_SOLVED 227 * - \ref SCIP_STAGE_EXITSOLVE 228 * - \ref SCIP_STAGE_FREETRANS 229 */ 230 SCIP_RETCODE SCIPwriteVarName( 231 SCIP* scip, /**< SCIP data structure */ 232 FILE* file, /**< output file, or NULL for stdout */ 233 SCIP_VAR* var, /**< variable to output */ 234 SCIP_Bool type /**< should the variable type be also posted */ 235 ) 236 { 237 assert(scip != NULL); 238 assert(var != NULL); 239 240 SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarName", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 241 242 /* print variable name */ 243 if( SCIPvarIsNegated(var) ) 244 { 245 SCIP_VAR* negatedvar; 246 247 SCIP_CALL( SCIPgetNegatedVar(scip, var, &negatedvar) ); 248 SCIPinfoMessage(scip, file, "<~%s>", SCIPvarGetName(negatedvar)); 249 } 250 else 251 { 252 SCIPinfoMessage(scip, file, "<%s>", SCIPvarGetName(var)); 253 } 254 255 if( type ) 256 { 257 /* print variable type */ 258 SCIPinfoMessage(scip, file, "[%c]", 259 SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ? SCIP_VARTYPE_BINARY_CHAR : 260 SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER ? SCIP_VARTYPE_INTEGER_CHAR : 261 SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT ? SCIP_VARTYPE_IMPLINT_CHAR : SCIP_VARTYPE_CONTINUOUS_CHAR); 262 } 263 264 return SCIP_OKAY; 265 } 266 267 /** print the given list of variables to output stream separated by the given delimiter character; 268 * 269 * i. e. the variables x1, x2, ..., xn with given delimiter ',' are written as: \<x1\>, \<x2\>, ..., \<xn\>; 270 * 271 * the method SCIPparseVarsList() can parse such a string 272 * 273 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 274 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 275 * 276 * @pre This method can be called if @p scip is in one of the following stages: 277 * - \ref SCIP_STAGE_PROBLEM 278 * - \ref SCIP_STAGE_TRANSFORMING 279 * - \ref SCIP_STAGE_TRANSFORMED 280 * - \ref SCIP_STAGE_INITPRESOLVE 281 * - \ref SCIP_STAGE_PRESOLVING 282 * - \ref SCIP_STAGE_EXITPRESOLVE 283 * - \ref SCIP_STAGE_PRESOLVED 284 * - \ref SCIP_STAGE_INITSOLVE 285 * - \ref SCIP_STAGE_SOLVING 286 * - \ref SCIP_STAGE_SOLVED 287 * - \ref SCIP_STAGE_EXITSOLVE 288 * - \ref SCIP_STAGE_FREETRANS 289 * 290 * @note The printing process is done via the message handler system. 291 */ 292 SCIP_RETCODE SCIPwriteVarsList( 293 SCIP* scip, /**< SCIP data structure */ 294 FILE* file, /**< output file, or NULL for stdout */ 295 SCIP_VAR** vars, /**< variable array to output */ 296 int nvars, /**< number of variables */ 297 SCIP_Bool type, /**< should the variable type be also posted */ 298 char delimiter /**< character which is used for delimitation */ 299 ) 300 { 301 int v; 302 303 SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarsList", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 304 305 for( v = 0; v < nvars; ++v ) 306 { 307 if( v > 0 ) 308 { 309 SCIPinfoMessage(scip, file, "%c", delimiter); 310 } 311 312 /* print variable name */ 313 SCIP_CALL( SCIPwriteVarName(scip, file, vars[v], type) ); 314 } 315 316 return SCIP_OKAY; 317 } 318 319 /** print the given variables and coefficients as linear sum in the following form 320 * c1 \<x1\> + c2 \<x2\> ... + cn \<xn\> 321 * 322 * This string can be parsed by the method SCIPparseVarsLinearsum(). 323 * 324 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 325 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 326 * 327 * @pre This method can be called if @p scip is in one of the following stages: 328 * - \ref SCIP_STAGE_PROBLEM 329 * - \ref SCIP_STAGE_TRANSFORMING 330 * - \ref SCIP_STAGE_TRANSFORMED 331 * - \ref SCIP_STAGE_INITPRESOLVE 332 * - \ref SCIP_STAGE_PRESOLVING 333 * - \ref SCIP_STAGE_EXITPRESOLVE 334 * - \ref SCIP_STAGE_PRESOLVED 335 * - \ref SCIP_STAGE_INITSOLVE 336 * - \ref SCIP_STAGE_SOLVING 337 * - \ref SCIP_STAGE_SOLVED 338 * - \ref SCIP_STAGE_EXITSOLVE 339 * - \ref SCIP_STAGE_FREETRANS 340 * 341 * @note The printing process is done via the message handler system. 342 */ 343 SCIP_RETCODE SCIPwriteVarsLinearsum( 344 SCIP* scip, /**< SCIP data structure */ 345 FILE* file, /**< output file, or NULL for stdout */ 346 SCIP_VAR** vars, /**< variable array to output */ 347 SCIP_Real* vals, /**< array of coefficients or NULL if all coefficients are 1.0 */ 348 int nvars, /**< number of variables */ 349 SCIP_Bool type /**< should the variable type be also posted */ 350 ) 351 { 352 int v; 353 354 SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarsLinearsum", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 355 356 for( v = 0; v < nvars; ++v ) 357 { 358 if( vals != NULL ) 359 { 360 if( vals[v] == 1.0 ) 361 { 362 if( v > 0 ) 363 SCIPinfoMessage(scip, file, " +"); 364 } 365 else if( vals[v] == -1.0 ) 366 SCIPinfoMessage(scip, file, " -"); 367 else 368 SCIPinfoMessage(scip, file, " %+.15g", vals[v]); 369 } 370 else if( nvars > 0 ) 371 SCIPinfoMessage(scip, file, " +"); 372 373 /* print variable name */ 374 SCIP_CALL( SCIPwriteVarName(scip, file, vars[v], type) ); 375 } 376 377 return SCIP_OKAY; 378 } 379 380 /** print the given terms as signomial in the following form 381 * c1 \<x11\>^e11 \<x12\>^e12 ... \<x1n\>^e1n + c2 \<x21\>^e21 \<x22\>^e22 ... + ... + cn \<xn1\>^en1 ... 382 * 383 * This string can be parsed by the method SCIPparseVarsPolynomial(). 384 * 385 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 386 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 387 * 388 * @pre This method can be called if @p scip is in one of the following stages: 389 * - \ref SCIP_STAGE_PROBLEM 390 * - \ref SCIP_STAGE_TRANSFORMING 391 * - \ref SCIP_STAGE_TRANSFORMED 392 * - \ref SCIP_STAGE_INITPRESOLVE 393 * - \ref SCIP_STAGE_PRESOLVING 394 * - \ref SCIP_STAGE_EXITPRESOLVE 395 * - \ref SCIP_STAGE_PRESOLVED 396 * - \ref SCIP_STAGE_INITSOLVE 397 * - \ref SCIP_STAGE_SOLVING 398 * - \ref SCIP_STAGE_SOLVED 399 * - \ref SCIP_STAGE_EXITSOLVE 400 * - \ref SCIP_STAGE_FREETRANS 401 * 402 * @note The printing process is done via the message handler system. 403 */ 404 SCIP_RETCODE SCIPwriteVarsPolynomial( 405 SCIP* scip, /**< SCIP data structure */ 406 FILE* file, /**< output file, or NULL for stdout */ 407 SCIP_VAR*** monomialvars, /**< arrays with variables for each monomial */ 408 SCIP_Real** monomialexps, /**< arrays with variable exponents, or NULL if always 1.0 */ 409 SCIP_Real* monomialcoefs, /**< array with monomial coefficients */ 410 int* monomialnvars, /**< array with number of variables for each monomial */ 411 int nmonomials, /**< number of monomials */ 412 SCIP_Bool type /**< should the variable type be also posted */ 413 ) 414 { 415 int i; 416 int v; 417 418 assert(scip != NULL); 419 assert(monomialvars != NULL || nmonomials == 0); 420 assert(monomialcoefs != NULL || nmonomials == 0); 421 assert(monomialnvars != NULL || nmonomials == 0); 422 423 SCIP_CALL( SCIPcheckStage(scip, "SCIPwriteVarsPolynomial", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 424 425 if( nmonomials == 0 ) 426 { 427 SCIPinfoMessage(scip, file, " 0 "); 428 return SCIP_OKAY; 429 } 430 431 for( i = 0; i < nmonomials; ++i ) 432 { 433 if( monomialcoefs[i] == 1.0 ) /*lint !e613*/ 434 { 435 if( i > 0 ) 436 SCIPinfoMessage(scip, file, " +"); 437 } 438 else if( monomialcoefs[i] == -1.0 ) /*lint !e613*/ 439 SCIPinfoMessage(scip, file, " -"); 440 else 441 SCIPinfoMessage(scip, file, " %+.15g", monomialcoefs[i]); /*lint !e613*/ 442 443 assert(monomialvars[i] != NULL || monomialnvars[i] == 0); /*lint !e613*/ 444 445 for( v = 0; v < monomialnvars[i]; ++v ) /*lint !e613*/ 446 { 447 SCIP_CALL( SCIPwriteVarName(scip, file, monomialvars[i][v], type) ); /*lint !e613*/ 448 if( monomialexps != NULL && monomialexps[i] != NULL && monomialexps[i][v] != 1.0 ) 449 { 450 SCIPinfoMessage(scip, file, "^%.15g", monomialexps[i][v]); 451 } 452 } 453 } 454 455 return SCIP_OKAY; 456 } 457 458 /** parses variable information (in cip format) out of a string; if the parsing process was successful a variable is 459 * created and captured; if variable is of integral type, fractional bounds are automatically rounded; an integer 460 * variable with bounds zero and one is automatically converted into a binary variable 461 * 462 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 463 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 464 * 465 * @pre This method can be called if @p scip is in one of the following stages: 466 * - \ref SCIP_STAGE_PROBLEM 467 * - \ref SCIP_STAGE_TRANSFORMING 468 * - \ref SCIP_STAGE_INITPRESOLVE 469 * - \ref SCIP_STAGE_PRESOLVING 470 * - \ref SCIP_STAGE_EXITPRESOLVE 471 * - \ref SCIP_STAGE_PRESOLVED 472 * - \ref SCIP_STAGE_SOLVING 473 */ 474 SCIP_RETCODE SCIPparseVar( 475 SCIP* scip, /**< SCIP data structure */ 476 SCIP_VAR** var, /**< pointer to store the problem variable */ 477 const char* str, /**< string to parse */ 478 SCIP_Bool initial, /**< should var's column be present in the initial root LP? */ 479 SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */ 480 SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */ 481 SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */ 482 SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */ 483 SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */ 484 SCIP_VARDATA* vardata, /**< user data for this specific variable */ 485 char** endptr, /**< pointer to store the final string position if successful */ 486 SCIP_Bool* success /**< pointer store if the paring process was successful */ 487 ) 488 { 489 assert(var != NULL); 490 491 SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVar", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 492 493 switch( scip->set->stage ) 494 { 495 case SCIP_STAGE_PROBLEM: 496 SCIP_CALL( SCIPvarParseOriginal(var, scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat, 497 str, initial, removable, varcopy, vardelorig, vartrans, vardeltrans, vardata, endptr, success) ); 498 break; 499 500 case SCIP_STAGE_TRANSFORMING: 501 case SCIP_STAGE_INITPRESOLVE: 502 case SCIP_STAGE_PRESOLVING: 503 case SCIP_STAGE_EXITPRESOLVE: 504 case SCIP_STAGE_PRESOLVED: 505 case SCIP_STAGE_SOLVING: 506 SCIP_CALL( SCIPvarParseTransformed(var, scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat, 507 str, initial, removable, varcopy, vardelorig, vartrans, vardeltrans, vardata, endptr, success) ); 508 break; 509 510 default: 511 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 512 return SCIP_INVALIDCALL; 513 } /*lint !e788*/ 514 515 return SCIP_OKAY; 516 } 517 518 /** parses the given string for a variable name and stores the variable in the corresponding pointer if such a variable 519 * exits and returns the position where the parsing stopped 520 * 521 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 522 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 523 * 524 * @pre This method can be called if @p scip is in one of the following stages: 525 * - \ref SCIP_STAGE_PROBLEM 526 * - \ref SCIP_STAGE_TRANSFORMING 527 * - \ref SCIP_STAGE_INITPRESOLVE 528 * - \ref SCIP_STAGE_PRESOLVING 529 * - \ref SCIP_STAGE_EXITPRESOLVE 530 * - \ref SCIP_STAGE_PRESOLVED 531 * - \ref SCIP_STAGE_SOLVING 532 */ 533 SCIP_RETCODE SCIPparseVarName( 534 SCIP* scip, /**< SCIP data structure */ 535 const char* str, /**< string to parse */ 536 SCIP_VAR** var, /**< pointer to store the problem variable, or NULL if it does not exit */ 537 char** endptr /**< pointer to store the final string position if successful */ 538 ) 539 { 540 char varname[SCIP_MAXSTRLEN]; 541 542 assert(str != NULL); 543 assert(var != NULL); 544 assert(endptr != NULL); 545 546 SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarName", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 547 548 SCIPstrCopySection(str, '<', '>', varname, SCIP_MAXSTRLEN, endptr); 549 assert(*endptr != NULL); 550 551 if( *endptr == str ) 552 { 553 *var = NULL; 554 return SCIP_OKAY; 555 } 556 557 /* check if we have a negated variable */ 558 if( *varname == '~' ) 559 { 560 SCIPdebugMsg(scip, "parsed negated variable name <%s>\n", &varname[1]); 561 562 /* search for the variable and ignore '~' */ 563 (*var) = SCIPfindVar(scip, &varname[1]); 564 565 if( *var != NULL ) 566 { 567 SCIP_CALL( SCIPgetNegatedVar(scip, *var, var) ); 568 } 569 } 570 else 571 { 572 SCIPdebugMsg(scip, "parsed variable name <%s>\n", varname); 573 574 /* search for the variable */ 575 (*var) = SCIPfindVar(scip, varname); 576 } 577 578 str = *endptr; 579 580 /* skip additional variable type marker */ 581 if( *str == '[' && (str[1] == SCIP_VARTYPE_BINARY_CHAR || str[1] == SCIP_VARTYPE_INTEGER_CHAR || 582 str[1] == SCIP_VARTYPE_IMPLINT_CHAR || str[1] == SCIP_VARTYPE_CONTINUOUS_CHAR ) && str[2] == ']' ) 583 (*endptr) += 3; 584 585 return SCIP_OKAY; 586 } 587 588 /** parse the given string as variable list (here ',' is the delimiter)) (\<x1\>, \<x2\>, ..., \<xn\>) (see 589 * SCIPwriteVarsList() ); if it was successful, the pointer success is set to TRUE 590 * 591 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 592 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 593 * 594 * @pre This method can be called if @p scip is in one of the following stages: 595 * - \ref SCIP_STAGE_PROBLEM 596 * - \ref SCIP_STAGE_TRANSFORMING 597 * - \ref SCIP_STAGE_INITPRESOLVE 598 * - \ref SCIP_STAGE_PRESOLVING 599 * - \ref SCIP_STAGE_EXITPRESOLVE 600 * - \ref SCIP_STAGE_PRESOLVED 601 * - \ref SCIP_STAGE_SOLVING 602 * 603 * @note The pointer success in only set to FALSE in the case that a variable with a parsed variable name does not exist. 604 * 605 * @note If the number of (parsed) variables is greater than the available slots in the variable array, nothing happens 606 * except that the required size is stored in the corresponding integer; the reason for this approach is that we 607 * cannot reallocate memory, since we do not know how the memory has been allocated (e.g., by a C++ 'new' or SCIP 608 * memory functions). 609 */ 610 SCIP_RETCODE SCIPparseVarsList( 611 SCIP* scip, /**< SCIP data structure */ 612 const char* str, /**< string to parse */ 613 SCIP_VAR** vars, /**< array to store the parsed variable */ 614 int* nvars, /**< pointer to store number of parsed variables */ 615 int varssize, /**< size of the variable array */ 616 int* requiredsize, /**< pointer to store the required array size for the active variables */ 617 char** endptr, /**< pointer to store the final string position if successful */ 618 char delimiter, /**< character which is used for delimitation */ 619 SCIP_Bool* success /**< pointer to store the whether the parsing was successful or not */ 620 ) 621 { 622 SCIP_VAR** tmpvars; 623 SCIP_VAR* var; 624 int ntmpvars = 0; 625 int v; 626 627 assert( nvars != NULL ); 628 assert( requiredsize != NULL ); 629 assert( endptr != NULL ); 630 assert( success != NULL ); 631 632 SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarsList", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 633 634 /* allocate buffer memory for temporary storing the parsed variables */ 635 SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, varssize) ); 636 637 *success = TRUE; 638 639 do 640 { 641 *endptr = (char*)str; 642 643 /* parse variable name */ 644 SCIP_CALL( SCIPparseVarName(scip, str, &var, endptr) ); 645 646 if( var == NULL ) 647 break; 648 649 str = *endptr; 650 651 /* store the variable in the tmp array */ 652 if( ntmpvars < varssize ) 653 tmpvars[ntmpvars] = var; 654 655 ntmpvars++; 656 657 SCIP_CALL( SCIPskipSpace((char**)&str) ); 658 } 659 while( *str == delimiter ); 660 661 *endptr = (char*)str; 662 663 /* if all variable name searches were successful and the variable array has enough slots, copy the collected variables */ 664 if( (*success) && ntmpvars <= varssize ) 665 { 666 for( v = 0; v < ntmpvars; ++v ) 667 vars[v] = tmpvars[v]; 668 669 (*nvars) = ntmpvars; 670 } 671 else 672 (*nvars) = 0; 673 674 (*requiredsize) = ntmpvars; 675 676 /* free buffer arrays */ 677 SCIPfreeBufferArray(scip, &tmpvars); 678 679 return SCIP_OKAY; 680 } 681 682 /** parse the given string as linear sum of variables and coefficients (c1 \<x1\> + c2 \<x2\> + ... + cn \<xn\>) 683 * (see SCIPwriteVarsLinearsum() ); if it was successful, the pointer success is set to TRUE 684 * 685 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 686 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 687 * 688 * @pre This method can be called if @p scip is in one of the following stages: 689 * - \ref SCIP_STAGE_PROBLEM 690 * - \ref SCIP_STAGE_TRANSFORMING 691 * - \ref SCIP_STAGE_INITPRESOLVE 692 * - \ref SCIP_STAGE_PRESOLVING 693 * - \ref SCIP_STAGE_EXITPRESOLVE 694 * - \ref SCIP_STAGE_PRESOLVED 695 * - \ref SCIP_STAGE_SOLVING 696 * 697 * @note The pointer success in only set to FALSE in the case that a variable with a parsed variable name does not exist. 698 * 699 * @note If the number of (parsed) variables is greater than the available slots in the variable array, nothing happens 700 * except that the required size is stored in the corresponding integer; the reason for this approach is that we 701 * cannot reallocate memory, since we do not know how the memory has been allocated (e.g., by a C++ 'new' or SCIP 702 * memory functions). 703 */ 704 SCIP_RETCODE SCIPparseVarsLinearsum( 705 SCIP* scip, /**< SCIP data structure */ 706 const char* str, /**< string to parse */ 707 SCIP_VAR** vars, /**< array to store the parsed variables */ 708 SCIP_Real* vals, /**< array to store the parsed coefficients */ 709 int* nvars, /**< pointer to store number of parsed variables */ 710 int varssize, /**< size of the variable array */ 711 int* requiredsize, /**< pointer to store the required array size for the active variables */ 712 char** endptr, /**< pointer to store the final string position if successful */ 713 SCIP_Bool* success /**< pointer to store the whether the parsing was successful or not */ 714 ) 715 { 716 SCIP_VAR*** monomialvars; 717 SCIP_Real** monomialexps; 718 SCIP_Real* monomialcoefs; 719 int* monomialnvars; 720 int nmonomials; 721 722 SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarsLinearsum", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 723 724 assert(scip != NULL); 725 assert(str != NULL); 726 assert(vars != NULL || varssize == 0); 727 assert(vals != NULL || varssize == 0); 728 assert(nvars != NULL); 729 assert(requiredsize != NULL); 730 assert(endptr != NULL); 731 assert(success != NULL); 732 733 *requiredsize = 0; 734 735 SCIP_CALL( SCIPparseVarsPolynomial(scip, str, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, &nmonomials, endptr, success) ); 736 737 if( !*success ) 738 { 739 assert(nmonomials == 0); /* SCIPparseVarsPolynomial should have freed all buffers, so no need to call free here */ 740 return SCIP_OKAY; 741 } 742 743 /* check if linear sum is just "0" */ 744 if( nmonomials == 1 && monomialnvars[0] == 0 && monomialcoefs[0] == 0.0 ) 745 { 746 *nvars = 0; 747 *requiredsize = 0; 748 749 SCIPfreeParseVarsPolynomialData(scip, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, nmonomials); 750 751 return SCIP_OKAY; 752 } 753 754 *nvars = nmonomials; 755 *requiredsize = nmonomials; 756 757 /* if we have enough slots in the variables array, copy variables over */ 758 if( varssize >= nmonomials ) 759 { 760 int v; 761 762 for( v = 0; v < nmonomials; ++v ) 763 { 764 if( monomialnvars[v] == 0 ) 765 { 766 SCIPerrorMessage("constant in linear sum\n"); 767 *success = FALSE; 768 break; 769 } 770 if( monomialnvars[v] > 1 || monomialexps[v][0] != 1.0 ) 771 { 772 SCIPerrorMessage("nonlinear monomial in linear sum\n"); 773 *success = FALSE; 774 break; 775 } 776 assert(monomialnvars[v] == 1); 777 assert(monomialvars[v][0] != NULL); 778 assert(monomialexps[v][0] == 1.0); 779 780 vars[v] = monomialvars[v][0]; /*lint !e613*/ 781 vals[v] = monomialcoefs[v]; /*lint !e613*/ 782 } 783 } 784 785 SCIPfreeParseVarsPolynomialData(scip, &monomialvars, &monomialexps, &monomialcoefs, &monomialnvars, nmonomials); 786 787 return SCIP_OKAY; 788 } 789 790 /** parse the given string as signomial of variables and coefficients 791 * (c1 \<x11\>^e11 \<x12\>^e12 ... \<x1n\>^e1n + c2 \<x21\>^e21 \<x22\>^e22 ... + ... + cn \<xn1\>^en1 ...) 792 * (see SCIPwriteVarsPolynomial()); if it was successful, the pointer success is set to TRUE 793 * 794 * The user has to call SCIPfreeParseVarsPolynomialData(scip, monomialvars, monomialexps, 795 * monomialcoefs, monomialnvars, *nmonomials) short after SCIPparseVarsPolynomial to free all the 796 * allocated memory again. 797 * 798 * Parsing is stopped at the end of string (indicated by the \\0-character) or when no more monomials 799 * are recognized. 800 * 801 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 802 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 803 * 804 * @pre This method can be called if @p scip is in one of the following stages: 805 * - \ref SCIP_STAGE_PROBLEM 806 * - \ref SCIP_STAGE_TRANSFORMING 807 * - \ref SCIP_STAGE_INITPRESOLVE 808 * - \ref SCIP_STAGE_PRESOLVING 809 * - \ref SCIP_STAGE_EXITPRESOLVE 810 * - \ref SCIP_STAGE_PRESOLVED 811 * - \ref SCIP_STAGE_SOLVING 812 */ 813 SCIP_RETCODE SCIPparseVarsPolynomial( 814 SCIP* scip, /**< SCIP data structure */ 815 const char* str, /**< string to parse */ 816 SCIP_VAR**** monomialvars, /**< pointer to store arrays with variables for each monomial */ 817 SCIP_Real*** monomialexps, /**< pointer to store arrays with variable exponents */ 818 SCIP_Real** monomialcoefs, /**< pointer to store array with monomial coefficients */ 819 int** monomialnvars, /**< pointer to store array with number of variables for each monomial */ 820 int* nmonomials, /**< pointer to store number of parsed monomials */ 821 char** endptr, /**< pointer to store the final string position if successful */ 822 SCIP_Bool* success /**< pointer to store the whether the parsing was successful or not */ 823 ) 824 { 825 typedef enum 826 { 827 SCIPPARSEPOLYNOMIAL_STATE_BEGIN, /* we are at the beginning of a monomial */ 828 SCIPPARSEPOLYNOMIAL_STATE_INTERMED, /* we are in between the factors of a monomial */ 829 SCIPPARSEPOLYNOMIAL_STATE_COEF, /* we parse the coefficient of a monomial */ 830 SCIPPARSEPOLYNOMIAL_STATE_VARS, /* we parse monomial variables */ 831 SCIPPARSEPOLYNOMIAL_STATE_EXPONENT, /* we parse the exponent of a variable */ 832 SCIPPARSEPOLYNOMIAL_STATE_END, /* we are at the end the polynomial */ 833 SCIPPARSEPOLYNOMIAL_STATE_ERROR /* a parsing error occured */ 834 } SCIPPARSEPOLYNOMIAL_STATES; 835 836 SCIPPARSEPOLYNOMIAL_STATES state; 837 int monomialssize; 838 839 /* data of currently parsed monomial */ 840 int varssize; 841 int nvars; 842 SCIP_VAR** vars; 843 SCIP_Real* exponents; 844 SCIP_Real coef; 845 846 assert(scip != NULL); 847 assert(str != NULL); 848 assert(monomialvars != NULL); 849 assert(monomialexps != NULL); 850 assert(monomialnvars != NULL); 851 assert(monomialcoefs != NULL); 852 assert(nmonomials != NULL); 853 assert(endptr != NULL); 854 assert(success != NULL); 855 856 SCIP_CALL( SCIPcheckStage(scip, "SCIPparseVarsPolynomial", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 857 858 *success = FALSE; 859 *nmonomials = 0; 860 monomialssize = 0; 861 *monomialvars = NULL; 862 *monomialexps = NULL; 863 *monomialcoefs = NULL; 864 *monomialnvars = NULL; 865 866 /* initialize state machine */ 867 state = SCIPPARSEPOLYNOMIAL_STATE_BEGIN; 868 varssize = 0; 869 nvars = 0; 870 vars = NULL; 871 exponents = NULL; 872 coef = SCIP_INVALID; 873 874 SCIPdebugMsg(scip, "parsing polynomial from '%s'\n", str); 875 876 while( *str && state != SCIPPARSEPOLYNOMIAL_STATE_END && state != SCIPPARSEPOLYNOMIAL_STATE_ERROR ) 877 { 878 /* skip white space */ 879 SCIP_CALL( SCIPskipSpace((char**)&str) ); 880 881 assert(state != SCIPPARSEPOLYNOMIAL_STATE_END); 882 883 switch( state ) 884 { 885 case SCIPPARSEPOLYNOMIAL_STATE_BEGIN: 886 { 887 if( coef != SCIP_INVALID ) /*lint !e777*/ 888 { 889 SCIPdebugMsg(scip, "push monomial with coefficient <%g> and <%d> vars\n", coef, nvars); 890 891 /* push previous monomial */ 892 if( monomialssize <= *nmonomials ) 893 { 894 monomialssize = SCIPcalcMemGrowSize(scip, *nmonomials+1); 895 896 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialvars, *nmonomials, monomialssize) ); 897 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, *nmonomials, monomialssize) ); 898 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, *nmonomials, monomialssize) ); 899 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, *nmonomials, monomialssize) ); 900 } 901 902 if( nvars > 0 ) 903 { 904 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*monomialvars)[*nmonomials], vars, nvars) ); /*lint !e866*/ 905 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*monomialexps)[*nmonomials], exponents, nvars) ); /*lint !e866*/ 906 } 907 else 908 { 909 (*monomialvars)[*nmonomials] = NULL; 910 (*monomialexps)[*nmonomials] = NULL; 911 } 912 (*monomialcoefs)[*nmonomials] = coef; 913 (*monomialnvars)[*nmonomials] = nvars; 914 ++*nmonomials; 915 916 nvars = 0; 917 coef = SCIP_INVALID; 918 } 919 920 if( *str == '<' ) 921 { 922 /* there seem to come a variable at the beginning of a monomial 923 * so assume the coefficient is 1.0 924 */ 925 state = SCIPPARSEPOLYNOMIAL_STATE_VARS; 926 coef = 1.0; 927 } 928 else if( *str == '-' || *str == '+' || isdigit(*str) ) 929 state = SCIPPARSEPOLYNOMIAL_STATE_COEF; 930 else 931 state = SCIPPARSEPOLYNOMIAL_STATE_END; 932 933 break; 934 } 935 936 case SCIPPARSEPOLYNOMIAL_STATE_INTERMED: 937 { 938 if( *str == '<' ) 939 { 940 /* there seem to come another variable */ 941 state = SCIPPARSEPOLYNOMIAL_STATE_VARS; 942 } 943 else if( *str == '-' || *str == '+' || isdigit(*str) ) 944 { 945 /* there seem to come a coefficient, which means the next monomial */ 946 state = SCIPPARSEPOLYNOMIAL_STATE_BEGIN; 947 } 948 else /* since we cannot detect the symbols we stop parsing the polynomial */ 949 state = SCIPPARSEPOLYNOMIAL_STATE_END; 950 951 break; 952 } 953 954 case SCIPPARSEPOLYNOMIAL_STATE_COEF: 955 { 956 if( *str == '+' && !isdigit(str[1]) ) 957 { 958 /* only a plus sign, without number */ 959 coef = 1.0; 960 ++str; 961 } 962 else if( *str == '-' && !isdigit(str[1]) ) 963 { 964 /* only a minus sign, without number */ 965 coef = -1.0; 966 ++str; 967 } 968 else if( SCIPstrToRealValue(str, &coef, endptr) ) 969 { 970 str = *endptr; 971 } 972 else 973 { 974 SCIPerrorMessage("could not parse number in the beginning of '%s'\n", str); 975 state = SCIPPARSEPOLYNOMIAL_STATE_ERROR; 976 break; 977 } 978 979 /* after the coefficient we go into the intermediate state, i.e., expecting next variables */ 980 state = SCIPPARSEPOLYNOMIAL_STATE_INTERMED; /*lint !e838*/ 981 982 break; 983 } 984 985 case SCIPPARSEPOLYNOMIAL_STATE_VARS: 986 { 987 SCIP_VAR* var; 988 989 assert(*str == '<'); 990 991 /* parse variable name */ 992 SCIP_CALL( SCIPparseVarName(scip, str, &var, endptr) ); 993 994 /* check if variable name was parsed */ 995 if( *endptr == str ) 996 { 997 state = SCIPPARSEPOLYNOMIAL_STATE_END; 998 break; 999 } 1000 1001 if( var == NULL ) 1002 { 1003 SCIPerrorMessage("did not find variable in the beginning of %s\n", str); 1004 state = SCIPPARSEPOLYNOMIAL_STATE_ERROR; 1005 break; 1006 } 1007 1008 /* add variable to vars array */ 1009 if( nvars + 1 > varssize ) 1010 { 1011 varssize = SCIPcalcMemGrowSize(scip, nvars+1); 1012 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &vars, nvars, varssize) ); 1013 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &exponents, nvars, varssize) ); 1014 } 1015 assert(vars != NULL); 1016 assert(exponents != NULL); 1017 1018 vars[nvars] = var; 1019 exponents[nvars] = 1.0; 1020 ++nvars; 1021 1022 str = *endptr; 1023 1024 if( *str == '^' ) 1025 state = SCIPPARSEPOLYNOMIAL_STATE_EXPONENT; 1026 else 1027 state = SCIPPARSEPOLYNOMIAL_STATE_INTERMED; 1028 1029 break; 1030 } 1031 1032 case SCIPPARSEPOLYNOMIAL_STATE_EXPONENT: 1033 { 1034 assert(*str == '^'); 1035 assert(nvars > 0); /* we should be in a monomial that has already a variable */ 1036 assert(exponents != NULL); 1037 ++str; 1038 1039 if( !SCIPstrToRealValue(str, &exponents[nvars-1], endptr) ) 1040 { 1041 SCIPerrorMessage("could not parse number in the beginning of '%s'\n", str); 1042 state = SCIPPARSEPOLYNOMIAL_STATE_ERROR; 1043 break; 1044 } 1045 str = *endptr; 1046 1047 /* after the exponent we go into the intermediate state, i.e., expecting next variables */ 1048 state = SCIPPARSEPOLYNOMIAL_STATE_INTERMED; /*lint !e838*/ 1049 break; 1050 } 1051 1052 case SCIPPARSEPOLYNOMIAL_STATE_END: 1053 case SCIPPARSEPOLYNOMIAL_STATE_ERROR: 1054 default: 1055 SCIPerrorMessage("unexpected state\n"); 1056 return SCIP_READERROR; 1057 } 1058 } 1059 1060 /* set end pointer */ 1061 *endptr = (char*)str; 1062 1063 /* check state at end of string */ 1064 switch( state ) 1065 { 1066 case SCIPPARSEPOLYNOMIAL_STATE_BEGIN: 1067 case SCIPPARSEPOLYNOMIAL_STATE_END: 1068 case SCIPPARSEPOLYNOMIAL_STATE_INTERMED: 1069 { 1070 if( coef != SCIP_INVALID ) /*lint !e777*/ 1071 { 1072 /* push last monomial */ 1073 SCIPdebugMsg(scip, "push monomial with coefficient <%g> and <%d> vars\n", coef, nvars); 1074 if( monomialssize <= *nmonomials ) 1075 { 1076 monomialssize = *nmonomials+1; 1077 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialvars, *nmonomials, monomialssize) ); 1078 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, *nmonomials, monomialssize) ); 1079 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, *nmonomials, monomialssize) ); 1080 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, *nmonomials, monomialssize) ); 1081 } 1082 1083 if( nvars > 0 ) 1084 { 1085 /* shrink vars and exponents array to needed size and take over ownership */ 1086 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &vars, varssize, nvars) ); 1087 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &exponents, varssize, nvars) ); 1088 (*monomialvars)[*nmonomials] = vars; 1089 (*monomialexps)[*nmonomials] = exponents; 1090 vars = NULL; 1091 exponents = NULL; 1092 } 1093 else 1094 { 1095 (*monomialvars)[*nmonomials] = NULL; 1096 (*monomialexps)[*nmonomials] = NULL; 1097 } 1098 (*monomialcoefs)[*nmonomials] = coef; 1099 (*monomialnvars)[*nmonomials] = nvars; 1100 ++*nmonomials; 1101 } 1102 1103 *success = TRUE; 1104 break; 1105 } 1106 1107 case SCIPPARSEPOLYNOMIAL_STATE_COEF: 1108 case SCIPPARSEPOLYNOMIAL_STATE_VARS: 1109 case SCIPPARSEPOLYNOMIAL_STATE_EXPONENT: 1110 { 1111 SCIPerrorMessage("unexpected parsing state at end of polynomial string\n"); 1112 } 1113 /*lint -fallthrough*/ 1114 case SCIPPARSEPOLYNOMIAL_STATE_ERROR: 1115 assert(!*success); 1116 break; 1117 } 1118 1119 /* free memory to store current monomial, if still existing */ 1120 SCIPfreeBlockMemoryArrayNull(scip, &vars, varssize); 1121 SCIPfreeBlockMemoryArrayNull(scip, &exponents, varssize); 1122 1123 if( *success && *nmonomials > 0 ) 1124 { 1125 /* shrink arrays to required size, so we do not need to keep monomialssize around */ 1126 assert(*nmonomials <= monomialssize); 1127 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialvars, monomialssize, *nmonomials) ); 1128 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialexps, monomialssize, *nmonomials) ); 1129 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialnvars, monomialssize, *nmonomials) ); 1130 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, monomialcoefs, monomialssize, *nmonomials) ); 1131 1132 /* SCIPwriteVarsPolynomial(scip, NULL, *monomialvars, *monomialexps, *monomialcoefs, *monomialnvars, *nmonomials, FALSE); */ 1133 } 1134 else 1135 { 1136 /* in case of error, cleanup all data here */ 1137 SCIPfreeParseVarsPolynomialData(scip, monomialvars, monomialexps, monomialcoefs, monomialnvars, *nmonomials); 1138 *nmonomials = 0; 1139 } 1140 1141 return SCIP_OKAY; 1142 } 1143 1144 /** frees memory allocated when parsing a signomial from a string 1145 * 1146 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1147 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1148 * 1149 * @pre This method can be called if @p scip is in one of the following stages: 1150 * - \ref SCIP_STAGE_PROBLEM 1151 * - \ref SCIP_STAGE_TRANSFORMING 1152 * - \ref SCIP_STAGE_INITPRESOLVE 1153 * - \ref SCIP_STAGE_PRESOLVING 1154 * - \ref SCIP_STAGE_EXITPRESOLVE 1155 * - \ref SCIP_STAGE_PRESOLVED 1156 * - \ref SCIP_STAGE_SOLVING 1157 */ 1158 void SCIPfreeParseVarsPolynomialData( 1159 SCIP* scip, /**< SCIP data structure */ 1160 SCIP_VAR**** monomialvars, /**< pointer to store arrays with variables for each monomial */ 1161 SCIP_Real*** monomialexps, /**< pointer to store arrays with variable exponents */ 1162 SCIP_Real** monomialcoefs, /**< pointer to store array with monomial coefficients */ 1163 int** monomialnvars, /**< pointer to store array with number of variables for each monomial */ 1164 int nmonomials /**< pointer to store number of parsed monomials */ 1165 ) 1166 { 1167 int i; 1168 1169 assert(scip != NULL); 1170 assert(monomialvars != NULL); 1171 assert(monomialexps != NULL); 1172 assert(monomialcoefs != NULL); 1173 assert(monomialnvars != NULL); 1174 assert((*monomialvars != NULL) == (nmonomials > 0)); 1175 assert((*monomialexps != NULL) == (nmonomials > 0)); 1176 assert((*monomialcoefs != NULL) == (nmonomials > 0)); 1177 assert((*monomialnvars != NULL) == (nmonomials > 0)); 1178 1179 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPfreeParseVarsPolynomialData", FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 1180 1181 if( nmonomials == 0 ) 1182 return; 1183 1184 for( i = nmonomials - 1; i >= 0; --i ) 1185 { 1186 SCIPfreeBlockMemoryArrayNull(scip, &(*monomialexps)[i], (*monomialnvars)[i]); 1187 SCIPfreeBlockMemoryArrayNull(scip, &(*monomialvars)[i], (*monomialnvars)[i]); 1188 } 1189 1190 SCIPfreeBlockMemoryArray(scip, monomialcoefs, nmonomials); 1191 SCIPfreeBlockMemoryArray(scip, monomialnvars, nmonomials); 1192 SCIPfreeBlockMemoryArray(scip, monomialexps, nmonomials); 1193 SCIPfreeBlockMemoryArray(scip, monomialvars, nmonomials); 1194 } 1195 1196 /** increases usage counter of variable 1197 * 1198 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1199 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1200 * 1201 * @pre This method can be called if @p scip is in one of the following stages: 1202 * - \ref SCIP_STAGE_PROBLEM 1203 * - \ref SCIP_STAGE_TRANSFORMING 1204 * - \ref SCIP_STAGE_TRANSFORMED 1205 * - \ref SCIP_STAGE_INITPRESOLVE 1206 * - \ref SCIP_STAGE_PRESOLVING 1207 * - \ref SCIP_STAGE_EXITPRESOLVE 1208 * - \ref SCIP_STAGE_PRESOLVED 1209 * - \ref SCIP_STAGE_INITSOLVE 1210 * - \ref SCIP_STAGE_SOLVING 1211 * - \ref SCIP_STAGE_SOLVED 1212 * - \ref SCIP_STAGE_EXITSOLVE 1213 */ 1214 SCIP_RETCODE SCIPcaptureVar( 1215 SCIP* scip, /**< SCIP data structure */ 1216 SCIP_VAR* var /**< variable to capture */ 1217 ) 1218 { 1219 SCIP_CALL( SCIPcheckStage(scip, "SCIPcaptureVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 1220 assert(var->scip == scip); 1221 1222 SCIPvarCapture(var); 1223 1224 return SCIP_OKAY; 1225 } 1226 1227 /** decreases usage counter of variable, if the usage pointer reaches zero the variable gets freed 1228 * 1229 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1230 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1231 * 1232 * @pre This method can be called if @p scip is in one of the following stages: 1233 * - \ref SCIP_STAGE_PROBLEM 1234 * - \ref SCIP_STAGE_TRANSFORMING 1235 * - \ref SCIP_STAGE_TRANSFORMED 1236 * - \ref SCIP_STAGE_INITPRESOLVE 1237 * - \ref SCIP_STAGE_PRESOLVING 1238 * - \ref SCIP_STAGE_EXITPRESOLVE 1239 * - \ref SCIP_STAGE_PRESOLVED 1240 * - \ref SCIP_STAGE_INITSOLVE 1241 * - \ref SCIP_STAGE_SOLVING 1242 * - \ref SCIP_STAGE_SOLVED 1243 * - \ref SCIP_STAGE_EXITSOLVE 1244 * - \ref SCIP_STAGE_FREETRANS 1245 * 1246 * @note the pointer of the variable will be NULLed 1247 */ 1248 SCIP_RETCODE SCIPreleaseVar( 1249 SCIP* scip, /**< SCIP data structure */ 1250 SCIP_VAR** var /**< pointer to variable */ 1251 ) 1252 { 1253 assert(var != NULL); 1254 assert(*var != NULL); 1255 assert((*var)->scip == scip); 1256 1257 SCIP_CALL( SCIPcheckStage(scip, "SCIPreleaseVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1258 1259 switch( scip->set->stage ) 1260 { 1261 case SCIP_STAGE_PROBLEM: 1262 SCIP_CALL( SCIPvarRelease(var, scip->mem->probmem, scip->set, scip->eventqueue, scip->lp) ); 1263 return SCIP_OKAY; 1264 1265 case SCIP_STAGE_TRANSFORMING: 1266 case SCIP_STAGE_TRANSFORMED: 1267 case SCIP_STAGE_INITPRESOLVE: 1268 case SCIP_STAGE_PRESOLVING: 1269 case SCIP_STAGE_EXITPRESOLVE: 1270 case SCIP_STAGE_PRESOLVED: 1271 case SCIP_STAGE_INITSOLVE: 1272 case SCIP_STAGE_SOLVING: 1273 case SCIP_STAGE_SOLVED: 1274 case SCIP_STAGE_EXITSOLVE: 1275 case SCIP_STAGE_FREETRANS: 1276 if( !SCIPvarIsTransformed(*var) && (*var)->nuses == 1 && (*var)->data.original.transvar != NULL ) 1277 { 1278 SCIPerrorMessage("cannot release last use of original variable while associated transformed variable exists\n"); 1279 return SCIP_INVALIDCALL; 1280 } 1281 SCIP_CALL( SCIPvarRelease(var, scip->mem->probmem, scip->set, scip->eventqueue, scip->lp) ); 1282 return SCIP_OKAY; 1283 1284 default: 1285 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 1286 return SCIP_INVALIDCALL; 1287 } /*lint !e788*/ 1288 } 1289 1290 /** changes the name of a variable 1291 * 1292 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1293 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1294 * 1295 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PROBLEM 1296 * 1297 * @note to get the current name of a variable, use SCIPvarGetName() from pub_var.h 1298 */ 1299 SCIP_RETCODE SCIPchgVarName( 1300 SCIP* scip, /**< SCIP data structure */ 1301 SCIP_VAR* var, /**< variable */ 1302 const char* name /**< new name of constraint */ 1303 ) 1304 { 1305 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarName", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 1306 assert( var->scip == scip ); 1307 1308 if( SCIPgetStage(scip) != SCIP_STAGE_PROBLEM ) 1309 { 1310 SCIPerrorMessage("variable names can only be changed in problem creation stage\n"); 1311 SCIPABORT(); 1312 return SCIP_INVALIDCALL; /*lint !e527*/ 1313 } 1314 1315 /* remove variable's name from the namespace if the variable was already added */ 1316 if( SCIPvarGetProbindex(var) != -1 ) 1317 { 1318 SCIP_CALL( SCIPprobRemoveVarName(scip->origprob, var) ); 1319 } 1320 1321 /* change variable name */ 1322 SCIP_CALL( SCIPvarChgName(var, SCIPblkmem(scip), name) ); 1323 1324 /* add variable's name to the namespace if the variable was already added */ 1325 if( SCIPvarGetProbindex(var) != -1 ) 1326 { 1327 SCIP_CALL( SCIPprobAddVarName(scip->origprob, var) ); 1328 } 1329 1330 return SCIP_OKAY; 1331 } 1332 1333 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed, 1334 * a new transformed variable for this variable is created 1335 * 1336 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1337 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1338 * 1339 * @pre This method can be called if @p scip is in one of the following stages: 1340 * - \ref SCIP_STAGE_TRANSFORMING 1341 * - \ref SCIP_STAGE_TRANSFORMED 1342 * - \ref SCIP_STAGE_INITPRESOLVE 1343 * - \ref SCIP_STAGE_PRESOLVING 1344 * - \ref SCIP_STAGE_EXITPRESOLVE 1345 * - \ref SCIP_STAGE_PRESOLVED 1346 * - \ref SCIP_STAGE_INITSOLVE 1347 * - \ref SCIP_STAGE_SOLVING 1348 */ 1349 SCIP_RETCODE SCIPtransformVar( 1350 SCIP* scip, /**< SCIP data structure */ 1351 SCIP_VAR* var, /**< variable to get/create transformed variable for */ 1352 SCIP_VAR** transvar /**< pointer to store the transformed variable */ 1353 ) 1354 { 1355 assert(transvar != NULL); 1356 1357 SCIP_CALL( SCIPcheckStage(scip, "SCIPtransformVar", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 1358 1359 if( SCIPvarIsTransformed(var) ) 1360 { 1361 *transvar = var; 1362 SCIPvarCapture(*transvar); 1363 } 1364 else 1365 { 1366 SCIP_CALL( SCIPvarTransform(var, scip->mem->probmem, scip->set, scip->stat, scip->origprob->objsense, transvar) ); 1367 } 1368 1369 return SCIP_OKAY; 1370 } 1371 1372 /** gets and captures transformed variables for an array of variables; 1373 * if a variable of the array is not yet transformed, a new transformed variable for this variable is created; 1374 * it is possible to call this method with vars == transvars 1375 * 1376 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1377 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1378 * 1379 * @pre This method can be called if @p scip is in one of the following stages: 1380 * - \ref SCIP_STAGE_TRANSFORMING 1381 * - \ref SCIP_STAGE_TRANSFORMED 1382 * - \ref SCIP_STAGE_INITPRESOLVE 1383 * - \ref SCIP_STAGE_PRESOLVING 1384 * - \ref SCIP_STAGE_EXITPRESOLVE 1385 * - \ref SCIP_STAGE_PRESOLVED 1386 * - \ref SCIP_STAGE_INITSOLVE 1387 * - \ref SCIP_STAGE_SOLVING 1388 */ 1389 SCIP_RETCODE SCIPtransformVars( 1390 SCIP* scip, /**< SCIP data structure */ 1391 int nvars, /**< number of variables to get/create transformed variables for */ 1392 SCIP_VAR** vars, /**< array with variables to get/create transformed variables for */ 1393 SCIP_VAR** transvars /**< array to store the transformed variables */ 1394 ) 1395 { 1396 int v; 1397 1398 assert(nvars == 0 || vars != NULL); 1399 assert(nvars == 0 || transvars != NULL); 1400 1401 SCIP_CALL( SCIPcheckStage(scip, "SCIPtransformVars", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 1402 1403 for( v = 0; v < nvars; ++v ) 1404 { 1405 if( SCIPvarIsTransformed(vars[v]) ) 1406 { 1407 transvars[v] = vars[v]; 1408 SCIPvarCapture(transvars[v]); 1409 } 1410 else 1411 { 1412 SCIP_CALL( SCIPvarTransform(vars[v], scip->mem->probmem, scip->set, scip->stat, scip->origprob->objsense, 1413 &transvars[v]) ); 1414 } 1415 } 1416 1417 return SCIP_OKAY; 1418 } 1419 1420 /** gets corresponding transformed variable of a given variable; 1421 * returns NULL as transvar, if transformed variable is not yet existing 1422 * 1423 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1424 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1425 * 1426 * @pre This method can be called if @p scip is in one of the following stages: 1427 * - \ref SCIP_STAGE_TRANSFORMING 1428 * - \ref SCIP_STAGE_TRANSFORMED 1429 * - \ref SCIP_STAGE_INITPRESOLVE 1430 * - \ref SCIP_STAGE_PRESOLVING 1431 * - \ref SCIP_STAGE_EXITPRESOLVE 1432 * - \ref SCIP_STAGE_PRESOLVED 1433 * - \ref SCIP_STAGE_INITSOLVE 1434 * - \ref SCIP_STAGE_SOLVING 1435 * - \ref SCIP_STAGE_SOLVED 1436 * - \ref SCIP_STAGE_EXITSOLVE 1437 * - \ref SCIP_STAGE_FREETRANS 1438 */ 1439 SCIP_RETCODE SCIPgetTransformedVar( 1440 SCIP* scip, /**< SCIP data structure */ 1441 SCIP_VAR* var, /**< variable to get transformed variable for */ 1442 SCIP_VAR** transvar /**< pointer to store the transformed variable */ 1443 ) 1444 { 1445 assert(transvar != NULL); 1446 1447 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetTransformedVar", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1448 1449 if( SCIPvarIsTransformed(var) ) 1450 *transvar = var; 1451 else 1452 { 1453 SCIP_CALL( SCIPvarGetTransformed(var, scip->mem->probmem, scip->set, scip->stat, transvar) ); 1454 } 1455 1456 return SCIP_OKAY; 1457 } 1458 1459 /** gets corresponding transformed variables for an array of variables; 1460 * stores NULL in a transvars slot, if the transformed variable is not yet existing; 1461 * it is possible to call this method with vars == transvars, but remember that variables that are not 1462 * yet transformed will be replaced with NULL 1463 * 1464 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1465 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1466 * 1467 * @pre This method can be called if @p scip is in one of the following stages: 1468 * - \ref SCIP_STAGE_TRANSFORMING 1469 * - \ref SCIP_STAGE_TRANSFORMED 1470 * - \ref SCIP_STAGE_INITPRESOLVE 1471 * - \ref SCIP_STAGE_PRESOLVING 1472 * - \ref SCIP_STAGE_EXITPRESOLVE 1473 * - \ref SCIP_STAGE_PRESOLVED 1474 * - \ref SCIP_STAGE_INITSOLVE 1475 * - \ref SCIP_STAGE_SOLVING 1476 * - \ref SCIP_STAGE_SOLVED 1477 * - \ref SCIP_STAGE_EXITSOLVE 1478 * - \ref SCIP_STAGE_FREETRANS 1479 */ 1480 SCIP_RETCODE SCIPgetTransformedVars( 1481 SCIP* scip, /**< SCIP data structure */ 1482 int nvars, /**< number of variables to get transformed variables for */ 1483 SCIP_VAR** vars, /**< array with variables to get transformed variables for */ 1484 SCIP_VAR** transvars /**< array to store the transformed variables */ 1485 ) 1486 { 1487 int v; 1488 1489 assert(nvars == 0 || vars != NULL); 1490 assert(nvars == 0 || transvars != NULL); 1491 1492 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetTransformedVars", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1493 1494 for( v = 0; v < nvars; ++v ) 1495 { 1496 if( SCIPvarIsTransformed(vars[v]) ) 1497 transvars[v] = vars[v]; 1498 else 1499 { 1500 SCIP_CALL( SCIPvarGetTransformed(vars[v], scip->mem->probmem, scip->set, scip->stat, &transvars[v]) ); 1501 } 1502 } 1503 1504 return SCIP_OKAY; 1505 } 1506 1507 /** gets negated variable x' = lb + ub - x of variable x; negated variable is created, if not yet existing; 1508 * in difference to \ref SCIPcreateVar, the negated variable must not be released (unless captured explicitly) 1509 * 1510 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1511 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1512 * 1513 * @pre This method can be called if @p scip is in one of the following stages: 1514 * - \ref SCIP_STAGE_PROBLEM 1515 * - \ref SCIP_STAGE_TRANSFORMING 1516 * - \ref SCIP_STAGE_TRANSFORMED 1517 * - \ref SCIP_STAGE_INITPRESOLVE 1518 * - \ref SCIP_STAGE_PRESOLVING 1519 * - \ref SCIP_STAGE_EXITPRESOLVE 1520 * - \ref SCIP_STAGE_PRESOLVED 1521 * - \ref SCIP_STAGE_INITSOLVE 1522 * - \ref SCIP_STAGE_SOLVING 1523 * - \ref SCIP_STAGE_SOLVED 1524 * - \ref SCIP_STAGE_EXITSOLVE 1525 * - \ref SCIP_STAGE_FREETRANS 1526 */ 1527 SCIP_RETCODE SCIPgetNegatedVar( 1528 SCIP* scip, /**< SCIP data structure */ 1529 SCIP_VAR* var, /**< variable to get negated variable for */ 1530 SCIP_VAR** negvar /**< pointer to store the negated variable */ 1531 ) 1532 { 1533 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetNegatedVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1534 assert( var->scip == scip ); 1535 1536 SCIP_CALL( SCIPvarNegate(var, scip->mem->probmem, scip->set, scip->stat, negvar) ); 1537 1538 return SCIP_OKAY; 1539 } 1540 1541 /** gets negated variables x' = lb + ub - x of variables x; negated variables are created, if not yet existing 1542 * 1543 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1544 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1545 * 1546 * @pre This method can be called if @p scip is in one of the following stages: 1547 * - \ref SCIP_STAGE_PROBLEM 1548 * - \ref SCIP_STAGE_TRANSFORMING 1549 * - \ref SCIP_STAGE_TRANSFORMED 1550 * - \ref SCIP_STAGE_INITPRESOLVE 1551 * - \ref SCIP_STAGE_PRESOLVING 1552 * - \ref SCIP_STAGE_EXITPRESOLVE 1553 * - \ref SCIP_STAGE_PRESOLVED 1554 * - \ref SCIP_STAGE_INITSOLVE 1555 * - \ref SCIP_STAGE_SOLVING 1556 * - \ref SCIP_STAGE_SOLVED 1557 * - \ref SCIP_STAGE_EXITSOLVE 1558 * - \ref SCIP_STAGE_FREETRANS 1559 */ 1560 SCIP_RETCODE SCIPgetNegatedVars( 1561 SCIP* scip, /**< SCIP data structure */ 1562 int nvars, /**< number of variables to get negated variables for */ 1563 SCIP_VAR** vars, /**< array of variables to get negated variables for */ 1564 SCIP_VAR** negvars /**< array to store the negated variables */ 1565 ) 1566 { 1567 int v; 1568 1569 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetNegatedVars", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1570 1571 for( v = 0; v < nvars; ++v ) 1572 { 1573 SCIP_CALL( SCIPvarNegate(vars[v], scip->mem->probmem, scip->set, scip->stat, &(negvars[v])) ); 1574 } 1575 1576 return SCIP_OKAY; 1577 } 1578 1579 /** gets a binary variable that is equal to the given binary variable, and that is either active, fixed, or 1580 * multi-aggregated, or the negated variable of an active, fixed, or multi-aggregated variable 1581 * 1582 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1583 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1584 * 1585 * @pre This method can be called if @p scip is in one of the following stages: 1586 * - \ref SCIP_STAGE_PROBLEM 1587 * - \ref SCIP_STAGE_TRANSFORMED 1588 * - \ref SCIP_STAGE_INITPRESOLVE 1589 * - \ref SCIP_STAGE_PRESOLVING 1590 * - \ref SCIP_STAGE_EXITPRESOLVE 1591 * - \ref SCIP_STAGE_PRESOLVED 1592 * - \ref SCIP_STAGE_INITSOLVE 1593 * - \ref SCIP_STAGE_SOLVING 1594 * - \ref SCIP_STAGE_SOLVED 1595 * - \ref SCIP_STAGE_EXITSOLVE 1596 */ 1597 SCIP_RETCODE SCIPgetBinvarRepresentative( 1598 SCIP* scip, /**< SCIP data structure */ 1599 SCIP_VAR* var, /**< binary variable to get binary representative for */ 1600 SCIP_VAR** repvar, /**< pointer to store the binary representative */ 1601 SCIP_Bool* negated /**< pointer to store whether the negation of an active variable was returned */ 1602 ) 1603 { 1604 assert(scip != NULL); 1605 assert(var != NULL); 1606 assert(repvar != NULL); 1607 assert(negated != NULL); 1608 assert(var->scip == scip); 1609 1610 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetBinvarRepresentative", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 1611 1612 /* get the active representative of the given variable */ 1613 *repvar = var; 1614 *negated = FALSE; 1615 SCIP_CALL( SCIPvarGetProbvarBinary(repvar, negated) ); 1616 1617 /* negate the representative, if it corresponds to the negation of the given variable */ 1618 if( *negated ) 1619 { 1620 SCIP_CALL( SCIPgetNegatedVar(scip, *repvar, repvar) ); 1621 } 1622 1623 return SCIP_OKAY; 1624 } 1625 1626 /** gets binary variables that are equal to the given binary variables, and which are either active, fixed, or 1627 * multi-aggregated, or the negated variables of active, fixed, or multi-aggregated variables 1628 * 1629 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1630 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1631 * 1632 * @pre This method can be called if @p scip is in one of the following stages: 1633 * - \ref SCIP_STAGE_PROBLEM 1634 * - \ref SCIP_STAGE_TRANSFORMED 1635 * - \ref SCIP_STAGE_INITPRESOLVE 1636 * - \ref SCIP_STAGE_PRESOLVING 1637 * - \ref SCIP_STAGE_EXITPRESOLVE 1638 * - \ref SCIP_STAGE_PRESOLVED 1639 * - \ref SCIP_STAGE_INITSOLVE 1640 * - \ref SCIP_STAGE_SOLVING 1641 * - \ref SCIP_STAGE_SOLVED 1642 * - \ref SCIP_STAGE_EXITSOLVE 1643 */ 1644 SCIP_RETCODE SCIPgetBinvarRepresentatives( 1645 SCIP* scip, /**< SCIP data structure */ 1646 int nvars, /**< number of binary variables to get representatives for */ 1647 SCIP_VAR** vars, /**< binary variables to get binary representatives for */ 1648 SCIP_VAR** repvars, /**< array to store the binary representatives */ 1649 SCIP_Bool* negated /**< array to store whether the negation of an active variable was returned */ 1650 ) 1651 { 1652 int v; 1653 1654 assert(scip != NULL); 1655 assert(vars != NULL || nvars == 0); 1656 assert(repvars != NULL || nvars == 0); 1657 assert(negated != NULL || nvars == 0); 1658 1659 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetBinvarRepresentatives", FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 1660 1661 if( nvars == 0 ) 1662 return SCIP_OKAY; 1663 1664 /* get the active representative of the given variable */ 1665 BMScopyMemoryArray(repvars, vars, nvars); 1666 BMSclearMemoryArray(negated, nvars); 1667 SCIP_CALL( SCIPvarsGetProbvarBinary(&repvars, &negated, nvars) ); 1668 1669 /* negate the representatives, if they correspond to the negation of the given variables */ 1670 for( v = nvars - 1; v >= 0; --v ) 1671 if( negated[v] ) 1672 { 1673 SCIP_CALL( SCIPgetNegatedVar(scip, repvars[v], &(repvars[v])) ); 1674 } 1675 1676 return SCIP_OKAY; 1677 } 1678 1679 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on 1680 * 1681 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1682 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1683 * 1684 * @pre This method can be called if @p scip is in one of the following stages: 1685 * - \ref SCIP_STAGE_INITPRESOLVE 1686 * - \ref SCIP_STAGE_PRESOLVING 1687 * - \ref SCIP_STAGE_EXITPRESOLVE 1688 * - \ref SCIP_STAGE_PRESOLVED 1689 * - \ref SCIP_STAGE_INITSOLVE 1690 * - \ref SCIP_STAGE_SOLVING 1691 * - \ref SCIP_STAGE_SOLVED 1692 */ 1693 SCIP_RETCODE SCIPflattenVarAggregationGraph( 1694 SCIP* scip, /**< SCIP data structure */ 1695 SCIP_VAR* var /**< problem variable */ 1696 ) 1697 { 1698 assert( scip != NULL ); 1699 assert( var != NULL ); 1700 SCIP_CALL( SCIPcheckStage(scip, "SCIPflattenVarAggregationGraph", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 1701 1702 SCIP_CALL( SCIPvarFlattenAggregationGraph(var, scip->mem->probmem, scip->set, scip->eventqueue) ); 1703 1704 return SCIP_OKAY; 1705 } 1706 1707 /** Transforms a given linear sum of variables, that is a_1*x_1 + ... + a_n*x_n + c into a corresponding linear sum of 1708 * active variables, that is b_1*y_1 + ... + b_m*y_m + d. 1709 * 1710 * If the number of needed active variables is greater than the available slots in the variable array, nothing happens 1711 * except that the required size is stored in the corresponding variable (requiredsize). Otherwise, the active variable 1712 * representation is stored in the variable array, scalar array and constant. 1713 * 1714 * The reason for this approach is that we cannot reallocate memory, since we do not know how the memory has been 1715 * allocated (e.g., by a C++ 'new' or SCIP functions). 1716 * 1717 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1718 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1719 * 1720 * @pre This method can be called if @p scip is in one of the following stages: 1721 * - \ref SCIP_STAGE_TRANSFORMED 1722 * - \ref SCIP_STAGE_INITPRESOLVE 1723 * - \ref SCIP_STAGE_PRESOLVING 1724 * - \ref SCIP_STAGE_EXITPRESOLVE 1725 * - \ref SCIP_STAGE_PRESOLVED 1726 * - \ref SCIP_STAGE_INITSOLVE 1727 * - \ref SCIP_STAGE_SOLVING 1728 * - \ref SCIP_STAGE_SOLVED 1729 * - \ref SCIP_STAGE_EXITSOLVE 1730 * - \ref SCIP_STAGE_FREETRANS 1731 * 1732 * @note The resulting linear sum is stored into the given variable array, scalar array, and constant. That means the 1733 * given entries are overwritten. 1734 * 1735 * @note That method can be used to convert a single variables into variable space of active variables. Therefore call 1736 * the method with the linear sum 1.0*x + 0.0. 1737 */ 1738 SCIP_RETCODE SCIPgetProbvarLinearSum( 1739 SCIP* scip, /**< SCIP data structure */ 1740 SCIP_VAR** vars, /**< variable array x_1, ..., x_n in the linear sum which will be 1741 * overwritten by the variable array y_1, ..., y_m in the linear sum 1742 * w.r.t. active variables */ 1743 SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum which will be overwritten to the 1744 * scalars b_1, ..., b_m in the linear sum of the active variables */ 1745 int* nvars, /**< pointer to number of variables in the linear sum which will be 1746 * overwritten by the number of variables in the linear sum corresponding 1747 * to the active variables */ 1748 int varssize, /**< available slots in vars and scalars array which is needed to check if 1749 * the array are large enough for the linear sum w.r.t. active 1750 * variables */ 1751 SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c which 1752 * will chnage to constant d in the linear sum b_1*y_1 + ... + b_m*y_m + 1753 * d w.r.t. the active variables */ 1754 int* requiredsize, /**< pointer to store the required array size for the linear sum w.r.t. the 1755 * active variables */ 1756 SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */ 1757 ) 1758 { 1759 assert( scip != NULL ); 1760 assert( nvars != NULL ); 1761 assert( vars != NULL || *nvars == 0 ); 1762 assert( scalars != NULL || *nvars == 0 ); 1763 assert( constant != NULL ); 1764 assert( requiredsize != NULL ); 1765 assert( *nvars <= varssize ); 1766 1767 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetProbvarLinearSum", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1768 SCIP_CALL( SCIPvarGetActiveRepresentatives(scip->set, vars, scalars, nvars, varssize, constant, requiredsize, mergemultiples) ); 1769 1770 return SCIP_OKAY; 1771 } 1772 1773 /** transforms given variable, scalar and constant to the corresponding active, fixed, or 1774 * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable, 1775 * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation 1776 * with only one active variable (this can happen due to fixings after the multi-aggregation), 1777 * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0 1778 * 1779 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1780 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1781 * 1782 * @pre This method can be called if @p scip is in one of the following stages: 1783 * - \ref SCIP_STAGE_TRANSFORMED 1784 * - \ref SCIP_STAGE_INITPRESOLVE 1785 * - \ref SCIP_STAGE_PRESOLVING 1786 * - \ref SCIP_STAGE_EXITPRESOLVE 1787 * - \ref SCIP_STAGE_PRESOLVED 1788 * - \ref SCIP_STAGE_INITSOLVE 1789 * - \ref SCIP_STAGE_SOLVING 1790 * - \ref SCIP_STAGE_SOLVED 1791 * - \ref SCIP_STAGE_EXITSOLVE 1792 * - \ref SCIP_STAGE_FREETRANS 1793 */ 1794 SCIP_RETCODE SCIPgetProbvarSum( 1795 SCIP* scip, /**< SCIP data structure */ 1796 SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */ 1797 SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */ 1798 SCIP_Real* constant /**< pointer to constant c in sum a*x + c */ 1799 ) 1800 { 1801 assert(scip != NULL); 1802 assert(var != NULL); 1803 assert(scalar != NULL); 1804 assert(constant != NULL); 1805 1806 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetProbvarSum", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1807 SCIP_CALL( SCIPvarGetProbvarSum(var, scip->set, scalar, constant) ); 1808 1809 return SCIP_OKAY; 1810 } 1811 1812 /** return for given variables all their active counterparts; all active variables will be pairwise different 1813 * @note It does not hold that the first output variable is the active variable for the first input variable. 1814 * 1815 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 1816 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 1817 * 1818 * @pre This method can be called if @p scip is in one of the following stages: 1819 * - \ref SCIP_STAGE_TRANSFORMED 1820 * - \ref SCIP_STAGE_INITPRESOLVE 1821 * - \ref SCIP_STAGE_PRESOLVING 1822 * - \ref SCIP_STAGE_EXITPRESOLVE 1823 * - \ref SCIP_STAGE_PRESOLVED 1824 * - \ref SCIP_STAGE_INITSOLVE 1825 * - \ref SCIP_STAGE_SOLVING 1826 * - \ref SCIP_STAGE_SOLVED 1827 * - \ref SCIP_STAGE_EXITSOLVE 1828 * - \ref SCIP_STAGE_FREETRANS 1829 */ 1830 SCIP_RETCODE SCIPgetActiveVars( 1831 SCIP* scip, /**< SCIP data structure */ 1832 SCIP_VAR** vars, /**< variable array with given variables and as output all active 1833 * variables, if enough slots exist 1834 */ 1835 int* nvars, /**< number of given variables, and as output number of active variables, 1836 * if enough slots exist 1837 */ 1838 int varssize, /**< available slots in vars array */ 1839 int* requiredsize /**< pointer to store the required array size for the active variables */ 1840 ) 1841 { 1842 assert(scip != NULL); 1843 assert(nvars != NULL); 1844 assert(vars != NULL || *nvars == 0); 1845 assert(varssize >= *nvars); 1846 assert(requiredsize != NULL); 1847 1848 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetActiveVars", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 1849 SCIP_CALL( SCIPvarsGetActiveVars(scip->set, vars, nvars, varssize, requiredsize) ); 1850 1851 return SCIP_OKAY; 1852 } 1853 1854 /** returns the reduced costs of the variable in the current node's LP relaxation; 1855 * the current node has to have a feasible LP. 1856 * 1857 * returns SCIP_INVALID if the variable is active but not in the current LP; 1858 * returns 0 if the variable has been aggregated out or fixed in presolving. 1859 * 1860 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING 1861 * 1862 * @note The return value of this method should be used carefully if the dual feasibility check was explictely disabled. 1863 */ 1864 SCIP_Real SCIPgetVarRedcost( 1865 SCIP* scip, /**< SCIP data structure */ 1866 SCIP_VAR* var /**< variable to get reduced costs, should be a column in current node LP */ 1867 ) 1868 { 1869 assert( scip != NULL ); 1870 assert( var != NULL ); 1871 assert( var->scip == scip ); 1872 1873 switch( SCIPvarGetStatus(var) ) 1874 { 1875 case SCIP_VARSTATUS_ORIGINAL: 1876 if( var->data.original.transvar == NULL ) 1877 return SCIP_INVALID; 1878 return SCIPgetVarRedcost(scip, var->data.original.transvar); 1879 1880 case SCIP_VARSTATUS_COLUMN: 1881 return SCIPgetColRedcost(scip, SCIPvarGetCol(var)); 1882 1883 case SCIP_VARSTATUS_LOOSE: 1884 return SCIP_INVALID; 1885 1886 case SCIP_VARSTATUS_FIXED: 1887 case SCIP_VARSTATUS_AGGREGATED: 1888 case SCIP_VARSTATUS_MULTAGGR: 1889 case SCIP_VARSTATUS_NEGATED: 1890 return 0.0; 1891 1892 default: 1893 SCIPerrorMessage("unknown variable status\n"); 1894 SCIPABORT(); 1895 return 0.0; /*lint !e527*/ 1896 } 1897 } 1898 1899 /** returns the implied reduced costs of the variable in the current node's LP relaxation; 1900 * the current node has to have a feasible LP. 1901 * 1902 * returns SCIP_INVALID if the variable is active but not in the current LP; 1903 * returns 0 if the variable has been aggregated out or fixed in presolving. 1904 * 1905 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING 1906 * 1907 * @note The return value of this method should be used carefully if the dual feasibility check was explictely disabled. 1908 */ 1909 SCIP_Real SCIPgetVarImplRedcost( 1910 SCIP* scip, /**< SCIP data structure */ 1911 SCIP_VAR* var, /**< variable to get reduced costs, should be a column in current node LP */ 1912 SCIP_Bool varfixing /**< FALSE if for x == 0, TRUE for x == 1 */ 1913 ) 1914 { 1915 assert( scip != NULL ); 1916 assert( var != NULL ); 1917 assert( var->scip == scip ); 1918 1919 switch( SCIPvarGetStatus(var) ) 1920 { 1921 case SCIP_VARSTATUS_ORIGINAL: 1922 if( var->data.original.transvar == NULL ) 1923 return SCIP_INVALID; 1924 return SCIPgetVarImplRedcost(scip, var->data.original.transvar, varfixing); 1925 1926 case SCIP_VARSTATUS_COLUMN: 1927 return SCIPvarGetImplRedcost(var, scip->set, varfixing, scip->stat, scip->transprob, scip->lp); 1928 1929 case SCIP_VARSTATUS_LOOSE: 1930 return SCIP_INVALID; 1931 1932 case SCIP_VARSTATUS_FIXED: 1933 case SCIP_VARSTATUS_AGGREGATED: 1934 case SCIP_VARSTATUS_MULTAGGR: 1935 case SCIP_VARSTATUS_NEGATED: 1936 return 0.0; 1937 1938 default: 1939 SCIPerrorMessage("unknown variable status\n"); 1940 SCIPABORT(); 1941 return 0.0; /*lint !e527*/ 1942 } 1943 } 1944 1945 1946 /** returns the Farkas coefficient of the variable in the current node's LP relaxation; 1947 * the current node has to have an infeasible LP. 1948 * 1949 * returns SCIP_INVALID if the variable is active but not in the current LP; 1950 * returns 0 if the variable has been aggregated out or fixed in presolving. 1951 * 1952 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING 1953 */ 1954 SCIP_Real SCIPgetVarFarkasCoef( 1955 SCIP* scip, /**< SCIP data structure */ 1956 SCIP_VAR* var /**< variable to get reduced costs, should be a column in current node LP */ 1957 ) 1958 { 1959 assert(scip != NULL); 1960 assert(var != NULL); 1961 assert(var->scip == scip); 1962 1963 switch( SCIPvarGetStatus(var) ) 1964 { 1965 case SCIP_VARSTATUS_ORIGINAL: 1966 if( var->data.original.transvar == NULL ) 1967 return SCIP_INVALID; 1968 return SCIPgetVarFarkasCoef(scip,var->data.original.transvar); 1969 1970 case SCIP_VARSTATUS_COLUMN: 1971 return SCIPgetColFarkasCoef(scip,SCIPvarGetCol(var)); 1972 1973 case SCIP_VARSTATUS_LOOSE: 1974 return SCIP_INVALID; 1975 1976 case SCIP_VARSTATUS_FIXED: 1977 case SCIP_VARSTATUS_AGGREGATED: 1978 case SCIP_VARSTATUS_MULTAGGR: 1979 case SCIP_VARSTATUS_NEGATED: 1980 return 0.0; 1981 1982 default: 1983 SCIPerrorMessage("unknown variable status\n"); 1984 SCIPABORT(); 1985 return 0.0; /*lint !e527*/ 1986 } 1987 } 1988 1989 /** returns lower bound of variable directly before or after the bound change given by the bound change index 1990 * was applied 1991 */ 1992 SCIP_Real SCIPgetVarLbAtIndex( 1993 SCIP* scip, /**< SCIP data structure */ 1994 SCIP_VAR* var, /**< problem variable */ 1995 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */ 1996 SCIP_Bool after /**< should the bound change with given index be included? */ 1997 ) 1998 { 1999 SCIP_VARSTATUS varstatus; 2000 SCIP_BDCHGINFO* bdchginfo; 2001 assert(var != NULL); 2002 2003 varstatus = SCIPvarGetStatus(var); 2004 2005 /* get bounds of attached variables */ 2006 switch( varstatus ) 2007 { 2008 case SCIP_VARSTATUS_ORIGINAL: 2009 assert(var->data.original.transvar != NULL); 2010 return SCIPgetVarLbAtIndex(scip, var->data.original.transvar, bdchgidx, after); 2011 2012 case SCIP_VARSTATUS_COLUMN: 2013 case SCIP_VARSTATUS_LOOSE: 2014 if( bdchgidx == NULL ) 2015 return SCIPvarGetLbLocal(var); 2016 else 2017 { 2018 bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after); 2019 if( bdchginfo != NULL ) 2020 return SCIPbdchginfoGetNewbound(bdchginfo); 2021 else 2022 return var->glbdom.lb; 2023 } 2024 2025 case SCIP_VARSTATUS_FIXED: 2026 return var->glbdom.lb; 2027 2028 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */ 2029 assert(var->data.aggregate.var != NULL); 2030 if( var->data.aggregate.scalar > 0.0 ) 2031 { 2032 SCIP_Real lb; 2033 2034 lb = SCIPgetVarLbAtIndex(scip, var->data.aggregate.var, bdchgidx, after); 2035 2036 /* a > 0 -> get lower bound of y */ 2037 if( SCIPisInfinity(scip, -lb) ) 2038 return -SCIPinfinity(scip); 2039 else if( SCIPisInfinity(scip, lb) ) 2040 return SCIPinfinity(scip); 2041 else 2042 return var->data.aggregate.scalar * lb + var->data.aggregate.constant; 2043 } 2044 else if( var->data.aggregate.scalar < 0.0 ) 2045 { 2046 SCIP_Real ub; 2047 2048 ub = SCIPgetVarUbAtIndex(scip, var->data.aggregate.var, bdchgidx, after); 2049 2050 /* a < 0 -> get upper bound of y */ 2051 if( SCIPisInfinity(scip, -ub) ) 2052 return SCIPinfinity(scip); 2053 else if( SCIPisInfinity(scip, ub) ) 2054 return -SCIPinfinity(scip); 2055 else 2056 return var->data.aggregate.scalar * ub + var->data.aggregate.constant; 2057 } 2058 else 2059 { 2060 SCIPerrorMessage("scalar is zero in aggregation\n"); 2061 SCIPABORT(); 2062 return SCIP_INVALID; /*lint !e527*/ 2063 } 2064 2065 case SCIP_VARSTATUS_MULTAGGR: 2066 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */ 2067 if ( var->data.multaggr.nvars == 1 ) 2068 { 2069 assert(var->data.multaggr.vars != NULL); 2070 assert(var->data.multaggr.scalars != NULL); 2071 assert(var->data.multaggr.vars[0] != NULL); 2072 2073 if( var->data.multaggr.scalars[0] > 0.0 ) 2074 { 2075 SCIP_Real lb; 2076 2077 lb = SCIPgetVarLbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after); 2078 2079 /* a > 0 -> get lower bound of y */ 2080 if( SCIPisInfinity(scip, -lb) ) 2081 return -SCIPinfinity(scip); 2082 else if( SCIPisInfinity(scip, lb) ) 2083 return SCIPinfinity(scip); 2084 else 2085 return var->data.multaggr.scalars[0] * lb + var->data.multaggr.constant; 2086 } 2087 else if( var->data.multaggr.scalars[0] < 0.0 ) 2088 { 2089 SCIP_Real ub; 2090 2091 ub = SCIPgetVarUbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after); 2092 2093 /* a < 0 -> get upper bound of y */ 2094 if( SCIPisInfinity(scip, -ub) ) 2095 return SCIPinfinity(scip); 2096 else if( SCIPisInfinity(scip, ub) ) 2097 return -SCIPinfinity(scip); 2098 else 2099 return var->data.multaggr.scalars[0] * ub + var->data.multaggr.constant; 2100 } 2101 else 2102 { 2103 SCIPerrorMessage("scalar is zero in multi-aggregation\n"); 2104 SCIPABORT(); 2105 return SCIP_INVALID; /*lint !e527*/ 2106 } 2107 } 2108 SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n"); 2109 SCIPABORT(); 2110 return SCIP_INVALID; /*lint !e527*/ 2111 2112 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */ 2113 assert(var->negatedvar != NULL); 2114 assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED); 2115 assert(var->negatedvar->negatedvar == var); 2116 return var->data.negate.constant - SCIPgetVarUbAtIndex(scip, var->negatedvar, bdchgidx, after); 2117 2118 default: 2119 SCIPerrorMessage("unknown variable status\n"); 2120 SCIPABORT(); 2121 return SCIP_INVALID; /*lint !e527*/ 2122 } 2123 } 2124 2125 /** returns upper bound of variable directly before or after the bound change given by the bound change index 2126 * was applied 2127 */ 2128 SCIP_Real SCIPgetVarUbAtIndex( 2129 SCIP* scip, /**< SCIP data structure */ 2130 SCIP_VAR* var, /**< problem variable */ 2131 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */ 2132 SCIP_Bool after /**< should the bound change with given index be included? */ 2133 ) 2134 { 2135 SCIP_VARSTATUS varstatus; 2136 SCIP_BDCHGINFO* bdchginfo; 2137 assert(var != NULL); 2138 2139 varstatus = SCIPvarGetStatus(var); 2140 2141 /* get bounds of attached variables */ 2142 switch( varstatus ) 2143 { 2144 case SCIP_VARSTATUS_ORIGINAL: 2145 assert(var->data.original.transvar != NULL); 2146 return SCIPgetVarUbAtIndex(scip, var->data.original.transvar, bdchgidx, after); 2147 2148 case SCIP_VARSTATUS_COLUMN: 2149 case SCIP_VARSTATUS_LOOSE: 2150 if( bdchgidx == NULL ) 2151 return SCIPvarGetUbLocal(var); 2152 else 2153 { 2154 bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after); 2155 if( bdchginfo != NULL ) 2156 return SCIPbdchginfoGetNewbound(bdchginfo); 2157 else 2158 return var->glbdom.ub; 2159 } 2160 2161 case SCIP_VARSTATUS_FIXED: 2162 return var->glbdom.ub; 2163 2164 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */ 2165 assert(var->data.aggregate.var != NULL); 2166 if( var->data.aggregate.scalar > 0.0 ) 2167 { 2168 SCIP_Real ub; 2169 2170 ub = SCIPgetVarUbAtIndex(scip, var->data.aggregate.var, bdchgidx, after); 2171 2172 /* a > 0 -> get lower bound of y */ 2173 if( SCIPisInfinity(scip, -ub) ) 2174 return -SCIPinfinity(scip); 2175 else if( SCIPisInfinity(scip, ub) ) 2176 return SCIPinfinity(scip); 2177 else 2178 return var->data.aggregate.scalar * ub + var->data.aggregate.constant; 2179 } 2180 else if( var->data.aggregate.scalar < 0.0 ) 2181 { 2182 SCIP_Real lb; 2183 2184 lb = SCIPgetVarLbAtIndex(scip, var->data.aggregate.var, bdchgidx, after); 2185 2186 /* a < 0 -> get upper bound of y */ 2187 if ( SCIPisInfinity(scip, -lb) ) 2188 return SCIPinfinity(scip); 2189 else if ( SCIPisInfinity(scip, lb) ) 2190 return -SCIPinfinity(scip); 2191 else 2192 return var->data.aggregate.scalar * lb + var->data.aggregate.constant; 2193 } 2194 else 2195 { 2196 SCIPerrorMessage("scalar is zero in aggregation\n"); 2197 SCIPABORT(); 2198 return SCIP_INVALID; /*lint !e527*/ 2199 } 2200 2201 case SCIP_VARSTATUS_MULTAGGR: 2202 /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */ 2203 if ( var->data.multaggr.nvars == 1 ) 2204 { 2205 assert(var->data.multaggr.vars != NULL); 2206 assert(var->data.multaggr.scalars != NULL); 2207 assert(var->data.multaggr.vars[0] != NULL); 2208 2209 if( var->data.multaggr.scalars[0] > 0.0 ) 2210 { 2211 SCIP_Real ub; 2212 2213 ub = SCIPgetVarUbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after); 2214 2215 /* a > 0 -> get lower bound of y */ 2216 if ( SCIPisInfinity(scip, -ub) ) 2217 return -SCIPinfinity(scip); 2218 else if ( SCIPisInfinity(scip, ub) ) 2219 return SCIPinfinity(scip); 2220 else 2221 return var->data.multaggr.scalars[0] * ub + var->data.multaggr.constant; 2222 } 2223 else if( var->data.multaggr.scalars[0] < 0.0 ) 2224 { 2225 SCIP_Real lb; 2226 2227 lb = SCIPgetVarLbAtIndex(scip, var->data.multaggr.vars[0], bdchgidx, after); 2228 2229 /* a < 0 -> get upper bound of y */ 2230 if ( SCIPisInfinity(scip, -lb) ) 2231 return SCIPinfinity(scip); 2232 else if ( SCIPisInfinity(scip, lb) ) 2233 return -SCIPinfinity(scip); 2234 else 2235 return var->data.multaggr.scalars[0] * lb + var->data.multaggr.constant; 2236 } 2237 else 2238 { 2239 SCIPerrorMessage("scalar is zero in multi-aggregation\n"); 2240 SCIPABORT(); 2241 return SCIP_INVALID; /*lint !e527*/ 2242 } 2243 } 2244 SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n"); 2245 SCIPABORT(); 2246 return SCIP_INVALID; /*lint !e527*/ 2247 2248 case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */ 2249 assert(var->negatedvar != NULL); 2250 assert(SCIPvarGetStatus(var->negatedvar) != SCIP_VARSTATUS_NEGATED); 2251 assert(var->negatedvar->negatedvar == var); 2252 return var->data.negate.constant - SCIPgetVarLbAtIndex(scip, var->negatedvar, bdchgidx, after); 2253 2254 default: 2255 SCIPerrorMessage("unknown variable status\n"); 2256 SCIPABORT(); 2257 return SCIP_INVALID; /*lint !e527*/ 2258 } 2259 } 2260 2261 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index 2262 * was applied 2263 */ 2264 SCIP_Real SCIPgetVarBdAtIndex( 2265 SCIP* scip, /**< SCIP data structure */ 2266 SCIP_VAR* var, /**< problem variable */ 2267 SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */ 2268 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */ 2269 SCIP_Bool after /**< should the bound change with given index be included? */ 2270 ) 2271 { 2272 if( boundtype == SCIP_BOUNDTYPE_LOWER ) 2273 return SCIPgetVarLbAtIndex(scip, var, bdchgidx, after); 2274 else 2275 { 2276 assert(boundtype == SCIP_BOUNDTYPE_UPPER); 2277 return SCIPgetVarUbAtIndex(scip, var, bdchgidx, after); 2278 } 2279 } 2280 2281 /** returns whether the binary variable was fixed at the time given by the bound change index */ 2282 SCIP_Bool SCIPgetVarWasFixedAtIndex( 2283 SCIP* scip, /**< SCIP data structure */ 2284 SCIP_VAR* var, /**< problem variable */ 2285 SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */ 2286 SCIP_Bool after /**< should the bound change with given index be included? */ 2287 ) 2288 { 2289 assert(var != NULL); 2290 assert(SCIPvarIsBinary(var)); 2291 2292 /* check the current bounds first in order to decide at which bound change information we have to look 2293 * (which is expensive because we have to follow the aggregation tree to the active variable) 2294 */ 2295 return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPgetVarLbAtIndex(scip, var, bdchgidx, after) > 0.5) 2296 || (SCIPvarGetUbLocal(var) < 0.5 && SCIPgetVarUbAtIndex(scip, var, bdchgidx, after) < 0.5)); 2297 } 2298 2299 /** gets solution value for variable in current node 2300 * 2301 * @return solution value for variable in current node 2302 * 2303 * @pre This method can be called if @p scip is in one of the following stages: 2304 * - \ref SCIP_STAGE_PRESOLVED 2305 * - \ref SCIP_STAGE_SOLVING 2306 */ 2307 SCIP_Real SCIPgetVarSol( 2308 SCIP* scip, /**< SCIP data structure */ 2309 SCIP_VAR* var /**< variable to get solution value for */ 2310 ) 2311 { 2312 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2313 assert( var->scip == scip ); 2314 2315 return SCIPvarGetSol(var, SCIPtreeHasCurrentNodeLP(scip->tree)); 2316 } 2317 2318 /** gets solution values of multiple variables in current node 2319 * 2320 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2321 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2322 * 2323 * @pre This method can be called if @p scip is in one of the following stages: 2324 * - \ref SCIP_STAGE_PRESOLVED 2325 * - \ref SCIP_STAGE_SOLVING 2326 */ 2327 SCIP_RETCODE SCIPgetVarSols( 2328 SCIP* scip, /**< SCIP data structure */ 2329 int nvars, /**< number of variables to get solution value for */ 2330 SCIP_VAR** vars, /**< array with variables to get value for */ 2331 SCIP_Real* vals /**< array to store solution values of variables */ 2332 ) 2333 { 2334 int v; 2335 2336 assert(nvars == 0 || vars != NULL); 2337 assert(nvars == 0 || vals != NULL); 2338 2339 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarSols", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2340 2341 if( SCIPtreeHasCurrentNodeLP(scip->tree) ) 2342 { 2343 for( v = 0; v < nvars; ++v ) 2344 vals[v] = SCIPvarGetLPSol(vars[v]); 2345 } 2346 else 2347 { 2348 for( v = 0; v < nvars; ++v ) 2349 vals[v] = SCIPvarGetPseudoSol(vars[v]); 2350 } 2351 2352 return SCIP_OKAY; 2353 } 2354 2355 /** sets the solution value of all variables in the global relaxation solution to zero 2356 * 2357 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2358 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2359 * 2360 * @pre This method can be called if @p scip is in one of the following stages: 2361 * - \ref SCIP_STAGE_PRESOLVED 2362 * - \ref SCIP_STAGE_SOLVING 2363 */ 2364 SCIP_RETCODE SCIPclearRelaxSolVals( 2365 SCIP* scip, /**< SCIP data structure */ 2366 SCIP_RELAX* relax /**< relaxator data structure */ 2367 ) 2368 { 2369 SCIP_VAR** vars; 2370 int nvars; 2371 int v; 2372 2373 assert(scip != NULL); 2374 2375 SCIP_CALL( SCIPcheckStage(scip, "SCIPclearRelaxSolVals", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2376 2377 /* update the responsible relax pointer */ 2378 SCIPrelaxationSetSolRelax(scip->relaxation, relax); 2379 2380 /* the relaxation solution is already cleared */ 2381 if( SCIPrelaxationIsSolZero(scip->relaxation) ) 2382 return SCIP_OKAY; 2383 2384 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) ); 2385 2386 for( v = 0; v < nvars; v++ ) 2387 { 2388 SCIP_CALL( SCIPvarSetRelaxSol(vars[v], scip->set, scip->relaxation, 0.0, FALSE) ); 2389 } 2390 2391 SCIPrelaxationSetSolObj(scip->relaxation, 0.0); 2392 SCIPrelaxationSetSolZero(scip->relaxation, TRUE); 2393 2394 return SCIP_OKAY; 2395 } 2396 2397 /** sets the value of the given variable in the global relaxation solution; 2398 * this solution can be filled by the relaxation handlers and can be used by heuristics and for separation; 2399 * You can use SCIPclearRelaxSolVals() to set all values to zero, initially; 2400 * after setting all solution values, you have to call SCIPmarkRelaxSolValid() 2401 * to inform SCIP that the stored solution is valid 2402 * 2403 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2404 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2405 * 2406 * @pre This method can be called if @p scip is in one of the following stages: 2407 * - \ref SCIP_STAGE_PRESOLVED 2408 * - \ref SCIP_STAGE_SOLVING 2409 * 2410 * @note This method incrementally updates the objective value of the relaxation solution. If the whole solution 2411 * should be updated, using SCIPsetRelaxSolVals() instead or calling SCIPclearRelaxSolVals() before setting 2412 * the first value to reset the solution and the objective value to 0 may help the numerics. 2413 */ 2414 SCIP_RETCODE SCIPsetRelaxSolVal( 2415 SCIP* scip, /**< SCIP data structure */ 2416 SCIP_RELAX* relax, /**< relaxator data structure */ 2417 SCIP_VAR* var, /**< variable to set value for */ 2418 SCIP_Real val /**< solution value of variable */ 2419 ) 2420 { 2421 assert(scip != NULL); 2422 2423 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxSolVal", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2424 2425 SCIP_CALL( SCIPvarSetRelaxSol(var, scip->set, scip->relaxation, val, TRUE) ); 2426 2427 if( val != 0.0 ) 2428 SCIPrelaxationSetSolZero(scip->relaxation, FALSE); 2429 SCIPrelaxationSetSolValid(scip->relaxation, FALSE, FALSE); 2430 SCIPrelaxationSetSolRelax(scip->relaxation, relax); 2431 2432 return SCIP_OKAY; 2433 } 2434 2435 /** sets the values of the given variables in the global relaxation solution and informs SCIP about the validity 2436 * and whether the solution can be enforced via linear cuts; 2437 * this solution can be filled by the relaxation handlers and can be used by heuristics and for separation; 2438 * the solution is automatically cleared, s.t. all other variables get value 0.0 2439 * 2440 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2441 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2442 * 2443 * @pre This method can be called if @p scip is in one of the following stages: 2444 * - \ref SCIP_STAGE_PRESOLVED 2445 * - \ref SCIP_STAGE_SOLVING 2446 */ 2447 SCIP_RETCODE SCIPsetRelaxSolVals( 2448 SCIP* scip, /**< SCIP data structure */ 2449 SCIP_RELAX* relax, /**< relaxator data structure */ 2450 int nvars, /**< number of variables to set relaxation solution value for */ 2451 SCIP_VAR** vars, /**< array with variables to set value for */ 2452 SCIP_Real* vals, /**< array with solution values of variables */ 2453 SCIP_Bool includeslp /**< does the relaxator contain all cuts in the LP? */ 2454 ) 2455 { 2456 int v; 2457 2458 assert(scip != NULL); 2459 assert(nvars == 0 || vars != NULL); 2460 assert(nvars == 0 || vals != NULL); 2461 2462 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxSolVals", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2463 2464 SCIP_CALL( SCIPclearRelaxSolVals(scip, relax) ); 2465 2466 for( v = 0; v < nvars; v++ ) 2467 { 2468 SCIP_CALL( SCIPvarSetRelaxSol(vars[v], scip->set, scip->relaxation, vals[v], TRUE) ); 2469 } 2470 2471 SCIPrelaxationSetSolZero(scip->relaxation, FALSE); 2472 SCIPrelaxationSetSolValid(scip->relaxation, TRUE, includeslp); 2473 SCIPrelaxationSetSolRelax(scip->relaxation, relax); 2474 2475 return SCIP_OKAY; 2476 } 2477 2478 /** sets the values of the variables in the global relaxation solution to the values in the given primal solution 2479 * and informs SCIP about the validity and whether the solution can be enforced via linear cuts; 2480 * the relaxation solution can be filled by the relaxation handlers and might be used by heuristics and for separation 2481 * 2482 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2483 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2484 * 2485 * @pre This method can be called if @p scip is in one of the following stages: 2486 * - \ref SCIP_STAGE_PRESOLVED 2487 * - \ref SCIP_STAGE_SOLVING 2488 */ 2489 SCIP_RETCODE SCIPsetRelaxSolValsSol( 2490 SCIP* scip, /**< SCIP data structure */ 2491 SCIP_RELAX* relax, /**< relaxator data structure */ 2492 SCIP_SOL* sol, /**< primal relaxation solution */ 2493 SCIP_Bool includeslp /**< does the relaxator contain all cuts in the LP? */ 2494 ) 2495 { 2496 SCIP_VAR** vars; 2497 SCIP_Real* vals; 2498 int nvars; 2499 int v; 2500 2501 assert(scip != NULL); 2502 2503 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxSolValsSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2504 2505 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) ); 2506 2507 /* alloc buffer array for solution values of the variables and get the values */ 2508 SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) ); 2509 SCIP_CALL( SCIPgetSolVals(scip, sol, nvars, vars, vals) ); 2510 2511 SCIP_CALL( SCIPclearRelaxSolVals(scip, relax) ); 2512 2513 for( v = 0; v < nvars; v++ ) 2514 { 2515 SCIP_CALL( SCIPvarSetRelaxSol(vars[v], scip->set, scip->relaxation, vals[v], FALSE) ); 2516 } 2517 2518 SCIPrelaxationSetSolObj(scip->relaxation, SCIPsolGetObj(sol, scip->set, scip->transprob, scip->origprob)); 2519 2520 SCIPrelaxationSetSolZero(scip->relaxation, FALSE); 2521 SCIPrelaxationSetSolValid(scip->relaxation, TRUE, includeslp); 2522 SCIPrelaxationSetSolRelax(scip->relaxation, relax); 2523 2524 SCIPfreeBufferArray(scip, &vals); 2525 2526 return SCIP_OKAY; 2527 } 2528 2529 /** returns whether the relaxation solution is valid 2530 * 2531 * @return TRUE, if the relaxation solution is valid; FALSE, otherwise 2532 * 2533 * @pre This method can be called if @p scip is in one of the following stages: 2534 * - \ref SCIP_STAGE_PRESOLVED 2535 * - \ref SCIP_STAGE_SOLVING 2536 */ 2537 SCIP_Bool SCIPisRelaxSolValid( 2538 SCIP* scip /**< SCIP data structure */ 2539 ) 2540 { 2541 assert(scip != NULL); 2542 2543 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisRelaxSolValid", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2544 2545 return SCIPrelaxationIsSolValid(scip->relaxation); 2546 } 2547 2548 /** informs SCIP that the relaxation solution is valid and whether the relaxation can be enforced through linear cuts 2549 * 2550 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2551 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2552 * 2553 * @pre This method can be called if @p scip is in one of the following stages: 2554 * - \ref SCIP_STAGE_PRESOLVED 2555 * - \ref SCIP_STAGE_SOLVING 2556 */ 2557 SCIP_RETCODE SCIPmarkRelaxSolValid( 2558 SCIP* scip, /**< SCIP data structure */ 2559 SCIP_RELAX* relax, /**< relaxator data structure that set the current relaxation solution */ 2560 SCIP_Bool includeslp /**< does the relaxator contain all cuts in the LP? */ 2561 ) 2562 { 2563 assert(scip != NULL); 2564 2565 SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkRelaxSolValid", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2566 2567 SCIPrelaxationSetSolValid(scip->relaxation, TRUE, includeslp); 2568 SCIPrelaxationSetSolRelax(scip->relaxation, relax); 2569 2570 return SCIP_OKAY; 2571 } 2572 2573 /** informs SCIP, that the relaxation solution is invalid 2574 * 2575 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2576 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2577 * 2578 * @pre This method can be called if @p scip is in one of the following stages: 2579 * - \ref SCIP_STAGE_PRESOLVED 2580 * - \ref SCIP_STAGE_SOLVING 2581 */ 2582 SCIP_RETCODE SCIPmarkRelaxSolInvalid( 2583 SCIP* scip /**< SCIP data structure */ 2584 ) 2585 { 2586 assert(scip != NULL); 2587 2588 SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkRelaxSolInvalid", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2589 2590 SCIPrelaxationSetSolValid(scip->relaxation, FALSE, FALSE); 2591 2592 return SCIP_OKAY; 2593 } 2594 2595 /** gets the relaxation solution value of the given variable 2596 * 2597 * @return the relaxation solution value of the given variable 2598 * 2599 * @pre This method can be called if @p scip is in one of the following stages: 2600 * - \ref SCIP_STAGE_PRESOLVED 2601 * - \ref SCIP_STAGE_SOLVING 2602 */ 2603 SCIP_Real SCIPgetRelaxSolVal( 2604 SCIP* scip, /**< SCIP data structure */ 2605 SCIP_VAR* var /**< variable to get value for */ 2606 ) 2607 { 2608 assert(scip != NULL); 2609 assert(var != NULL); 2610 assert(var->scip == scip); 2611 2612 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetRelaxSolVal", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2613 2614 if( !SCIPrelaxationIsSolValid(scip->relaxation) ) 2615 { 2616 SCIPerrorMessage("Relaxation Solution is not valid!\n"); 2617 SCIPABORT(); 2618 return SCIP_INVALID; /*lint !e527*/ 2619 } 2620 2621 return SCIPvarGetRelaxSol(var, scip->set); 2622 } 2623 2624 /** gets the relaxation solution objective value 2625 * 2626 * @return the objective value of the relaxation solution 2627 * 2628 * @pre This method can be called if @p scip is in one of the following stages: 2629 * - \ref SCIP_STAGE_PRESOLVED 2630 * - \ref SCIP_STAGE_SOLVING 2631 */ 2632 SCIP_Real SCIPgetRelaxSolObj( 2633 SCIP* scip /**< SCIP data structure */ 2634 ) 2635 { 2636 assert(scip != NULL); 2637 2638 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetRelaxSolObj", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2639 2640 if( !SCIPrelaxationIsSolValid(scip->relaxation) ) 2641 { 2642 SCIPerrorMessage("Relaxation Solution is not valid!\n"); 2643 SCIPABORT(); 2644 return SCIP_INVALID; /*lint !e527*/ 2645 } 2646 2647 return SCIPrelaxationGetSolObj(scip->relaxation); 2648 } 2649 2650 /** determine which branching direction should be evaluated first by strong branching 2651 * 2652 * @return TRUE iff strong branching should first evaluate the down child 2653 * 2654 */ 2655 SCIP_Bool SCIPisStrongbranchDownFirst( 2656 SCIP* scip, /**< SCIP data structure */ 2657 SCIP_VAR* var /**< variable to determine the branching direction on */ 2658 ) 2659 { 2660 switch( scip->set->branch_firstsbchild ) 2661 { 2662 case 'u': 2663 return FALSE; 2664 case 'd': 2665 return TRUE; 2666 case 'a': 2667 return (SCIPvarGetNLocksDown(var) > SCIPvarGetNLocksUp(var)); 2668 default: 2669 assert(scip->set->branch_firstsbchild == 'h'); 2670 return (SCIPgetVarAvgCutoffs(scip, var, SCIP_BRANCHDIR_DOWNWARDS) > SCIPgetVarAvgCutoffs(scip, var, SCIP_BRANCHDIR_UPWARDS)); 2671 } 2672 } 2673 2674 /** start strong branching - call before any strong branching 2675 * 2676 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2677 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2678 * 2679 * @pre This method can be called if @p scip is in one of the following stages: 2680 * - \ref SCIP_STAGE_PRESOLVED 2681 * - \ref SCIP_STAGE_SOLVING 2682 * 2683 * @note if propagation is enabled, strong branching is not done directly on the LP, but probing nodes are created 2684 * which allow to perform propagation but also creates some overhead 2685 */ 2686 SCIP_RETCODE SCIPstartStrongbranch( 2687 SCIP* scip, /**< SCIP data structure */ 2688 SCIP_Bool enablepropagation /**< should propagation be done before solving the strong branching LP? */ 2689 ) 2690 { 2691 assert( scip != NULL ); 2692 SCIP_CALL( SCIPcheckStage(scip, "SCIPstartStrongbranch", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2693 2694 assert(!SCIPinProbing(scip)); 2695 2696 SCIPdebugMsg(scip, "starting strong branching mode%s: lpcount=%" SCIP_LONGINT_FORMAT "\n", enablepropagation ? " with propagation" : "", scip->stat->lpcount - scip->stat->nsbdivinglps); 2697 2698 /* start probing mode to allow propagation before solving the strong branching LPs; if no propagation should be done, 2699 * start the strong branching mode in the LP interface 2700 */ 2701 if( enablepropagation ) 2702 { 2703 if( SCIPtreeProbing(scip->tree) ) 2704 { 2705 SCIPerrorMessage("cannot start strong branching with propagation while in probing mode\n"); 2706 return SCIP_INVALIDCALL; 2707 } 2708 2709 if( scip->lp != NULL && SCIPlpDiving(scip->lp) ) 2710 { 2711 SCIPerrorMessage("cannot start strong branching with propagation while in diving mode\n"); 2712 return SCIP_INVALIDCALL; 2713 } 2714 2715 /* other then in SCIPstartProbing(), we do not disable collecting variable statistics during strong branching; 2716 * we cannot disable it, because the pseudo costs would not be updated, otherwise, 2717 * and reliability branching would end up doing strong branching all the time 2718 */ 2719 SCIP_CALL( SCIPtreeStartProbing(scip->tree, scip->mem->probmem, scip->set, scip->lp, scip->relaxation, scip->transprob, TRUE) ); 2720 2721 /* inform the LP that the current probing mode is used for strong branching */ 2722 SCIPlpStartStrongbranchProbing(scip->lp); 2723 } 2724 else 2725 { 2726 SCIP_CALL( SCIPlpStartStrongbranch(scip->lp) ); 2727 } 2728 2729 /* reset local strong branching info */ 2730 scip->stat->lastsblpsolstats[0] = scip->stat->lastsblpsolstats[1] = SCIP_LPSOLSTAT_NOTSOLVED; 2731 2732 return SCIP_OKAY; 2733 } 2734 2735 /** end strong branching - call after any strong branching 2736 * 2737 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2738 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2739 * 2740 * @pre This method can be called if @p scip is in one of the following stages: 2741 * - \ref SCIP_STAGE_PRESOLVED 2742 * - \ref SCIP_STAGE_SOLVING 2743 */ 2744 SCIP_RETCODE SCIPendStrongbranch( 2745 SCIP* scip /**< SCIP data structure */ 2746 ) 2747 { 2748 assert( scip != NULL ); 2749 2750 SCIP_CALL( SCIPcheckStage(scip, "SCIPendStrongbranch", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2751 2752 /* depending on whether the strong branching mode was started with propagation enabled or not, we end the strong 2753 * branching probing mode or the LP strong branching mode 2754 */ 2755 if( SCIPtreeProbing(scip->tree) ) 2756 { 2757 SCIP_NODE* node; 2758 SCIP_DOMCHG* domchg; 2759 SCIP_VAR** boundchgvars; 2760 SCIP_Real* bounds; 2761 SCIP_BOUNDTYPE* boundtypes; 2762 int nboundchgs; 2763 int nbnds; 2764 int i; 2765 2766 /* collect all bound changes deducted during probing, which were applied at the probing root and apply them to the 2767 * focusnode 2768 */ 2769 node = SCIPgetCurrentNode(scip); 2770 assert(SCIPnodeGetType(node) == SCIP_NODETYPE_PROBINGNODE); 2771 assert(SCIPgetProbingDepth(scip) == 0); 2772 2773 domchg = SCIPnodeGetDomchg(node); 2774 nboundchgs = SCIPdomchgGetNBoundchgs(domchg); 2775 2776 SCIP_CALL( SCIPallocBufferArray(scip, &boundchgvars, nboundchgs) ); 2777 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nboundchgs) ); 2778 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nboundchgs) ); 2779 2780 for( i = 0, nbnds = 0; i < nboundchgs; ++i ) 2781 { 2782 SCIP_BOUNDCHG* boundchg; 2783 2784 boundchg = SCIPdomchgGetBoundchg(domchg, i); 2785 2786 /* ignore redundant bound changes */ 2787 if( SCIPboundchgIsRedundant(boundchg) ) 2788 continue; 2789 2790 boundchgvars[nbnds] = SCIPboundchgGetVar(boundchg); 2791 bounds[nbnds] = SCIPboundchgGetNewbound(boundchg); 2792 boundtypes[nbnds] = SCIPboundchgGetBoundtype(boundchg); 2793 ++nbnds; 2794 } 2795 2796 SCIPdebugMsg(scip, "ending strong branching with probing: %d bound changes collected\n", nbnds); 2797 2798 /* inform the LP that the probing mode is not used for strong branching anymore */ 2799 SCIPlpEndStrongbranchProbing(scip->lp); 2800 2801 /* switch back from probing to normal operation mode and restore variables and constraints to focus node */ 2802 SCIP_CALL( SCIPtreeEndProbing(scip->tree, scip->reopt, scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat, 2803 scip->transprob, scip->origprob, scip->lp, scip->relaxation, scip->primal, 2804 scip->branchcand, scip->eventqueue, scip->eventfilter, scip->cliquetable) ); 2805 2806 /* apply the collected bound changes */ 2807 for( i = 0; i < nbnds; ++i ) 2808 { 2809 if( boundtypes[i] == SCIP_BOUNDTYPE_LOWER ) 2810 { 2811 SCIPdebugMsg(scip, "apply probing lower bound change <%s> >= %.9g\n", SCIPvarGetName(boundchgvars[i]), bounds[i]); 2812 SCIP_CALL( SCIPchgVarLb(scip, boundchgvars[i], bounds[i]) ); 2813 } 2814 else 2815 { 2816 SCIPdebugMsg(scip, "apply probing upper bound change <%s> <= %.9g\n", SCIPvarGetName(boundchgvars[i]), bounds[i]); 2817 SCIP_CALL( SCIPchgVarUb(scip, boundchgvars[i], bounds[i]) ); 2818 } 2819 } 2820 2821 SCIPfreeBufferArray(scip, &boundtypes); 2822 SCIPfreeBufferArray(scip, &bounds); 2823 SCIPfreeBufferArray(scip, &boundchgvars); 2824 } 2825 else 2826 { 2827 SCIPdebugMsg(scip, "ending strong branching\n"); 2828 2829 SCIP_CALL( SCIPlpEndStrongbranch(scip->lp) ); 2830 } 2831 2832 return SCIP_OKAY; 2833 } 2834 2835 /** analyze the strong branching for the given variable; that includes conflict analysis for infeasible branches and 2836 * storing of root reduced cost information 2837 */ 2838 static 2839 SCIP_RETCODE analyzeStrongbranch( 2840 SCIP* scip, /**< SCIP data structure */ 2841 SCIP_VAR* var, /**< variable to analyze */ 2842 SCIP_Bool* downinf, /**< pointer to store whether the downwards branch is infeasible, or NULL */ 2843 SCIP_Bool* upinf, /**< pointer to store whether the upwards branch is infeasible, or NULL */ 2844 SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an 2845 * infeasible downwards branch, or NULL */ 2846 SCIP_Bool* upconflict /**< pointer to store whether a conflict constraint was created for an 2847 * infeasible upwards branch, or NULL */ 2848 ) 2849 { 2850 SCIP_COL* col; 2851 SCIP_Bool downcutoff; 2852 SCIP_Bool upcutoff; 2853 2854 col = SCIPvarGetCol(var); 2855 assert(col != NULL); 2856 2857 downcutoff = col->sbdownvalid && SCIPsetIsGE(scip->set, col->sbdown, scip->lp->cutoffbound); 2858 upcutoff = col->sbupvalid && SCIPsetIsGE(scip->set, col->sbup, scip->lp->cutoffbound); 2859 2860 if( downinf != NULL ) 2861 *downinf = downcutoff; 2862 if( upinf != NULL ) 2863 *upinf = upcutoff; 2864 2865 /* analyze infeasible strong branching sub problems: 2866 * because the strong branching's bound change is necessary for infeasibility, it cannot be undone; 2867 * therefore, infeasible strong branchings on non-binary variables will not produce a valid conflict constraint 2868 */ 2869 if( scip->set->conf_enable && scip->set->conf_usesb && scip->set->nconflicthdlrs > 0 2870 && SCIPvarIsBinary(var) && SCIPtreeGetCurrentDepth(scip->tree) > 0 ) 2871 { 2872 if( (downcutoff && SCIPsetFeasCeil(scip->set, col->primsol-1.0) >= col->lb - 0.5) 2873 || (upcutoff && SCIPsetFeasFloor(scip->set, col->primsol+1.0) <= col->ub + 0.5) ) 2874 { 2875 assert(downconflict != NULL); 2876 assert(upconflict != NULL); 2877 SCIP_CALL( SCIPconflictAnalyzeStrongbranch(scip->conflict, scip->conflictstore, scip->mem->probmem, scip->set, scip->stat, 2878 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, col, downconflict, upconflict) ); 2879 } 2880 } 2881 2882 /* the strong branching results can be used to strengthen the root reduced cost information which is used for example 2883 * to propagate against the cutoff bound 2884 * 2885 * @note Ignore the results if the LP solution of the down (up) branch LP is smaller which should not happened by 2886 * theory but can arise due to numerical issues. 2887 */ 2888 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 && SCIPvarIsBinary(var) && SCIPlpIsDualReliable(scip->lp) ) 2889 { 2890 SCIP_Real lpobjval; 2891 2892 assert(SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL); 2893 2894 lpobjval = SCIPlpGetObjval(scip->lp, scip->set, scip->transprob); 2895 2896 if( col->sbdownvalid && SCIPsetFeasCeil(scip->set, col->primsol-1.0) >= col->lb - 0.5 && lpobjval < col->sbdown ) 2897 SCIPvarUpdateBestRootSol(var, scip->set, SCIPvarGetUbGlobal(var), -(col->sbdown - lpobjval), lpobjval); 2898 if( col->sbupvalid && SCIPsetFeasFloor(scip->set, col->primsol+1.0) <= col->ub + 0.5 && lpobjval < col->sbup ) 2899 SCIPvarUpdateBestRootSol(var, scip->set, SCIPvarGetLbGlobal(var), col->sbup - lpobjval, lpobjval); 2900 } 2901 2902 return SCIP_OKAY; 2903 } 2904 2905 /** gets strong branching information on column variable with fractional value 2906 * 2907 * Before calling this method, the strong branching mode must have been activated by calling SCIPstartStrongbranch(); 2908 * after strong branching was done for all candidate variables, the strong branching mode must be ended by 2909 * SCIPendStrongbranch(). Since this method does not apply domain propagation before strongbranching, 2910 * propagation should not be enabled in the SCIPstartStrongbranch() call. 2911 * 2912 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 2913 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 2914 * 2915 * @pre This method can be called if @p scip is in one of the following stages: 2916 * - \ref SCIP_STAGE_PRESOLVED 2917 * - \ref SCIP_STAGE_SOLVING 2918 */ 2919 SCIP_RETCODE SCIPgetVarStrongbranchFrac( 2920 SCIP* scip, /**< SCIP data structure */ 2921 SCIP_VAR* var, /**< variable to get strong branching values for */ 2922 int itlim, /**< iteration limit for strong branchings */ 2923 SCIP_Bool idempotent, /**< should scip's state remain the same after the call (statistics, column states...), or should it be updated ? */ 2924 SCIP_Real* down, /**< stores dual bound after branching column down */ 2925 SCIP_Real* up, /**< stores dual bound after branching column up */ 2926 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL; 2927 * otherwise, it can only be used as an estimate value */ 2928 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL; 2929 * otherwise, it can only be used as an estimate value */ 2930 SCIP_Bool* downinf, /**< pointer to store whether the downwards branch is infeasible, or NULL */ 2931 SCIP_Bool* upinf, /**< pointer to store whether the upwards branch is infeasible, or NULL */ 2932 SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an 2933 * infeasible downwards branch, or NULL */ 2934 SCIP_Bool* upconflict, /**< pointer to store whether a conflict constraint was created for an 2935 * infeasible upwards branch, or NULL */ 2936 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred or the 2937 * solving process should be stopped (e.g., due to a time limit) */ 2938 ) 2939 { 2940 SCIP_COL* col; 2941 SCIP_Real localdown; 2942 SCIP_Real localup; 2943 SCIP_Bool localdownvalid; 2944 SCIP_Bool localupvalid; 2945 2946 assert(scip != NULL); 2947 assert(var != NULL); 2948 assert(lperror != NULL); 2949 assert(!SCIPtreeProbing(scip->tree)); /* we should not be in strong branching with propagation mode */ 2950 assert(var->scip == scip); 2951 2952 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchFrac", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 2953 2954 if( downvalid != NULL ) 2955 *downvalid = FALSE; 2956 if( upvalid != NULL ) 2957 *upvalid = FALSE; 2958 if( downinf != NULL ) 2959 *downinf = FALSE; 2960 if( upinf != NULL ) 2961 *upinf = FALSE; 2962 if( downconflict != NULL ) 2963 *downconflict = FALSE; 2964 if( upconflict != NULL ) 2965 *upconflict = FALSE; 2966 2967 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 2968 { 2969 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var)); 2970 return SCIP_INVALIDDATA; 2971 } 2972 2973 col = SCIPvarGetCol(var); 2974 assert(col != NULL); 2975 2976 if( !SCIPcolIsInLP(col) ) 2977 { 2978 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var)); 2979 return SCIP_INVALIDDATA; 2980 } 2981 2982 /* check if the solving process should be aborted */ 2983 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) ) 2984 { 2985 /* mark this as if the LP failed */ 2986 *lperror = TRUE; 2987 return SCIP_OKAY; 2988 } 2989 2990 /* call strong branching for column with fractional value */ 2991 SCIP_CALL( SCIPcolGetStrongbranch(col, FALSE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, !idempotent, !idempotent, 2992 &localdown, &localup, &localdownvalid, &localupvalid, lperror) ); 2993 2994 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to 2995 * declare the sub nodes infeasible 2996 */ 2997 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve ) 2998 { 2999 if( !idempotent ) /*lint !e774*/ 3000 { 3001 SCIP_CALL( analyzeStrongbranch(scip, var, downinf, upinf, downconflict, upconflict) ); 3002 } 3003 else 3004 { 3005 if( downinf != NULL ) 3006 *downinf = localdownvalid && SCIPsetIsGE(scip->set, localdown, scip->lp->cutoffbound); 3007 if( upinf != NULL ) 3008 *upinf = localupvalid && SCIPsetIsGE(scip->set, localup, scip->lp->cutoffbound); 3009 } 3010 } 3011 3012 if( down != NULL ) 3013 *down = localdown; 3014 if( up != NULL ) 3015 *up = localup; 3016 if( downvalid != NULL ) 3017 *downvalid = localdownvalid; 3018 if( upvalid != NULL ) 3019 *upvalid = localupvalid; 3020 3021 return SCIP_OKAY; 3022 } 3023 3024 /** create, solve, and evaluate a single strong branching child (for strong branching with propagation) */ 3025 static 3026 SCIP_RETCODE performStrongbranchWithPropagation( 3027 SCIP* scip, /**< SCIP data structure */ 3028 SCIP_VAR* var, /**< variable to get strong branching values for */ 3029 SCIP_Bool down, /**< do we regard the down child? */ 3030 SCIP_Bool firstchild, /**< is this the first of the two strong branching children? */ 3031 SCIP_Bool propagate, /**< should domain propagation be performed? */ 3032 SCIP_Real newbound, /**< new bound to apply at the strong branching child */ 3033 int itlim, /**< iteration limit for strong branchings */ 3034 int maxproprounds, /**< maximum number of propagation rounds (-1: no limit, -2: parameter 3035 * settings) */ 3036 SCIP_Real* value, /**< stores dual bound for strong branching child */ 3037 SCIP_Bool* valid, /**< stores whether the returned value is a valid dual bound, or NULL; 3038 * otherwise, it can only be used as an estimate value */ 3039 SCIP_Longint* ndomreductions, /**< pointer to store the number of domain reductions found, or NULL */ 3040 SCIP_Bool* conflict, /**< pointer to store whether a conflict constraint was created for an 3041 * infeasible strong branching child, or NULL */ 3042 SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occurred or the 3043 * solving process should be stopped (e.g., due to a time limit) */ 3044 SCIP_VAR** vars, /**< active problem variables */ 3045 int nvars, /**< number of active problem variables */ 3046 SCIP_Real* newlbs, /**< array to store valid lower bounds for all active variables, or NULL */ 3047 SCIP_Real* newubs, /**< array to store valid upper bounds for all active variables, or NULL */ 3048 SCIP_Bool* foundsol, /**< pointer to store whether a primal solution was found during strong branching */ 3049 SCIP_Bool* cutoff /**< pointer to store whether the strong branching child is infeasible */ 3050 ) 3051 { 3052 SCIP_Longint ndomreds; 3053 3054 assert(value != NULL); 3055 assert(foundsol != NULL); 3056 assert(cutoff != NULL); 3057 assert(lperror != NULL); 3058 assert(valid != NULL ? !(*valid) : TRUE); 3059 3060 *foundsol = FALSE; 3061 *cutoff = FALSE; 3062 *lperror = FALSE; 3063 3064 /* check whether the strong branching child is already infeasible due to the bound change */ 3065 if( down ) 3066 { 3067 /* the down branch is infeasible due to the branching bound change; since this means that solval is not within the 3068 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which 3069 * are valid for and were already applied at the probing root 3070 */ 3071 if( newbound < SCIPvarGetLbLocal(var) - 0.5 ) 3072 { 3073 *value = SCIPinfinity(scip); 3074 3075 if( valid != NULL ) 3076 *valid = TRUE; 3077 3078 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */ 3079 if( conflict != NULL ) 3080 *conflict = TRUE; 3081 3082 *cutoff = TRUE; 3083 3084 return SCIP_OKAY; 3085 } 3086 } 3087 else 3088 { 3089 /* the up branch is infeasible due to the branching bound change; since this means that solval is not within the 3090 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which 3091 * are valid for and were already applied at the probing root 3092 */ 3093 if( newbound > SCIPvarGetUbLocal(var) + 0.5 ) 3094 { 3095 *value = SCIPinfinity(scip); 3096 3097 if( valid != NULL ) 3098 *valid = TRUE; 3099 3100 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */ 3101 if( conflict != NULL ) 3102 *conflict = TRUE; 3103 3104 *cutoff = TRUE; 3105 3106 return SCIP_OKAY; 3107 } 3108 } 3109 3110 /* we need to ensure that we can create at least one new probing node without exceeding the maximal tree depth */ 3111 if( SCIP_MAXTREEDEPTH > SCIPtreeGetProbingDepth(scip->tree) ) 3112 { 3113 /* create a new probing node for the strong branching child and apply the new bound for the variable */ 3114 SCIP_CALL( SCIPnewProbingNode(scip) ); 3115 3116 if( down ) 3117 { 3118 assert(SCIPisGE(scip, newbound, SCIPvarGetLbLocal(var))); 3119 if( SCIPisLT(scip, newbound, SCIPvarGetUbLocal(var)) ) 3120 { 3121 SCIP_CALL( SCIPchgVarUbProbing(scip, var, newbound) ); 3122 } 3123 } 3124 else 3125 { 3126 assert(SCIPisLE(scip, newbound, SCIPvarGetUbLocal(var))); 3127 if( SCIPisGT(scip, newbound, SCIPvarGetLbLocal(var)) ) 3128 { 3129 SCIP_CALL( SCIPchgVarLbProbing(scip, var, newbound) ); 3130 } 3131 } 3132 } 3133 else 3134 { 3135 if( valid != NULL ) 3136 *valid = FALSE; 3137 3138 *cutoff = FALSE; 3139 3140 if( conflict != NULL ) 3141 *conflict = FALSE; 3142 3143 return SCIP_OKAY; 3144 } 3145 3146 /* propagate domains at the probing node */ 3147 if( propagate ) 3148 { 3149 /* start time measuring */ 3150 SCIPclockStart(scip->stat->strongpropclock, scip->set); 3151 3152 ndomreds = 0; 3153 SCIP_CALL( SCIPpropagateProbing(scip, maxproprounds, cutoff, &ndomreds) ); 3154 3155 /* store number of domain reductions in strong branching */ 3156 if( down ) 3157 SCIPstatAdd(scip->stat, scip->set, nsbdowndomchgs, ndomreds); 3158 else 3159 SCIPstatAdd(scip->stat, scip->set, nsbupdomchgs, ndomreds); 3160 3161 if( ndomreductions != NULL ) 3162 *ndomreductions = ndomreds; 3163 3164 /* stop time measuring */ 3165 SCIPclockStop(scip->stat->strongpropclock, scip->set); 3166 3167 if( *cutoff ) 3168 { 3169 *value = SCIPinfinity(scip); 3170 3171 if( valid != NULL ) 3172 *valid = TRUE; 3173 3174 SCIPdebugMsg(scip, "%s branch of var <%s> detected infeasible during propagation\n", 3175 down ? "down" : "up", SCIPvarGetName(var)); 3176 } 3177 } 3178 3179 /* if propagation did not already detect infeasibility, solve the probing LP */ 3180 if( !(*cutoff) ) 3181 { 3182 SCIP_CALL( SCIPsolveProbingLP(scip, itlim, lperror, cutoff) ); 3183 assert(SCIPisLPRelax(scip)); 3184 3185 if( *cutoff ) 3186 { 3187 assert(!(*lperror)); 3188 3189 *value = SCIPinfinity(scip); 3190 3191 if( valid != NULL ) 3192 *valid = TRUE; 3193 3194 SCIPdebugMsg(scip, "%s branch of var <%s> detected infeasible in LP solving: status=%d\n", 3195 down ? "down" : "up", SCIPvarGetName(var), SCIPgetLPSolstat(scip)); 3196 } 3197 else if( !(*lperror) ) 3198 { 3199 /* save the lp solution status */ 3200 scip->stat->lastsblpsolstats[down ? 0 : 1] = SCIPgetLPSolstat(scip); 3201 3202 switch( SCIPgetLPSolstat(scip) ) 3203 { 3204 case SCIP_LPSOLSTAT_OPTIMAL: 3205 { 3206 *value = SCIPgetLPObjval(scip); 3207 assert(SCIPisLT(scip, *value, SCIPgetCutoffbound(scip))); 3208 3209 SCIPdebugMsg(scip, "probing LP solved to optimality, objective value: %16.9g\n", *value); 3210 3211 if( valid != NULL ) 3212 *valid = TRUE; 3213 3214 /* check the strong branching LP solution for feasibility */ 3215 SCIP_CALL( SCIPtryStrongbranchLPSol(scip, foundsol, cutoff) ); 3216 break; 3217 } 3218 case SCIP_LPSOLSTAT_ITERLIMIT: 3219 ++scip->stat->nsbtimesiterlimhit; 3220 /*lint -fallthrough*/ 3221 case SCIP_LPSOLSTAT_TIMELIMIT: 3222 { 3223 /* use LP value as estimate */ 3224 SCIP_LPI* lpi; 3225 SCIP_Real objval; 3226 SCIP_Real looseobjval; 3227 3228 SCIPdebugMsg(scip, "probing LP hit %s limit\n", SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_ITERLIMIT ? "iteration" : "time"); 3229 3230 /* we access the LPI directly, because when a time limit was hit, we cannot access objective value and dual 3231 * feasibility using the SCIPlp... methods; we should try to avoid direct calls to the LPI, but this is rather 3232 * uncritical here, because we are immediately after the SCIPsolveProbingLP() call, because we access the LPI 3233 * read-only, and we check SCIPlpiWasSolved() first 3234 */ 3235 SCIP_CALL( SCIPgetLPI(scip, &lpi) ); 3236 3237 if( SCIPlpiWasSolved(lpi) ) 3238 { 3239 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) ); 3240 looseobjval = SCIPlpGetLooseObjval(scip->lp, scip->set, scip->transprob); 3241 3242 /* the infinity value in the LPI should not be smaller than SCIP's infinity value */ 3243 assert(!SCIPlpiIsInfinity(lpi, objval) || SCIPisInfinity(scip, objval)); 3244 3245 /* we use SCIP's infinity value here because a value larger than this is counted as infeasible by SCIP */ 3246 if( SCIPisInfinity(scip, objval) ) 3247 *value = SCIPinfinity(scip); 3248 else if( SCIPisInfinity(scip, -looseobjval) ) 3249 *value = -SCIPinfinity(scip); 3250 else 3251 *value = objval + looseobjval; 3252 3253 if( SCIPlpiIsDualFeasible(lpi) ) 3254 { 3255 if( valid != NULL ) 3256 *valid = TRUE; 3257 3258 if( SCIPisGE(scip, *value, SCIPgetCutoffbound(scip)) ) 3259 *cutoff = TRUE; 3260 } 3261 } 3262 break; 3263 } 3264 case SCIP_LPSOLSTAT_ERROR: 3265 case SCIP_LPSOLSTAT_UNBOUNDEDRAY: 3266 *lperror = TRUE; 3267 break; 3268 case SCIP_LPSOLSTAT_NOTSOLVED: /* should only be the case for *cutoff = TRUE or *lperror = TRUE */ 3269 case SCIP_LPSOLSTAT_OBJLIMIT: /* in this case, *cutoff should be TRUE and we should not get here */ 3270 case SCIP_LPSOLSTAT_INFEASIBLE: /* in this case, *cutoff should be TRUE and we should not get here */ 3271 default: 3272 SCIPerrorMessage("invalid LP solution status <%d>\n", SCIPgetLPSolstat(scip)); 3273 return SCIP_INVALIDDATA; 3274 } /*lint !e788*/ 3275 } 3276 3277 /* If columns are missing in the LP, the cutoff flag may be wrong. Therefore, we need to set it and the valid pointer 3278 * to false here. 3279 */ 3280 if( (*cutoff) && !SCIPallColsInLP(scip) ) 3281 { 3282 *cutoff = FALSE; 3283 } 3284 3285 #ifndef NDEBUG 3286 if( *lperror ) 3287 { 3288 SCIPdebugMsg(scip, "error during strong branching probing LP solving: status=%d\n", SCIPgetLPSolstat(scip)); 3289 } 3290 #endif 3291 } 3292 3293 /* if the subproblem was feasible, we store the local bounds of the variables after propagation and (possibly) 3294 * conflict analysis 3295 * @todo do this after propagation? should be able to get valid bounds more often, but they might be weaker 3296 */ 3297 if( !(*cutoff) && newlbs != NULL) 3298 { 3299 int v; 3300 3301 assert(newubs != NULL); 3302 3303 /* initialize the newlbs and newubs to the current local bounds */ 3304 if( firstchild ) 3305 { 3306 for( v = 0; v < nvars; ++v ) 3307 { 3308 newlbs[v] = SCIPvarGetLbLocal(vars[v]); 3309 newubs[v] = SCIPvarGetUbLocal(vars[v]); 3310 } 3311 } 3312 /* update newlbs and newubs: take the weaker of the already stored bounds and the current local bounds */ 3313 else 3314 { 3315 for( v = 0; v < nvars; ++v ) 3316 { 3317 SCIP_Real lb = SCIPvarGetLbLocal(vars[v]); 3318 SCIP_Real ub = SCIPvarGetUbLocal(vars[v]); 3319 3320 newlbs[v] = MIN(newlbs[v], lb); 3321 newubs[v] = MAX(newubs[v], ub); 3322 } 3323 } 3324 } 3325 3326 /* revert all changes at the probing node */ 3327 SCIP_CALL( SCIPbacktrackProbing(scip, 0) ); 3328 3329 return SCIP_OKAY; 3330 } 3331 3332 /** gets strong branching information with previous domain propagation on column variable 3333 * 3334 * Before calling this method, the strong branching mode must have been activated by calling SCIPstartStrongbranch(); 3335 * after strong branching was done for all candidate variables, the strong branching mode must be ended by 3336 * SCIPendStrongbranch(). Since this method applies domain propagation before strongbranching, propagation has to be be 3337 * enabled in the SCIPstartStrongbranch() call. 3338 * 3339 * Before solving the strong branching LP, domain propagation can be performed. The number of propagation rounds 3340 * can be specified by the parameter @p maxproprounds. 3341 * 3342 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 3343 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 3344 * 3345 * @pre This method can be called if @p scip is in one of the following stages: 3346 * - \ref SCIP_STAGE_PRESOLVED 3347 * - \ref SCIP_STAGE_SOLVING 3348 * 3349 * @warning When using this method, LP banching candidates and solution values must be copied beforehand, because 3350 * they are updated w.r.t. the strong branching LP solution. 3351 */ 3352 SCIP_RETCODE SCIPgetVarStrongbranchWithPropagation( 3353 SCIP* scip, /**< SCIP data structure */ 3354 SCIP_VAR* var, /**< variable to get strong branching values for */ 3355 SCIP_Real solval, /**< value of the variable in the current LP solution */ 3356 SCIP_Real lpobjval, /**< LP objective value of the current LP solution */ 3357 int itlim, /**< iteration limit for strong branchings */ 3358 int maxproprounds, /**< maximum number of propagation rounds (-1: no limit, -2: parameter 3359 * settings) */ 3360 SCIP_Real* down, /**< stores dual bound after branching column down */ 3361 SCIP_Real* up, /**< stores dual bound after branching column up */ 3362 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL; 3363 * otherwise, it can only be used as an estimate value */ 3364 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL; 3365 * otherwise, it can only be used as an estimate value */ 3366 SCIP_Longint* ndomredsdown, /**< pointer to store the number of domain reductions down, or NULL */ 3367 SCIP_Longint* ndomredsup, /**< pointer to store the number of domain reductions up, or NULL */ 3368 SCIP_Bool* downinf, /**< pointer to store whether the downwards branch is infeasible, or NULL */ 3369 SCIP_Bool* upinf, /**< pointer to store whether the upwards branch is infeasible, or NULL */ 3370 SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an 3371 * infeasible downwards branch, or NULL */ 3372 SCIP_Bool* upconflict, /**< pointer to store whether a conflict constraint was created for an 3373 * infeasible upwards branch, or NULL */ 3374 SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occurred or the 3375 * solving process should be stopped (e.g., due to a time limit) */ 3376 SCIP_Real* newlbs, /**< array to store valid lower bounds for all active variables, or NULL */ 3377 SCIP_Real* newubs /**< array to store valid upper bounds for all active variables, or NULL */ 3378 ) 3379 { 3380 SCIP_COL* col; 3381 SCIP_VAR** vars; 3382 SCIP_Longint oldniters; 3383 SCIP_Real newub; 3384 SCIP_Real newlb; 3385 SCIP_Bool propagate; 3386 SCIP_Bool cutoff; 3387 SCIP_Bool downchild; 3388 SCIP_Bool firstchild; 3389 SCIP_Bool foundsol; 3390 SCIP_Bool downvalidlocal; 3391 SCIP_Bool upvalidlocal; 3392 SCIP_Bool allcolsinlp; 3393 SCIP_Bool enabledconflict; 3394 int oldnconflicts; 3395 int nvars; 3396 3397 assert(scip != NULL); 3398 assert(var != NULL); 3399 assert(SCIPvarIsIntegral(var)); 3400 assert(down != NULL); 3401 assert(up != NULL); 3402 assert(lperror != NULL); 3403 assert((newlbs != NULL) == (newubs != NULL)); 3404 assert(SCIPinProbing(scip)); 3405 assert(var->scip == scip); 3406 3407 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchWithPropagation", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 3408 3409 /* check whether propagation should be performed */ 3410 propagate = (maxproprounds != 0 && maxproprounds != -3); 3411 3412 /* Check, if all existing columns are in LP. 3413 * If this is not the case, we may still return that the up and down dual bounds are valid, because the branching 3414 * rule should not apply them otherwise. 3415 * However, we must not set the downinf or upinf pointers to TRUE based on the dual bound, because we cannot 3416 * guarantee that this node can be cut off. 3417 */ 3418 allcolsinlp = SCIPallColsInLP(scip); 3419 3420 /* if maxproprounds is -2, change it to 0, which for the following calls means using the parameter settings */ 3421 if( maxproprounds == -2 ) 3422 maxproprounds = 0; 3423 3424 *down = lpobjval; 3425 *up = lpobjval; 3426 if( downvalid != NULL ) 3427 *downvalid = FALSE; 3428 if( upvalid != NULL ) 3429 *upvalid = FALSE; 3430 if( downinf != NULL ) 3431 *downinf = FALSE; 3432 if( upinf != NULL ) 3433 *upinf = FALSE; 3434 if( downconflict != NULL ) 3435 *downconflict = FALSE; 3436 if( upconflict != NULL ) 3437 *upconflict = FALSE; 3438 if( ndomredsdown != NULL ) 3439 *ndomredsdown = 0; 3440 if( ndomredsup != NULL ) 3441 *ndomredsup = 0; 3442 3443 *lperror = FALSE; 3444 3445 vars = SCIPgetVars(scip); 3446 nvars = SCIPgetNVars(scip); 3447 3448 scip->stat->lastsblpsolstats[0] = scip->stat->lastsblpsolstats[1] = SCIP_LPSOLSTAT_NOTSOLVED; 3449 3450 /* check if the solving process should be aborted */ 3451 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) ) 3452 { 3453 /* mark this as if the LP failed */ 3454 *lperror = TRUE; 3455 return SCIP_OKAY; 3456 } 3457 3458 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 3459 { 3460 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var)); 3461 return SCIP_INVALIDDATA; 3462 } 3463 3464 col = SCIPvarGetCol(var); 3465 assert(col != NULL); 3466 3467 if( !SCIPcolIsInLP(col) ) 3468 { 3469 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var)); 3470 return SCIP_INVALIDDATA; 3471 } 3472 3473 newlb = SCIPfeasFloor(scip, solval + 1.0); 3474 newub = SCIPfeasCeil(scip, solval - 1.0); 3475 3476 SCIPdebugMsg(scip, "strong branching on var <%s>: solval=%g, lb=%g, ub=%g\n", SCIPvarGetName(var), solval, 3477 SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)); 3478 3479 /* the up branch is infeasible due to the branching bound change; since this means that solval is not within the 3480 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which 3481 * are valid for and were already applied at the probing root 3482 */ 3483 if( newlb > SCIPvarGetUbLocal(var) + 0.5 ) 3484 { 3485 *up = SCIPinfinity(scip); 3486 3487 if( upinf != NULL ) 3488 *upinf = TRUE; 3489 3490 if( upvalid != NULL ) 3491 *upvalid = TRUE; 3492 3493 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */ 3494 if( upconflict != NULL ) 3495 *upconflict = TRUE; 3496 3497 SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval, 3498 *down, *up, FALSE, TRUE, 0LL, INT_MAX); 3499 3500 /* we do not regard the down branch; its valid pointer stays set to FALSE */ 3501 return SCIP_OKAY; 3502 } 3503 3504 /* the down branch is infeasible due to the branching bound change; since this means that solval is not within the 3505 * bounds, this should only happen if previous strong branching calls on other variables detected bound changes which 3506 * are valid for and were already applied at the probing root 3507 */ 3508 if( newub < SCIPvarGetLbLocal(var) - 0.5 ) 3509 { 3510 *down = SCIPinfinity(scip); 3511 3512 if( downinf != NULL ) 3513 *downinf = TRUE; 3514 3515 if( downvalid != NULL ) 3516 *downvalid = TRUE; 3517 3518 /* bound changes are applied in SCIPendStrongbranch(), which can be seen as a conflict constraint */ 3519 if( downconflict != NULL ) 3520 *downconflict = TRUE; 3521 3522 SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval, 3523 *down, *up, TRUE, FALSE, 0LL, INT_MAX); 3524 3525 /* we do not regard the up branch; its valid pointer stays set to FALSE */ 3526 return SCIP_OKAY; 3527 } 3528 3529 /* We now do strong branching by creating the two potential child nodes as probing nodes and solving them one after 3530 * the other. We will stop when the first child is detected infeasible, saving the effort we would need for the 3531 * second child. Since empirically, the up child tends to be infeasible more often, we do strongbranching first on 3532 * the up branch. 3533 */ 3534 oldniters = scip->stat->nsbdivinglpiterations; 3535 firstchild = TRUE; 3536 cutoff = FALSE; 3537 3538 /* switch conflict analysis according to usesb parameter */ 3539 enabledconflict = scip->set->conf_enable; 3540 scip->set->conf_enable = (scip->set->conf_enable && scip->set->conf_usesb); 3541 3542 /* @todo: decide the branch to look at first based on the cutoffs in previous calls? */ 3543 downchild = SCIPisStrongbranchDownFirst(scip, var); 3544 3545 downvalidlocal = FALSE; 3546 upvalidlocal = FALSE; 3547 3548 do 3549 { 3550 oldnconflicts = SCIPconflictGetNConflicts(scip->conflict); 3551 3552 if( downchild ) 3553 { 3554 SCIP_CALL( performStrongbranchWithPropagation(scip, var, downchild, firstchild, propagate, newub, itlim, maxproprounds, 3555 down, &downvalidlocal, ndomredsdown, downconflict, lperror, vars, nvars, newlbs, newubs, &foundsol, &cutoff) ); 3556 3557 /* check whether a new solutions rendered the previous child infeasible */ 3558 if( foundsol && !firstchild && allcolsinlp ) 3559 { 3560 if( SCIPisGE(scip, *up, SCIPgetCutoffbound(scip)) ) 3561 { 3562 if( upinf != NULL ) 3563 *upinf = TRUE; 3564 } 3565 } 3566 3567 /* check for infeasibility */ 3568 if( cutoff ) 3569 { 3570 if( downinf != NULL ) 3571 *downinf = TRUE; 3572 3573 if( downconflict != NULL && 3574 (SCIPvarGetLbLocal(var) > newub + 0.5 || SCIPconflictGetNConflicts(scip->conflict) > oldnconflicts) ) 3575 { 3576 *downconflict = TRUE; 3577 } 3578 3579 if( !scip->set->branch_forceall ) 3580 { 3581 /* if this is the first call, we do not regard the up branch, its valid pointer is initially set to FALSE */ 3582 break; 3583 } 3584 } 3585 } 3586 else 3587 { 3588 SCIP_CALL( performStrongbranchWithPropagation(scip, var, downchild, firstchild, propagate, newlb, itlim, maxproprounds, 3589 up, &upvalidlocal, ndomredsup, upconflict, lperror, vars, nvars, newlbs, newubs, &foundsol, &cutoff) ); 3590 3591 /* check whether a new solutions rendered the previous child infeasible */ 3592 if( foundsol && !firstchild && allcolsinlp ) 3593 { 3594 if( SCIPisGE(scip, *down, SCIPgetCutoffbound(scip)) ) 3595 { 3596 if( downinf != NULL ) 3597 *downinf = TRUE; 3598 } 3599 } 3600 3601 /* check for infeasibility */ 3602 if( cutoff ) 3603 { 3604 if( upinf != NULL ) 3605 *upinf = TRUE; 3606 3607 assert(upinf == NULL || (*upinf) == TRUE); 3608 3609 if( upconflict != NULL && 3610 (SCIPvarGetUbLocal(var) < newlb - 0.5 || SCIPconflictGetNConflicts(scip->conflict) > oldnconflicts) ) 3611 { 3612 *upconflict = TRUE; 3613 } 3614 3615 if( !scip->set->branch_forceall ) 3616 { 3617 /* if this is the first call, we do not regard the down branch, its valid pointer is initially set to FALSE */ 3618 break; 3619 } 3620 } 3621 } 3622 3623 downchild = !downchild; 3624 firstchild = !firstchild; 3625 } 3626 while( !firstchild ); 3627 3628 /* set strong branching information in column */ 3629 if( *lperror ) 3630 { 3631 SCIPcolInvalidateStrongbranchData(col, scip->set, scip->stat, scip->lp); 3632 } 3633 else 3634 { 3635 SCIPcolSetStrongbranchData(col, scip->set, scip->stat, scip->lp, lpobjval, solval, 3636 *down, *up, downvalidlocal, upvalidlocal, scip->stat->nsbdivinglpiterations - oldniters, itlim); 3637 } 3638 3639 if( downvalid != NULL ) 3640 *downvalid = downvalidlocal; 3641 if( upvalid != NULL ) 3642 *upvalid = upvalidlocal; 3643 3644 scip->set->conf_enable = enabledconflict; 3645 3646 return SCIP_OKAY; /*lint !e438*/ 3647 } 3648 3649 /** gets strong branching information on column variable x with integral LP solution value (val); that is, the down branch 3650 * is (val -1.0) and the up brach ins (val +1.0) 3651 * 3652 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 3653 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 3654 * 3655 * @pre This method can be called if @p scip is in one of the following stages: 3656 * - \ref SCIP_STAGE_PRESOLVED 3657 * - \ref SCIP_STAGE_SOLVING 3658 * 3659 * @note If the integral LP solution value is the lower or upper bound of the variable, the corresponding branch will be 3660 * marked as infeasible. That is, the valid pointer and the infeasible pointer are set to TRUE. 3661 */ 3662 SCIP_RETCODE SCIPgetVarStrongbranchInt( 3663 SCIP* scip, /**< SCIP data structure */ 3664 SCIP_VAR* var, /**< variable to get strong branching values for */ 3665 int itlim, /**< iteration limit for strong branchings */ 3666 SCIP_Bool idempotent, /**< should scip's state remain the same after the call (statistics, column states...), or should it be updated ? */ 3667 SCIP_Real* down, /**< stores dual bound after branching column down */ 3668 SCIP_Real* up, /**< stores dual bound after branching column up */ 3669 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL; 3670 * otherwise, it can only be used as an estimate value */ 3671 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL; 3672 * otherwise, it can only be used as an estimate value */ 3673 SCIP_Bool* downinf, /**< pointer to store whether the downwards branch is infeasible, or NULL */ 3674 SCIP_Bool* upinf, /**< pointer to store whether the upwards branch is infeasible, or NULL */ 3675 SCIP_Bool* downconflict, /**< pointer to store whether a conflict constraint was created for an 3676 * infeasible downwards branch, or NULL */ 3677 SCIP_Bool* upconflict, /**< pointer to store whether a conflict constraint was created for an 3678 * infeasible upwards branch, or NULL */ 3679 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred or the 3680 * solving process should be stopped (e.g., due to a time limit) */ 3681 ) 3682 { 3683 SCIP_COL* col; 3684 SCIP_Real localdown; 3685 SCIP_Real localup; 3686 SCIP_Bool localdownvalid; 3687 SCIP_Bool localupvalid; 3688 3689 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchInt", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 3690 3691 assert(lperror != NULL); 3692 assert(var->scip == scip); 3693 3694 if( downvalid != NULL ) 3695 *downvalid = FALSE; 3696 if( upvalid != NULL ) 3697 *upvalid = FALSE; 3698 if( downinf != NULL ) 3699 *downinf = FALSE; 3700 if( upinf != NULL ) 3701 *upinf = FALSE; 3702 if( downconflict != NULL ) 3703 *downconflict = FALSE; 3704 if( upconflict != NULL ) 3705 *upconflict = FALSE; 3706 3707 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 3708 { 3709 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var)); 3710 return SCIP_INVALIDDATA; 3711 } 3712 3713 col = SCIPvarGetCol(var); 3714 assert(col != NULL); 3715 3716 if( !SCIPcolIsInLP(col) ) 3717 { 3718 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var)); 3719 return SCIP_INVALIDDATA; 3720 } 3721 3722 /* check if the solving process should be aborted */ 3723 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) ) 3724 { 3725 /* mark this as if the LP failed */ 3726 *lperror = TRUE; 3727 return SCIP_OKAY; 3728 } 3729 3730 /* call strong branching for column */ 3731 SCIP_CALL( SCIPcolGetStrongbranch(col, TRUE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, !idempotent, !idempotent, 3732 &localdown, &localup, &localdownvalid, &localupvalid, lperror) ); 3733 3734 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to 3735 * declare the sub nodes infeasible 3736 */ 3737 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve ) 3738 { 3739 if( !idempotent ) /*lint !e774*/ 3740 { 3741 SCIP_CALL( analyzeStrongbranch(scip, var, downinf, upinf, downconflict, upconflict) ); 3742 } 3743 else 3744 { 3745 if( downinf != NULL ) 3746 *downinf = localdownvalid && SCIPsetIsGE(scip->set, localdown, scip->lp->cutoffbound); 3747 if( upinf != NULL ) 3748 *upinf = localupvalid && SCIPsetIsGE(scip->set, localup, scip->lp->cutoffbound); 3749 } 3750 } 3751 3752 if( down != NULL ) 3753 *down = localdown; 3754 if( up != NULL ) 3755 *up = localup; 3756 if( downvalid != NULL ) 3757 *downvalid = localdownvalid; 3758 if( upvalid != NULL ) 3759 *upvalid = localupvalid; 3760 3761 return SCIP_OKAY; 3762 } 3763 3764 /** gets strong branching information on column variables with fractional values 3765 * 3766 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 3767 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 3768 * 3769 * @pre This method can be called if @p scip is in one of the following stages: 3770 * - \ref SCIP_STAGE_PRESOLVED 3771 * - \ref SCIP_STAGE_SOLVING 3772 */ 3773 SCIP_RETCODE SCIPgetVarsStrongbranchesFrac( 3774 SCIP* scip, /**< SCIP data structure */ 3775 SCIP_VAR** vars, /**< variables to get strong branching values for */ 3776 int nvars, /**< number of variables */ 3777 int itlim, /**< iteration limit for strong branchings */ 3778 SCIP_Real* down, /**< stores dual bounds after branching variables down */ 3779 SCIP_Real* up, /**< stores dual bounds after branching variables up */ 3780 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL; 3781 * otherwise, they can only be used as an estimate value */ 3782 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL; 3783 * otherwise, they can only be used as an estimate value */ 3784 SCIP_Bool* downinf, /**< array to store whether the downward branches are infeasible, or NULL */ 3785 SCIP_Bool* upinf, /**< array to store whether the upward branches are infeasible, or NULL */ 3786 SCIP_Bool* downconflict, /**< array to store whether conflict constraints were created for 3787 * infeasible downward branches, or NULL */ 3788 SCIP_Bool* upconflict, /**< array to store whether conflict constraints were created for 3789 * infeasible upward branches, or NULL */ 3790 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred or the 3791 * solving process should be stopped (e.g., due to a time limit) */ 3792 ) 3793 { 3794 SCIP_COL** cols; 3795 int j; 3796 3797 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarsStrongbranchesFrac", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 3798 3799 assert( lperror != NULL ); 3800 assert( vars != NULL ); 3801 3802 /* set up data */ 3803 cols = NULL; 3804 SCIP_CALL( SCIPallocBufferArray(scip, &cols, nvars) ); 3805 assert(cols != NULL); 3806 for( j = 0; j < nvars; ++j ) 3807 { 3808 SCIP_VAR* var; 3809 SCIP_COL* col; 3810 3811 if( downvalid != NULL ) 3812 downvalid[j] = FALSE; 3813 if( upvalid != NULL ) 3814 upvalid[j] = FALSE; 3815 if( downinf != NULL ) 3816 downinf[j] = FALSE; 3817 if( upinf != NULL ) 3818 upinf[j] = FALSE; 3819 if( downconflict != NULL ) 3820 downconflict[j] = FALSE; 3821 if( upconflict != NULL ) 3822 upconflict[j] = FALSE; 3823 3824 var = vars[j]; 3825 assert( var != NULL ); 3826 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 3827 { 3828 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var)); 3829 SCIPfreeBufferArray(scip, &cols); 3830 return SCIP_INVALIDDATA; 3831 } 3832 3833 col = SCIPvarGetCol(var); 3834 assert(col != NULL); 3835 cols[j] = col; 3836 3837 if( !SCIPcolIsInLP(col) ) 3838 { 3839 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var)); 3840 SCIPfreeBufferArray(scip, &cols); 3841 return SCIP_INVALIDDATA; 3842 } 3843 } 3844 3845 /* check if the solving process should be aborted */ 3846 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) ) 3847 { 3848 /* mark this as if the LP failed */ 3849 *lperror = TRUE; 3850 } 3851 else 3852 { 3853 /* call strong branching for columns with fractional value */ 3854 SCIP_CALL( SCIPcolGetStrongbranches(cols, nvars, FALSE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, 3855 down, up, downvalid, upvalid, lperror) ); 3856 3857 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to 3858 * declare the sub nodes infeasible 3859 */ 3860 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve ) 3861 { 3862 for( j = 0; j < nvars; ++j ) 3863 { 3864 SCIP_CALL( analyzeStrongbranch(scip, vars[j], (downinf != NULL) ? (&(downinf[j])) : NULL, 3865 (upinf != NULL) ? (&(upinf[j])) : NULL, (downconflict != NULL) ? (&(downconflict[j])) : NULL, 3866 (upconflict != NULL) ? (&(upconflict[j])) : NULL) ); 3867 } 3868 } 3869 } 3870 SCIPfreeBufferArray(scip, &cols); 3871 3872 return SCIP_OKAY; 3873 } 3874 3875 /** gets strong branching information on column variables with integral values 3876 * 3877 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 3878 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 3879 * 3880 * @pre This method can be called if @p scip is in one of the following stages: 3881 * - \ref SCIP_STAGE_PRESOLVED 3882 * - \ref SCIP_STAGE_SOLVING 3883 */ 3884 SCIP_RETCODE SCIPgetVarsStrongbranchesInt( 3885 SCIP* scip, /**< SCIP data structure */ 3886 SCIP_VAR** vars, /**< variables to get strong branching values for */ 3887 int nvars, /**< number of variables */ 3888 int itlim, /**< iteration limit for strong branchings */ 3889 SCIP_Real* down, /**< stores dual bounds after branching variables down */ 3890 SCIP_Real* up, /**< stores dual bounds after branching variables up */ 3891 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL; 3892 * otherwise, they can only be used as an estimate value */ 3893 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL; 3894 * otherwise, they can only be used as an estimate value */ 3895 SCIP_Bool* downinf, /**< array to store whether the downward branches are infeasible, or NULL */ 3896 SCIP_Bool* upinf, /**< array to store whether the upward branches are infeasible, or NULL */ 3897 SCIP_Bool* downconflict, /**< array to store whether conflict constraints were created for 3898 * infeasible downward branches, or NULL */ 3899 SCIP_Bool* upconflict, /**< array to store whether conflict constraints were created for 3900 * infeasible upward branches, or NULL */ 3901 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred or the 3902 * solving process should be stopped (e.g., due to a time limit) */ 3903 ) 3904 { 3905 SCIP_COL** cols; 3906 int j; 3907 3908 assert(lperror != NULL); 3909 3910 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarsStrongbranchesInt", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 3911 3912 assert( vars != NULL ); 3913 3914 /* set up data */ 3915 cols = NULL; 3916 SCIP_CALL( SCIPallocBufferArray(scip, &cols, nvars) ); 3917 assert(cols != NULL); 3918 for( j = 0; j < nvars; ++j ) 3919 { 3920 SCIP_VAR* var; 3921 SCIP_COL* col; 3922 3923 if( downvalid != NULL ) 3924 downvalid[j] = FALSE; 3925 if( upvalid != NULL ) 3926 upvalid[j] = FALSE; 3927 if( downinf != NULL ) 3928 downinf[j] = FALSE; 3929 if( upinf != NULL ) 3930 upinf[j] = FALSE; 3931 if( downconflict != NULL ) 3932 downconflict[j] = FALSE; 3933 if( upconflict != NULL ) 3934 upconflict[j] = FALSE; 3935 3936 var = vars[j]; 3937 assert( var != NULL ); 3938 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 3939 { 3940 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable <%s>\n", SCIPvarGetName(var)); 3941 SCIPfreeBufferArray(scip, &cols); 3942 return SCIP_INVALIDDATA; 3943 } 3944 3945 col = SCIPvarGetCol(var); 3946 assert(col != NULL); 3947 cols[j] = col; 3948 3949 if( !SCIPcolIsInLP(col) ) 3950 { 3951 SCIPerrorMessage("cannot get strong branching information on variable <%s> not in current LP\n", SCIPvarGetName(var)); 3952 SCIPfreeBufferArray(scip, &cols); 3953 return SCIP_INVALIDDATA; 3954 } 3955 } 3956 3957 /* check if the solving process should be aborted */ 3958 if( SCIPsolveIsStopped(scip->set, scip->stat, FALSE) ) 3959 { 3960 /* mark this as if the LP failed */ 3961 *lperror = TRUE; 3962 } 3963 else 3964 { 3965 /* call strong branching for columns */ 3966 SCIP_CALL( SCIPcolGetStrongbranches(cols, nvars, TRUE, scip->set, scip->stat, scip->transprob, scip->lp, itlim, 3967 down, up, downvalid, upvalid, lperror) ); 3968 3969 /* check, if the branchings are infeasible; in exact solving mode, we cannot trust the strong branching enough to 3970 * declare the sub nodes infeasible 3971 */ 3972 if( !(*lperror) && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && !scip->set->misc_exactsolve ) 3973 { 3974 for( j = 0; j < nvars; ++j ) 3975 { 3976 SCIP_CALL( analyzeStrongbranch(scip, vars[j], (downinf != NULL) ? (&(downinf[j])) : NULL, 3977 (upinf != NULL) ? (&(upinf[j])) : NULL, (downconflict != NULL) ? (&(downconflict[j])) : NULL, 3978 (upconflict != NULL) ? (&(upconflict[j])) : NULL) ); 3979 } 3980 } 3981 } 3982 SCIPfreeBufferArray(scip, &cols); 3983 3984 return SCIP_OKAY; 3985 } 3986 3987 /** get LP solution status of last strong branching call (currently only works for strong branching with propagation) */ 3988 SCIP_LPSOLSTAT SCIPgetLastStrongbranchLPSolStat( 3989 SCIP* scip, /**< SCIP data structure */ 3990 SCIP_BRANCHDIR branchdir /**< branching direction for which LP solution status is requested */ 3991 ) 3992 { 3993 assert(NULL != scip); 3994 assert(branchdir == SCIP_BRANCHDIR_DOWNWARDS || branchdir == SCIP_BRANCHDIR_UPWARDS); 3995 3996 return scip->stat->lastsblpsolstats[branchdir == SCIP_BRANCHDIR_DOWNWARDS ? 0 : 1]; 3997 } 3998 3999 /** gets strong branching information on COLUMN variable of the last SCIPgetVarStrongbranch() call; 4000 * returns values of SCIP_INVALID, if strong branching was not yet called on the given variable; 4001 * keep in mind, that the returned old values may have nothing to do with the current LP solution 4002 * 4003 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4004 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4005 * 4006 * @pre This method can be called if @p scip is in one of the following stages: 4007 * - \ref SCIP_STAGE_SOLVING 4008 * - \ref SCIP_STAGE_SOLVED 4009 */ 4010 SCIP_RETCODE SCIPgetVarStrongbranchLast( 4011 SCIP* scip, /**< SCIP data structure */ 4012 SCIP_VAR* var, /**< variable to get last strong branching values for */ 4013 SCIP_Real* down, /**< stores dual bound after branching column down */ 4014 SCIP_Real* up, /**< stores dual bound after branching column up */ 4015 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL; 4016 * otherwise, it can only be used as an estimate value */ 4017 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL; 4018 * otherwise, it can only be used as an estimate value */ 4019 SCIP_Real* solval, /**< stores LP solution value of variable at the last strong branching call, or NULL */ 4020 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */ 4021 ) 4022 { 4023 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarStrongbranchLast", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 4024 4025 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 4026 { 4027 SCIPerrorMessage("cannot get strong branching information on non-COLUMN variable\n"); 4028 return SCIP_INVALIDDATA; 4029 } 4030 4031 SCIPcolGetStrongbranchLast(SCIPvarGetCol(var), down, up, downvalid, upvalid, solval, lpobjval); 4032 4033 return SCIP_OKAY; 4034 } 4035 4036 /** sets strong branching information for a column variable 4037 * 4038 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4039 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4040 * 4041 * @pre This method can be called if @p scip is in one of the following stages: 4042 * - \ref SCIP_STAGE_SOLVING 4043 */ 4044 SCIP_RETCODE SCIPsetVarStrongbranchData( 4045 SCIP* scip, /**< SCIP data structure */ 4046 SCIP_VAR* var, /**< variable to set last strong branching values for */ 4047 SCIP_Real lpobjval, /**< objective value of the current LP */ 4048 SCIP_Real primsol, /**< primal solution value of the column in the current LP */ 4049 SCIP_Real down, /**< dual bound after branching column down */ 4050 SCIP_Real up, /**< dual bound after branching column up */ 4051 SCIP_Bool downvalid, /**< is the returned down value a valid dual bound? */ 4052 SCIP_Bool upvalid, /**< is the returned up value a valid dual bound? */ 4053 SCIP_Longint iter, /**< total number of strong branching iterations */ 4054 int itlim /**< iteration limit applied to the strong branching call */ 4055 ) 4056 { 4057 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetVarStrongbranchData", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 4058 4059 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 4060 { 4061 SCIPerrorMessage("cannot set strong branching information on non-COLUMN variable\n"); 4062 return SCIP_INVALIDDATA; 4063 } 4064 4065 SCIPcolSetStrongbranchData(SCIPvarGetCol(var), scip->set, scip->stat, scip->lp, lpobjval, primsol, 4066 down, up, downvalid, upvalid, iter, itlim); 4067 4068 return SCIP_OKAY; 4069 } 4070 4071 /** rounds the current solution and tries it afterwards; if feasible, adds it to storage 4072 * 4073 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4074 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4075 * 4076 * @pre This method can be called if @p scip is in one of the following stages: 4077 * - \ref SCIP_STAGE_SOLVING 4078 */ 4079 SCIP_RETCODE SCIPtryStrongbranchLPSol( 4080 SCIP* scip, /**< SCIP data structure */ 4081 SCIP_Bool* foundsol, /**< stores whether solution was feasible and good enough to keep */ 4082 SCIP_Bool* cutoff /**< stores whether solution was cutoff due to exceeding the cutoffbound */ 4083 ) 4084 { 4085 assert(scip != NULL); 4086 assert(foundsol != NULL); 4087 assert(cutoff != NULL); 4088 4089 SCIP_CALL( SCIPcheckStage(scip, "SCIPtryStrongbranchLPSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 4090 4091 if( scip->set->branch_checksbsol ) 4092 { 4093 SCIP_SOL* sol; 4094 SCIP_Bool rounded = TRUE; 4095 SCIP_Real value = SCIPgetLPObjval(scip); 4096 SCIP_Longint oldnbestsolsfound = scip->primal->nbestsolsfound; 4097 4098 /* start clock for strong branching solutions */ 4099 SCIPclockStart(scip->stat->sbsoltime, scip->set); 4100 4101 SCIP_CALL( SCIPcreateLPSol(scip, &sol, NULL) ); 4102 SCIPsolSetStrongbranching(sol); 4103 4104 /* try to round the strong branching solution */ 4105 if( scip->set->branch_roundsbsol ) 4106 { 4107 SCIP_CALL( SCIProundSol(scip, sol, &rounded) ); 4108 } 4109 4110 /* check the solution for feasibility if rounding worked well (or was not tried) */ 4111 if( rounded ) 4112 { 4113 SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, FALSE, TRUE, FALSE, foundsol) ); 4114 } 4115 else 4116 { 4117 SCIP_CALL( SCIPfreeSol(scip, &sol) ); 4118 } 4119 4120 if( *foundsol ) 4121 { 4122 SCIPdebugMsg(scip, "found new solution in strong branching\n"); 4123 4124 scip->stat->nsbsolsfound++; 4125 4126 if( scip->primal->nbestsolsfound != oldnbestsolsfound ) 4127 { 4128 scip->stat->nsbbestsolsfound++; 4129 } 4130 4131 if( SCIPisGE(scip, value, SCIPgetCutoffbound(scip)) ) 4132 *cutoff = TRUE; 4133 } 4134 4135 /* stop clock for strong branching solutions */ 4136 SCIPclockStop(scip->stat->sbsoltime, scip->set); 4137 } 4138 return SCIP_OKAY; 4139 } 4140 4141 4142 /** gets node number of the last node in current branch and bound run, where strong branching was used on the 4143 * given variable, or -1 if strong branching was never applied to the variable in current run 4144 * 4145 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4146 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4147 * 4148 * @pre This method can be called if @p scip is in one of the following stages: 4149 * - \ref SCIP_STAGE_TRANSFORMING 4150 * - \ref SCIP_STAGE_TRANSFORMED 4151 * - \ref SCIP_STAGE_INITPRESOLVE 4152 * - \ref SCIP_STAGE_PRESOLVING 4153 * - \ref SCIP_STAGE_EXITPRESOLVE 4154 * - \ref SCIP_STAGE_PRESOLVED 4155 * - \ref SCIP_STAGE_INITSOLVE 4156 * - \ref SCIP_STAGE_SOLVING 4157 * - \ref SCIP_STAGE_SOLVED 4158 * - \ref SCIP_STAGE_EXITSOLVE 4159 */ 4160 SCIP_Longint SCIPgetVarStrongbranchNode( 4161 SCIP* scip, /**< SCIP data structure */ 4162 SCIP_VAR* var /**< variable to get last strong branching node for */ 4163 ) 4164 { 4165 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarStrongbranchNode", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 4166 4167 assert( var->scip == scip ); 4168 4169 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 4170 return -1; 4171 4172 return SCIPcolGetStrongbranchNode(SCIPvarGetCol(var)); 4173 } 4174 4175 /** if strong branching was already applied on the variable at the current node, returns the number of LPs solved after 4176 * the LP where the strong branching on this variable was applied; 4177 * if strong branching was not yet applied on the variable at the current node, returns INT_MAX 4178 * 4179 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4180 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4181 * 4182 * @pre This method can be called if @p scip is in one of the following stages: 4183 * - \ref SCIP_STAGE_TRANSFORMING 4184 * - \ref SCIP_STAGE_TRANSFORMED 4185 * - \ref SCIP_STAGE_INITPRESOLVE 4186 * - \ref SCIP_STAGE_PRESOLVING 4187 * - \ref SCIP_STAGE_EXITPRESOLVE 4188 * - \ref SCIP_STAGE_PRESOLVED 4189 * - \ref SCIP_STAGE_INITSOLVE 4190 * - \ref SCIP_STAGE_SOLVING 4191 * - \ref SCIP_STAGE_SOLVED 4192 * - \ref SCIP_STAGE_EXITSOLVE 4193 */ 4194 SCIP_Longint SCIPgetVarStrongbranchLPAge( 4195 SCIP* scip, /**< SCIP data structure */ 4196 SCIP_VAR* var /**< variable to get strong branching LP age for */ 4197 ) 4198 { 4199 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarStrongbranchLPAge", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 4200 4201 assert( var->scip == scip ); 4202 4203 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 4204 return SCIP_LONGINT_MAX; 4205 4206 return SCIPcolGetStrongbranchLPAge(SCIPvarGetCol(var), scip->stat); 4207 } 4208 4209 /** gets number of times, strong branching was applied in current run on the given variable 4210 * 4211 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4212 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4213 * 4214 * @pre This method can be called if @p scip is in one of the following stages: 4215 * - \ref SCIP_STAGE_TRANSFORMING 4216 * - \ref SCIP_STAGE_TRANSFORMED 4217 * - \ref SCIP_STAGE_INITPRESOLVE 4218 * - \ref SCIP_STAGE_PRESOLVING 4219 * - \ref SCIP_STAGE_EXITPRESOLVE 4220 * - \ref SCIP_STAGE_PRESOLVED 4221 * - \ref SCIP_STAGE_INITSOLVE 4222 * - \ref SCIP_STAGE_SOLVING 4223 * - \ref SCIP_STAGE_SOLVED 4224 * - \ref SCIP_STAGE_EXITSOLVE 4225 */ 4226 int SCIPgetVarNStrongbranchs( 4227 SCIP* scip, /**< SCIP data structure */ 4228 SCIP_VAR* var /**< variable to get last strong branching node for */ 4229 ) 4230 { 4231 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarNStrongbranchs", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 4232 4233 assert( var->scip == scip ); 4234 4235 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 4236 return 0; 4237 4238 return SCIPcolGetNStrongbranchs(SCIPvarGetCol(var)); 4239 } 4240 4241 /** adds given values to lock numbers of type @p locktype of variable for rounding 4242 * 4243 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4244 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4245 * 4246 * @pre This method can be called if @p scip is in one of the following stages: 4247 * - \ref SCIP_STAGE_PROBLEM 4248 * - \ref SCIP_STAGE_TRANSFORMING 4249 * - \ref SCIP_STAGE_TRANSFORMED 4250 * - \ref SCIP_STAGE_INITPRESOLVE 4251 * - \ref SCIP_STAGE_PRESOLVING 4252 * - \ref SCIP_STAGE_EXITPRESOLVE 4253 * - \ref SCIP_STAGE_PRESOLVED 4254 * - \ref SCIP_STAGE_INITSOLVE 4255 * - \ref SCIP_STAGE_SOLVING 4256 * - \ref SCIP_STAGE_EXITSOLVE 4257 * - \ref SCIP_STAGE_FREETRANS 4258 */ 4259 SCIP_RETCODE SCIPaddVarLocksType( 4260 SCIP* scip, /**< SCIP data structure */ 4261 SCIP_VAR* var, /**< problem variable */ 4262 SCIP_LOCKTYPE locktype, /**< type of the variable locks */ 4263 int nlocksdown, /**< modification in number of rounding down locks */ 4264 int nlocksup /**< modification in number of rounding up locks */ 4265 ) 4266 { 4267 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarLocksType", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) ); 4268 4269 assert( var->scip == scip ); 4270 4271 switch( scip->set->stage ) 4272 { 4273 case SCIP_STAGE_PROBLEM: 4274 assert(!SCIPvarIsTransformed(var)); 4275 /*lint -fallthrough*/ 4276 case SCIP_STAGE_TRANSFORMING: 4277 case SCIP_STAGE_TRANSFORMED: 4278 case SCIP_STAGE_INITPRESOLVE: 4279 case SCIP_STAGE_PRESOLVING: 4280 case SCIP_STAGE_EXITPRESOLVE: 4281 case SCIP_STAGE_PRESOLVED: 4282 case SCIP_STAGE_INITSOLVE: 4283 case SCIP_STAGE_SOLVING: 4284 case SCIP_STAGE_EXITSOLVE: 4285 case SCIP_STAGE_FREETRANS: 4286 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, locktype, nlocksdown, nlocksup) ); 4287 return SCIP_OKAY; 4288 4289 default: 4290 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 4291 return SCIP_INVALIDCALL; 4292 } /*lint !e788*/ 4293 } 4294 4295 /** adds given values to lock numbers of variable for rounding 4296 * 4297 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4298 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4299 * 4300 * @pre This method can be called if @p scip is in one of the following stages: 4301 * - \ref SCIP_STAGE_PROBLEM 4302 * - \ref SCIP_STAGE_TRANSFORMING 4303 * - \ref SCIP_STAGE_TRANSFORMED 4304 * - \ref SCIP_STAGE_INITPRESOLVE 4305 * - \ref SCIP_STAGE_PRESOLVING 4306 * - \ref SCIP_STAGE_EXITPRESOLVE 4307 * - \ref SCIP_STAGE_PRESOLVED 4308 * - \ref SCIP_STAGE_INITSOLVE 4309 * - \ref SCIP_STAGE_SOLVING 4310 * - \ref SCIP_STAGE_EXITSOLVE 4311 * - \ref SCIP_STAGE_FREETRANS 4312 * 4313 * @note This method will always add variable locks of type model 4314 * 4315 * @note It is recommented to use SCIPaddVarLocksType() 4316 */ 4317 SCIP_RETCODE SCIPaddVarLocks( 4318 SCIP* scip, /**< SCIP data structure */ 4319 SCIP_VAR* var, /**< problem variable */ 4320 int nlocksdown, /**< modification in number of rounding down locks */ 4321 int nlocksup /**< modification in number of rounding up locks */ 4322 ) 4323 { 4324 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarLocks", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) ); 4325 4326 SCIP_CALL( SCIPaddVarLocksType(scip, var, SCIP_LOCKTYPE_MODEL, nlocksdown, nlocksup) ); 4327 4328 return SCIP_OKAY; 4329 } 4330 4331 /** add locks of variable with respect to the lock status of the constraint and its negation; 4332 * this method should be called whenever the lock status of a variable in a constraint changes, for example if 4333 * the coefficient of the variable changed its sign or if the left or right hand sides of the constraint were 4334 * added or removed 4335 * 4336 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4337 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4338 * 4339 * @pre This method can be called if @p scip is in one of the following stages: 4340 * - \ref SCIP_STAGE_PROBLEM 4341 * - \ref SCIP_STAGE_TRANSFORMING 4342 * - \ref SCIP_STAGE_TRANSFORMED 4343 * - \ref SCIP_STAGE_INITPRESOLVE 4344 * - \ref SCIP_STAGE_PRESOLVING 4345 * - \ref SCIP_STAGE_EXITPRESOLVE 4346 * - \ref SCIP_STAGE_INITSOLVE 4347 * - \ref SCIP_STAGE_SOLVING 4348 * - \ref SCIP_STAGE_EXITSOLVE 4349 * - \ref SCIP_STAGE_FREETRANS 4350 */ 4351 SCIP_RETCODE SCIPlockVarCons( 4352 SCIP* scip, /**< SCIP data structure */ 4353 SCIP_VAR* var, /**< problem variable */ 4354 SCIP_CONS* cons, /**< constraint */ 4355 SCIP_Bool lockdown, /**< should the rounding be locked in downwards direction? */ 4356 SCIP_Bool lockup /**< should the rounding be locked in upwards direction? */ 4357 ) 4358 { 4359 int nlocksdown[NLOCKTYPES]; 4360 int nlocksup[NLOCKTYPES]; 4361 int i; 4362 4363 SCIP_CALL( SCIPcheckStage(scip, "SCIPlockVarCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) ); 4364 4365 assert( var->scip == scip ); 4366 4367 for( i = 0; i < NLOCKTYPES; i++ ) 4368 { 4369 nlocksdown[i] = 0; 4370 nlocksup[i] = 0; 4371 4372 if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) ) 4373 { 4374 if( lockdown ) 4375 ++nlocksdown[i]; 4376 if( lockup ) 4377 ++nlocksup[i]; 4378 } 4379 if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) ) 4380 { 4381 if( lockdown ) 4382 ++nlocksup[i]; 4383 if( lockup ) 4384 ++nlocksdown[i]; 4385 } 4386 } 4387 4388 switch( scip->set->stage ) 4389 { 4390 case SCIP_STAGE_PROBLEM: 4391 assert(!SCIPvarIsTransformed(var)); 4392 /*lint -fallthrough*/ 4393 case SCIP_STAGE_TRANSFORMING: 4394 case SCIP_STAGE_TRANSFORMED: 4395 case SCIP_STAGE_INITPRESOLVE: 4396 case SCIP_STAGE_PRESOLVING: 4397 case SCIP_STAGE_EXITPRESOLVE: 4398 case SCIP_STAGE_INITSOLVE: 4399 case SCIP_STAGE_SOLVING: 4400 case SCIP_STAGE_EXITSOLVE: 4401 case SCIP_STAGE_FREETRANS: 4402 for( i = 0; i < NLOCKTYPES; i++ ) 4403 { 4404 if( nlocksdown[i] == 0 && nlocksup[i] == 0 ) 4405 continue; 4406 4407 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) ); 4408 } 4409 return SCIP_OKAY; 4410 4411 default: 4412 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 4413 return SCIP_INVALIDCALL; 4414 } /*lint !e788*/ 4415 } 4416 4417 /** remove locks of type @p locktype of variable with respect to the lock status of the constraint and its negation; 4418 * this method should be called whenever the lock status of a variable in a constraint changes, for example if 4419 * the coefficient of the variable changed its sign or if the left or right hand sides of the constraint were 4420 * added or removed 4421 * 4422 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4423 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4424 * 4425 * @pre This method can be called if @p scip is in one of the following stages: 4426 * - \ref SCIP_STAGE_PROBLEM 4427 * - \ref SCIP_STAGE_TRANSFORMING 4428 * - \ref SCIP_STAGE_TRANSFORMED 4429 * - \ref SCIP_STAGE_INITPRESOLVE 4430 * - \ref SCIP_STAGE_PRESOLVING 4431 * - \ref SCIP_STAGE_EXITPRESOLVE 4432 * - \ref SCIP_STAGE_INITSOLVE 4433 * - \ref SCIP_STAGE_SOLVING 4434 * - \ref SCIP_STAGE_EXITSOLVE 4435 * - \ref SCIP_STAGE_FREETRANS 4436 */ 4437 SCIP_RETCODE SCIPunlockVarCons( 4438 SCIP* scip, /**< SCIP data structure */ 4439 SCIP_VAR* var, /**< problem variable */ 4440 SCIP_CONS* cons, /**< constraint */ 4441 SCIP_Bool lockdown, /**< should the rounding be unlocked in downwards direction? */ 4442 SCIP_Bool lockup /**< should the rounding be unlocked in upwards direction? */ 4443 ) 4444 { 4445 int nlocksdown[NLOCKTYPES]; 4446 int nlocksup[NLOCKTYPES]; 4447 int i; 4448 4449 SCIP_CALL( SCIPcheckStage(scip, "SCIPunlockVarCons", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) ); 4450 4451 assert( var->scip == scip ); 4452 4453 for( i = 0; i < NLOCKTYPES; i++ ) 4454 { 4455 nlocksdown[i] = 0; 4456 nlocksup[i] = 0; 4457 4458 if( SCIPconsIsLockedTypePos(cons, (SCIP_LOCKTYPE) i) ) 4459 { 4460 if( lockdown ) 4461 ++nlocksdown[i]; 4462 if( lockup ) 4463 ++nlocksup[i]; 4464 } 4465 if( SCIPconsIsLockedTypeNeg(cons, (SCIP_LOCKTYPE) i) ) 4466 { 4467 if( lockdown ) 4468 ++nlocksup[i]; 4469 if( lockup ) 4470 ++nlocksdown[i]; 4471 } 4472 } 4473 switch( scip->set->stage ) 4474 { 4475 case SCIP_STAGE_PROBLEM: 4476 assert(!SCIPvarIsTransformed(var)); 4477 /*lint -fallthrough*/ 4478 case SCIP_STAGE_TRANSFORMING: 4479 case SCIP_STAGE_TRANSFORMED: 4480 case SCIP_STAGE_INITPRESOLVE: 4481 case SCIP_STAGE_PRESOLVING: 4482 case SCIP_STAGE_EXITPRESOLVE: 4483 case SCIP_STAGE_INITSOLVE: 4484 case SCIP_STAGE_SOLVING: 4485 case SCIP_STAGE_EXITSOLVE: 4486 case SCIP_STAGE_FREETRANS: 4487 for( i = 0; i < NLOCKTYPES; i++ ) 4488 { 4489 if( nlocksdown[i] == 0 && nlocksup[i] == 0 ) 4490 continue; 4491 4492 SCIP_CALL( SCIPvarAddLocks(var, scip->mem->probmem, scip->set, scip->eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) ); 4493 } 4494 return SCIP_OKAY; 4495 4496 default: 4497 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 4498 return SCIP_INVALIDCALL; 4499 } /*lint !e788*/ 4500 } 4501 4502 /** changes variable's objective value 4503 * 4504 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4505 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4506 * 4507 * @pre This method can be called if @p scip is in one of the following stages: 4508 * - \ref SCIP_STAGE_PROBLEM 4509 * - \ref SCIP_STAGE_TRANSFORMING 4510 * - \ref SCIP_STAGE_PRESOLVING 4511 * - \ref SCIP_STAGE_PRESOLVED 4512 */ 4513 SCIP_RETCODE SCIPchgVarObj( 4514 SCIP* scip, /**< SCIP data structure */ 4515 SCIP_VAR* var, /**< variable to change the objective value for */ 4516 SCIP_Real newobj /**< new objective value */ 4517 ) 4518 { 4519 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarObj", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 4520 4521 assert( var->scip == scip ); 4522 4523 /* forbid infinite objective values */ 4524 if( SCIPisInfinity(scip, REALABS(newobj)) ) 4525 { 4526 SCIPerrorMessage("invalid objective value: objective value is infinite\n"); 4527 return SCIP_INVALIDDATA; 4528 } 4529 4530 switch( scip->set->stage ) 4531 { 4532 case SCIP_STAGE_PROBLEM: 4533 assert(!SCIPvarIsTransformed(var)); 4534 SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set, scip->origprob, scip->primal, scip->lp, scip->eventqueue, newobj) ); 4535 return SCIP_OKAY; 4536 4537 case SCIP_STAGE_TRANSFORMED: 4538 case SCIP_STAGE_TRANSFORMING: 4539 case SCIP_STAGE_PRESOLVING: 4540 case SCIP_STAGE_PRESOLVED: 4541 SCIP_CALL( SCIPvarChgObj(var, scip->mem->probmem, scip->set, scip->transprob, scip->primal, scip->lp, scip->eventqueue, newobj) ); 4542 return SCIP_OKAY; 4543 4544 default: 4545 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 4546 return SCIP_INVALIDCALL; 4547 } /*lint !e788*/ 4548 } 4549 4550 /** adds value to variable's objective value 4551 * 4552 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4553 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4554 * 4555 * @pre This method can be called if @p scip is in one of the following stages: 4556 * - \ref SCIP_STAGE_PROBLEM 4557 * - \ref SCIP_STAGE_TRANSFORMING 4558 * - \ref SCIP_STAGE_PRESOLVING 4559 * - \ref SCIP_STAGE_EXITPRESOLVE 4560 * - \ref SCIP_STAGE_PRESOLVED 4561 */ 4562 SCIP_RETCODE SCIPaddVarObj( 4563 SCIP* scip, /**< SCIP data structure */ 4564 SCIP_VAR* var, /**< variable to change the objective value for */ 4565 SCIP_Real addobj /**< additional objective value */ 4566 ) 4567 { 4568 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarObj", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 4569 4570 assert( var->scip == scip ); 4571 4572 switch( scip->set->stage ) 4573 { 4574 case SCIP_STAGE_PROBLEM: 4575 assert(!SCIPvarIsTransformed(var)); 4576 SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal, 4577 scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) ); 4578 return SCIP_OKAY; 4579 4580 case SCIP_STAGE_TRANSFORMING: 4581 case SCIP_STAGE_PRESOLVING: 4582 case SCIP_STAGE_EXITPRESOLVE: 4583 case SCIP_STAGE_PRESOLVED: 4584 SCIP_CALL( SCIPvarAddObj(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->primal, 4585 scip->tree, scip->reopt, scip->lp, scip->eventfilter, scip->eventqueue, addobj) ); 4586 return SCIP_OKAY; 4587 4588 default: 4589 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 4590 return SCIP_INVALIDCALL; 4591 } /*lint !e788*/ 4592 } 4593 4594 /** returns the adjusted (i.e. rounded, if the given variable is of integral type) lower bound value; 4595 * does not change the bounds of the variable 4596 * 4597 * @return adjusted lower bound for the given variable; the bound of the variable is not changed 4598 * 4599 * @pre This method can be called if @p scip is in one of the following stages: 4600 * - \ref SCIP_STAGE_PROBLEM 4601 * - \ref SCIP_STAGE_TRANSFORMING 4602 * - \ref SCIP_STAGE_TRANSFORMED 4603 * - \ref SCIP_STAGE_INITPRESOLVE 4604 * - \ref SCIP_STAGE_PRESOLVING 4605 * - \ref SCIP_STAGE_EXITPRESOLVE 4606 * - \ref SCIP_STAGE_PRESOLVED 4607 * - \ref SCIP_STAGE_INITSOLVE 4608 * - \ref SCIP_STAGE_SOLVING 4609 * - \ref SCIP_STAGE_SOLVED 4610 * - \ref SCIP_STAGE_EXITSOLVE 4611 * - \ref SCIP_STAGE_FREETRANS 4612 */ 4613 SCIP_Real SCIPadjustedVarLb( 4614 SCIP* scip, /**< SCIP data structure */ 4615 SCIP_VAR* var, /**< variable to adjust the bound for */ 4616 SCIP_Real lb /**< lower bound value to adjust */ 4617 ) 4618 { 4619 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPadjustedVarLb", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 4620 4621 SCIPvarAdjustLb(var, scip->set, &lb); 4622 4623 return lb; 4624 } 4625 4626 /** returns the adjusted (i.e. rounded, if the given variable is of integral type) upper bound value; 4627 * does not change the bounds of the variable 4628 * 4629 * @return adjusted upper bound for the given variable; the bound of the variable is not changed 4630 * 4631 * @pre This method can be called if @p scip is in one of the following stages: 4632 * - \ref SCIP_STAGE_PROBLEM 4633 * - \ref SCIP_STAGE_TRANSFORMING 4634 * - \ref SCIP_STAGE_TRANSFORMED 4635 * - \ref SCIP_STAGE_INITPRESOLVE 4636 * - \ref SCIP_STAGE_PRESOLVING 4637 * - \ref SCIP_STAGE_EXITPRESOLVE 4638 * - \ref SCIP_STAGE_PRESOLVED 4639 * - \ref SCIP_STAGE_INITSOLVE 4640 * - \ref SCIP_STAGE_SOLVING 4641 * - \ref SCIP_STAGE_SOLVED 4642 * - \ref SCIP_STAGE_EXITSOLVE 4643 * - \ref SCIP_STAGE_FREETRANS 4644 */ 4645 SCIP_Real SCIPadjustedVarUb( 4646 SCIP* scip, /**< SCIP data structure */ 4647 SCIP_VAR* var, /**< variable to adjust the bound for */ 4648 SCIP_Real ub /**< upper bound value to adjust */ 4649 ) 4650 { 4651 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPadjustedVarUb", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 4652 4653 SCIPvarAdjustUb(var, scip->set, &ub); 4654 4655 return ub; 4656 } 4657 4658 /** depending on SCIP's stage, changes lower bound of variable in the problem, in preprocessing, or in current node; 4659 * if possible, adjusts bound to integral value; doesn't store any inference information in the bound change, such 4660 * that in conflict analysis, this change is treated like a branching decision 4661 * 4662 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 4663 * SCIPgetVars()) gets resorted. 4664 * 4665 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4666 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4667 * 4668 * @pre This method can be called if @p scip is in one of the following stages: 4669 * - \ref SCIP_STAGE_PROBLEM 4670 * - \ref SCIP_STAGE_TRANSFORMING 4671 * - \ref SCIP_STAGE_PRESOLVING 4672 * - \ref SCIP_STAGE_SOLVING 4673 * 4674 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 4675 */ 4676 SCIP_RETCODE SCIPchgVarLb( 4677 SCIP* scip, /**< SCIP data structure */ 4678 SCIP_VAR* var, /**< variable to change the bound for */ 4679 SCIP_Real newbound /**< new value for bound */ 4680 ) 4681 { 4682 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLb", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 4683 4684 SCIPvarAdjustLb(var, scip->set, &newbound); 4685 4686 /* ignore tightenings of lower bounds to +infinity during solving process */ 4687 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 4688 { 4689 #ifndef NDEBUG 4690 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var), 4691 SCIPvarGetLbLocal(var)); 4692 #endif 4693 return SCIP_OKAY; 4694 } 4695 4696 switch( scip->set->stage ) 4697 { 4698 case SCIP_STAGE_PROBLEM: 4699 assert(!SCIPvarIsTransformed(var)); 4700 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4701 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 4702 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4703 scip->branchcand, scip->eventqueue, newbound) ); 4704 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) ); 4705 break; 4706 4707 case SCIP_STAGE_TRANSFORMING: 4708 case SCIP_STAGE_PRESOLVED: 4709 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4710 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 4711 break; 4712 4713 case SCIP_STAGE_PRESOLVING: 4714 if( !SCIPinProbing(scip) ) 4715 { 4716 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 4717 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 4718 4719 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 4720 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, 4721 var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) ); 4722 4723 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 4724 { 4725 SCIP_Bool infeasible; 4726 4727 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) ); 4728 assert(!infeasible); 4729 } 4730 break; 4731 } 4732 /*lint -fallthrough*/ 4733 case SCIP_STAGE_SOLVING: 4734 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 4735 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 4736 scip->cliquetable, var, newbound, 4737 SCIP_BOUNDTYPE_LOWER, FALSE) ); 4738 break; 4739 4740 default: 4741 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 4742 return SCIP_INVALIDCALL; 4743 } /*lint !e788*/ 4744 4745 return SCIP_OKAY; 4746 } 4747 4748 /** depending on SCIP's stage, changes upper bound of variable in the problem, in preprocessing, or in current node; 4749 * if possible, adjusts bound to integral value; doesn't store any inference information in the bound change, such 4750 * that in conflict analysis, this change is treated like a branching decision 4751 * 4752 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 4753 * SCIPgetVars()) gets resorted. 4754 * 4755 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4756 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4757 * 4758 * @pre This method can be called if @p scip is in one of the following stages: 4759 * - \ref SCIP_STAGE_PROBLEM 4760 * - \ref SCIP_STAGE_TRANSFORMING 4761 * - \ref SCIP_STAGE_PRESOLVING 4762 * - \ref SCIP_STAGE_SOLVING 4763 * 4764 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 4765 */ 4766 SCIP_RETCODE SCIPchgVarUb( 4767 SCIP* scip, /**< SCIP data structure */ 4768 SCIP_VAR* var, /**< variable to change the bound for */ 4769 SCIP_Real newbound /**< new value for bound */ 4770 ) 4771 { 4772 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUb", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 4773 4774 SCIPvarAdjustUb(var, scip->set, &newbound); 4775 4776 /* ignore tightenings of upper bounds to -infinity during solving process */ 4777 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 4778 { 4779 #ifndef NDEBUG 4780 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var), 4781 SCIPvarGetUbLocal(var)); 4782 #endif 4783 return SCIP_OKAY; 4784 } 4785 4786 switch( scip->set->stage ) 4787 { 4788 case SCIP_STAGE_PROBLEM: 4789 assert(!SCIPvarIsTransformed(var)); 4790 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4791 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 4792 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4793 scip->branchcand, scip->eventqueue, newbound) ); 4794 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) ); 4795 break; 4796 4797 case SCIP_STAGE_TRANSFORMING: 4798 case SCIP_STAGE_PRESOLVED: 4799 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4800 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 4801 break; 4802 4803 case SCIP_STAGE_PRESOLVING: 4804 if( !SCIPinProbing(scip) ) 4805 { 4806 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 4807 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 4808 4809 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 4810 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 4811 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) ); 4812 4813 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 4814 { 4815 SCIP_Bool infeasible; 4816 4817 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) ); 4818 assert(!infeasible); 4819 } 4820 break; 4821 } 4822 /*lint -fallthrough*/ 4823 case SCIP_STAGE_SOLVING: 4824 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 4825 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 4826 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) ); 4827 break; 4828 4829 default: 4830 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 4831 return SCIP_INVALIDCALL; 4832 } /*lint !e788*/ 4833 4834 return SCIP_OKAY; 4835 } 4836 4837 /** changes lower bound of variable in the given node; if possible, adjust bound to integral value; doesn't store any 4838 * inference information in the bound change, such that in conflict analysis, this change is treated like a branching 4839 * decision 4840 * 4841 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4842 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4843 * 4844 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING 4845 */ 4846 SCIP_RETCODE SCIPchgVarLbNode( 4847 SCIP* scip, /**< SCIP data structure */ 4848 SCIP_NODE* node, /**< node to change bound at, or NULL for current node */ 4849 SCIP_VAR* var, /**< variable to change the bound for */ 4850 SCIP_Real newbound /**< new value for bound */ 4851 ) 4852 { 4853 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbNode", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 4854 4855 if( node == NULL ) 4856 { 4857 SCIP_CALL( SCIPchgVarLb(scip, var, newbound) ); 4858 } 4859 else 4860 { 4861 SCIPvarAdjustLb(var, scip->set, &newbound); 4862 4863 /* ignore tightenings of lower bounds to +infinity during solving process */ 4864 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 4865 { 4866 #ifndef NDEBUG 4867 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var), 4868 SCIPvarGetLbLocal(var)); 4869 #endif 4870 return SCIP_OKAY; 4871 } 4872 4873 SCIP_CALL( SCIPnodeAddBoundchg(node, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 4874 scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 4875 SCIP_BOUNDTYPE_LOWER, FALSE) ); 4876 } 4877 4878 return SCIP_OKAY; 4879 } 4880 4881 /** changes upper bound of variable in the given node; if possible, adjust bound to integral value; doesn't store any 4882 * inference information in the bound change, such that in conflict analysis, this change is treated like a branching 4883 * decision 4884 * 4885 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4886 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4887 * 4888 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING 4889 */ 4890 SCIP_RETCODE SCIPchgVarUbNode( 4891 SCIP* scip, /**< SCIP data structure */ 4892 SCIP_NODE* node, /**< node to change bound at, or NULL for current node */ 4893 SCIP_VAR* var, /**< variable to change the bound for */ 4894 SCIP_Real newbound /**< new value for bound */ 4895 ) 4896 { 4897 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbNode", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 4898 4899 if( node == NULL ) 4900 { 4901 SCIP_CALL( SCIPchgVarUb(scip, var, newbound) ); 4902 } 4903 else 4904 { 4905 SCIPvarAdjustUb(var, scip->set, &newbound); 4906 4907 /* ignore tightenings of upper bounds to -infinity during solving process */ 4908 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 4909 { 4910 #ifndef NDEBUG 4911 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var), 4912 SCIPvarGetUbLocal(var)); 4913 #endif 4914 return SCIP_OKAY; 4915 } 4916 4917 SCIP_CALL( SCIPnodeAddBoundchg(node, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 4918 scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 4919 SCIP_BOUNDTYPE_UPPER, FALSE) ); 4920 } 4921 4922 return SCIP_OKAY; 4923 } 4924 4925 /** changes global lower bound of variable; if possible, adjust bound to integral value; also tightens the local bound, 4926 * if the global bound is better than the local bound 4927 * 4928 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 4929 * SCIPgetVars()) gets resorted. 4930 * 4931 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 4932 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 4933 * 4934 * @pre This method can be called if @p scip is in one of the following stages: 4935 * - \ref SCIP_STAGE_PROBLEM 4936 * - \ref SCIP_STAGE_TRANSFORMING 4937 * - \ref SCIP_STAGE_TRANSFORMED 4938 * - \ref SCIP_STAGE_PRESOLVING 4939 * - \ref SCIP_STAGE_SOLVING 4940 * 4941 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 4942 */ 4943 SCIP_RETCODE SCIPchgVarLbGlobal( 4944 SCIP* scip, /**< SCIP data structure */ 4945 SCIP_VAR* var, /**< variable to change the bound for */ 4946 SCIP_Real newbound /**< new value for bound */ 4947 ) 4948 { 4949 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbGlobal", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 4950 4951 SCIPvarAdjustLb(var, scip->set, &newbound); 4952 4953 /* ignore tightenings of lower bounds to +infinity during solving process */ 4954 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 4955 { 4956 #ifndef NDEBUG 4957 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var), 4958 SCIPvarGetLbLocal(var)); 4959 #endif 4960 return SCIP_OKAY; 4961 } 4962 4963 switch( scip->set->stage ) 4964 { 4965 case SCIP_STAGE_PROBLEM: 4966 assert(!SCIPvarIsTransformed(var)); 4967 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4968 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 4969 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4970 scip->branchcand, scip->eventqueue, newbound) ); 4971 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) ); 4972 break; 4973 4974 case SCIP_STAGE_TRANSFORMING: 4975 case SCIP_STAGE_TRANSFORMED: 4976 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 4977 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 4978 break; 4979 4980 case SCIP_STAGE_PRESOLVING: 4981 if( !SCIPinProbing(scip) ) 4982 { 4983 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 4984 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 4985 4986 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 4987 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 4988 SCIP_BOUNDTYPE_LOWER, FALSE) ); 4989 4990 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 4991 { 4992 SCIP_Bool infeasible; 4993 4994 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) ); 4995 assert(!infeasible); 4996 } 4997 break; 4998 } 4999 /*lint -fallthrough*/ 5000 case SCIP_STAGE_SOLVING: 5001 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5002 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5003 SCIP_BOUNDTYPE_LOWER, FALSE) ); 5004 break; 5005 5006 default: 5007 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5008 return SCIP_INVALIDCALL; 5009 } /*lint !e788*/ 5010 5011 return SCIP_OKAY; 5012 } 5013 5014 /** changes global upper bound of variable; if possible, adjust bound to integral value; also tightens the local bound, 5015 * if the global bound is better than the local bound 5016 * 5017 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 5018 * SCIPgetVars()) gets resorted. 5019 * 5020 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5021 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5022 * 5023 * @pre This method can be called if @p scip is in one of the following stages: 5024 * - \ref SCIP_STAGE_PROBLEM 5025 * - \ref SCIP_STAGE_TRANSFORMING 5026 * - \ref SCIP_STAGE_TRANSFORMED 5027 * - \ref SCIP_STAGE_PRESOLVING 5028 * - \ref SCIP_STAGE_SOLVING 5029 * 5030 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 5031 */ 5032 SCIP_RETCODE SCIPchgVarUbGlobal( 5033 SCIP* scip, /**< SCIP data structure */ 5034 SCIP_VAR* var, /**< variable to change the bound for */ 5035 SCIP_Real newbound /**< new value for bound */ 5036 ) 5037 { 5038 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbGlobal", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5039 5040 SCIPvarAdjustUb(var, scip->set, &newbound); 5041 5042 /* ignore tightenings of upper bounds to -infinity during solving process */ 5043 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 5044 { 5045 #ifndef NDEBUG 5046 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var), 5047 SCIPvarGetUbLocal(var)); 5048 #endif 5049 return SCIP_OKAY; 5050 } 5051 5052 switch( scip->set->stage ) 5053 { 5054 case SCIP_STAGE_PROBLEM: 5055 assert(!SCIPvarIsTransformed(var)); 5056 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5057 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5058 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5059 scip->branchcand, scip->eventqueue, newbound) ); 5060 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) ); 5061 break; 5062 5063 case SCIP_STAGE_TRANSFORMING: 5064 case SCIP_STAGE_TRANSFORMED: 5065 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5066 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5067 break; 5068 5069 case SCIP_STAGE_PRESOLVING: 5070 if( !SCIPinProbing(scip) ) 5071 { 5072 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 5073 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 5074 5075 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5076 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5077 SCIP_BOUNDTYPE_UPPER, FALSE) ); 5078 5079 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 5080 { 5081 SCIP_Bool infeasible; 5082 5083 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, &infeasible) ); 5084 assert(!infeasible); 5085 } 5086 break; 5087 } 5088 /*lint -fallthrough*/ 5089 case SCIP_STAGE_SOLVING: 5090 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5091 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5092 SCIP_BOUNDTYPE_UPPER, FALSE) ); 5093 break; 5094 5095 default: 5096 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5097 return SCIP_INVALIDCALL; 5098 } /*lint !e788*/ 5099 5100 return SCIP_OKAY; 5101 } 5102 5103 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet 5104 * 5105 * Lazy bounds are bounds that are already enforced by constraints and the objective function. 5106 * Setting a lazy lower bound has the consequence that for variables which lower bound equals the lazy lower bound, 5107 * the lower bound does not need to be passed on to the LP solver. 5108 * This is especially useful in a column generation (branch-and-price) setting. 5109 * 5110 * @attention If the variable has a global lower bound below lazylb, then the global lower bound is tightened to 5111 * lazylb by a call to SCIPchgVarLbGlobal(). 5112 * 5113 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5114 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5115 * 5116 * @pre This method can be called if @p scip is in one of the following stages: 5117 * - \ref SCIP_STAGE_PROBLEM 5118 * - \ref SCIP_STAGE_TRANSFORMING 5119 * - \ref SCIP_STAGE_TRANSFORMED 5120 * - \ref SCIP_STAGE_PRESOLVING 5121 * - \ref SCIP_STAGE_SOLVING 5122 */ 5123 SCIP_RETCODE SCIPchgVarLbLazy( 5124 SCIP* scip, /**< SCIP data structure */ 5125 SCIP_VAR* var, /**< problem variable */ 5126 SCIP_Real lazylb /**< the lazy lower bound to be set */ 5127 ) 5128 { 5129 assert(scip != NULL); 5130 assert(var != NULL); 5131 5132 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarLbLazy", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5133 5134 if( SCIPisGT(scip, lazylb, SCIPvarGetLbGlobal(var)) ) 5135 { 5136 SCIP_CALL( SCIPchgVarLbGlobal(scip, var, lazylb) ); 5137 } 5138 5139 SCIP_CALL( SCIPvarChgLbLazy(var, scip->set, lazylb) ); 5140 5141 return SCIP_OKAY; 5142 } 5143 5144 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet 5145 * 5146 * Lazy bounds are bounds that are already enforced by constraints and the objective function. 5147 * Setting a lazy upper bound has the consequence that for variables which upper bound equals the lazy upper bound, 5148 * the upper bound does not need to be passed on to the LP solver. 5149 * This is especially useful in a column generation (branch-and-price) setting. 5150 * 5151 * @attention If the variable has a global upper bound above lazyub, then the global upper bound is tightened to 5152 * lazyub by a call to SCIPchgVarUbGlobal(). 5153 * 5154 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5155 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5156 * 5157 * @pre This method can be called if @p scip is in one of the following stages: 5158 * - \ref SCIP_STAGE_PROBLEM 5159 * - \ref SCIP_STAGE_TRANSFORMING 5160 * - \ref SCIP_STAGE_TRANSFORMED 5161 * - \ref SCIP_STAGE_PRESOLVING 5162 * - \ref SCIP_STAGE_SOLVING 5163 */ 5164 SCIP_RETCODE SCIPchgVarUbLazy( 5165 SCIP* scip, /**< SCIP data structure */ 5166 SCIP_VAR* var, /**< problem variable */ 5167 SCIP_Real lazyub /**< the lazy lower bound to be set */ 5168 ) 5169 { 5170 assert(scip != NULL); 5171 assert(var != NULL); 5172 5173 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarUbLazy", FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5174 5175 if( SCIPisLT(scip, lazyub, SCIPvarGetUbGlobal(var)) ) 5176 { 5177 SCIP_CALL( SCIPchgVarUbGlobal(scip, var, lazyub) ); 5178 } 5179 5180 SCIP_CALL( SCIPvarChgUbLazy(var, scip->set, lazyub) ); 5181 5182 return SCIP_OKAY; 5183 } 5184 5185 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter 5186 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value; 5187 * doesn't store any inference information in the bound change, such that in conflict analysis, this change 5188 * is treated like a branching decision 5189 * 5190 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 5191 * SCIPgetVars()) gets resorted. 5192 * 5193 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5194 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5195 * 5196 * @pre This method can be called if @p scip is in one of the following stages: 5197 * - \ref SCIP_STAGE_PROBLEM 5198 * - \ref SCIP_STAGE_PRESOLVING 5199 * - \ref SCIP_STAGE_SOLVING 5200 * 5201 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 5202 */ 5203 SCIP_RETCODE SCIPtightenVarLb( 5204 SCIP* scip, /**< SCIP data structure */ 5205 SCIP_VAR* var, /**< variable to change the bound for */ 5206 SCIP_Real newbound, /**< new value for bound */ 5207 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 5208 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */ 5209 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 5210 ) 5211 { 5212 SCIP_Real lb; 5213 SCIP_Real ub; 5214 5215 assert(infeasible != NULL); 5216 5217 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarLb", FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5218 /** @todo if needed provide pending local/global bound changes that will be flushed after leaving diving mode (as in struct_tree.h) */ 5219 assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || !SCIPinDive(scip)); 5220 5221 *infeasible = FALSE; 5222 if( tightened != NULL ) 5223 *tightened = FALSE; 5224 5225 SCIPvarAdjustLb(var, scip->set, &newbound); 5226 5227 /* ignore tightenings of lower bounds to +infinity during solving process */ 5228 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 5229 { 5230 #ifndef NDEBUG 5231 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var), 5232 SCIPvarGetLbLocal(var)); 5233 #endif 5234 return SCIP_OKAY; 5235 } 5236 5237 /* get current bounds */ 5238 lb = SCIPcomputeVarLbLocal(scip, var); 5239 ub = SCIPcomputeVarUbLocal(scip, var); 5240 assert(SCIPsetIsLE(scip->set, lb, ub)); 5241 5242 if( SCIPsetIsFeasGT(scip->set, newbound, ub) ) 5243 { 5244 *infeasible = TRUE; 5245 return SCIP_OKAY; 5246 } 5247 newbound = MIN(newbound, ub); 5248 5249 if( (force && SCIPsetIsLE(scip->set, newbound, lb)) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) ) 5250 return SCIP_OKAY; 5251 5252 switch( scip->set->stage ) 5253 { 5254 case SCIP_STAGE_PROBLEM: 5255 assert(!SCIPvarIsTransformed(var)); 5256 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5257 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5258 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5259 scip->branchcand, scip->eventqueue, newbound) ); 5260 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) ); 5261 break; 5262 case SCIP_STAGE_TRANSFORMED: 5263 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5264 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5265 break; 5266 case SCIP_STAGE_PRESOLVING: 5267 if( !SCIPinProbing(scip) ) 5268 { 5269 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 5270 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 5271 5272 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5273 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5274 SCIP_BOUNDTYPE_LOWER, FALSE) ); 5275 5276 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 5277 { 5278 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 5279 assert(!(*infeasible)); 5280 } 5281 break; 5282 } 5283 /*lint -fallthrough*/ 5284 case SCIP_STAGE_SOLVING: 5285 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 5286 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, 5287 var, newbound, SCIP_BOUNDTYPE_LOWER, FALSE) ); 5288 break; 5289 5290 default: 5291 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5292 return SCIP_INVALIDCALL; 5293 } /*lint !e788*/ 5294 5295 /* check whether the lower bound improved */ 5296 if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) ) 5297 *tightened = TRUE; 5298 5299 return SCIP_OKAY; 5300 } 5301 5302 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter 5303 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value; 5304 * doesn't store any inference information in the bound change, such that in conflict analysis, this change 5305 * is treated like a branching decision 5306 * 5307 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 5308 * SCIPgetVars()) gets resorted. 5309 * 5310 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5311 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5312 * 5313 * @pre This method can be called if @p scip is in one of the following stages: 5314 * - \ref SCIP_STAGE_PROBLEM 5315 * - \ref SCIP_STAGE_PRESOLVING 5316 * - \ref SCIP_STAGE_SOLVING 5317 * 5318 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 5319 */ 5320 SCIP_RETCODE SCIPtightenVarUb( 5321 SCIP* scip, /**< SCIP data structure */ 5322 SCIP_VAR* var, /**< variable to change the bound for */ 5323 SCIP_Real newbound, /**< new value for bound */ 5324 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 5325 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */ 5326 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 5327 ) 5328 { 5329 SCIP_Real lb; 5330 SCIP_Real ub; 5331 5332 assert(infeasible != NULL); 5333 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarUb", FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5334 5335 /** @todo if needed provide pending local/global bound changes that will be flushed after leaving diving mode (as in struct_tree.h) */ 5336 assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || !SCIPinDive(scip)); 5337 5338 *infeasible = FALSE; 5339 if( tightened != NULL ) 5340 *tightened = FALSE; 5341 5342 SCIPvarAdjustUb(var, scip->set, &newbound); 5343 5344 /* ignore tightenings of upper bounds to -infinity during solving process */ 5345 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 5346 { 5347 #ifndef NDEBUG 5348 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var), 5349 SCIPvarGetUbLocal(var)); 5350 #endif 5351 return SCIP_OKAY; 5352 } 5353 5354 /* get current bounds */ 5355 lb = SCIPcomputeVarLbLocal(scip, var); 5356 ub = SCIPcomputeVarUbLocal(scip, var); 5357 assert(SCIPsetIsLE(scip->set, lb, ub)); 5358 5359 if( SCIPsetIsFeasLT(scip->set, newbound, lb) ) 5360 { 5361 *infeasible = TRUE; 5362 return SCIP_OKAY; 5363 } 5364 newbound = MAX(newbound, lb); 5365 5366 if( (force && SCIPsetIsGE(scip->set, newbound, ub)) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) ) 5367 return SCIP_OKAY; 5368 5369 switch( scip->set->stage ) 5370 { 5371 case SCIP_STAGE_PROBLEM: 5372 assert(!SCIPvarIsTransformed(var)); 5373 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5374 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5375 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5376 scip->branchcand, scip->eventqueue, newbound) ); 5377 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) ); 5378 break; 5379 case SCIP_STAGE_TRANSFORMED: 5380 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5381 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5382 break; 5383 case SCIP_STAGE_PRESOLVING: 5384 if( !SCIPinProbing(scip) ) 5385 { 5386 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 5387 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 5388 5389 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5390 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5391 SCIP_BOUNDTYPE_UPPER, FALSE) ); 5392 5393 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 5394 { 5395 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 5396 assert(!(*infeasible)); 5397 } 5398 break; 5399 } 5400 /*lint -fallthrough*/ 5401 case SCIP_STAGE_SOLVING: 5402 SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 5403 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 5404 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, FALSE) ); 5405 break; 5406 5407 default: 5408 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5409 return SCIP_INVALIDCALL; 5410 } /*lint !e788*/ 5411 5412 /* check whether the upper bound improved */ 5413 if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) ) 5414 *tightened = TRUE; 5415 5416 return SCIP_OKAY; 5417 } 5418 5419 /** fixes variable in preprocessing or in the current node, if the new bound is tighter (w.r.t. bound strengthening 5420 * epsilon) than the current bound; if possible, adjusts bound to integral value; the given inference constraint is 5421 * stored, such that the conflict analysis is able to find out the reason for the deduction of the bound change 5422 * 5423 * @note In presolving stage when not in probing mode the variable will be fixed directly, otherwise this method 5424 * changes first the lowerbound by calling SCIPinferVarLbCons and second the upperbound by calling 5425 * SCIPinferVarUbCons 5426 * 5427 * @note If SCIP is in presolving stage, it can happen that the internal variable array (which get be accessed via 5428 * SCIPgetVars()) gets resorted. 5429 * 5430 * @note During presolving, an integer variable which bound changes to {0,1} is upgraded to a binary variable. 5431 */ 5432 SCIP_RETCODE SCIPinferVarFixCons( 5433 SCIP* scip, /**< SCIP data structure */ 5434 SCIP_VAR* var, /**< variable to change the bound for */ 5435 SCIP_Real fixedval, /**< new value for fixation */ 5436 SCIP_CONS* infercons, /**< constraint that deduced the bound change */ 5437 int inferinfo, /**< user information for inference to help resolving the conflict */ 5438 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 5439 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */ 5440 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 5441 ) 5442 { 5443 assert(scip != NULL); 5444 assert(var != NULL); 5445 assert(infeasible != NULL); 5446 5447 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarFixCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5448 5449 if( tightened != NULL ) 5450 *tightened = FALSE; 5451 5452 /* in presolving case we take the shortcut to directly fix the variables */ 5453 if( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPtreeGetCurrentDepth(scip->tree) == 0 ) 5454 { 5455 SCIP_Bool fixed; 5456 5457 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 5458 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, 5459 scip->eventqueue, scip->cliquetable, fixedval, infeasible, &fixed) ); 5460 5461 if( tightened != NULL ) 5462 *tightened = fixed; 5463 } 5464 /* otherwise we use the lb and ub methods */ 5465 else 5466 { 5467 SCIP_Bool lbtightened; 5468 5469 SCIP_CALL( SCIPinferVarLbCons(scip, var, fixedval, infercons, inferinfo, force, infeasible, &lbtightened) ); 5470 5471 if( ! (*infeasible) ) 5472 { 5473 SCIP_CALL( SCIPinferVarUbCons(scip, var, fixedval, infercons, inferinfo, force, infeasible, tightened) ); 5474 5475 if( tightened != NULL ) 5476 *tightened |= lbtightened; 5477 } 5478 } 5479 5480 return SCIP_OKAY; 5481 } 5482 5483 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter 5484 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value; 5485 * the given inference constraint is stored, such that the conflict analysis is able to find out the reason 5486 * for the deduction of the bound change 5487 * 5488 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 5489 * SCIPgetVars()) gets resorted. 5490 * 5491 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5492 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5493 * 5494 * @pre This method can be called if @p scip is in one of the following stages: 5495 * - \ref SCIP_STAGE_PROBLEM 5496 * - \ref SCIP_STAGE_PRESOLVING 5497 * - \ref SCIP_STAGE_SOLVING 5498 * 5499 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 5500 */ 5501 SCIP_RETCODE SCIPinferVarLbCons( 5502 SCIP* scip, /**< SCIP data structure */ 5503 SCIP_VAR* var, /**< variable to change the bound for */ 5504 SCIP_Real newbound, /**< new value for bound */ 5505 SCIP_CONS* infercons, /**< constraint that deduced the bound change */ 5506 int inferinfo, /**< user information for inference to help resolving the conflict */ 5507 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 5508 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */ 5509 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 5510 ) 5511 { 5512 SCIP_Real lb; 5513 SCIP_Real ub; 5514 5515 assert(infeasible != NULL); 5516 5517 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarLbCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5518 5519 *infeasible = FALSE; 5520 if( tightened != NULL ) 5521 *tightened = FALSE; 5522 5523 SCIPvarAdjustLb(var, scip->set, &newbound); 5524 5525 /* ignore tightenings of lower bounds to +infinity during solving process */ 5526 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 5527 { 5528 #ifndef NDEBUG 5529 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var), 5530 SCIPvarGetLbLocal(var)); 5531 #endif 5532 return SCIP_OKAY; 5533 } 5534 5535 /* get current bounds */ 5536 lb = SCIPvarGetLbLocal(var); 5537 ub = SCIPvarGetUbLocal(var); 5538 assert(SCIPsetIsLE(scip->set, lb, ub)); 5539 5540 if( SCIPsetIsFeasGT(scip->set, newbound, ub) ) 5541 { 5542 *infeasible = TRUE; 5543 return SCIP_OKAY; 5544 } 5545 newbound = MIN(newbound, ub); 5546 5547 if( (force && SCIPsetIsLE(scip->set, newbound, lb)) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) ) 5548 return SCIP_OKAY; 5549 5550 switch( scip->set->stage ) 5551 { 5552 case SCIP_STAGE_PROBLEM: 5553 assert(!SCIPvarIsTransformed(var)); 5554 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5555 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5556 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5557 scip->branchcand, scip->eventqueue, newbound) ); 5558 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) ); 5559 break; 5560 5561 case SCIP_STAGE_PRESOLVING: 5562 if( !SCIPinProbing(scip) ) 5563 { 5564 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 5565 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 5566 5567 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5568 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5569 SCIP_BOUNDTYPE_LOWER, FALSE) ); 5570 5571 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 5572 { 5573 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 5574 assert(!(*infeasible)); 5575 } 5576 break; 5577 } 5578 /*lint -fallthrough*/ 5579 case SCIP_STAGE_SOLVING: 5580 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 5581 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 5582 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, infercons, NULL, inferinfo, FALSE) ); 5583 break; 5584 5585 default: 5586 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5587 return SCIP_INVALIDCALL; 5588 } /*lint !e788*/ 5589 5590 /* check whether the lower bound improved */ 5591 if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) ) 5592 *tightened = TRUE; 5593 5594 return SCIP_OKAY; 5595 } 5596 5597 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter 5598 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value; 5599 * the given inference constraint is stored, such that the conflict analysis is able to find out the reason 5600 * for the deduction of the bound change 5601 * 5602 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 5603 * SCIPgetVars()) gets resorted. 5604 * 5605 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5606 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5607 * 5608 * @pre This method can be called if @p scip is in one of the following stages: 5609 * - \ref SCIP_STAGE_PROBLEM 5610 * - \ref SCIP_STAGE_PRESOLVING 5611 * - \ref SCIP_STAGE_SOLVING 5612 * 5613 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 5614 */ 5615 SCIP_RETCODE SCIPinferVarUbCons( 5616 SCIP* scip, /**< SCIP data structure */ 5617 SCIP_VAR* var, /**< variable to change the bound for */ 5618 SCIP_Real newbound, /**< new value for bound */ 5619 SCIP_CONS* infercons, /**< constraint that deduced the bound change */ 5620 int inferinfo, /**< user information for inference to help resolving the conflict */ 5621 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 5622 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */ 5623 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 5624 ) 5625 { 5626 SCIP_Real lb; 5627 SCIP_Real ub; 5628 5629 assert(infeasible != NULL); 5630 5631 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarUbCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5632 5633 *infeasible = FALSE; 5634 if( tightened != NULL ) 5635 *tightened = FALSE; 5636 5637 SCIPvarAdjustUb(var, scip->set, &newbound); 5638 5639 /* ignore tightenings of upper bounds to -infinity during solving process */ 5640 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 5641 { 5642 #ifndef NDEBUG 5643 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var), 5644 SCIPvarGetUbLocal(var)); 5645 #endif 5646 return SCIP_OKAY; 5647 } 5648 5649 /* get current bounds */ 5650 lb = SCIPvarGetLbLocal(var); 5651 ub = SCIPvarGetUbLocal(var); 5652 assert(SCIPsetIsLE(scip->set, lb, ub)); 5653 5654 if( SCIPsetIsFeasLT(scip->set, newbound, lb) ) 5655 { 5656 *infeasible = TRUE; 5657 return SCIP_OKAY; 5658 } 5659 newbound = MAX(newbound, lb); 5660 5661 if( (force && SCIPsetIsGE(scip->set, newbound, ub)) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) ) 5662 return SCIP_OKAY; 5663 5664 switch( scip->set->stage ) 5665 { 5666 case SCIP_STAGE_PROBLEM: 5667 assert(!SCIPvarIsTransformed(var)); 5668 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5669 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5670 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5671 scip->branchcand, scip->eventqueue, newbound) ); 5672 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) ); 5673 break; 5674 5675 case SCIP_STAGE_PRESOLVING: 5676 if( !SCIPinProbing(scip) ) 5677 { 5678 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 5679 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 5680 5681 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5682 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5683 SCIP_BOUNDTYPE_UPPER, FALSE) ); 5684 5685 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 5686 { 5687 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 5688 assert(!(*infeasible)); 5689 } 5690 break; 5691 } 5692 /*lint -fallthrough*/ 5693 case SCIP_STAGE_SOLVING: 5694 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 5695 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 5696 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, infercons, NULL, inferinfo, FALSE) ); 5697 break; 5698 5699 default: 5700 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5701 return SCIP_INVALIDCALL; 5702 } /*lint !e788*/ 5703 5704 /* check whether the upper bound improved */ 5705 if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) ) 5706 *tightened = TRUE; 5707 5708 return SCIP_OKAY; 5709 } 5710 5711 /** depending on SCIP's stage, fixes binary variable in the problem, in preprocessing, or in current node; 5712 * the given inference constraint is stored, such that the conflict analysis is able to find out the reason for the 5713 * deduction of the fixing 5714 * 5715 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5716 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5717 * 5718 * @pre This method can be called if @p scip is in one of the following stages: 5719 * - \ref SCIP_STAGE_PROBLEM 5720 * - \ref SCIP_STAGE_PRESOLVING 5721 * - \ref SCIP_STAGE_SOLVING 5722 */ 5723 SCIP_RETCODE SCIPinferBinvarCons( 5724 SCIP* scip, /**< SCIP data structure */ 5725 SCIP_VAR* var, /**< binary variable to fix */ 5726 SCIP_Bool fixedval, /**< value to fix binary variable to */ 5727 SCIP_CONS* infercons, /**< constraint that deduced the fixing */ 5728 int inferinfo, /**< user information for inference to help resolving the conflict */ 5729 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */ 5730 SCIP_Bool* tightened /**< pointer to store whether the fixing tightened the local bounds, or NULL */ 5731 ) 5732 { 5733 SCIP_Real lb; 5734 SCIP_Real ub; 5735 5736 assert(SCIPvarIsBinary(var)); 5737 assert(fixedval == TRUE || fixedval == FALSE); 5738 assert(infeasible != NULL); 5739 5740 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferBinvarCons", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5741 5742 *infeasible = FALSE; 5743 if( tightened != NULL ) 5744 *tightened = FALSE; 5745 5746 /* get current bounds */ 5747 lb = SCIPvarGetLbLocal(var); 5748 ub = SCIPvarGetUbLocal(var); 5749 assert(SCIPsetIsEQ(scip->set, lb, 0.0) || SCIPsetIsEQ(scip->set, lb, 1.0)); 5750 assert(SCIPsetIsEQ(scip->set, ub, 0.0) || SCIPsetIsEQ(scip->set, ub, 1.0)); 5751 assert(SCIPsetIsLE(scip->set, lb, ub)); 5752 5753 /* check, if variable is already fixed */ 5754 if( (lb > 0.5) || (ub < 0.5) ) 5755 { 5756 *infeasible = (fixedval == (lb < 0.5)); 5757 5758 return SCIP_OKAY; 5759 } 5760 5761 /* apply the fixing */ 5762 switch( scip->set->stage ) 5763 { 5764 case SCIP_STAGE_PROBLEM: 5765 assert(!SCIPvarIsTransformed(var)); 5766 if( fixedval == TRUE ) 5767 { 5768 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) ); 5769 } 5770 else 5771 { 5772 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) ); 5773 } 5774 break; 5775 5776 case SCIP_STAGE_PRESOLVING: 5777 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 ) 5778 { 5779 SCIP_Bool fixed; 5780 5781 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 5782 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue, 5783 scip->cliquetable, (SCIP_Real)fixedval, infeasible, &fixed) ); 5784 break; 5785 } 5786 /*lint -fallthrough*/ 5787 case SCIP_STAGE_SOLVING: 5788 if( fixedval == TRUE ) 5789 { 5790 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 5791 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 5792 scip->cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, infercons, NULL, inferinfo, FALSE) ); 5793 } 5794 else 5795 { 5796 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 5797 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 5798 scip->cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, infercons, NULL, inferinfo, FALSE) ); 5799 } 5800 break; 5801 5802 default: 5803 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5804 return SCIP_INVALIDCALL; 5805 } /*lint !e788*/ 5806 5807 if( tightened != NULL ) 5808 *tightened = TRUE; 5809 5810 return SCIP_OKAY; 5811 } 5812 5813 /** fixes variable in preprocessing or in the current node, if the new bound is tighter (w.r.t. bound strengthening 5814 * epsilon) than the current bound; if possible, adjusts bound to integral value; the given inference constraint is 5815 * stored, such that the conflict analysis is able to find out the reason for the deduction of the bound change 5816 * 5817 * @note In presolving stage when not in probing mode the variable will be fixed directly, otherwise this method 5818 * changes first the lowerbound by calling SCIPinferVarLbProp and second the upperbound by calling 5819 * SCIPinferVarUbProp 5820 * 5821 * @note If SCIP is in presolving stage, it can happen that the internal variable array (which get be accessed via 5822 * SCIPgetVars()) gets resorted. 5823 * 5824 * @note During presolving, an integer variable which bound changes to {0,1} is upgraded to a binary variable. 5825 */ 5826 SCIP_RETCODE SCIPinferVarFixProp( 5827 SCIP* scip, /**< SCIP data structure */ 5828 SCIP_VAR* var, /**< variable to change the bound for */ 5829 SCIP_Real fixedval, /**< new value for fixation */ 5830 SCIP_PROP* inferprop, /**< propagator that deduced the bound change */ 5831 int inferinfo, /**< user information for inference to help resolving the conflict */ 5832 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 5833 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */ 5834 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 5835 ) 5836 { 5837 assert(scip != NULL); 5838 assert(var != NULL); 5839 assert(infeasible != NULL); 5840 5841 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarFixProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5842 5843 if( tightened != NULL ) 5844 *tightened = FALSE; 5845 5846 /* in presolving case we take the shortcut to directly fix the variables */ 5847 if( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPtreeGetCurrentDepth(scip->tree) == 0 ) 5848 { 5849 SCIP_Bool fixed; 5850 5851 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 5852 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue, 5853 scip->cliquetable, fixedval, infeasible, &fixed) ); 5854 5855 if( tightened != NULL ) 5856 *tightened = fixed; 5857 } 5858 /* otherwise we use the lb and ub methods */ 5859 else 5860 { 5861 SCIP_Bool lbtightened; 5862 5863 SCIP_CALL( SCIPinferVarLbProp(scip, var, fixedval, inferprop, inferinfo, force, infeasible, &lbtightened) ); 5864 5865 if( ! (*infeasible) ) 5866 { 5867 SCIP_CALL( SCIPinferVarUbProp(scip, var, fixedval, inferprop, inferinfo, force, infeasible, tightened) ); 5868 5869 if( tightened != NULL ) 5870 *tightened |= lbtightened; 5871 } 5872 } 5873 5874 return SCIP_OKAY; 5875 } 5876 5877 /** changes lower bound of variable in preprocessing or in the current node, if the new bound is tighter 5878 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value; 5879 * the given inference propagator is stored, such that the conflict analysis is able to find out the reason 5880 * for the deduction of the bound change 5881 * 5882 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 5883 * SCIPgetVars()) gets resorted. 5884 * 5885 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 5886 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 5887 * 5888 * @pre This method can be called if @p scip is in one of the following stages: 5889 * - \ref SCIP_STAGE_PROBLEM 5890 * - \ref SCIP_STAGE_PRESOLVING 5891 * - \ref SCIP_STAGE_SOLVING 5892 * 5893 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 5894 */ 5895 SCIP_RETCODE SCIPinferVarLbProp( 5896 SCIP* scip, /**< SCIP data structure */ 5897 SCIP_VAR* var, /**< variable to change the bound for */ 5898 SCIP_Real newbound, /**< new value for bound */ 5899 SCIP_PROP* inferprop, /**< propagator that deduced the bound change */ 5900 int inferinfo, /**< user information for inference to help resolving the conflict */ 5901 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 5902 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */ 5903 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 5904 ) 5905 { 5906 SCIP_Real lb; 5907 SCIP_Real ub; 5908 5909 assert(infeasible != NULL); 5910 5911 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarLbProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 5912 5913 *infeasible = FALSE; 5914 if( tightened != NULL ) 5915 *tightened = FALSE; 5916 5917 SCIPvarAdjustLb(var, scip->set, &newbound); 5918 5919 /* ignore tightenings of lower bounds to +infinity during solving process */ 5920 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 5921 { 5922 #ifndef NDEBUG 5923 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var), 5924 SCIPvarGetLbLocal(var)); 5925 #endif 5926 return SCIP_OKAY; 5927 } 5928 5929 /* get current bounds */ 5930 lb = SCIPvarGetLbLocal(var); 5931 ub = SCIPvarGetUbLocal(var); 5932 assert(SCIPsetIsLE(scip->set, lb, ub)); 5933 5934 if( SCIPsetIsFeasGT(scip->set, newbound, ub) ) 5935 { 5936 *infeasible = TRUE; 5937 return SCIP_OKAY; 5938 } 5939 newbound = MIN(newbound, ub); 5940 5941 if( (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) 5942 || SCIPsetIsLE(scip->set, newbound, lb) ) 5943 return SCIP_OKAY; 5944 5945 switch( scip->set->stage ) 5946 { 5947 case SCIP_STAGE_PROBLEM: 5948 assert(!SCIPvarIsTransformed(var)); 5949 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5950 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 5951 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 5952 scip->branchcand, scip->eventqueue, newbound) ); 5953 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) ); 5954 break; 5955 5956 case SCIP_STAGE_PRESOLVING: 5957 if( !SCIPinProbing(scip) ) 5958 { 5959 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 5960 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 5961 5962 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 5963 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 5964 SCIP_BOUNDTYPE_LOWER, FALSE) ); 5965 5966 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 5967 { 5968 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 5969 assert(!(*infeasible)); 5970 } 5971 break; 5972 } 5973 /*lint -fallthrough*/ 5974 case SCIP_STAGE_SOLVING: 5975 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 5976 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 5977 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_LOWER, NULL, inferprop, inferinfo, FALSE) ); 5978 break; 5979 5980 default: 5981 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 5982 return SCIP_INVALIDCALL; 5983 } /*lint !e788*/ 5984 5985 /* check whether the lower bound improved */ 5986 if( tightened != NULL && lb < SCIPcomputeVarLbLocal(scip, var) ) 5987 *tightened = TRUE; 5988 5989 return SCIP_OKAY; 5990 } 5991 5992 /** changes upper bound of variable in preprocessing or in the current node, if the new bound is tighter 5993 * (w.r.t. bound strengthening epsilon) than the current bound; if possible, adjusts bound to integral value; 5994 * the given inference propagator is stored, such that the conflict analysis is able to find out the reason 5995 * for the deduction of the bound change 5996 * 5997 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 5998 * SCIPgetVars()) gets resorted. 5999 * 6000 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6001 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6002 * 6003 * @pre This method can be called if @p scip is in one of the following stages: 6004 * - \ref SCIP_STAGE_PROBLEM 6005 * - \ref SCIP_STAGE_PRESOLVING 6006 * - \ref SCIP_STAGE_SOLVING 6007 * 6008 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 6009 */ 6010 SCIP_RETCODE SCIPinferVarUbProp( 6011 SCIP* scip, /**< SCIP data structure */ 6012 SCIP_VAR* var, /**< variable to change the bound for */ 6013 SCIP_Real newbound, /**< new value for bound */ 6014 SCIP_PROP* inferprop, /**< propagator that deduced the bound change */ 6015 int inferinfo, /**< user information for inference to help resolving the conflict */ 6016 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 6017 SCIP_Bool* infeasible, /**< pointer to store whether the bound change is infeasible */ 6018 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 6019 ) 6020 { 6021 SCIP_Real lb; 6022 SCIP_Real ub; 6023 6024 assert(infeasible != NULL); 6025 6026 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferVarUbProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6027 6028 *infeasible = FALSE; 6029 if( tightened != NULL ) 6030 *tightened = FALSE; 6031 6032 SCIPvarAdjustUb(var, scip->set, &newbound); 6033 6034 /* ignore tightenings of upper bounds to -infinity during solving process */ 6035 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 6036 { 6037 #ifndef NDEBUG 6038 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var), 6039 SCIPvarGetUbLocal(var)); 6040 #endif 6041 return SCIP_OKAY; 6042 } 6043 6044 /* get current bounds */ 6045 lb = SCIPvarGetLbLocal(var); 6046 ub = SCIPvarGetUbLocal(var); 6047 assert(SCIPsetIsLE(scip->set, lb, ub)); 6048 6049 if( SCIPsetIsFeasLT(scip->set, newbound, lb) ) 6050 { 6051 *infeasible = TRUE; 6052 return SCIP_OKAY; 6053 } 6054 newbound = MAX(newbound, lb); 6055 6056 if( (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) 6057 || SCIPsetIsGE(scip->set, newbound, ub) ) 6058 return SCIP_OKAY; 6059 6060 switch( scip->set->stage ) 6061 { 6062 case SCIP_STAGE_PROBLEM: 6063 assert(!SCIPvarIsTransformed(var)); 6064 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6065 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 6066 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6067 scip->branchcand, scip->eventqueue, newbound) ); 6068 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) ); 6069 break; 6070 6071 case SCIP_STAGE_PRESOLVING: 6072 if( !SCIPinProbing(scip) ) 6073 { 6074 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 6075 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 6076 6077 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 6078 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 6079 SCIP_BOUNDTYPE_UPPER, FALSE) ); 6080 6081 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 6082 { 6083 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 6084 assert(!(*infeasible)); 6085 } 6086 break; 6087 } 6088 /*lint -fallthrough*/ 6089 case SCIP_STAGE_SOLVING: 6090 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 6091 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, 6092 scip->cliquetable, var, newbound, SCIP_BOUNDTYPE_UPPER, NULL, inferprop, inferinfo, FALSE) ); 6093 break; 6094 6095 default: 6096 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 6097 return SCIP_INVALIDCALL; 6098 } /*lint !e788*/ 6099 6100 /* check whether the upper bound improved */ 6101 if( tightened != NULL && ub > SCIPcomputeVarUbLocal(scip, var) ) 6102 *tightened = TRUE; 6103 6104 return SCIP_OKAY; 6105 } 6106 6107 /** depending on SCIP's stage, fixes binary variable in the problem, in preprocessing, or in current node; 6108 * the given inference propagator is stored, such that the conflict analysis is able to find out the reason for the 6109 * deduction of the fixing 6110 * 6111 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6112 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6113 * 6114 * @pre This method can be called if @p scip is in one of the following stages: 6115 * - \ref SCIP_STAGE_PROBLEM 6116 * - \ref SCIP_STAGE_PRESOLVING 6117 * - \ref SCIP_STAGE_PRESOLVED 6118 * - \ref SCIP_STAGE_SOLVING 6119 */ 6120 SCIP_RETCODE SCIPinferBinvarProp( 6121 SCIP* scip, /**< SCIP data structure */ 6122 SCIP_VAR* var, /**< binary variable to fix */ 6123 SCIP_Bool fixedval, /**< value to fix binary variable to */ 6124 SCIP_PROP* inferprop, /**< propagator that deduced the fixing */ 6125 int inferinfo, /**< user information for inference to help resolving the conflict */ 6126 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */ 6127 SCIP_Bool* tightened /**< pointer to store whether the fixing tightened the local bounds, or NULL */ 6128 ) 6129 { 6130 SCIP_Real lb; 6131 SCIP_Real ub; 6132 6133 assert(SCIPvarIsBinary(var)); 6134 assert(fixedval == TRUE || fixedval == FALSE); 6135 assert(infeasible != NULL); 6136 6137 SCIP_CALL( SCIPcheckStage(scip, "SCIPinferBinvarProp", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6138 6139 *infeasible = FALSE; 6140 if( tightened != NULL ) 6141 *tightened = FALSE; 6142 6143 /* get current bounds */ 6144 lb = SCIPvarGetLbLocal(var); 6145 ub = SCIPvarGetUbLocal(var); 6146 assert(SCIPsetIsEQ(scip->set, lb, 0.0) || SCIPsetIsEQ(scip->set, lb, 1.0)); 6147 assert(SCIPsetIsEQ(scip->set, ub, 0.0) || SCIPsetIsEQ(scip->set, ub, 1.0)); 6148 assert(SCIPsetIsLE(scip->set, lb, ub)); 6149 6150 /* check, if variable is already fixed */ 6151 if( (lb > 0.5) || (ub < 0.5) ) 6152 { 6153 *infeasible = (fixedval == (lb < 0.5)); 6154 6155 return SCIP_OKAY; 6156 } 6157 6158 /* apply the fixing */ 6159 switch( scip->set->stage ) 6160 { 6161 case SCIP_STAGE_PROBLEM: 6162 assert(!SCIPvarIsTransformed(var)); 6163 if( fixedval == TRUE ) 6164 { 6165 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) ); 6166 } 6167 else 6168 { 6169 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) ); 6170 } 6171 break; 6172 6173 case SCIP_STAGE_PRESOLVING: 6174 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 ) 6175 { 6176 SCIP_Bool fixed; 6177 6178 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6179 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue, 6180 scip->cliquetable, (SCIP_Real)fixedval, infeasible, &fixed) ); 6181 break; 6182 } 6183 /*lint -fallthrough*/ 6184 case SCIP_STAGE_SOLVING: 6185 if( fixedval == TRUE ) 6186 { 6187 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 6188 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, 1.0, 6189 SCIP_BOUNDTYPE_LOWER, NULL, inferprop, inferinfo, FALSE) ); 6190 } 6191 else 6192 { 6193 SCIP_CALL( SCIPnodeAddBoundinfer(SCIPtreeGetCurrentNode(scip->tree), scip->mem->probmem, scip->set, scip->stat, 6194 scip->transprob, scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, 0.0, 6195 SCIP_BOUNDTYPE_UPPER, NULL, inferprop, inferinfo, FALSE) ); 6196 } 6197 break; 6198 6199 default: 6200 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 6201 return SCIP_INVALIDCALL; 6202 } /*lint !e788*/ 6203 6204 if( tightened != NULL ) 6205 *tightened = TRUE; 6206 6207 return SCIP_OKAY; 6208 } 6209 6210 /** changes global lower bound of variable in preprocessing or in the current node, if the new bound is tighter 6211 * (w.r.t. bound strengthening epsilon) than the current global bound; if possible, adjusts bound to integral value; 6212 * also tightens the local bound, if the global bound is better than the local bound 6213 * 6214 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 6215 * SCIPgetVars()) gets resorted. 6216 * 6217 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6218 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6219 * 6220 * @pre This method can be called if @p scip is in one of the following stages: 6221 * - \ref SCIP_STAGE_PROBLEM 6222 * - \ref SCIP_STAGE_TRANSFORMING 6223 * - \ref SCIP_STAGE_PRESOLVING 6224 * - \ref SCIP_STAGE_SOLVING 6225 * 6226 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 6227 */ 6228 SCIP_RETCODE SCIPtightenVarLbGlobal( 6229 SCIP* scip, /**< SCIP data structure */ 6230 SCIP_VAR* var, /**< variable to change the bound for */ 6231 SCIP_Real newbound, /**< new value for bound */ 6232 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 6233 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */ 6234 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 6235 ) 6236 { 6237 SCIP_Real lb; 6238 SCIP_Real ub; 6239 6240 assert(infeasible != NULL); 6241 6242 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarLbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6243 6244 *infeasible = FALSE; 6245 if( tightened != NULL ) 6246 *tightened = FALSE; 6247 6248 SCIPvarAdjustLb(var, scip->set, &newbound); 6249 6250 /* ignore tightenings of lower bounds to +infinity during solving process */ 6251 if( SCIPisInfinity(scip, newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 6252 { 6253 #ifndef NDEBUG 6254 SCIPwarningMessage(scip, "ignore lower bound tightening for %s from %e to +infinity\n", SCIPvarGetName(var), 6255 SCIPvarGetLbLocal(var)); 6256 #endif 6257 return SCIP_OKAY; 6258 } 6259 6260 /* get current bounds */ 6261 lb = SCIPvarGetLbGlobal(var); 6262 ub = SCIPvarGetUbGlobal(var); 6263 assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPsetIsLE(scip->set, lb, ub)); 6264 6265 if( SCIPsetIsFeasGT(scip->set, newbound, ub) ) 6266 { 6267 *infeasible = TRUE; 6268 return SCIP_OKAY; 6269 } 6270 newbound = MIN(newbound, ub); 6271 6272 /* bound changes of less than epsilon are ignored by SCIPvarChgLb or raise an assert in SCIPnodeAddBoundinfer, 6273 * so don't apply them even if force is set 6274 */ 6275 if( SCIPsetIsEQ(scip->set, lb, newbound) || (!force && !SCIPsetIsLbBetter(scip->set, newbound, lb, ub)) ) 6276 return SCIP_OKAY; 6277 6278 switch( scip->set->stage ) 6279 { 6280 case SCIP_STAGE_PROBLEM: 6281 assert(!SCIPvarIsTransformed(var)); 6282 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6283 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 6284 SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6285 scip->branchcand, scip->eventqueue, newbound) ); 6286 SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) ); 6287 break; 6288 6289 case SCIP_STAGE_TRANSFORMING: 6290 SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6291 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 6292 break; 6293 6294 case SCIP_STAGE_PRESOLVING: 6295 if( !SCIPinProbing(scip) ) 6296 { 6297 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 6298 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 6299 6300 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 6301 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 6302 SCIP_BOUNDTYPE_LOWER, FALSE) ); 6303 6304 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 6305 { 6306 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 6307 assert(!(*infeasible)); 6308 } 6309 break; 6310 } 6311 /*lint -fallthrough*/ 6312 case SCIP_STAGE_SOLVING: 6313 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 6314 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 6315 SCIP_BOUNDTYPE_LOWER, FALSE) ); 6316 break; 6317 6318 default: 6319 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 6320 return SCIP_INVALIDCALL; 6321 } /*lint !e788*/ 6322 6323 /* coverity: unreachable code */ 6324 if( tightened != NULL && lb < SCIPcomputeVarLbGlobal(scip, var) ) 6325 *tightened = TRUE; 6326 6327 return SCIP_OKAY; 6328 } 6329 6330 /** changes global upper bound of variable in preprocessing or in the current node, if the new bound is tighter 6331 * (w.r.t. bound strengthening epsilon) than the current global bound; if possible, adjusts bound to integral value; 6332 * also tightens the local bound, if the global bound is better than the local bound 6333 * 6334 * @warning If SCIP is in presolving stage, it can happen that the internal variable array (which can be accessed via 6335 * SCIPgetVars()) gets resorted. 6336 * 6337 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6338 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6339 * 6340 * @pre This method can be called if @p scip is in one of the following stages: 6341 * - \ref SCIP_STAGE_PROBLEM 6342 * - \ref SCIP_STAGE_TRANSFORMING 6343 * - \ref SCIP_STAGE_PRESOLVING 6344 * - \ref SCIP_STAGE_SOLVING 6345 * 6346 * @note During presolving, an integer variable whose bound changes to {0,1} is upgraded to a binary variable. 6347 */ 6348 SCIP_RETCODE SCIPtightenVarUbGlobal( 6349 SCIP* scip, /**< SCIP data structure */ 6350 SCIP_VAR* var, /**< variable to change the bound for */ 6351 SCIP_Real newbound, /**< new value for bound */ 6352 SCIP_Bool force, /**< force tightening even if below bound strengthening tolerance */ 6353 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */ 6354 SCIP_Bool* tightened /**< pointer to store whether the bound was tightened, or NULL */ 6355 ) 6356 { 6357 SCIP_Real lb; 6358 SCIP_Real ub; 6359 6360 assert(infeasible != NULL); 6361 6362 SCIP_CALL( SCIPcheckStage(scip, "SCIPtightenVarUbGlobal", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6363 6364 *infeasible = FALSE; 6365 if( tightened != NULL ) 6366 *tightened = FALSE; 6367 6368 SCIPvarAdjustUb(var, scip->set, &newbound); 6369 6370 /* ignore tightenings of upper bounds to -infinity during solving process */ 6371 if( SCIPisInfinity(scip, -newbound) && SCIPgetStage(scip) == SCIP_STAGE_SOLVING ) 6372 { 6373 #ifndef NDEBUG 6374 SCIPwarningMessage(scip, "ignore upper bound tightening for %s from %e to -infinity\n", SCIPvarGetName(var), 6375 SCIPvarGetUbLocal(var)); 6376 #endif 6377 return SCIP_OKAY; 6378 } 6379 6380 /* get current bounds */ 6381 lb = SCIPvarGetLbGlobal(var); 6382 ub = SCIPvarGetUbGlobal(var); 6383 assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPsetIsLE(scip->set, lb, ub)); 6384 6385 if( SCIPsetIsFeasLT(scip->set, newbound, lb) ) 6386 { 6387 *infeasible = TRUE; 6388 return SCIP_OKAY; 6389 } 6390 newbound = MAX(newbound, lb); 6391 6392 /* bound changes of less than epsilon are ignored by SCIPvarChgUb or raise an assert in SCIPnodeAddBoundinfer, 6393 * so don't apply them even if force is set 6394 */ 6395 if( SCIPsetIsEQ(scip->set, ub, newbound) || (!force && !SCIPsetIsUbBetter(scip->set, newbound, lb, ub)) ) 6396 return SCIP_OKAY; 6397 6398 switch( scip->set->stage ) 6399 { 6400 case SCIP_STAGE_PROBLEM: 6401 assert(!SCIPvarIsTransformed(var)); 6402 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6403 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 6404 SCIP_CALL( SCIPvarChgUbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6405 scip->branchcand, scip->eventqueue, newbound) ); 6406 SCIP_CALL( SCIPvarChgUbOriginal(var, scip->set, newbound) ); 6407 break; 6408 6409 case SCIP_STAGE_TRANSFORMING: 6410 SCIP_CALL( SCIPvarChgUbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp, 6411 scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) ); 6412 break; 6413 6414 case SCIP_STAGE_PRESOLVING: 6415 if( !SCIPinProbing(scip) ) 6416 { 6417 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 6418 assert(scip->tree->root == SCIPtreeGetCurrentNode(scip->tree)); 6419 6420 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 6421 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 6422 SCIP_BOUNDTYPE_UPPER, FALSE) ); 6423 6424 if( (SCIP_VARTYPE)var->vartype == SCIP_VARTYPE_INTEGER && SCIPvarIsBinary(var) ) 6425 { 6426 SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_BINARY, infeasible) ); 6427 assert(!(*infeasible)); 6428 } 6429 break; 6430 } 6431 /*lint -fallthrough*/ 6432 case SCIP_STAGE_SOLVING: 6433 SCIP_CALL( SCIPnodeAddBoundchg(scip->tree->root, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 6434 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, scip->cliquetable, var, newbound, 6435 SCIP_BOUNDTYPE_UPPER, FALSE) ); 6436 break; 6437 6438 default: 6439 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 6440 return SCIP_INVALIDCALL; 6441 } /*lint !e788*/ 6442 6443 /* coverity: unreachable code */ 6444 if( tightened != NULL && ub > SCIPcomputeVarUbGlobal(scip, var) ) 6445 *tightened = TRUE; 6446 6447 return SCIP_OKAY; 6448 } 6449 6450 /* some simple variable functions implemented as defines */ 6451 #undef SCIPcomputeVarLbGlobal 6452 #undef SCIPcomputeVarUbGlobal 6453 #undef SCIPcomputeVarLbLocal 6454 #undef SCIPcomputeVarUbLocal 6455 6456 /** for a multi-aggregated variable, returns the global lower bound computed by adding the global bounds from all aggregation variables 6457 * 6458 * This global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is not updated if bounds of aggregation variables are changing 6459 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetLbGlobal. 6460 * 6461 * @return the global lower bound computed by adding the global bounds from all aggregation variables 6462 */ 6463 SCIP_Real SCIPcomputeVarLbGlobal( 6464 SCIP* scip, /**< SCIP data structure */ 6465 SCIP_VAR* var /**< variable to compute the bound for */ 6466 ) 6467 { 6468 assert(scip != NULL); 6469 assert(var != NULL); 6470 6471 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR ) 6472 return SCIPvarGetMultaggrLbGlobal(var, scip->set); 6473 else 6474 return SCIPvarGetLbGlobal(var); 6475 } 6476 6477 /** for a multi-aggregated variable, returns the global upper bound computed by adding the global bounds from all aggregation variables 6478 * 6479 * This global bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is not updated if bounds of aggregation variables are changing 6480 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetUbGlobal 6481 * 6482 * @return the global upper bound computed by adding the global bounds from all aggregation variables 6483 */ 6484 SCIP_Real SCIPcomputeVarUbGlobal( 6485 SCIP* scip, /**< SCIP data structure */ 6486 SCIP_VAR* var /**< variable to compute the bound for */ 6487 ) 6488 { 6489 assert(scip != NULL); 6490 assert(var != NULL); 6491 6492 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR ) 6493 return SCIPvarGetMultaggrUbGlobal(var, scip->set); 6494 else 6495 return SCIPvarGetUbGlobal(var); 6496 } 6497 6498 /** for a multi-aggregated variable, returns the local lower bound computed by adding the local bounds from all aggregation variables 6499 * 6500 * This local bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is not updated if bounds of aggregation variables are changing 6501 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetLbLocal. 6502 * 6503 * @return the local lower bound computed by adding the global bounds from all aggregation variables 6504 */ 6505 SCIP_Real SCIPcomputeVarLbLocal( 6506 SCIP* scip, /**< SCIP data structure */ 6507 SCIP_VAR* var /**< variable to compute the bound for */ 6508 ) 6509 { 6510 assert(scip != NULL); 6511 assert(var != NULL); 6512 6513 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR ) 6514 return SCIPvarGetMultaggrLbLocal(var, scip->set); 6515 else 6516 return SCIPvarGetLbLocal(var); 6517 } 6518 6519 /** for a multi-aggregated variable, returns the local upper bound computed by adding the local bounds from all aggregation variables 6520 * 6521 * This local bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is not updated if bounds of aggregation variables are changing 6522 * calling this function for a non-multi-aggregated variable results in a call to SCIPvarGetUbLocal. 6523 * 6524 * @return the local upper bound computed by adding the global bounds from all aggregation variables 6525 */ 6526 SCIP_Real SCIPcomputeVarUbLocal( 6527 SCIP* scip, /**< SCIP data structure */ 6528 SCIP_VAR* var /**< variable to compute the bound for */ 6529 ) 6530 { 6531 assert(scip != NULL); 6532 assert(var != NULL); 6533 6534 if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR ) 6535 return SCIPvarGetMultaggrUbLocal(var, scip->set); 6536 else 6537 return SCIPvarGetUbLocal(var); 6538 } 6539 6540 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all 6541 * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is 6542 * not updated if bounds of aggregation variables are changing 6543 * 6544 * calling this function for a non-multi-aggregated variable is not allowed 6545 */ 6546 SCIP_Real SCIPgetVarMultaggrLbGlobal( 6547 SCIP* scip, /**< SCIP data structure */ 6548 SCIP_VAR* var /**< variable to compute the bound for */ 6549 ) 6550 { 6551 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR); 6552 return SCIPvarGetMultaggrLbGlobal(var, scip->set); 6553 } 6554 6555 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all 6556 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is 6557 * not updated if bounds of aggregation variables are changing 6558 * 6559 * calling this function for a non-multi-aggregated variable is not allowed 6560 */ 6561 SCIP_Real SCIPgetVarMultaggrUbGlobal( 6562 SCIP* scip, /**< SCIP data structure */ 6563 SCIP_VAR* var /**< variable to compute the bound for */ 6564 ) 6565 { 6566 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR); 6567 return SCIPvarGetMultaggrUbGlobal(var, scip->set); 6568 } 6569 6570 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all 6571 * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is 6572 * not updated if bounds of aggregation variables are changing 6573 * 6574 * calling this function for a non-multi-aggregated variable is not allowed 6575 */ 6576 SCIP_Real SCIPgetVarMultaggrLbLocal( 6577 SCIP* scip, /**< SCIP data structure */ 6578 SCIP_VAR* var /**< variable to compute the bound for */ 6579 ) 6580 { 6581 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR); 6582 return SCIPvarGetMultaggrLbLocal(var, scip->set); 6583 } 6584 6585 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all 6586 * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is 6587 * not updated if bounds of aggregation variables are changing 6588 * 6589 * calling this function for a non-multi-aggregated variable is not allowed 6590 */ 6591 SCIP_Real SCIPgetVarMultaggrUbLocal( 6592 SCIP* scip, /**< SCIP data structure */ 6593 SCIP_VAR* var /**< variable to compute the bound for */ 6594 ) 6595 { 6596 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR); 6597 return SCIPvarGetMultaggrUbLocal(var, scip->set); 6598 } 6599 6600 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal 6601 * solution or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is 6602 * available 6603 * 6604 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6605 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6606 * 6607 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING 6608 */ 6609 SCIP_RETCODE SCIPgetVarClosestVlb( 6610 SCIP* scip, /**< SCIP data structure */ 6611 SCIP_VAR* var, /**< active problem variable */ 6612 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */ 6613 SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */ 6614 int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */ 6615 ) 6616 { 6617 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarClosestVlb", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6618 6619 SCIPvarGetClosestVlb(var, sol, scip->set, scip->stat, closestvlb, closestvlbidx); 6620 6621 return SCIP_OKAY; 6622 } 6623 6624 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution; 6625 * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available 6626 * 6627 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6628 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6629 * 6630 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_SOLVING 6631 */ 6632 SCIP_RETCODE SCIPgetVarClosestVub( 6633 SCIP* scip, /**< SCIP data structure */ 6634 SCIP_VAR* var, /**< active problem variable */ 6635 SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */ 6636 SCIP_Real* closestvub, /**< pointer to store the value of the closest variable lower bound */ 6637 int* closestvubidx /**< pointer to store the index of the closest variable lower bound */ 6638 ) 6639 { 6640 SCIP_CALL( SCIPcheckStage(scip, "SCIPgetVarClosestVub", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6641 6642 SCIPvarGetClosestVub(var, sol, scip->set, scip->stat, closestvub, closestvubidx); 6643 6644 return SCIP_OKAY; 6645 } 6646 6647 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z; 6648 * if z is binary, the corresponding valid implication for z is also added; 6649 * if z is non-continuous and 1/b not too small, the corresponding valid upper/lower bound 6650 * z <= (x-d)/b or z >= (x-d)/b (depending on the sign of of b) is added, too; 6651 * improves the global bounds of the variable and the vlb variable if possible 6652 * 6653 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6654 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6655 * 6656 * @pre This method can be called if @p scip is in one of the following stages: 6657 * - \ref SCIP_STAGE_PRESOLVING 6658 * - \ref SCIP_STAGE_PRESOLVED 6659 * - \ref SCIP_STAGE_SOLVING 6660 */ 6661 SCIP_RETCODE SCIPaddVarVlb( 6662 SCIP* scip, /**< SCIP data structure */ 6663 SCIP_VAR* var, /**< problem variable */ 6664 SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */ 6665 SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */ 6666 SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */ 6667 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */ 6668 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */ 6669 ) 6670 { 6671 int nlocalbdchgs; 6672 6673 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarVlb", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6674 6675 SCIP_CALL( SCIPvarAddVlb(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->tree, 6676 scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, vlbvar, vlbcoef, vlbconstant, 6677 TRUE, infeasible, &nlocalbdchgs) ); 6678 6679 *nbdchgs = nlocalbdchgs; 6680 6681 /* if x is not continuous we add a variable bound for z; do not add it if cofficient would be too small or we already 6682 * detected infeasibility 6683 */ 6684 if( !(*infeasible) && SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisZero(scip, 1.0/vlbcoef) ) 6685 { 6686 if( vlbcoef > 0.0 ) 6687 { 6688 /* if b > 0, we have a variable upper bound: x >= b*z + d => z <= (x-d)/b */ 6689 SCIP_CALL( SCIPvarAddVub(vlbvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6690 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vlbcoef, 6691 -vlbconstant/vlbcoef, TRUE, infeasible, &nlocalbdchgs) ); 6692 } 6693 else 6694 { 6695 /* if b < 0, we have a variable lower bound: x >= b*z + d => z >= (x-d)/b */ 6696 SCIP_CALL( SCIPvarAddVlb(vlbvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6697 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vlbcoef, 6698 -vlbconstant/vlbcoef, TRUE, infeasible, &nlocalbdchgs) ); 6699 } 6700 *nbdchgs += nlocalbdchgs; 6701 } 6702 6703 return SCIP_OKAY; 6704 } 6705 6706 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z; 6707 * if z is binary, the corresponding valid implication for z is also added; 6708 * if z is non-continuous and 1/b not too small, the corresponding valid lower/upper bound 6709 * z >= (x-d)/b or z <= (x-d)/b (depending on the sign of of b) is added, too; 6710 * improves the global bounds of the variable and the vlb variable if possible 6711 * 6712 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6713 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6714 * 6715 * @pre This method can be called if @p scip is in one of the following stages: 6716 * - \ref SCIP_STAGE_PRESOLVING 6717 * - \ref SCIP_STAGE_PRESOLVED 6718 * - \ref SCIP_STAGE_SOLVING 6719 */ 6720 SCIP_RETCODE SCIPaddVarVub( 6721 SCIP* scip, /**< SCIP data structure */ 6722 SCIP_VAR* var, /**< problem variable */ 6723 SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */ 6724 SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */ 6725 SCIP_Real vubconstant, /**< constant d in x <= b*z + d */ 6726 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */ 6727 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */ 6728 ) 6729 { 6730 int nlocalbdchgs; 6731 6732 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarVub", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6733 6734 SCIP_CALL( SCIPvarAddVub(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, scip->tree, 6735 scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, vubvar, vubcoef, vubconstant, TRUE, 6736 infeasible, &nlocalbdchgs) ); 6737 6738 *nbdchgs = nlocalbdchgs; 6739 6740 /* if x is not continuous we add a variable bound for z; do not add it if cofficient would be too small or we already 6741 * detected infeasibility 6742 */ 6743 if( !(*infeasible) && SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisZero(scip, 1.0/vubcoef) ) 6744 { 6745 if( vubcoef > 0.0 ) 6746 { 6747 /* if b < 0, we have a variable lower bound: x >= b*z + d => z >= (x-d)/b */ 6748 SCIP_CALL( SCIPvarAddVlb(vubvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6749 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vubcoef, 6750 -vubconstant/vubcoef, TRUE, infeasible, &nlocalbdchgs) ); 6751 } 6752 else 6753 { 6754 /* if b > 0, we have a variable upper bound: x >= b*z + d => z <= (x-d)/b */ 6755 SCIP_CALL( SCIPvarAddVub(vubvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6756 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 1.0/vubcoef, 6757 -vubconstant/vubcoef, TRUE, infeasible, &nlocalbdchgs) ); 6758 } 6759 *nbdchgs += nlocalbdchgs; 6760 } 6761 6762 return SCIP_OKAY; 6763 } 6764 6765 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b; 6766 * also adds the corresponding implication or variable bound to the implied variable; 6767 * if the implication is conflicting, the variable is fixed to the opposite value; 6768 * if the variable is already fixed to the given value, the implication is performed immediately; 6769 * if the implication is redundant with respect to the variables' global bounds, it is ignored 6770 * 6771 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6772 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6773 * 6774 * @pre This method can be called if @p scip is in one of the following stages: 6775 * - \ref SCIP_STAGE_TRANSFORMED 6776 * - \ref SCIP_STAGE_PRESOLVING 6777 * - \ref SCIP_STAGE_PRESOLVED 6778 * - \ref SCIP_STAGE_SOLVING 6779 */ 6780 SCIP_RETCODE SCIPaddVarImplication( 6781 SCIP* scip, /**< SCIP data structure */ 6782 SCIP_VAR* var, /**< problem variable */ 6783 SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */ 6784 SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */ 6785 SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) 6786 * or y >= b (SCIP_BOUNDTYPE_LOWER) */ 6787 SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */ 6788 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */ 6789 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */ 6790 ) 6791 { 6792 SCIP_VAR* implprobvar; 6793 6794 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarImplication", FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6795 6796 assert(infeasible != NULL); 6797 *infeasible = FALSE; 6798 6799 if ( nbdchgs != NULL ) 6800 *nbdchgs = 0; 6801 6802 if( !SCIPvarIsBinary(var) ) 6803 { 6804 SCIPerrorMessage("can't add implication for nonbinary variable\n"); 6805 return SCIP_INVALIDDATA; 6806 } 6807 6808 implprobvar = SCIPvarGetProbvar(implvar); 6809 /* transform implication containing two binary variables to a clique; the condition ensures that the active representative 6810 * of implvar is actually binary 6811 */ 6812 if( SCIPvarIsBinary(implvar) && (SCIPvarIsActive(implvar) || (implprobvar != NULL && SCIPvarIsBinary(implprobvar))) ) 6813 { 6814 assert(SCIPisFeasEQ(scip, implbound, 1.0) || SCIPisFeasZero(scip, implbound)); 6815 assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPisFeasZero(scip, implbound)); 6816 6817 /* only add clique if implication is not redundant with respect to global bounds of the implication variable */ 6818 if( (impltype == SCIP_BOUNDTYPE_LOWER && SCIPvarGetLbGlobal(implvar) < 0.5) || 6819 (impltype == SCIP_BOUNDTYPE_UPPER && SCIPvarGetUbGlobal(implvar) > 0.5) ) 6820 { 6821 SCIP_VAR* vars[2]; 6822 SCIP_Bool vals[2]; 6823 6824 vars[0] = var; 6825 vars[1] = implvar; 6826 vals[0] = varfixing; 6827 vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER); 6828 6829 SCIP_CALL( SCIPaddClique(scip, vars, vals, 2, FALSE, infeasible, nbdchgs) ); 6830 } 6831 6832 return SCIP_OKAY; 6833 } 6834 6835 /* the implication graph can only handle 'real' binary (SCIP_VARTYPE_BINARY) variables, therefore we transform the 6836 * implication in variable bounds, (lowerbound of y will be abbreviated by lby, upperbound equivlaent) the follwing 6837 * four cases are: 6838 * 6839 * 1. (x >= 1 => y >= b) => y >= (b - lby) * x + lby 6840 * 2. (x >= 1 => y <= b) => y <= (b - uby) * x + uby 6841 * 3. (x <= 0 => y >= b) => y >= (lby - b) * x + b 6842 * 4. (x <= 0 => y <= b) => y <= (uby - b) * x + b 6843 */ 6844 if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY ) 6845 { 6846 SCIP_Real lby; 6847 SCIP_Real uby; 6848 6849 lby = SCIPvarGetLbGlobal(implvar); 6850 uby = SCIPvarGetUbGlobal(implvar); 6851 6852 if( varfixing == TRUE ) 6853 { 6854 if( impltype == SCIP_BOUNDTYPE_LOWER ) 6855 { 6856 /* we return if the lower bound is infinity */ 6857 if( SCIPisInfinity(scip, -lby) ) 6858 return SCIP_OKAY; 6859 6860 SCIP_CALL( SCIPvarAddVlb(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6861 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 6862 implbound - lby, lby, TRUE, infeasible, nbdchgs) ); 6863 } 6864 else 6865 { 6866 /* we return if the upper bound is infinity */ 6867 if( SCIPisInfinity(scip, uby) ) 6868 return SCIP_OKAY; 6869 6870 SCIP_CALL( SCIPvarAddVub(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6871 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 6872 implbound - uby, uby, TRUE, infeasible, nbdchgs) ); 6873 } 6874 } 6875 else 6876 { 6877 if( impltype == SCIP_BOUNDTYPE_LOWER ) 6878 { 6879 /* we return if the lower bound is infinity */ 6880 if( SCIPisInfinity(scip, -lby) ) 6881 return SCIP_OKAY; 6882 6883 SCIP_CALL( SCIPvarAddVlb(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6884 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 6885 lby - implbound, implbound, TRUE, infeasible, nbdchgs) ); 6886 } 6887 else 6888 { 6889 /* we return if the upper bound is infinity */ 6890 if( SCIPisInfinity(scip, uby) ) 6891 return SCIP_OKAY; 6892 6893 SCIP_CALL( SCIPvarAddVub(implvar, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6894 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, var, 6895 uby - implbound, implbound, TRUE, infeasible, nbdchgs) ); 6896 } 6897 } 6898 } 6899 else 6900 { 6901 SCIP_CALL( SCIPvarAddImplic(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 6902 scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventqueue, varfixing, implvar, impltype, 6903 implbound, TRUE, infeasible, nbdchgs) ); 6904 } 6905 6906 return SCIP_OKAY; 6907 } 6908 6909 /** adds a clique information to SCIP, stating that at most one of the given binary variables can be set to 1; 6910 * if a variable appears twice in the same clique, the corresponding implications are performed 6911 * 6912 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 6913 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 6914 * 6915 * @pre This method can be called if @p scip is in one of the following stages: 6916 * - \ref SCIP_STAGE_TRANSFORMED 6917 * - \ref SCIP_STAGE_PRESOLVING 6918 * - \ref SCIP_STAGE_PRESOLVED 6919 * - \ref SCIP_STAGE_SOLVING 6920 */ 6921 SCIP_RETCODE SCIPaddClique( 6922 SCIP* scip, /**< SCIP data structure */ 6923 SCIP_VAR** vars, /**< binary variables in the clique from which at most one can be set to 1 */ 6924 SCIP_Bool* values, /**< values of the variables in the clique; NULL to use TRUE for all vars */ 6925 int nvars, /**< number of variables in the clique */ 6926 SCIP_Bool isequation, /**< is the clique an equation or an inequality? */ 6927 SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */ 6928 int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */ 6929 ) 6930 { 6931 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddClique", FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 6932 6933 *infeasible = FALSE; 6934 if( nbdchgs != NULL ) 6935 *nbdchgs = 0; 6936 6937 if( nvars > 1 ) 6938 { 6939 /* add the clique to the clique table */ 6940 SCIP_CALL( SCIPcliquetableAdd(scip->cliquetable, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 6941 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, vars, values, nvars, isequation, 6942 infeasible, nbdchgs) ); 6943 } 6944 6945 return SCIP_OKAY; 6946 } 6947 6948 /** relabels the given labels in-place in an increasing fashion: the first seen label is 0, the next label 1, etc... 6949 * 6950 * @note every label equal to -1 is treated as a previously unseen, unique label and gets a new ordered label. 6951 */ 6952 static 6953 SCIP_RETCODE relabelOrderConsistent( 6954 SCIP*const scip, /**< SCIP data structure */ 6955 int* labels, /**< current labels that will be overwritten */ 6956 int const nlabels, /**< number of variables in the clique */ 6957 int* nclasses /**< pointer to store the total number of distinct labels */ 6958 ) 6959 { 6960 SCIP_HASHMAP* classidx2newlabel; 6961 6962 int classidx; 6963 int i; 6964 6965 SCIP_CALL( SCIPhashmapCreate(&classidx2newlabel, SCIPblkmem(scip), nlabels) ); 6966 6967 classidx = 0; 6968 6969 /* loop over labels to create local class indices that obey the variable order */ 6970 for( i = 0; i < nlabels; ++i ) 6971 { 6972 int currentlabel = labels[i]; 6973 int localclassidx; 6974 6975 /* labels equal to -1 are stored as singleton classes */ 6976 if( currentlabel == -1 ) 6977 { 6978 ++classidx; 6979 localclassidx = classidx; 6980 } 6981 else 6982 { 6983 assert(currentlabel >= 0); 6984 /* look up the class index image in the hash map; if it is not stored yet, new class index is created and stored */ 6985 if( !SCIPhashmapExists(classidx2newlabel, (void*)(size_t)currentlabel) ) 6986 { 6987 ++classidx; 6988 localclassidx = classidx; 6989 SCIP_CALL( SCIPhashmapInsertInt(classidx2newlabel, (void*)(size_t)currentlabel, classidx) ); /*lint !e571*/ 6990 } 6991 else 6992 { 6993 localclassidx = SCIPhashmapGetImageInt(classidx2newlabel, (void*)(size_t)currentlabel); /*lint !e571*/ 6994 } 6995 } 6996 assert(localclassidx - 1 >= 0); 6997 assert(localclassidx - 1 <= i); 6998 6999 /* indices start with zero, but we have an offset of 1 because we cannot store 0 in a hashmap */ 7000 labels[i] = localclassidx - 1; 7001 } 7002 7003 assert(classidx > 0); 7004 assert(classidx <= nlabels); 7005 *nclasses = classidx; 7006 7007 SCIPhashmapFree(&classidx2newlabel); 7008 7009 return SCIP_OKAY; 7010 } 7011 7012 /** sort the variables w.r.t. the given labels; thereby ensure the current order of the variables with the same label. */ 7013 static 7014 SCIP_RETCODE labelSortStable( 7015 SCIP* scip, /**< SCIP data structure */ 7016 SCIP_VAR** vars, /**< variable array */ 7017 int* classlabels, /**< array that contains a class label for every variable */ 7018 SCIP_VAR** sortedvars, /**< array to store variables after stable sorting */ 7019 int* sortedindices, /**< array to store indices of sorted variables in the original vars array */ 7020 int* classesstartposs, /**< starting position array for each label class (must have size nclasses + 1) */ 7021 int nvars, /**< size of the vars arrays */ 7022 int nclasses /**< number of label classes */ 7023 ) 7024 { 7025 SCIP_VAR*** varpointers; 7026 int** indexpointers; 7027 int* classcount; 7028 7029 int nextpos; 7030 int c; 7031 int v; 7032 7033 assert(scip != NULL); 7034 assert(vars != NULL); 7035 assert(sortedindices != NULL); 7036 assert(classesstartposs != NULL); 7037 7038 assert(nvars == 0 || vars != NULL); 7039 7040 if( nvars == 0 ) 7041 return SCIP_OKAY; 7042 7043 assert(classlabels != NULL); 7044 assert(nclasses > 0); 7045 7046 /* we first count all class cardinalities and allocate temporary memory for a bucket sort */ 7047 SCIP_CALL( SCIPallocBufferArray(scip, &classcount, nclasses) ); 7048 BMSclearMemoryArray(classcount, nclasses); 7049 7050 /* first we count for each class the number of elements */ 7051 for( v = nvars - 1; v >= 0; --v ) 7052 { 7053 assert(0 <= classlabels[v] && classlabels[v] < nclasses); 7054 ++(classcount[classlabels[v]]); 7055 } 7056 7057 #ifndef NDEBUG 7058 BMSclearMemoryArray(sortedvars, nvars); 7059 BMSclearMemoryArray(sortedindices, nvars); 7060 #endif 7061 SCIP_CALL( SCIPallocBufferArray(scip, &varpointers, nclasses) ); 7062 SCIP_CALL( SCIPallocBufferArray(scip, &indexpointers, nclasses) ); 7063 7064 nextpos = 0; 7065 /* now we initialize all start pointers for each class, so they will be ordered */ 7066 for( c = 0; c < nclasses; ++c ) 7067 { 7068 /* to reach the goal that all variables of each class will be standing next to each other we will initialize the 7069 * starting pointers for each class by adding the cardinality of each class to the last class starting pointer 7070 * e.g. class1 has 4 elements and class2 has 3 elements then the starting pointer for class1 will be the pointer 7071 * to sortedvars[0], the starting pointer to class2 will be the pointer to sortedvars[4] and to class3 it will be 7072 * the pointer to sortedvars[7] 7073 */ 7074 varpointers[c] = (SCIP_VAR**) (sortedvars + nextpos); 7075 indexpointers[c] = (int*) (sortedindices + nextpos); 7076 classesstartposs[c] = nextpos; 7077 assert(classcount[c] > 0); 7078 nextpos += classcount[c]; 7079 assert(nextpos > 0); 7080 } 7081 assert(nextpos == nvars); 7082 classesstartposs[c] = nextpos; 7083 7084 /* now we copy all variables to the right order */ 7085 for( v = 0; v < nvars; ++v ) 7086 { 7087 /* copy variable itself to the right position */ 7088 *(varpointers[classlabels[v]]) = vars[v]; /*lint !e613*/ 7089 ++(varpointers[classlabels[v]]); 7090 7091 /* copy index */ 7092 *(indexpointers[classlabels[v]]) = v; 7093 ++(indexpointers[classlabels[v]]); 7094 } 7095 7096 /* in debug mode, we ensure the correctness of the mapping */ 7097 #ifndef NDEBUG 7098 for( v = 0; v < nvars; ++v ) 7099 { 7100 assert(sortedvars[v] != NULL); 7101 assert(sortedindices[v] >= 0); 7102 7103 /* assert that the sorted indices map back to the correct variable in the original order */ 7104 assert(vars[sortedindices[v]] == sortedvars[v]); 7105 } 7106 #endif 7107 7108 /* free temporary memory */ 7109 SCIPfreeBufferArray(scip, &indexpointers); 7110 SCIPfreeBufferArray(scip, &varpointers); 7111 SCIPfreeBufferArray(scip, &classcount); 7112 7113 return SCIP_OKAY; 7114 } 7115 7116 7117 /* calculate clique partition for a maximal amount of comparisons on variables due to expensive algorithm 7118 * @todo: check for a good value, maybe it's better to check parts of variables 7119 */ 7120 #define MAXNCLIQUEVARSCOMP 1000000 7121 7122 /** calculates a partition of the given set of binary variables into cliques; 7123 * afterwards the output array contains one value for each variable, such that two variables got the same value iff they 7124 * were assigned to the same clique; 7125 * the first variable is always assigned to clique 0, and a variable can only be assigned to clique i if at least one of 7126 * the preceding variables was assigned to clique i-1; 7127 * for each clique at most 1 variables can be set to TRUE in a feasible solution; 7128 * 7129 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7130 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7131 * 7132 * @pre This method can be called if @p scip is in one of the following stages: 7133 * - \ref SCIP_STAGE_INITPRESOLVE 7134 * - \ref SCIP_STAGE_PRESOLVING 7135 * - \ref SCIP_STAGE_EXITPRESOLVE 7136 * - \ref SCIP_STAGE_PRESOLVED 7137 * - \ref SCIP_STAGE_SOLVING 7138 */ 7139 static 7140 SCIP_RETCODE calcCliquePartitionGreedy( 7141 SCIP*const scip, /**< SCIP data structure */ 7142 SCIP_VAR**const vars, /**< binary variables in the clique from which at most one can be set to 1 */ 7143 SCIP_Bool*const values, /**< clique value (TRUE or FALSE) for each variable in the clique */ 7144 int const nvars, /**< number of variables in the array */ 7145 int*const cliquepartition, /**< array of length nvars to store the clique partition */ 7146 int*const ncliques /**< pointer to store the number of cliques actually contained in the partition */ 7147 ) 7148 { 7149 SCIP_VAR** cliquevars; 7150 SCIP_Bool* cliquevalues; 7151 int i; 7152 int maxncliquevarscomp; 7153 int ncliquevars; 7154 7155 /* allocate temporary memory for storing the variables of the current clique */ 7156 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &cliquevars, nvars) ); 7157 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &cliquevalues, nvars) ); 7158 7159 /* initialize the cliquepartition array with -1 */ 7160 for( i = nvars - 1; i >= 0; --i ) 7161 cliquepartition[i] = -1; 7162 7163 maxncliquevarscomp = (int) MIN(nvars * (SCIP_Longint)nvars, MAXNCLIQUEVARSCOMP); 7164 /* calculate the clique partition */ 7165 *ncliques = 0; 7166 for( i = 0; i < nvars; ++i ) 7167 { 7168 if( cliquepartition[i] == -1 ) 7169 { 7170 int j; 7171 7172 /* variable starts a new clique */ 7173 cliquepartition[i] = *ncliques; 7174 cliquevars[0] = vars[i]; 7175 cliquevalues[0] = values[i]; 7176 ncliquevars = 1; 7177 7178 /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique */ 7179 if( SCIPvarIsActive(vars[i]) && SCIPvarGetNCliques(vars[i], values[i]) > 0 ) 7180 { 7181 /* greedily fill up the clique */ 7182 for( j = i+1; j < nvars; ++j ) 7183 { 7184 /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique */ 7185 if( cliquepartition[j] == -1 && SCIPvarIsActive(vars[j]) ) 7186 { 7187 int k; 7188 7189 /* check if every variable in the current clique can be extended by tmpvars[j] */ 7190 for( k = ncliquevars - 1; k >= 0; --k ) 7191 { 7192 if( !SCIPvarsHaveCommonClique(vars[j], values[j], cliquevars[k], cliquevalues[k], FALSE) ) 7193 break; 7194 } 7195 7196 if( k == -1 ) 7197 { 7198 /* put the variable into the same clique */ 7199 cliquepartition[j] = cliquepartition[i]; 7200 cliquevars[ncliquevars] = vars[j]; 7201 cliquevalues[ncliquevars] = values[j]; 7202 ++ncliquevars; 7203 } 7204 } 7205 } 7206 } 7207 7208 /* this clique is finished */ 7209 ++(*ncliques); 7210 } 7211 assert(cliquepartition[i] >= 0 && cliquepartition[i] < i+1); 7212 7213 /* break if we reached the maximal number of comparisons */ 7214 if( i * nvars > maxncliquevarscomp ) 7215 break; 7216 } 7217 /* if we had to many variables fill up the cliquepartition and put each variable in a separate clique */ 7218 for( ; i < nvars; ++i ) 7219 { 7220 if( cliquepartition[i] == -1 ) 7221 { 7222 cliquepartition[i] = *ncliques; 7223 ++(*ncliques); 7224 } 7225 } 7226 7227 SCIPsetFreeBufferArray(scip->set, &cliquevalues); 7228 SCIPsetFreeBufferArray(scip->set, &cliquevars); 7229 7230 return SCIP_OKAY; 7231 } 7232 7233 /** calculates a partition of the given set of binary variables into cliques; takes into account independent clique components 7234 * 7235 * The algorithm performs the following steps: 7236 * - recomputes connected components of the clique table, if necessary 7237 * - computes a clique partition for every connected component greedily. 7238 * - relabels the resulting clique partition such that it satisfies the description below 7239 * 7240 * afterwards the output array contains one value for each variable, such that two variables got the same value iff they 7241 * were assigned to the same clique; 7242 * the first variable is always assigned to clique 0, and a variable can only be assigned to clique i if at least one of 7243 * the preceding variables was assigned to clique i-1; 7244 * for each clique at most 1 variables can be set to TRUE in a feasible solution; 7245 * 7246 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7247 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7248 * 7249 * @pre This method can be called if @p scip is in one of the following stages: 7250 * - \ref SCIP_STAGE_INITPRESOLVE 7251 * - \ref SCIP_STAGE_PRESOLVING 7252 * - \ref SCIP_STAGE_EXITPRESOLVE 7253 * - \ref SCIP_STAGE_PRESOLVED 7254 * - \ref SCIP_STAGE_SOLVING 7255 */ 7256 SCIP_RETCODE SCIPcalcCliquePartition( 7257 SCIP*const scip, /**< SCIP data structure */ 7258 SCIP_VAR**const vars, /**< binary variables in the clique from which at most one can be set to 1 */ 7259 int const nvars, /**< number of variables in the clique */ 7260 int*const cliquepartition, /**< array of length nvars to store the clique partition */ 7261 int*const ncliques /**< pointer to store the number of cliques actually contained in the partition */ 7262 ) 7263 { 7264 SCIP_VAR** tmpvars; 7265 7266 SCIP_VAR** sortedtmpvars; 7267 SCIP_Bool* tmpvalues; 7268 SCIP_Bool* sortedtmpvalues; 7269 int* componentlabels; 7270 int* sortedindices; 7271 int* componentstartposs; 7272 int i; 7273 int c; 7274 7275 int ncomponents; 7276 7277 assert(scip != NULL); 7278 assert(nvars == 0 || vars != NULL); 7279 assert(nvars == 0 || cliquepartition != NULL); 7280 assert(ncliques != NULL); 7281 7282 SCIP_CALL( SCIPcheckStage(scip, "SCIPcalcCliquePartition", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 7283 7284 if( nvars == 0 ) 7285 { 7286 *ncliques = 0; 7287 return SCIP_OKAY; 7288 } 7289 7290 /* early abort if no cliques are present */ 7291 if( SCIPgetNCliques(scip) == 0 ) 7292 { 7293 for( i = 0; i < nvars; ++i ) 7294 cliquepartition[i] = i; 7295 7296 *ncliques = nvars; 7297 7298 return SCIP_OKAY; 7299 } 7300 7301 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &tmpvalues, nvars) ); 7302 SCIP_CALL( SCIPsetDuplicateBufferArray(scip->set, &tmpvars, vars, nvars) ); 7303 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &componentlabels, nvars) ); 7304 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedindices, nvars) ); 7305 7306 /* initialize the tmpvalues array */ 7307 for( i = nvars - 1; i >= 0; --i ) 7308 { 7309 tmpvalues[i] = TRUE; 7310 cliquepartition[i] = -1; 7311 } 7312 7313 /* get corresponding active problem variables */ 7314 SCIP_CALL( SCIPvarsGetProbvarBinary(&tmpvars, &tmpvalues, nvars) ); 7315 7316 ncomponents = -1; 7317 7318 /* update clique components if necessary */ 7319 if( SCIPcliquetableNeedsComponentUpdate(scip->cliquetable) ) 7320 { 7321 SCIP_VAR** allvars; 7322 int nallbinvars; 7323 int nallintvars; 7324 int nallimplvars; 7325 7326 SCIP_CALL( SCIPgetVarsData(scip, &allvars, NULL, &nallbinvars, &nallintvars, &nallimplvars, NULL) ); 7327 7328 SCIP_CALL( SCIPcliquetableComputeCliqueComponents(scip->cliquetable, scip->set, SCIPblkmem(scip), allvars, nallbinvars, nallintvars, nallimplvars) ); 7329 } 7330 7331 assert(!SCIPcliquetableNeedsComponentUpdate(scip->cliquetable)); 7332 7333 /* store the global clique component labels */ 7334 for( i = 0; i < nvars; ++i ) 7335 { 7336 if( SCIPvarIsActive(tmpvars[i]) ) 7337 componentlabels[i] = SCIPcliquetableGetVarComponentIdx(scip->cliquetable, tmpvars[i]); 7338 else 7339 componentlabels[i] = -1; 7340 } 7341 7342 /* relabel component labels order consistent as prerequisite for a stable sort */ 7343 SCIP_CALL( relabelOrderConsistent(scip, componentlabels, nvars, &ncomponents) ); 7344 assert(ncomponents >= 1); 7345 assert(ncomponents <= nvars); 7346 7347 /* allocate storage array for the starting positions of the components */ 7348 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &componentstartposs, ncomponents + 1) ); 7349 7350 /* stable sort the variables w.r.t. the component labels so that we can restrict the quadratic algorithm to the components */ 7351 if( ncomponents > 1 ) 7352 { 7353 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedtmpvars, nvars) ); 7354 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &sortedtmpvalues, nvars) ); 7355 SCIP_CALL( labelSortStable(scip, tmpvars, componentlabels, sortedtmpvars, sortedindices, componentstartposs, nvars, ncomponents) ); 7356 7357 /* reassign the tmpvalues with respect to the sorting */ 7358 for( i = 0; i < nvars; ++i ) 7359 { 7360 assert(tmpvars[sortedindices[i]] == sortedtmpvars[i]); 7361 sortedtmpvalues[i] = tmpvalues[sortedindices[i]]; 7362 } 7363 } 7364 else 7365 { 7366 /* if we have only one large connected component, skip the stable sorting and prepare the data differently */ 7367 sortedtmpvars = tmpvars; 7368 sortedtmpvalues = tmpvalues; 7369 componentstartposs[0] = 0; 7370 componentstartposs[1] = nvars; 7371 7372 /* sorted indices are the identity */ 7373 for( i = 0; i < nvars; ++i ) 7374 sortedindices[i] = i; 7375 } 7376 7377 *ncliques = 0; 7378 /* calculate a greedy clique partition for each connected component */ 7379 for( c = 0; c < ncomponents; ++c ) 7380 { 7381 int* localcliquepartition; 7382 int nlocalcliques; 7383 int ncomponentvars; 7384 int l; 7385 7386 /* extract the number of variables in this connected component */ 7387 ncomponentvars = componentstartposs[c + 1] - componentstartposs[c]; 7388 nlocalcliques = 0; 7389 7390 /* allocate necessary memory to hold the intermediate component clique partition */ 7391 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &localcliquepartition, ncomponentvars) ); 7392 7393 /* call greedy clique algorithm for all component variables */ 7394 SCIP_CALL( calcCliquePartitionGreedy(scip, &(sortedtmpvars[componentstartposs[c]]), &(sortedtmpvalues[componentstartposs[c]]), 7395 ncomponentvars, localcliquepartition, &nlocalcliques) ); 7396 7397 assert(nlocalcliques >= 1); 7398 assert(nlocalcliques <= ncomponentvars); 7399 7400 /* store the obtained clique partition with an offset of ncliques for the original variables */ 7401 for( l = componentstartposs[c]; l < componentstartposs[c + 1]; ++l ) 7402 { 7403 int origvaridx = sortedindices[l]; 7404 assert(cliquepartition[origvaridx] == -1); 7405 assert(localcliquepartition[l - componentstartposs[c]] <= l - componentstartposs[c]); 7406 cliquepartition[origvaridx] = localcliquepartition[l - componentstartposs[c]] + (*ncliques); 7407 } 7408 *ncliques += nlocalcliques; 7409 7410 /* free the local clique partition */ 7411 SCIPsetFreeBufferArray(scip->set, &localcliquepartition); 7412 } 7413 7414 /* except in the two trivial cases, we have to ensure the order consistency of the partition indices */ 7415 if( ncomponents > 1 && ncomponents < nvars ) 7416 { 7417 int partitionsize; 7418 SCIP_CALL( relabelOrderConsistent(scip, cliquepartition, nvars, &partitionsize) ); 7419 7420 assert(partitionsize == *ncliques); 7421 } 7422 7423 if( ncomponents > 1 ) 7424 { 7425 SCIPsetFreeBufferArray(scip->set, &sortedtmpvalues); 7426 SCIPsetFreeBufferArray(scip->set, &sortedtmpvars); 7427 } 7428 7429 /* use the greedy algorithm as a whole to verify the result on small number of variables */ 7430 #ifdef SCIP_DISABLED_CODE 7431 { 7432 int* debugcliquepartition; 7433 int ndebugcliques; 7434 7435 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &debugcliquepartition, nvars) ); 7436 7437 /* call greedy clique algorithm for all component variables */ 7438 SCIP_CALL( calcCliquePartitionGreedy(scip, tmpvars, tmpvalues, nvars, debugcliquepartition, &ndebugcliques) ); 7439 7440 /* loop and compare the traditional greedy clique with */ 7441 for( i = 0; i < nvars; ++i ) 7442 assert(i * nvars > MAXNCLIQUEVARSCOMP || cliquepartition[i] == debugcliquepartition[i]); 7443 7444 SCIPsetFreeBufferArray(scip->set, &debugcliquepartition); 7445 } 7446 #endif 7447 7448 /* free temporary memory */ 7449 SCIPsetFreeBufferArray(scip->set, &componentstartposs); 7450 SCIPsetFreeBufferArray(scip->set, &sortedindices); 7451 SCIPsetFreeBufferArray(scip->set, &componentlabels); 7452 SCIPsetFreeBufferArray(scip->set, &tmpvars); 7453 SCIPsetFreeBufferArray(scip->set, &tmpvalues); 7454 7455 return SCIP_OKAY; 7456 } 7457 7458 /** calculates a partition of the given set of binary variables into negated cliques; 7459 * afterwards the output array contains one value for each variable, such that two variables got the same value iff they 7460 * were assigned to the same negated clique; 7461 * the first variable is always assigned to clique 0 and a variable can only be assigned to clique i if at least one of 7462 * the preceding variables was assigned to clique i-1; 7463 * for each clique with n_c variables at least n_c-1 variables can be set to TRUE in a feasible solution; 7464 * 7465 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7466 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7467 * 7468 * @pre This method can be called if @p scip is in one of the following stages: 7469 * - \ref SCIP_STAGE_INITPRESOLVE 7470 * - \ref SCIP_STAGE_PRESOLVING 7471 * - \ref SCIP_STAGE_EXITPRESOLVE 7472 * - \ref SCIP_STAGE_PRESOLVED 7473 * - \ref SCIP_STAGE_SOLVING 7474 */ 7475 SCIP_RETCODE SCIPcalcNegatedCliquePartition( 7476 SCIP*const scip, /**< SCIP data structure */ 7477 SCIP_VAR**const vars, /**< binary variables in the clique from which at most one can be set to 1 */ 7478 int const nvars, /**< number of variables in the clique */ 7479 int*const cliquepartition, /**< array of length nvars to store the clique partition */ 7480 int*const ncliques /**< pointer to store the number of cliques actually contained in the partition */ 7481 ) 7482 { 7483 SCIP_VAR** negvars; 7484 int v; 7485 7486 assert(scip != NULL); 7487 assert(cliquepartition != NULL || nvars == 0); 7488 assert(ncliques != NULL); 7489 7490 if( nvars == 0 ) 7491 { 7492 *ncliques = 0; 7493 return SCIP_OKAY; 7494 } 7495 assert(vars != NULL); 7496 7497 /* allocate temporary memory */ 7498 SCIP_CALL( SCIPsetAllocBufferArray(scip->set, &negvars, nvars) ); 7499 7500 /* get all negated variables */ 7501 for( v = nvars - 1; v >= 0; --v ) 7502 { 7503 SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &(negvars[v])) ); 7504 } 7505 7506 /* calculate cliques on negated variables, which are "negated" cliques on normal variables array */ 7507 SCIP_CALL( SCIPcalcCliquePartition( scip, negvars, nvars, cliquepartition, ncliques) ); 7508 7509 /* free temporary memory */ 7510 SCIPsetFreeBufferArray(scip->set, &negvars); 7511 7512 return SCIP_OKAY; 7513 } 7514 7515 7516 /** force SCIP to clean up all cliques; cliques do not get automatically cleaned up after presolving. Use 7517 * this method to prevent inactive variables in cliques when retrieved via SCIPgetCliques() 7518 * 7519 * @return SCIP_OKAY if everything worked, otherwise a suitable error code is passed 7520 * 7521 * @pre This method can be called if @p scip is in one of the following stages: 7522 * - \ref SCIP_STAGE_TRANSFORMED 7523 * - \ref SCIP_STAGE_INITPRESOLVE 7524 * - \ref SCIP_STAGE_PRESOLVING 7525 * - \ref SCIP_STAGE_EXITPRESOLVE 7526 * - \ref SCIP_STAGE_PRESOLVED 7527 * - \ref SCIP_STAGE_INITSOLVE 7528 * - \ref SCIP_STAGE_SOLVING 7529 * - \ref SCIP_STAGE_SOLVED 7530 * - \ref SCIP_STAGE_EXITSOLVE 7531 */ 7532 SCIP_RETCODE SCIPcleanupCliques( 7533 SCIP* scip, /**< SCIP data structure */ 7534 SCIP_Bool* infeasible /**< pointer to store if cleanup detected infeasibility */ 7535 ) 7536 { 7537 int nlocalbdchgs; 7538 SCIP_Bool globalinfeasibility; 7539 7540 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPcleanupCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 7541 7542 globalinfeasibility = FALSE; 7543 nlocalbdchgs = 0; 7544 SCIP_CALL( SCIPcliquetableCleanup(scip->cliquetable, scip->mem->probmem, scip->set, scip->stat, scip->transprob, 7545 scip->origprob, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventqueue, &nlocalbdchgs, 7546 &globalinfeasibility) ); 7547 7548 if( infeasible != NULL ) 7549 *infeasible = globalinfeasibility; 7550 7551 if( globalinfeasibility ) 7552 scip->stat->status = SCIP_STATUS_INFEASIBLE; 7553 7554 return SCIP_OKAY; 7555 } 7556 7557 /** gets the number of cliques in the clique table 7558 * 7559 * @return number of cliques in the clique table 7560 * 7561 * @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques() 7562 * to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques 7563 * 7564 * @pre This method can be called if @p scip is in one of the following stages: 7565 * - \ref SCIP_STAGE_TRANSFORMED 7566 * - \ref SCIP_STAGE_INITPRESOLVE 7567 * - \ref SCIP_STAGE_PRESOLVING 7568 * - \ref SCIP_STAGE_EXITPRESOLVE 7569 * - \ref SCIP_STAGE_PRESOLVED 7570 * - \ref SCIP_STAGE_INITSOLVE 7571 * - \ref SCIP_STAGE_SOLVING 7572 * - \ref SCIP_STAGE_SOLVED 7573 * - \ref SCIP_STAGE_EXITSOLVE 7574 */ 7575 int SCIPgetNCliques( 7576 SCIP* scip /**< SCIP data structure */ 7577 ) 7578 { 7579 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 7580 7581 return SCIPcliquetableGetNCliques(scip->cliquetable); 7582 } 7583 7584 /** gets the number of cliques created so far by the cliquetable 7585 * 7586 * @return number of cliques created so far by the cliquetable 7587 * 7588 * @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques() 7589 * to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques 7590 * 7591 * @pre This method can be called if @p scip is in one of the following stages: 7592 * - \ref SCIP_STAGE_TRANSFORMED 7593 * - \ref SCIP_STAGE_INITPRESOLVE 7594 * - \ref SCIP_STAGE_PRESOLVING 7595 * - \ref SCIP_STAGE_EXITPRESOLVE 7596 * - \ref SCIP_STAGE_PRESOLVED 7597 * - \ref SCIP_STAGE_INITSOLVE 7598 * - \ref SCIP_STAGE_SOLVING 7599 * - \ref SCIP_STAGE_SOLVED 7600 * - \ref SCIP_STAGE_EXITSOLVE 7601 */ 7602 int SCIPgetNCliquesCreated( 7603 SCIP* scip /**< SCIP data structure */ 7604 ) 7605 { 7606 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCliquesCreated", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 7607 7608 return SCIPcliquetableGetNCliquesCreated(scip->cliquetable); 7609 } 7610 7611 /** gets the array of cliques in the clique table 7612 * 7613 * @return array of cliques in the clique table 7614 * 7615 * @note cliques do not get automatically cleaned up after presolving. Use SCIPcleanupCliques() 7616 * to prevent inactive variables in cliques when retrieved via SCIPgetCliques(). This might reduce the number of cliques 7617 * 7618 * @pre This method can be called if @p scip is in one of the following stages: 7619 * - \ref SCIP_STAGE_TRANSFORMED 7620 * - \ref SCIP_STAGE_INITPRESOLVE 7621 * - \ref SCIP_STAGE_PRESOLVING 7622 * - \ref SCIP_STAGE_EXITPRESOLVE 7623 * - \ref SCIP_STAGE_PRESOLVED 7624 * - \ref SCIP_STAGE_INITSOLVE 7625 * - \ref SCIP_STAGE_SOLVING 7626 * - \ref SCIP_STAGE_SOLVED 7627 * - \ref SCIP_STAGE_EXITSOLVE 7628 */ 7629 SCIP_CLIQUE** SCIPgetCliques( 7630 SCIP* scip /**< SCIP data structure */ 7631 ) 7632 { 7633 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetCliques", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 7634 7635 return SCIPcliquetableGetCliques(scip->cliquetable); 7636 } 7637 7638 /** returns whether there is a clique that contains both given variable/value pairs; 7639 * the variables must be active binary variables; 7640 * if regardimplics is FALSE, only the cliques in the clique table are looked at; 7641 * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded 7642 * 7643 * @return TRUE, if there is a clique that contains both variable/clique pairs; FALSE, otherwise 7644 * 7645 * @pre This method can be called if @p scip is in one of the following stages: 7646 * - \ref SCIP_STAGE_TRANSFORMED 7647 * - \ref SCIP_STAGE_INITPRESOLVE 7648 * - \ref SCIP_STAGE_PRESOLVING 7649 * - \ref SCIP_STAGE_EXITPRESOLVE 7650 * - \ref SCIP_STAGE_PRESOLVED 7651 * - \ref SCIP_STAGE_INITSOLVE 7652 * - \ref SCIP_STAGE_SOLVING 7653 * - \ref SCIP_STAGE_SOLVED 7654 * - \ref SCIP_STAGE_EXITSOLVE 7655 * 7656 * @note a variable with it's negated variable are NOT! in a clique 7657 * @note a variable with itself are in a clique 7658 */ 7659 SCIP_Bool SCIPhaveVarsCommonClique( 7660 SCIP* scip, /**< SCIP data structure */ 7661 SCIP_VAR* var1, /**< first variable */ 7662 SCIP_Bool value1, /**< value of first variable */ 7663 SCIP_VAR* var2, /**< second variable */ 7664 SCIP_Bool value2, /**< value of second variable */ 7665 SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */ 7666 ) 7667 { 7668 assert(scip != NULL); 7669 assert(var1 != NULL); 7670 assert(var2 != NULL); 7671 assert(SCIPvarIsActive(var1)); 7672 assert(SCIPvarIsActive(var2)); 7673 assert(SCIPvarIsBinary(var1)); 7674 assert(SCIPvarIsBinary(var2)); 7675 7676 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPhaveVarsCommonClique", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 7677 7678 /* if both variables together have more cliques then actual cliques exist, then they have a common clique (in debug 7679 * mode we check this for correctness), otherwise we need to call the pairwise comparison method for these variables 7680 */ 7681 #ifndef NDEBUG 7682 assert((SCIPvarGetNCliques(var1, value1) + SCIPvarGetNCliques(var2, value2) > SCIPcliquetableGetNCliques(scip->cliquetable)) ? SCIPvarsHaveCommonClique(var1, value1, var2, value2, FALSE) : TRUE); 7683 #endif 7684 7685 return (SCIPvarGetNCliques(var1, value1) + SCIPvarGetNCliques(var2, value2) > SCIPcliquetableGetNCliques(scip->cliquetable) 7686 || SCIPvarsHaveCommonClique(var1, value1, var2, value2, regardimplics)); 7687 } 7688 7689 /** writes the clique graph to a gml file 7690 * 7691 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7692 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7693 * 7694 * @pre This method can be called if @p scip is in one of the following stages: 7695 * - \ref SCIP_STAGE_TRANSFORMED 7696 * - \ref SCIP_STAGE_INITPRESOLVE 7697 * - \ref SCIP_STAGE_PRESOLVING 7698 * - \ref SCIP_STAGE_EXITPRESOLVE 7699 * - \ref SCIP_STAGE_PRESOLVED 7700 * - \ref SCIP_STAGE_INITSOLVE 7701 * - \ref SCIP_STAGE_SOLVING 7702 * - \ref SCIP_STAGE_SOLVED 7703 * - \ref SCIP_STAGE_EXITSOLVE 7704 * 7705 * @note there can be duplicated arcs in the output file 7706 * 7707 * If @p writenodeweights is true, only nodes corresponding to variables that have a fractional value and only edges 7708 * between such nodes are written. 7709 */ 7710 SCIP_RETCODE SCIPwriteCliqueGraph( 7711 SCIP* scip, /**< SCIP data structure */ 7712 const char* fname, /**< name of file */ 7713 SCIP_Bool writenodeweights /**< should we write weights of nodes? */ 7714 ) 7715 { 7716 FILE* gmlfile; 7717 SCIP_HASHMAP* nodehashmap; 7718 SCIP_CLIQUE** cliques; 7719 SCIP_VAR** clqvars; 7720 SCIP_VAR** allvars; 7721 SCIP_Bool* clqvalues; 7722 char nodename[SCIP_MAXSTRLEN]; 7723 int nallvars; 7724 int nbinvars; 7725 int nintvars; 7726 int nimplvars; 7727 int ncliques; 7728 int c; 7729 int v1; 7730 int v2; 7731 int id1; 7732 int id2; 7733 7734 assert(scip != NULL); 7735 assert(fname != NULL); 7736 7737 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPwriteCliqueGraph", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 7738 7739 /* get all active variables */ 7740 SCIP_CALL( SCIPgetVarsData(scip, &allvars, &nallvars, &nbinvars, &nintvars, &nimplvars, NULL) ); 7741 7742 /* no possible variables for cliques exist */ 7743 if( nbinvars + nimplvars == 0 ) 7744 return SCIP_OKAY; 7745 7746 ncliques = SCIPgetNCliques(scip); 7747 7748 /* no cliques and do not wont to check for binary implications */ 7749 if( ncliques == 0 ) 7750 return SCIP_OKAY; 7751 7752 /* open gml file */ 7753 gmlfile = fopen(fname, "w"); 7754 7755 if( gmlfile == NULL ) 7756 { 7757 SCIPerrorMessage("cannot open graph file <%s>\n", fname); 7758 SCIPABORT(); 7759 return SCIP_INVALIDDATA; /*lint !e527*/ 7760 } 7761 7762 /* create the hash map */ 7763 SCIP_CALL_FINALLY( SCIPhashmapCreate(&nodehashmap, SCIPblkmem(scip), nbinvars+nimplvars), fclose(gmlfile) ); 7764 7765 /* write starting of gml file */ 7766 SCIPgmlWriteOpening(gmlfile, TRUE); 7767 7768 cliques = SCIPgetCliques(scip); 7769 7770 /* write nodes and arcs for all cliques */ 7771 for( c = ncliques - 1; c >= 0; --c ) 7772 { 7773 clqvalues = SCIPcliqueGetValues(cliques[c]); 7774 clqvars = SCIPcliqueGetVars(cliques[c]); 7775 7776 for( v1 = SCIPcliqueGetNVars(cliques[c]) - 1; v1 >= 0; --v1 ) 7777 { 7778 id1 = clqvalues[v1] ? SCIPvarGetProbindex(clqvars[v1]) : (nallvars + SCIPvarGetProbindex(clqvars[v1])); 7779 7780 /* if corresponding node was not added yet, add it */ 7781 if( !SCIPhashmapExists(nodehashmap, (void*)(size_t)id1) ) 7782 { 7783 assert(id1 >= 0); 7784 SCIP_CALL_FINALLY( SCIPhashmapInsertInt(nodehashmap, (void*)(size_t)id1, 1), fclose(gmlfile) ); /*lint !e571*/ 7785 7786 (void) SCIPsnprintf(nodename, SCIP_MAXSTRLEN, "%s%s", (id1 >= nallvars ? "~" : ""), SCIPvarGetName(clqvars[v1])); 7787 7788 /* write new gml node for new variable */ 7789 if ( writenodeweights ) 7790 { 7791 if ( ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v1])) ) 7792 SCIPgmlWriteNodeWeight(gmlfile, (unsigned int)id1, nodename, NULL, NULL, NULL, SCIPgetSolVal(scip, NULL, clqvars[v1])); 7793 } 7794 else 7795 { 7796 SCIPgmlWriteNode(gmlfile, (unsigned int)id1, nodename, NULL, NULL, NULL); 7797 } 7798 } 7799 7800 for( v2 = SCIPcliqueGetNVars(cliques[c]) - 1; v2 >= 0; --v2 ) 7801 { 7802 if( v1 == v2 ) 7803 continue; 7804 7805 id2 = clqvalues[v2] ? SCIPvarGetProbindex(clqvars[v2]) : (nallvars + SCIPvarGetProbindex(clqvars[v2])); 7806 7807 /* if corresponding node was not added yet, add it */ 7808 if( !SCIPhashmapExists(nodehashmap, (void*)(size_t)id2) ) 7809 { 7810 assert(id2 >= 0); 7811 SCIP_CALL_FINALLY( SCIPhashmapInsertInt(nodehashmap, (void*)(size_t)id2, 1), fclose(gmlfile) ); /*lint !e571*/ 7812 7813 (void) SCIPsnprintf(nodename, SCIP_MAXSTRLEN, "%s%s", (id2 >= nallvars ? "~" : ""), SCIPvarGetName(clqvars[v2])); 7814 7815 /* write new gml node for new variable */ 7816 if ( writenodeweights ) 7817 { 7818 if ( ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v2])) ) 7819 SCIPgmlWriteNodeWeight(gmlfile, (unsigned int)id2, nodename, NULL, NULL, NULL, SCIPgetSolVal(scip, NULL, clqvars[v2])); 7820 } 7821 else 7822 { 7823 SCIPgmlWriteNode(gmlfile, (unsigned int)id2, nodename, NULL, NULL, NULL); 7824 } 7825 } 7826 7827 /* write gml arc between resultant and operand */ 7828 if ( ! writenodeweights || ! SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, clqvars[v2])) ) 7829 SCIPgmlWriteArc(gmlfile, (unsigned int)id1, (unsigned int)id2, NULL, NULL); 7830 } 7831 } 7832 } 7833 7834 /* free the hash map */ 7835 SCIPhashmapFree(&nodehashmap); 7836 7837 SCIPgmlWriteClosing(gmlfile); 7838 fclose(gmlfile); 7839 7840 return SCIP_OKAY; 7841 } 7842 7843 /** Removes (irrelevant) variable from all its global structures, i.e. cliques, implications and variable bounds. 7844 * This is an advanced method which should be used with care. 7845 * 7846 * @return SCIP_OKAY if everything worked, otherwise a suitable error code is passed 7847 * 7848 * @pre This method can be called if @p scip is in one of the following stages: 7849 * - \ref SCIP_STAGE_TRANSFORMED 7850 * - \ref SCIP_STAGE_INITPRESOLVE 7851 * - \ref SCIP_STAGE_PRESOLVING 7852 * - \ref SCIP_STAGE_EXITPRESOLVE 7853 * - \ref SCIP_STAGE_PRESOLVED 7854 * - \ref SCIP_STAGE_INITSOLVE 7855 * - \ref SCIP_STAGE_SOLVING 7856 * - \ref SCIP_STAGE_SOLVED 7857 * - \ref SCIP_STAGE_EXITSOLVE 7858 */ 7859 SCIP_RETCODE SCIPremoveVarFromGlobalStructures( 7860 SCIP* scip, /**< SCIP data structure */ 7861 SCIP_VAR* var /**< variable to remove from global structures */ 7862 ) 7863 { 7864 assert(scip != NULL); 7865 7866 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPremoveVarFromGlobalStructures", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 7867 7868 /* mark the variable as deletable from global structures - This is necessary for the delayed clean up of cliques */ 7869 SCIPvarMarkDeleteGlobalStructures(var); 7870 7871 /* remove variable from all its cliques, implications, and variable bounds */ 7872 SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, SCIPblkmem(scip), scip->cliquetable, scip->set, TRUE, FALSE, TRUE) ); 7873 7874 return SCIP_OKAY; 7875 } 7876 7877 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score 7878 * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching 7879 * 7880 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7881 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7882 * 7883 * @pre This method can be called if @p scip is in one of the following stages: 7884 * - \ref SCIP_STAGE_PROBLEM 7885 * - \ref SCIP_STAGE_TRANSFORMING 7886 * - \ref SCIP_STAGE_TRANSFORMED 7887 * - \ref SCIP_STAGE_INITPRESOLVE 7888 * - \ref SCIP_STAGE_PRESOLVING 7889 * - \ref SCIP_STAGE_EXITPRESOLVE 7890 * - \ref SCIP_STAGE_PRESOLVED 7891 * - \ref SCIP_STAGE_SOLVING 7892 */ 7893 SCIP_RETCODE SCIPchgVarBranchFactor( 7894 SCIP* scip, /**< SCIP data structure */ 7895 SCIP_VAR* var, /**< problem variable */ 7896 SCIP_Real branchfactor /**< factor to weigh variable's branching score with */ 7897 ) 7898 { 7899 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 7900 7901 SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, branchfactor) ); 7902 7903 return SCIP_OKAY; 7904 } 7905 7906 /** scales the branch factor of the variable with the given value 7907 * 7908 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7909 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7910 * 7911 * @pre This method can be called if @p scip is in one of the following stages: 7912 * - \ref SCIP_STAGE_PROBLEM 7913 * - \ref SCIP_STAGE_TRANSFORMING 7914 * - \ref SCIP_STAGE_TRANSFORMED 7915 * - \ref SCIP_STAGE_INITPRESOLVE 7916 * - \ref SCIP_STAGE_PRESOLVING 7917 * - \ref SCIP_STAGE_EXITPRESOLVE 7918 * - \ref SCIP_STAGE_PRESOLVED 7919 * - \ref SCIP_STAGE_SOLVING 7920 */ 7921 SCIP_RETCODE SCIPscaleVarBranchFactor( 7922 SCIP* scip, /**< SCIP data structure */ 7923 SCIP_VAR* var, /**< problem variable */ 7924 SCIP_Real scale /**< factor to scale variable's branching factor with */ 7925 ) 7926 { 7927 SCIP_CALL( SCIPcheckStage(scip, "SCIPscaleVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 7928 7929 SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, scale * SCIPvarGetBranchFactor(var)) ); 7930 7931 return SCIP_OKAY; 7932 } 7933 7934 /** adds the given value to the branch factor of the variable 7935 * 7936 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7937 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7938 * 7939 * @pre This method can be called if @p scip is in one of the following stages: 7940 * - \ref SCIP_STAGE_PROBLEM 7941 * - \ref SCIP_STAGE_TRANSFORMING 7942 * - \ref SCIP_STAGE_TRANSFORMED 7943 * - \ref SCIP_STAGE_INITPRESOLVE 7944 * - \ref SCIP_STAGE_PRESOLVING 7945 * - \ref SCIP_STAGE_EXITPRESOLVE 7946 * - \ref SCIP_STAGE_PRESOLVED 7947 * - \ref SCIP_STAGE_SOLVING 7948 */ 7949 SCIP_RETCODE SCIPaddVarBranchFactor( 7950 SCIP* scip, /**< SCIP data structure */ 7951 SCIP_VAR* var, /**< problem variable */ 7952 SCIP_Real addfactor /**< value to add to the branch factor of the variable */ 7953 ) 7954 { 7955 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarBranchFactor", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 7956 7957 SCIP_CALL( SCIPvarChgBranchFactor(var, scip->set, addfactor + SCIPvarGetBranchFactor(var)) ); 7958 7959 return SCIP_OKAY; 7960 } 7961 7962 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables 7963 * with lower priority in selection of branching variable 7964 * 7965 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 7966 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 7967 * 7968 * @pre This method can be called if @p scip is in one of the following stages: 7969 * - \ref SCIP_STAGE_PROBLEM 7970 * - \ref SCIP_STAGE_TRANSFORMING 7971 * - \ref SCIP_STAGE_TRANSFORMED 7972 * - \ref SCIP_STAGE_INITPRESOLVE 7973 * - \ref SCIP_STAGE_PRESOLVING 7974 * - \ref SCIP_STAGE_EXITPRESOLVE 7975 * - \ref SCIP_STAGE_PRESOLVED 7976 * - \ref SCIP_STAGE_SOLVING 7977 * 7978 * @note the default branching priority is 0 7979 */ 7980 SCIP_RETCODE SCIPchgVarBranchPriority( 7981 SCIP* scip, /**< SCIP data structure */ 7982 SCIP_VAR* var, /**< problem variable */ 7983 int branchpriority /**< branch priority of the variable */ 7984 ) 7985 { 7986 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 7987 7988 assert( var->scip == scip ); 7989 7990 if( SCIPisTransformed(scip) ) 7991 { 7992 assert(scip->branchcand != NULL); 7993 7994 /* inform the pseudo branch candidates that the branch priority changes and change the branch priority */ 7995 SCIP_CALL( SCIPbranchcandUpdateVarBranchPriority(scip->branchcand, scip->set, var, branchpriority) ); 7996 } 7997 else 7998 { 7999 /* change the branching priority of the variable */ 8000 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) ); 8001 } 8002 8003 return SCIP_OKAY; 8004 } 8005 8006 /** changes the branch priority of the variable to the given value, if it is larger than the current priority 8007 * 8008 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8009 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8010 * 8011 * @pre This method can be called if @p scip is in one of the following stages: 8012 * - \ref SCIP_STAGE_PROBLEM 8013 * - \ref SCIP_STAGE_TRANSFORMING 8014 * - \ref SCIP_STAGE_TRANSFORMED 8015 * - \ref SCIP_STAGE_INITPRESOLVE 8016 * - \ref SCIP_STAGE_PRESOLVING 8017 * - \ref SCIP_STAGE_EXITPRESOLVE 8018 * - \ref SCIP_STAGE_PRESOLVED 8019 * - \ref SCIP_STAGE_SOLVING 8020 */ 8021 SCIP_RETCODE SCIPupdateVarBranchPriority( 8022 SCIP* scip, /**< SCIP data structure */ 8023 SCIP_VAR* var, /**< problem variable */ 8024 int branchpriority /**< new branch priority of the variable, if it is larger than current priority */ 8025 ) 8026 { 8027 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 8028 8029 assert( var->scip == scip ); 8030 8031 if( branchpriority > SCIPvarGetBranchPriority(var) ) 8032 { 8033 SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) ); 8034 } 8035 8036 return SCIP_OKAY; 8037 } 8038 8039 /** adds the given value to the branch priority of the variable 8040 * 8041 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8042 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8043 * 8044 * @pre This method can be called if @p scip is in one of the following stages: 8045 * - \ref SCIP_STAGE_PROBLEM 8046 * - \ref SCIP_STAGE_TRANSFORMING 8047 * - \ref SCIP_STAGE_TRANSFORMED 8048 * - \ref SCIP_STAGE_INITPRESOLVE 8049 * - \ref SCIP_STAGE_PRESOLVING 8050 * - \ref SCIP_STAGE_EXITPRESOLVE 8051 * - \ref SCIP_STAGE_PRESOLVED 8052 * - \ref SCIP_STAGE_SOLVING 8053 */ 8054 SCIP_RETCODE SCIPaddVarBranchPriority( 8055 SCIP* scip, /**< SCIP data structure */ 8056 SCIP_VAR* var, /**< problem variable */ 8057 int addpriority /**< value to add to the branch priority of the variable */ 8058 ) 8059 { 8060 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddVarBranchPriority", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 8061 8062 assert( var->scip == scip ); 8063 8064 SCIP_CALL( SCIPvarChgBranchPriority(var, addpriority + SCIPvarGetBranchPriority(var)) ); 8065 8066 return SCIP_OKAY; 8067 } 8068 8069 /** sets the branch direction of the variable (-1: prefer downwards branch, 0: automatic selection, +1: prefer upwards 8070 * branch) 8071 * 8072 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8073 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8074 * 8075 * @pre This method can be called if @p scip is in one of the following stages: 8076 * - \ref SCIP_STAGE_PROBLEM 8077 * - \ref SCIP_STAGE_TRANSFORMING 8078 * - \ref SCIP_STAGE_TRANSFORMED 8079 * - \ref SCIP_STAGE_INITPRESOLVE 8080 * - \ref SCIP_STAGE_PRESOLVING 8081 * - \ref SCIP_STAGE_EXITPRESOLVE 8082 * - \ref SCIP_STAGE_PRESOLVED 8083 * - \ref SCIP_STAGE_SOLVING 8084 */ 8085 SCIP_RETCODE SCIPchgVarBranchDirection( 8086 SCIP* scip, /**< SCIP data structure */ 8087 SCIP_VAR* var, /**< problem variable */ 8088 SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */ 8089 ) 8090 { 8091 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarBranchDirection", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 8092 8093 assert( var->scip == scip ); 8094 8095 SCIP_CALL( SCIPvarChgBranchDirection(var, branchdirection) ); 8096 8097 return SCIP_OKAY; 8098 } 8099 8100 /** tightens the variable bounds due to a new variable type */ 8101 static 8102 SCIP_RETCODE tightenBounds( 8103 SCIP* scip, /**< SCIP data structure */ 8104 SCIP_VAR* var, /**< variable to change the bound for */ 8105 SCIP_VARTYPE vartype, /**< new type of variable */ 8106 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected (, due to 8107 * integrality condition of the new variable type) */ 8108 ) 8109 { 8110 assert(scip != NULL); 8111 assert(SCIPgetStage(scip) == SCIP_STAGE_PROBLEM || SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING); 8112 assert(scip->set->stage == SCIP_STAGE_PROBLEM || SCIPvarIsTransformed(var)); 8113 assert(var->scip == scip); 8114 8115 *infeasible = FALSE; 8116 8117 /* adjusts bounds if the variable type changed form continuous to non-continuous (integral) */ 8118 if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS && vartype != SCIP_VARTYPE_CONTINUOUS ) 8119 { 8120 SCIP_Bool tightened; 8121 8122 /* we adjust variable bounds to integers first, since otherwise a later bound tightening with a fractional old 8123 * bound may give an assert because SCIP expects non-continuous variables to have non-fractional bounds 8124 * 8125 * we adjust bounds with a fractionality within [eps,feastol] only if the resulting bound change is a bound 8126 * tightening, because relaxing bounds may not be allowed 8127 */ 8128 if( !SCIPisFeasIntegral(scip, SCIPvarGetLbGlobal(var)) || 8129 (!SCIPisIntegral(scip, SCIPvarGetLbGlobal(var)) && SCIPvarGetLbGlobal(var) < SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))) || 8130 (!SCIPsetIsEQ(scip->set, SCIPvarGetLbGlobal(var), SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))) && 8131 SCIPvarGetLbGlobal(var) < SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var))) 8132 ) 8133 { 8134 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var)), TRUE, infeasible, &tightened) ); 8135 if( *infeasible ) 8136 return SCIP_OKAY; 8137 8138 /* the only reason for not applying a forced boundchange is when the new bound is reduced because the variables upper bound is below the new bound 8139 * in a concrete case, lb == ub == 100.99999001; even though within feastol of 101, the lower bound cannot be tighented to 101 due to the upper bound 8140 */ 8141 assert(tightened || SCIPisFeasLE(scip, SCIPvarGetUbGlobal(var), SCIPfeasCeil(scip, SCIPvarGetLbGlobal(var)))); 8142 } 8143 if( !SCIPisFeasIntegral(scip, SCIPvarGetUbGlobal(var)) || 8144 (!SCIPisIntegral(scip, SCIPvarGetUbGlobal(var)) && SCIPvarGetUbGlobal(var) > SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var))) 8145 ) 8146 { 8147 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var)), TRUE, infeasible, &tightened) ); 8148 if( *infeasible ) 8149 return SCIP_OKAY; 8150 8151 assert(tightened || SCIPisFeasGE(scip, SCIPvarGetLbGlobal(var), SCIPfeasFloor(scip, SCIPvarGetUbGlobal(var)))); 8152 } 8153 } 8154 8155 return SCIP_OKAY; 8156 } 8157 8158 /** changes type of variable in the problem; 8159 * 8160 * @warning This type change might change the variable array returned from SCIPgetVars() and SCIPgetVarsData(); 8161 * 8162 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8163 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8164 * 8165 * @pre This method can be called if @p scip is in one of the following stages: 8166 * - \ref SCIP_STAGE_PROBLEM 8167 * - \ref SCIP_STAGE_TRANSFORMING 8168 * - \ref SCIP_STAGE_PRESOLVING 8169 * 8170 * @note If SCIP is already beyond the SCIP_STAGE_PROBLEM and a original variable is passed, the variable type of the 8171 * corresponding transformed variable is changed; the type of the original variable does not change 8172 * 8173 * @note If the type changes from a continuous variable to a non-continuous variable the bounds of the variable get 8174 * adjusted w.r.t. to integrality information 8175 */ 8176 SCIP_RETCODE SCIPchgVarType( 8177 SCIP* scip, /**< SCIP data structure */ 8178 SCIP_VAR* var, /**< variable to change the bound for */ 8179 SCIP_VARTYPE vartype, /**< new type of variable */ 8180 SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected (, due to 8181 * integrality condition of the new variable type) */ 8182 ) 8183 { 8184 SCIP_CALL( SCIPcheckStage(scip, "SCIPchgVarType", FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 8185 8186 assert(var != NULL); 8187 assert(var->scip == scip); 8188 8189 if( SCIPvarIsNegated(var) ) 8190 { 8191 SCIPdebugMsg(scip, "upgrading type of negated variable <%s> from %d to %d\n", SCIPvarGetName(var), SCIPvarGetType(var), vartype); 8192 var = SCIPvarGetNegationVar(var); 8193 } 8194 #ifndef NDEBUG 8195 else 8196 { 8197 if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM ) 8198 { 8199 SCIPdebugMsg(scip, "upgrading type of variable <%s> from %d to %d\n", SCIPvarGetName(var), SCIPvarGetType(var), vartype); 8200 } 8201 } 8202 #endif 8203 8204 /* change variable type */ 8205 switch( scip->set->stage ) 8206 { 8207 case SCIP_STAGE_PROBLEM: 8208 assert(!SCIPvarIsTransformed(var)); 8209 8210 /* first adjust the variable due to new integrality information */ 8211 SCIP_CALL( tightenBounds(scip, var, vartype, infeasible) ); 8212 8213 /* second change variable type */ 8214 if( SCIPvarGetProbindex(var) >= 0 ) 8215 { 8216 SCIP_CALL( SCIPprobChgVarType(scip->origprob, scip->mem->probmem, scip->set, scip->primal, scip->lp, 8217 scip->branchcand, scip->eventqueue, scip->cliquetable, var, vartype) ); 8218 } 8219 else 8220 { 8221 SCIP_CALL( SCIPvarChgType(var, scip->mem->probmem, scip->set, scip->primal, scip->lp, 8222 scip->eventqueue, vartype) ); 8223 } 8224 break; 8225 8226 case SCIP_STAGE_PRESOLVING: 8227 if( !SCIPvarIsTransformed(var) ) 8228 { 8229 SCIP_VAR* transvar; 8230 8231 SCIP_CALL( SCIPgetTransformedVar(scip, var, &transvar) ); 8232 assert(transvar != NULL); 8233 8234 /* recall method with transformed variable */ 8235 SCIP_CALL( SCIPchgVarType(scip, transvar, vartype, infeasible) ); 8236 return SCIP_OKAY; 8237 } 8238 8239 /* first adjust the variable due to new integrality information */ 8240 SCIP_CALL( tightenBounds(scip, var, vartype, infeasible) ); 8241 8242 /* second change variable type */ 8243 if( SCIPvarGetProbindex(var) >= 0 ) 8244 { 8245 SCIP_CALL( SCIPprobChgVarType(scip->transprob, scip->mem->probmem, scip->set, scip->primal, scip->lp, 8246 scip->branchcand, scip->eventqueue, scip->cliquetable, var, vartype) ); 8247 } 8248 else 8249 { 8250 SCIP_CALL( SCIPvarChgType(var, scip->mem->probmem, scip->set, scip->primal, scip->lp, 8251 scip->eventqueue, vartype) ); 8252 } 8253 break; 8254 8255 default: 8256 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 8257 return SCIP_INVALIDCALL; 8258 } /*lint !e788*/ 8259 8260 return SCIP_OKAY; 8261 } 8262 8263 /** in problem creation and solving stage, both bounds of the variable are set to the given value; 8264 * in presolving stage, the variable is converted into a fixed variable, and bounds are changed respectively; 8265 * conversion into a fixed variable changes the vars array returned from SCIPgetVars() and SCIPgetVarsData(), 8266 * and also renders arrays returned from the SCIPvarGetImpl...() methods invalid 8267 * 8268 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8269 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8270 * 8271 * @pre This method can be called if @p scip is in one of the following stages: 8272 * - \ref SCIP_STAGE_PROBLEM 8273 * - \ref SCIP_STAGE_PRESOLVING 8274 * - \ref SCIP_STAGE_SOLVING 8275 */ 8276 SCIP_RETCODE SCIPfixVar( 8277 SCIP* scip, /**< SCIP data structure */ 8278 SCIP_VAR* var, /**< variable to fix */ 8279 SCIP_Real fixedval, /**< value to fix variable to */ 8280 SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */ 8281 SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */ 8282 ) 8283 { 8284 assert(var != NULL); 8285 assert(infeasible != NULL); 8286 assert(fixed != NULL); 8287 8288 SCIP_CALL( SCIPcheckStage(scip, "SCIPfixVar", FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 8289 8290 *infeasible = FALSE; 8291 *fixed = FALSE; 8292 8293 /* in the problem creation stage, modify the bounds as requested, independently from the current bounds */ 8294 if( scip->set->stage != SCIP_STAGE_PROBLEM ) 8295 { 8296 if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(scip->set, fixedval)) 8297 || SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetLbLocal(var)) 8298 || SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetUbLocal(var)) ) 8299 { 8300 *infeasible = TRUE; 8301 return SCIP_OKAY; 8302 } 8303 else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED ) 8304 { 8305 *infeasible = !SCIPsetIsFeasEQ(scip->set, fixedval, SCIPvarGetLbLocal(var)); 8306 return SCIP_OKAY; 8307 } 8308 } 8309 else 8310 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL); 8311 8312 switch( scip->set->stage ) 8313 { 8314 case SCIP_STAGE_PROBLEM: 8315 /* in the problem creation stage, modify the bounds as requested, independently from the current bounds; 8316 * we have to make sure, that the order of the bound changes does not intermediately produce an invalid 8317 * interval lb > ub 8318 */ 8319 if( fixedval <= SCIPvarGetLbLocal(var) ) 8320 { 8321 SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) ); 8322 SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) ); 8323 *fixed = TRUE; 8324 } 8325 else 8326 { 8327 SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) ); 8328 SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) ); 8329 *fixed = TRUE; 8330 } 8331 return SCIP_OKAY; 8332 8333 case SCIP_STAGE_PRESOLVING: 8334 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 ) 8335 { 8336 SCIP_CALL( SCIPvarFix(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 8337 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue, 8338 scip->cliquetable, fixedval, infeasible, fixed) ); 8339 return SCIP_OKAY; 8340 } 8341 /*lint -fallthrough*/ 8342 case SCIP_STAGE_SOLVING: 8343 if( SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetLbLocal(var)) ) 8344 { 8345 if( SCIPsetIsFeasGT(scip->set, fixedval, SCIPvarGetUbLocal(var)) ) 8346 { 8347 *infeasible = TRUE; 8348 return SCIP_OKAY; 8349 } 8350 else 8351 { 8352 SCIP_CALL( SCIPchgVarLb(scip, var, fixedval) ); 8353 *fixed = TRUE; 8354 } 8355 } 8356 if( SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetUbLocal(var)) ) 8357 { 8358 if( SCIPsetIsFeasLT(scip->set, fixedval, SCIPvarGetLbLocal(var)) ) 8359 { 8360 *infeasible = TRUE; 8361 return SCIP_OKAY; 8362 } 8363 else 8364 { 8365 SCIP_CALL( SCIPchgVarUb(scip, var, fixedval) ); 8366 *fixed = TRUE; 8367 } 8368 } 8369 return SCIP_OKAY; 8370 8371 default: 8372 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 8373 return SCIP_INVALIDCALL; 8374 } /*lint !e788*/ 8375 } 8376 8377 /** From a given equality a*x + b*y == c, aggregates one of the variables and removes it from the set of 8378 * active problem variables. This changes the vars array returned from SCIPgetVars() and SCIPgetVarsData(), 8379 * and also renders the arrays returned from the SCIPvarGetImpl...() methods for the two variables invalid. 8380 * In the first step, the equality is transformed into an equality with active problem variables 8381 * a'*x' + b'*y' == c'. If x' == y', this leads to the detection of redundancy if a' == -b' and c' == 0, 8382 * of infeasibility, if a' == -b' and c' != 0, or to a variable fixing x' == c'/(a'+b') (and possible 8383 * infeasibility) otherwise. 8384 * In the second step, the variable to be aggregated is chosen among x' and y', prefering a less strict variable 8385 * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers 8386 * over integers, and integers over binaries). If none of the variables is continuous, it is tried to find an integer 8387 * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to 8388 * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by 8389 * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable. 8390 * 8391 * The output flags have the following meaning: 8392 * - infeasible: the problem is infeasible 8393 * - redundant: the equality can be deleted from the constraint set 8394 * - aggregated: the aggregation was successfully performed (the variables were not aggregated before) 8395 * 8396 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8397 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8398 * 8399 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PRESOLVING 8400 */ 8401 SCIP_RETCODE SCIPaggregateVars( 8402 SCIP* scip, /**< SCIP data structure */ 8403 SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */ 8404 SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */ 8405 SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */ 8406 SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */ 8407 SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */ 8408 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */ 8409 SCIP_Bool* redundant, /**< pointer to store whether the equality is (now) redundant */ 8410 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */ 8411 ) 8412 { 8413 SCIP_Real constantx; 8414 SCIP_Real constanty; 8415 8416 assert(infeasible != NULL); 8417 assert(redundant != NULL); 8418 assert(aggregated != NULL); 8419 8420 SCIP_CALL( SCIPcheckStage(scip, "SCIPaggregateVars", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 8421 8422 *infeasible = FALSE; 8423 *redundant = FALSE; 8424 *aggregated = FALSE; 8425 8426 if( SCIPtreeProbing(scip->tree) ) 8427 { 8428 SCIPerrorMessage("cannot aggregate variables during probing\n"); 8429 return SCIP_INVALIDCALL; 8430 } 8431 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 8432 8433 /* do not perform aggregation if it is globally deactivated */ 8434 if( scip->set->presol_donotaggr ) 8435 return SCIP_OKAY; 8436 8437 /* get the corresponding equality in active problem variable space: 8438 * transform both expressions "a*x + 0" and "b*y + 0" into problem variable space 8439 */ 8440 constantx = 0.0; 8441 constanty = 0.0; 8442 SCIP_CALL( SCIPvarGetProbvarSum(&varx, scip->set, &scalarx, &constantx) ); 8443 SCIP_CALL( SCIPvarGetProbvarSum(&vary, scip->set, &scalary, &constanty) ); 8444 8445 /* we cannot aggregate multi-aggregated variables */ 8446 if( SCIPvarGetStatus(varx) == SCIP_VARSTATUS_MULTAGGR || SCIPvarGetStatus(vary) == SCIP_VARSTATUS_MULTAGGR ) 8447 return SCIP_OKAY; 8448 8449 /* move the constant to the right hand side to acquire the form "a'*x' + b'*y' == c'" */ 8450 rhs -= (constantx + constanty); 8451 8452 /* if a scalar is zero, treat the variable as fixed-to-zero variable */ 8453 if( SCIPsetIsZero(scip->set, scalarx) ) 8454 varx = NULL; 8455 if( SCIPsetIsZero(scip->set, scalary) ) 8456 vary = NULL; 8457 8458 /* capture the special cases that less than two variables are left, due to resolutions to a fixed variable or 8459 * to the same active variable 8460 */ 8461 if( varx == NULL && vary == NULL ) 8462 { 8463 /* both variables were resolved to fixed variables */ 8464 *infeasible = !SCIPsetIsZero(scip->set, rhs); 8465 *redundant = TRUE; 8466 } 8467 else if( varx == NULL ) 8468 { 8469 assert(SCIPsetIsZero(scip->set, scalarx)); 8470 assert(!SCIPsetIsZero(scip->set, scalary)); 8471 8472 /* variable x was resolved to fixed variable: variable y can be fixed to c'/b' */ 8473 SCIP_CALL( SCIPvarFix(vary, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 8474 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue, 8475 scip->cliquetable, rhs/scalary, infeasible, aggregated) ); 8476 *redundant = TRUE; 8477 } 8478 else if( vary == NULL ) 8479 { 8480 assert(SCIPsetIsZero(scip->set, scalary)); 8481 assert(!SCIPsetIsZero(scip->set, scalarx)); 8482 8483 /* variable y was resolved to fixed variable: variable x can be fixed to c'/a' */ 8484 SCIP_CALL( SCIPvarFix(varx, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 8485 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue, 8486 scip->cliquetable, rhs/scalarx, infeasible, aggregated) ); 8487 *redundant = TRUE; 8488 } 8489 else if( varx == vary ) 8490 { 8491 /* both variables were resolved to the same active problem variable: this variable can be fixed */ 8492 scalarx += scalary; 8493 if( SCIPsetIsZero(scip->set, scalarx) ) 8494 { 8495 /* left hand side of equality is zero: equality is potentially infeasible */ 8496 *infeasible = !SCIPsetIsZero(scip->set, rhs); 8497 } 8498 else 8499 { 8500 /* sum of scalars is not zero: fix variable x' == y' to c'/(a'+b') */ 8501 SCIP_CALL( SCIPvarFix(varx, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 8502 scip->primal, scip->tree, scip->reopt, scip->lp, scip->branchcand, scip->eventfilter, scip->eventqueue, 8503 scip->cliquetable, rhs/scalarx, infeasible, aggregated) ); 8504 } 8505 *redundant = TRUE; 8506 } 8507 else 8508 { 8509 /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */ 8510 SCIP_CALL( SCIPvarTryAggregateVars(scip->set, scip->mem->probmem, scip->stat, scip->transprob, scip->origprob, 8511 scip->primal, scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventfilter, 8512 scip->eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) ); 8513 *redundant = *aggregated; 8514 } 8515 8516 return SCIP_OKAY; 8517 } 8518 8519 /** converts variable into multi-aggregated variable; this changes the variable array returned from 8520 * SCIPgetVars() and SCIPgetVarsData(); 8521 * 8522 * @warning The integrality condition is not checked anymore on the multi-aggregated variable. You must not 8523 * multi-aggregate an integer variable without being sure, that integrality on the aggregation variables 8524 * implies integrality on the aggregated variable. 8525 * 8526 * The output flags have the following meaning: 8527 * - infeasible: the problem is infeasible 8528 * - aggregated: the aggregation was successfully performed (the variables were not aggregated before) 8529 * 8530 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8531 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8532 * 8533 * @pre This method can only be called if @p scip is in stage \ref SCIP_STAGE_PRESOLVING 8534 */ 8535 SCIP_RETCODE SCIPmultiaggregateVar( 8536 SCIP* scip, /**< SCIP data structure */ 8537 SCIP_VAR* var, /**< variable x to aggregate */ 8538 int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */ 8539 SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */ 8540 SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */ 8541 SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */ 8542 SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */ 8543 SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */ 8544 ) 8545 { 8546 SCIP_CALL( SCIPcheckStage(scip, "SCIPmultiaggregateVar", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 8547 8548 assert(var->scip == scip); 8549 8550 if( SCIPtreeProbing(scip->tree) ) 8551 { 8552 SCIPerrorMessage("cannot multi-aggregate variables during probing\n"); 8553 return SCIP_INVALIDCALL; 8554 } 8555 assert(SCIPtreeGetCurrentDepth(scip->tree) == 0); 8556 8557 SCIP_CALL( SCIPvarMultiaggregate(var, scip->mem->probmem, scip->set, scip->stat, scip->transprob, scip->origprob, 8558 scip->primal, scip->tree, scip->reopt, scip->lp, scip->cliquetable, scip->branchcand, scip->eventfilter, 8559 scip->eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) ); 8560 8561 return SCIP_OKAY; 8562 } 8563 8564 /** returns whether aggregation of variables is not allowed */ 8565 SCIP_Bool SCIPdoNotAggr( 8566 SCIP* scip /**< SCIP data structure */ 8567 ) 8568 { 8569 assert(scip != NULL); 8570 8571 return scip->set->presol_donotaggr; 8572 } 8573 8574 /** returns whether multi-aggregation is disabled */ 8575 SCIP_Bool SCIPdoNotMultaggr( 8576 SCIP* scip /**< SCIP data structure */ 8577 ) 8578 { 8579 assert(scip != NULL); 8580 8581 return scip->set->presol_donotmultaggr; 8582 } 8583 8584 /** returns whether variable is not allowed to be aggregated */ 8585 SCIP_Bool SCIPdoNotAggrVar( 8586 SCIP* scip, /**< SCIP data structure */ 8587 SCIP_VAR* var /**< variable x to aggregate */ 8588 ) 8589 { 8590 assert(scip != NULL); 8591 assert(var != NULL); 8592 assert(var->scip == scip); 8593 8594 return scip->set->presol_donotaggr || SCIPvarDoNotAggr(var); 8595 } 8596 8597 /** returns whether variable is not allowed to be multi-aggregated */ 8598 SCIP_Bool SCIPdoNotMultaggrVar( 8599 SCIP* scip, /**< SCIP data structure */ 8600 SCIP_VAR* var /**< variable x to aggregate */ 8601 ) 8602 { 8603 assert(scip != NULL); 8604 assert(var != NULL); 8605 assert(var->scip == scip); 8606 8607 return scip->set->presol_donotmultaggr || SCIPvarDoNotMultaggr(var); 8608 } 8609 8610 /** returns whether dual reductions are allowed during propagation and presolving 8611 * 8612 * @deprecated Please use SCIPallowStrongDualReds() 8613 */ 8614 SCIP_Bool SCIPallowDualReds( 8615 SCIP* scip /**< SCIP data structure */ 8616 ) 8617 { 8618 assert(scip != NULL); 8619 8620 return !scip->set->reopt_enable && scip->set->misc_allowstrongdualreds; 8621 } 8622 8623 /** returns whether strong dual reductions are allowed during propagation and presolving 8624 * 8625 * @note A reduction is called strong dual, if it may discard feasible/optimal solutions, but leaves at least one 8626 * optimal solution intact. Often such reductions are based on analyzing the objective function and variable 8627 * locks. 8628 */ 8629 SCIP_Bool SCIPallowStrongDualReds( 8630 SCIP* scip /**< SCIP data structure */ 8631 ) 8632 { 8633 assert(scip != NULL); 8634 8635 return !scip->set->reopt_enable && scip->set->misc_allowstrongdualreds; 8636 } 8637 8638 /** returns whether propagation w.r.t. current objective is allowed 8639 * 8640 * @deprecated Please use SCIPallowWeakDualReds() 8641 */ 8642 SCIP_Bool SCIPallowObjProp( 8643 SCIP* scip /**< SCIP data structure */ 8644 ) 8645 { 8646 assert(scip != NULL); 8647 8648 return !scip->set->reopt_enable && scip->set->misc_allowweakdualreds; 8649 } 8650 8651 /** returns whether weak dual reductions are allowed during propagation and presolving 8652 * 8653 * @note A reduction is called weak dual, if it may discard feasible solutions, but leaves at all optimal solutions 8654 * intact. Often such reductions are based on analyzing the objective function, reduced costs, and/or dual LPs. 8655 */ 8656 SCIP_Bool SCIPallowWeakDualReds( 8657 SCIP* scip /**< SCIP data structure */ 8658 ) 8659 { 8660 assert(scip != NULL); 8661 8662 return !scip->set->reopt_enable && scip->set->misc_allowweakdualreds; 8663 } 8664 8665 /** marks the variable that it must not be aggregated 8666 * 8667 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8668 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8669 * 8670 * @pre This method can be called if @p scip is in one of the following stages: 8671 * - \ref SCIP_STAGE_INIT 8672 * - \ref SCIP_STAGE_PROBLEM 8673 * - \ref SCIP_STAGE_TRANSFORMING 8674 * - \ref SCIP_STAGE_TRANSFORMED 8675 * - \ref SCIP_STAGE_INITPRESOLVE 8676 * - \ref SCIP_STAGE_PRESOLVING 8677 * - \ref SCIP_STAGE_EXITPRESOLVE 8678 * 8679 * @note There exists no "unmark" method since it has to be ensured that if a plugin requires that a variable is not 8680 * aggregated that this is will be the case. 8681 */ 8682 SCIP_RETCODE SCIPmarkDoNotAggrVar( 8683 SCIP* scip, /**< SCIP data structure */ 8684 SCIP_VAR* var /**< variable to delete */ 8685 ) 8686 { 8687 assert(scip != NULL); 8688 assert(var != NULL); 8689 assert(var->scip == scip); 8690 8691 SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkDoNotAggrVar", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE) ); 8692 8693 SCIP_CALL( SCIPvarMarkDoNotAggr(var) ); 8694 8695 return SCIP_OKAY; 8696 } 8697 8698 /** marks the variable that it must not be multi-aggregated 8699 * 8700 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8701 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8702 * 8703 * @pre This method can be called if @p scip is in one of the following stages: 8704 * - \ref SCIP_STAGE_INIT 8705 * - \ref SCIP_STAGE_PROBLEM 8706 * - \ref SCIP_STAGE_TRANSFORMING 8707 * - \ref SCIP_STAGE_TRANSFORMED 8708 * - \ref SCIP_STAGE_INITPRESOLVE 8709 * - \ref SCIP_STAGE_PRESOLVING 8710 * - \ref SCIP_STAGE_EXITPRESOLVE 8711 * 8712 * @note There exists no "unmark" method since it has to be ensured that if a plugin requires that a variable is not 8713 * multi-aggregated that this is will be the case. 8714 */ 8715 SCIP_RETCODE SCIPmarkDoNotMultaggrVar( 8716 SCIP* scip, /**< SCIP data structure */ 8717 SCIP_VAR* var /**< variable to delete */ 8718 ) 8719 { 8720 assert(scip != NULL); 8721 assert(var != NULL); 8722 assert(var->scip == scip); 8723 8724 SCIP_CALL( SCIPcheckStage(scip, "SCIPmarkDoNotMultaggrVar", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE) ); 8725 8726 SCIP_CALL( SCIPvarMarkDoNotMultaggr(var) ); 8727 8728 return SCIP_OKAY; 8729 } 8730 8731 /** enables the collection of statistics for a variable 8732 * 8733 * @pre This method can be called if @p scip is in one of the following stages: 8734 * - \ref SCIP_STAGE_PROBLEM 8735 * - \ref SCIP_STAGE_INITPRESOLVE 8736 * - \ref SCIP_STAGE_PRESOLVING 8737 * - \ref SCIP_STAGE_EXITPRESOLVE 8738 * - \ref SCIP_STAGE_SOLVING 8739 * - \ref SCIP_STAGE_SOLVED 8740 */ 8741 void SCIPenableVarHistory( 8742 SCIP* scip /**< SCIP data structure */ 8743 ) 8744 { 8745 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPenableVarHistory", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8746 8747 SCIPstatEnableVarHistory(scip->stat); 8748 } 8749 8750 /** disables the collection of any statistic for a variable 8751 * 8752 * @pre This method can be called if @p scip is in one of the following stages: 8753 * - \ref SCIP_STAGE_PROBLEM 8754 * - \ref SCIP_STAGE_INITPRESOLVE 8755 * - \ref SCIP_STAGE_PRESOLVING 8756 * - \ref SCIP_STAGE_EXITPRESOLVE 8757 * - \ref SCIP_STAGE_SOLVING 8758 * - \ref SCIP_STAGE_SOLVED 8759 */ 8760 void SCIPdisableVarHistory( 8761 SCIP* scip /**< SCIP data structure */ 8762 ) 8763 { 8764 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPdisableVarHistory", FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8765 8766 SCIPstatDisableVarHistory(scip->stat); 8767 } 8768 8769 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of "solvaldelta" in the 8770 * variable's solution value and resulting change of "objdelta" in the in the LP's objective value; 8771 * the update is ignored, if the objective value difference is infinite 8772 * 8773 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 8774 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 8775 * 8776 * @pre This method can be called if @p scip is in one of the following stages: 8777 * - \ref SCIP_STAGE_SOLVING 8778 * - \ref SCIP_STAGE_SOLVED 8779 */ 8780 SCIP_RETCODE SCIPupdateVarPseudocost( 8781 SCIP* scip, /**< SCIP data structure */ 8782 SCIP_VAR* var, /**< problem variable */ 8783 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */ 8784 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */ 8785 SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */ 8786 ) 8787 { 8788 SCIP_CALL( SCIPcheckStage(scip, "SCIPupdateVarPseudocost", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8789 8790 if( !SCIPsetIsInfinity(scip->set, 2*objdelta) ) /* differences infinity - eps should also be treated as infinity */ 8791 { 8792 if( scip->set->branch_divingpscost || (!scip->lp->diving && !SCIPtreeProbing(scip->tree)) ) 8793 { 8794 SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, solvaldelta, objdelta, weight) ); 8795 } 8796 } 8797 8798 return SCIP_OKAY; 8799 } 8800 8801 /** gets the variable's pseudo cost value for the given change of the variable's LP value 8802 * 8803 * @return the variable's pseudo cost value for the given change of the variable's LP value 8804 * 8805 * @pre This method can be called if @p scip is in one of the following stages: 8806 * - \ref SCIP_STAGE_INITPRESOLVE 8807 * - \ref SCIP_STAGE_PRESOLVING 8808 * - \ref SCIP_STAGE_EXITPRESOLVE 8809 * - \ref SCIP_STAGE_PRESOLVED 8810 * - \ref SCIP_STAGE_INITSOLVE 8811 * - \ref SCIP_STAGE_SOLVING 8812 * - \ref SCIP_STAGE_SOLVED 8813 */ 8814 SCIP_Real SCIPgetVarPseudocostVal( 8815 SCIP* scip, /**< SCIP data structure */ 8816 SCIP_VAR* var, /**< problem variable */ 8817 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */ 8818 ) 8819 { 8820 assert( var->scip == scip ); 8821 8822 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostVal", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8823 8824 return SCIPvarGetPseudocost(var, scip->stat, solvaldelta); 8825 } 8826 8827 /** gets the variable's pseudo cost value for the given change of the variable's LP value, 8828 * only using the pseudo cost information of the current run 8829 * 8830 * @return the variable's pseudo cost value for the given change of the variable's LP value, 8831 * only using the pseudo cost information of the current run 8832 * 8833 * @pre This method can be called if @p scip is in one of the following stages: 8834 * - \ref SCIP_STAGE_INITPRESOLVE 8835 * - \ref SCIP_STAGE_PRESOLVING 8836 * - \ref SCIP_STAGE_EXITPRESOLVE 8837 * - \ref SCIP_STAGE_PRESOLVED 8838 * - \ref SCIP_STAGE_INITSOLVE 8839 * - \ref SCIP_STAGE_SOLVING 8840 * - \ref SCIP_STAGE_SOLVED 8841 */ 8842 SCIP_Real SCIPgetVarPseudocostValCurrentRun( 8843 SCIP* scip, /**< SCIP data structure */ 8844 SCIP_VAR* var, /**< problem variable */ 8845 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */ 8846 ) 8847 { 8848 assert( var->scip == scip ); 8849 8850 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostValCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8851 8852 return SCIPvarGetPseudocostCurrentRun(var, scip->stat, solvaldelta); 8853 } 8854 8855 /** gets the variable's pseudo cost value for the given direction 8856 * 8857 * @return the variable's pseudo cost value for the given direction 8858 * 8859 * @pre This method can be called if @p scip is in one of the following stages: 8860 * - \ref SCIP_STAGE_INITPRESOLVE 8861 * - \ref SCIP_STAGE_PRESOLVING 8862 * - \ref SCIP_STAGE_EXITPRESOLVE 8863 * - \ref SCIP_STAGE_PRESOLVED 8864 * - \ref SCIP_STAGE_INITSOLVE 8865 * - \ref SCIP_STAGE_SOLVING 8866 * - \ref SCIP_STAGE_SOLVED 8867 */ 8868 SCIP_Real SCIPgetVarPseudocost( 8869 SCIP* scip, /**< SCIP data structure */ 8870 SCIP_VAR* var, /**< problem variable */ 8871 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 8872 ) 8873 { 8874 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocost", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8875 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS); 8876 assert(var->scip == scip); 8877 8878 return SCIPvarGetPseudocost(var, scip->stat, dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0); 8879 } 8880 8881 /** gets the variable's pseudo cost value for the given direction, 8882 * only using the pseudo cost information of the current run 8883 * 8884 * @return the variable's pseudo cost value for the given direction, 8885 * only using the pseudo cost information of the current run 8886 * 8887 * @pre This method can be called if @p scip is in one of the following stages: 8888 * - \ref SCIP_STAGE_INITPRESOLVE 8889 * - \ref SCIP_STAGE_PRESOLVING 8890 * - \ref SCIP_STAGE_EXITPRESOLVE 8891 * - \ref SCIP_STAGE_PRESOLVED 8892 * - \ref SCIP_STAGE_INITSOLVE 8893 * - \ref SCIP_STAGE_SOLVING 8894 * - \ref SCIP_STAGE_SOLVED 8895 */ 8896 SCIP_Real SCIPgetVarPseudocostCurrentRun( 8897 SCIP* scip, /**< SCIP data structure */ 8898 SCIP_VAR* var, /**< problem variable */ 8899 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 8900 ) 8901 { 8902 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8903 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS); 8904 assert(var->scip == scip); 8905 8906 return SCIPvarGetPseudocostCurrentRun(var, scip->stat, dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0); 8907 } 8908 8909 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction 8910 * 8911 * @return the variable's (possible fractional) number of pseudo cost updates for the given direction 8912 * 8913 * @pre This method can be called if @p scip is in one of the following stages: 8914 * - \ref SCIP_STAGE_INITPRESOLVE 8915 * - \ref SCIP_STAGE_PRESOLVING 8916 * - \ref SCIP_STAGE_EXITPRESOLVE 8917 * - \ref SCIP_STAGE_PRESOLVED 8918 * - \ref SCIP_STAGE_INITSOLVE 8919 * - \ref SCIP_STAGE_SOLVING 8920 * - \ref SCIP_STAGE_SOLVED 8921 */ 8922 SCIP_Real SCIPgetVarPseudocostCount( 8923 SCIP* scip, /**< SCIP data structure */ 8924 SCIP_VAR* var, /**< problem variable */ 8925 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 8926 ) 8927 { 8928 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCount", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8929 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS); 8930 assert(var->scip == scip); 8931 8932 return SCIPvarGetPseudocostCount(var, dir); 8933 } 8934 8935 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction, 8936 * only using the pseudo cost information of the current run 8937 * 8938 * @return the variable's (possible fractional) number of pseudo cost updates for the given direction, 8939 * only using the pseudo cost information of the current run 8940 * 8941 * @pre This method can be called if @p scip is in one of the following stages: 8942 * - \ref SCIP_STAGE_INITPRESOLVE 8943 * - \ref SCIP_STAGE_PRESOLVING 8944 * - \ref SCIP_STAGE_EXITPRESOLVE 8945 * - \ref SCIP_STAGE_PRESOLVED 8946 * - \ref SCIP_STAGE_INITSOLVE 8947 * - \ref SCIP_STAGE_SOLVING 8948 * - \ref SCIP_STAGE_SOLVED 8949 */ 8950 SCIP_Real SCIPgetVarPseudocostCountCurrentRun( 8951 SCIP* scip, /**< SCIP data structure */ 8952 SCIP_VAR* var, /**< problem variable */ 8953 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 8954 ) 8955 { 8956 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostCountCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8957 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS); 8958 assert(var->scip == scip); 8959 8960 return SCIPvarGetPseudocostCountCurrentRun(var, dir); 8961 } 8962 8963 /** get pseudo cost variance of the variable, either for entire solve or only for current branch and bound run 8964 * 8965 * @return returns the (corrected) variance of pseudo code information collected so far. 8966 * 8967 * @pre This method can be called if @p scip is in one of the following stages: 8968 * - \ref SCIP_STAGE_INITPRESOLVE 8969 * - \ref SCIP_STAGE_PRESOLVING 8970 * - \ref SCIP_STAGE_EXITPRESOLVE 8971 * - \ref SCIP_STAGE_PRESOLVED 8972 * - \ref SCIP_STAGE_INITSOLVE 8973 * - \ref SCIP_STAGE_SOLVING 8974 * - \ref SCIP_STAGE_SOLVED 8975 */ 8976 SCIP_Real SCIPgetVarPseudocostVariance( 8977 SCIP* scip, /**< SCIP data structure */ 8978 SCIP_VAR* var, /**< problem variable */ 8979 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */ 8980 SCIP_Bool onlycurrentrun /**< only for pseudo costs of current branch and bound run */ 8981 ) 8982 { 8983 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostVariance", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 8984 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS); 8985 assert(var->scip == scip); 8986 8987 return SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun); 8988 } 8989 8990 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs 8991 * 8992 * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains 8993 * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability 8994 * of 2 * clevel - 1. 8995 * 8996 * @return value of confidence bound for this variable 8997 */ 8998 SCIP_Real SCIPcalculatePscostConfidenceBound( 8999 SCIP* scip, /**< SCIP data structure */ 9000 SCIP_VAR* var, /**< variable in question */ 9001 SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */ 9002 SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */ 9003 SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */ 9004 ) 9005 { 9006 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPcalculatePscostConfidenceBound", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9007 9008 return SCIPvarCalcPscostConfidenceBound(var, scip->set, dir, onlycurrentrun, clevel); 9009 } 9010 9011 /** check if variable pseudo-costs have a significant difference in location. The significance depends on 9012 * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which 9013 * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the 9014 * unknown location means of the underlying pseudo-cost distributions of x and y. 9015 * 9016 * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually 9017 * better than x (despite the current information), meaning that y can be expected to yield branching 9018 * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is 9019 * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average) 9020 * than y. 9021 * 9022 * @note The order of x and y matters for the one-sided hypothesis 9023 * 9024 * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads 9025 * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x. 9026 * 9027 * @return TRUE if the hypothesis can be safely rejected at the given confidence level 9028 */ 9029 SCIP_Bool SCIPsignificantVarPscostDifference( 9030 SCIP* scip, /**< SCIP data structure */ 9031 SCIP_VAR* varx, /**< variable x */ 9032 SCIP_Real fracx, /**< the fractionality of variable x */ 9033 SCIP_VAR* vary, /**< variable y */ 9034 SCIP_Real fracy, /**< the fractionality of variable y */ 9035 SCIP_BRANCHDIR dir, /**< branching direction */ 9036 SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */ 9037 SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */ 9038 ) 9039 { 9040 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPsignificantVarPscostDifference", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9041 9042 return SCIPvarSignificantPscostDifference(scip->set, scip->stat, varx, fracx, vary, fracy, dir, clevel, onesided); 9043 } 9044 9045 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to 9046 * exceed a \p threshold. This is useful to determine if past observations provide enough evidence 9047 * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement 9048 * of at least \p threshold. 9049 * 9050 * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if 9051 * the estimated probability to exceed \p threshold is less than 25 %. 9052 * 9053 * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels 9054 * of confidence. 9055 * 9056 * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold 9057 * at the given confidence level \p clevel. 9058 */ 9059 SCIP_Bool SCIPpscostThresholdProbabilityTest( 9060 SCIP* scip, /**< SCIP data structure */ 9061 SCIP_VAR* var, /**< variable x */ 9062 SCIP_Real frac, /**< the fractionality of variable x */ 9063 SCIP_Real threshold, /**< the threshold to test against */ 9064 SCIP_BRANCHDIR dir, /**< branching direction */ 9065 SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */ 9066 ) 9067 { 9068 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPpscostThresholdProbabilityTest", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9069 9070 return SCIPvarPscostThresholdProbabilityTest(scip->set, scip->stat, var, frac, threshold, dir, clevel); 9071 } 9072 9073 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative 9074 * Error is calculated at a specific confidence level 9075 * 9076 * @return TRUE if relative error in variable pseudo costs is smaller than \p threshold 9077 */ 9078 SCIP_Bool SCIPisVarPscostRelerrorReliable( 9079 SCIP* scip, /**< SCIP data structure */ 9080 SCIP_VAR* var, /**< variable in question */ 9081 SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */ 9082 SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */ 9083 ) 9084 { 9085 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisVarPscostRelerrorReliable", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9086 9087 return SCIPvarIsPscostRelerrorReliable(var, scip->set, scip->stat, threshold, clevel); 9088 } 9089 9090 /** gets the variable's pseudo cost score value for the given LP solution value 9091 * 9092 * @return the variable's pseudo cost score value for the given LP solution value 9093 * 9094 * @pre This method can be called if @p scip is in one of the following stages: 9095 * - \ref SCIP_STAGE_INITPRESOLVE 9096 * - \ref SCIP_STAGE_PRESOLVING 9097 * - \ref SCIP_STAGE_EXITPRESOLVE 9098 * - \ref SCIP_STAGE_PRESOLVED 9099 * - \ref SCIP_STAGE_INITSOLVE 9100 * - \ref SCIP_STAGE_SOLVING 9101 * - \ref SCIP_STAGE_SOLVED 9102 */ 9103 SCIP_Real SCIPgetVarPseudocostScore( 9104 SCIP* scip, /**< SCIP data structure */ 9105 SCIP_VAR* var, /**< problem variable */ 9106 SCIP_Real solval /**< variable's LP solution value */ 9107 ) 9108 { 9109 SCIP_Real downsol; 9110 SCIP_Real upsol; 9111 SCIP_Real pscostdown; 9112 SCIP_Real pscostup; 9113 9114 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9115 9116 assert( var->scip == scip ); 9117 9118 downsol = SCIPsetFeasCeil(scip->set, solval-1.0); 9119 upsol = SCIPsetFeasFloor(scip->set, solval+1.0); 9120 pscostdown = SCIPvarGetPseudocost(var, scip->stat, downsol-solval); 9121 pscostup = SCIPvarGetPseudocost(var, scip->stat, upsol-solval); 9122 9123 return SCIPbranchGetScore(scip->set, var, pscostdown, pscostup); 9124 } 9125 9126 /** gets the variable's pseudo cost score value for the given LP solution value, 9127 * only using the pseudo cost information of the current run 9128 * 9129 * @return the variable's pseudo cost score value for the given LP solution value, 9130 * only using the pseudo cost information of the current run 9131 * 9132 * @pre This method can be called if @p scip is in one of the following stages: 9133 * - \ref SCIP_STAGE_INITPRESOLVE 9134 * - \ref SCIP_STAGE_PRESOLVING 9135 * - \ref SCIP_STAGE_EXITPRESOLVE 9136 * - \ref SCIP_STAGE_PRESOLVED 9137 * - \ref SCIP_STAGE_INITSOLVE 9138 * - \ref SCIP_STAGE_SOLVING 9139 * - \ref SCIP_STAGE_SOLVED 9140 */ 9141 SCIP_Real SCIPgetVarPseudocostScoreCurrentRun( 9142 SCIP* scip, /**< SCIP data structure */ 9143 SCIP_VAR* var, /**< problem variable */ 9144 SCIP_Real solval /**< variable's LP solution value */ 9145 ) 9146 { 9147 SCIP_Real downsol; 9148 SCIP_Real upsol; 9149 SCIP_Real pscostdown; 9150 SCIP_Real pscostup; 9151 9152 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarPseudocostScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9153 9154 assert( var->scip == scip ); 9155 9156 downsol = SCIPsetFeasCeil(scip->set, solval-1.0); 9157 upsol = SCIPsetFeasFloor(scip->set, solval+1.0); 9158 pscostdown = SCIPvarGetPseudocostCurrentRun(var, scip->stat, downsol-solval); 9159 pscostup = SCIPvarGetPseudocostCurrentRun(var, scip->stat, upsol-solval); 9160 9161 return SCIPbranchGetScore(scip->set, var, pscostdown, pscostup); 9162 } 9163 9164 /** returns the variable's VSIDS value 9165 * 9166 * @return the variable's VSIDS value 9167 * 9168 * @pre This method can be called if @p scip is in one of the following stages: 9169 * - \ref SCIP_STAGE_INITPRESOLVE 9170 * - \ref SCIP_STAGE_PRESOLVING 9171 * - \ref SCIP_STAGE_EXITPRESOLVE 9172 * - \ref SCIP_STAGE_PRESOLVED 9173 * - \ref SCIP_STAGE_INITSOLVE 9174 * - \ref SCIP_STAGE_SOLVING 9175 * - \ref SCIP_STAGE_SOLVED 9176 */ 9177 SCIP_Real SCIPgetVarVSIDS( 9178 SCIP* scip, /**< SCIP data structure */ 9179 SCIP_VAR* var, /**< problem variable */ 9180 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9181 ) 9182 { 9183 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarVSIDS", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9184 9185 assert( var->scip == scip ); 9186 9187 if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS ) 9188 { 9189 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir); 9190 return SCIP_INVALID; 9191 } 9192 9193 return SCIPvarGetVSIDS(var, scip->stat, dir); 9194 } 9195 9196 /** returns the variable's VSIDS value only using conflicts of the current run 9197 * 9198 * @return the variable's VSIDS value only using conflicts of the current run 9199 * 9200 * @pre This method can be called if @p scip is in one of the following stages: 9201 * - \ref SCIP_STAGE_INITPRESOLVE 9202 * - \ref SCIP_STAGE_PRESOLVING 9203 * - \ref SCIP_STAGE_EXITPRESOLVE 9204 * - \ref SCIP_STAGE_PRESOLVED 9205 * - \ref SCIP_STAGE_INITSOLVE 9206 * - \ref SCIP_STAGE_SOLVING 9207 * - \ref SCIP_STAGE_SOLVED 9208 */ 9209 SCIP_Real SCIPgetVarVSIDSCurrentRun( 9210 SCIP* scip, /**< SCIP data structure */ 9211 SCIP_VAR* var, /**< problem variable */ 9212 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9213 ) 9214 { 9215 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarVSIDSCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9216 9217 assert( var->scip == scip ); 9218 9219 if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS ) 9220 { 9221 SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir); 9222 return SCIP_INVALID; 9223 } 9224 9225 return SCIPvarGetVSIDSCurrentRun(var, scip->stat, dir); 9226 } 9227 9228 /** returns the variable's conflict score value 9229 * 9230 * @return the variable's conflict score value 9231 * 9232 * @pre This method can be called if @p scip is in one of the following stages: 9233 * - \ref SCIP_STAGE_INITPRESOLVE 9234 * - \ref SCIP_STAGE_PRESOLVING 9235 * - \ref SCIP_STAGE_EXITPRESOLVE 9236 * - \ref SCIP_STAGE_PRESOLVED 9237 * - \ref SCIP_STAGE_INITSOLVE 9238 * - \ref SCIP_STAGE_SOLVING 9239 * - \ref SCIP_STAGE_SOLVED 9240 */ 9241 SCIP_Real SCIPgetVarConflictScore( 9242 SCIP* scip, /**< SCIP data structure */ 9243 SCIP_VAR* var /**< problem variable */ 9244 ) 9245 { 9246 SCIP_Real downscore; 9247 SCIP_Real upscore; 9248 9249 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9250 9251 assert( var->scip == scip ); 9252 9253 downscore = SCIPvarGetVSIDS(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9254 upscore = SCIPvarGetVSIDS(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9255 9256 return SCIPbranchGetScore(scip->set, var, downscore, upscore); 9257 } 9258 9259 /** returns the variable's conflict score value only using conflicts of the current run 9260 * 9261 * @return the variable's conflict score value only using conflicts of the current run 9262 * 9263 * @pre This method can be called if @p scip is in one of the following stages: 9264 * - \ref SCIP_STAGE_INITPRESOLVE 9265 * - \ref SCIP_STAGE_PRESOLVING 9266 * - \ref SCIP_STAGE_EXITPRESOLVE 9267 * - \ref SCIP_STAGE_PRESOLVED 9268 * - \ref SCIP_STAGE_INITSOLVE 9269 * - \ref SCIP_STAGE_SOLVING 9270 * - \ref SCIP_STAGE_SOLVED 9271 */ 9272 SCIP_Real SCIPgetVarConflictScoreCurrentRun( 9273 SCIP* scip, /**< SCIP data structure */ 9274 SCIP_VAR* var /**< problem variable */ 9275 ) 9276 { 9277 SCIP_Real downscore; 9278 SCIP_Real upscore; 9279 9280 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9281 9282 assert( var->scip == scip ); 9283 9284 downscore = SCIPvarGetVSIDSCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9285 upscore = SCIPvarGetVSIDSCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9286 9287 return SCIPbranchGetScore(scip->set, var, downscore, upscore); 9288 } 9289 9290 /** returns the variable's conflict length score 9291 * 9292 * @return the variable's conflict length score 9293 * 9294 * @pre This method can be called if @p scip is in one of the following stages: 9295 * - \ref SCIP_STAGE_INITPRESOLVE 9296 * - \ref SCIP_STAGE_PRESOLVING 9297 * - \ref SCIP_STAGE_EXITPRESOLVE 9298 * - \ref SCIP_STAGE_PRESOLVED 9299 * - \ref SCIP_STAGE_INITSOLVE 9300 * - \ref SCIP_STAGE_SOLVING 9301 * - \ref SCIP_STAGE_SOLVED 9302 */ 9303 SCIP_Real SCIPgetVarConflictlengthScore( 9304 SCIP* scip, /**< SCIP data structure */ 9305 SCIP_VAR* var /**< problem variable */ 9306 ) 9307 { 9308 SCIP_Real downscore; 9309 SCIP_Real upscore; 9310 9311 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictlengthScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9312 9313 assert( var->scip == scip ); 9314 9315 downscore = SCIPvarGetAvgConflictlength(var, SCIP_BRANCHDIR_DOWNWARDS); 9316 upscore = SCIPvarGetAvgConflictlength(var, SCIP_BRANCHDIR_UPWARDS); 9317 9318 return SCIPbranchGetScore(scip->set, var, downscore, upscore); 9319 } 9320 9321 /** returns the variable's conflict length score only using conflicts of the current run 9322 * 9323 * @return the variable's conflict length score only using conflicts of the current run 9324 * 9325 * @pre This method can be called if @p scip is in one of the following stages: 9326 * - \ref SCIP_STAGE_INITPRESOLVE 9327 * - \ref SCIP_STAGE_PRESOLVING 9328 * - \ref SCIP_STAGE_EXITPRESOLVE 9329 * - \ref SCIP_STAGE_PRESOLVED 9330 * - \ref SCIP_STAGE_INITSOLVE 9331 * - \ref SCIP_STAGE_SOLVING 9332 * - \ref SCIP_STAGE_SOLVED 9333 */ 9334 SCIP_Real SCIPgetVarConflictlengthScoreCurrentRun( 9335 SCIP* scip, /**< SCIP data structure */ 9336 SCIP_VAR* var /**< problem variable */ 9337 ) 9338 { 9339 SCIP_Real downscore; 9340 SCIP_Real upscore; 9341 9342 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarConflictlengthScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9343 9344 assert( var->scip == scip ); 9345 9346 downscore = SCIPvarGetAvgConflictlengthCurrentRun(var, SCIP_BRANCHDIR_DOWNWARDS); 9347 upscore = SCIPvarGetAvgConflictlengthCurrentRun(var, SCIP_BRANCHDIR_UPWARDS); 9348 9349 return SCIPbranchGetScore(scip->set, var, downscore, upscore); 9350 } 9351 9352 /** returns the variable's average conflict length 9353 * 9354 * @return the variable's average conflict length 9355 * 9356 * @pre This method can be called if @p scip is in one of the following stages: 9357 * - \ref SCIP_STAGE_INITPRESOLVE 9358 * - \ref SCIP_STAGE_PRESOLVING 9359 * - \ref SCIP_STAGE_EXITPRESOLVE 9360 * - \ref SCIP_STAGE_PRESOLVED 9361 * - \ref SCIP_STAGE_INITSOLVE 9362 * - \ref SCIP_STAGE_SOLVING 9363 * - \ref SCIP_STAGE_SOLVED 9364 */ 9365 SCIP_Real SCIPgetVarAvgConflictlength( 9366 SCIP* scip, /**< SCIP data structure */ 9367 SCIP_VAR* var, /**< problem variable */ 9368 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9369 ) 9370 { 9371 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgConflictlength", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9372 9373 assert( var->scip == scip ); 9374 9375 return SCIPvarGetAvgConflictlength(var, dir); 9376 } 9377 9378 /** returns the variable's average conflict length only using conflicts of the current run 9379 * 9380 * @return the variable's average conflict length only using conflicts of the current run 9381 * 9382 * @pre This method can be called if @p scip is in one of the following stages: 9383 * - \ref SCIP_STAGE_INITPRESOLVE 9384 * - \ref SCIP_STAGE_PRESOLVING 9385 * - \ref SCIP_STAGE_EXITPRESOLVE 9386 * - \ref SCIP_STAGE_PRESOLVED 9387 * - \ref SCIP_STAGE_INITSOLVE 9388 * - \ref SCIP_STAGE_SOLVING 9389 * - \ref SCIP_STAGE_SOLVED 9390 */ 9391 SCIP_Real SCIPgetVarAvgConflictlengthCurrentRun( 9392 SCIP* scip, /**< SCIP data structure */ 9393 SCIP_VAR* var, /**< problem variable */ 9394 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9395 ) 9396 { 9397 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgConflictlengthCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9398 9399 assert( var->scip == scip ); 9400 9401 return SCIPvarGetAvgConflictlengthCurrentRun(var, dir); 9402 } 9403 9404 /** returns the average number of inferences found after branching on the variable in given direction; 9405 * if branching on the variable in the given direction was yet evaluated, the average number of inferences 9406 * over all variables for branching in the given direction is returned 9407 * 9408 * @return the average number of inferences found after branching on the variable in given direction 9409 * 9410 * @pre This method can be called if @p scip is in one of the following stages: 9411 * - \ref SCIP_STAGE_INITPRESOLVE 9412 * - \ref SCIP_STAGE_PRESOLVING 9413 * - \ref SCIP_STAGE_EXITPRESOLVE 9414 * - \ref SCIP_STAGE_PRESOLVED 9415 * - \ref SCIP_STAGE_INITSOLVE 9416 * - \ref SCIP_STAGE_SOLVING 9417 * - \ref SCIP_STAGE_SOLVED 9418 */ 9419 SCIP_Real SCIPgetVarAvgInferences( 9420 SCIP* scip, /**< SCIP data structure */ 9421 SCIP_VAR* var, /**< problem variable */ 9422 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9423 ) 9424 { 9425 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferences", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9426 9427 assert( var->scip == scip ); 9428 9429 return SCIPvarGetAvgInferences(var, scip->stat, dir); 9430 } 9431 9432 /** returns the average number of inferences found after branching on the variable in given direction in the current run; 9433 * if branching on the variable in the given direction was yet evaluated, the average number of inferences 9434 * over all variables for branching in the given direction is returned 9435 * 9436 * @return the average number of inferences found after branching on the variable in given direction in the current run 9437 * 9438 * @pre This method can be called if @p scip is in one of the following stages: 9439 * - \ref SCIP_STAGE_INITPRESOLVE 9440 * - \ref SCIP_STAGE_PRESOLVING 9441 * - \ref SCIP_STAGE_EXITPRESOLVE 9442 * - \ref SCIP_STAGE_PRESOLVED 9443 * - \ref SCIP_STAGE_INITSOLVE 9444 * - \ref SCIP_STAGE_SOLVING 9445 * - \ref SCIP_STAGE_SOLVED 9446 */ 9447 SCIP_Real SCIPgetVarAvgInferencesCurrentRun( 9448 SCIP* scip, /**< SCIP data structure */ 9449 SCIP_VAR* var, /**< problem variable */ 9450 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9451 ) 9452 { 9453 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferencesCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9454 9455 assert( var->scip == scip ); 9456 9457 return SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, dir); 9458 } 9459 9460 /** returns the variable's average inference score value 9461 * 9462 * @return the variable's average inference score value 9463 * 9464 * @pre This method can be called if @p scip is in one of the following stages: 9465 * - \ref SCIP_STAGE_INITPRESOLVE 9466 * - \ref SCIP_STAGE_PRESOLVING 9467 * - \ref SCIP_STAGE_EXITPRESOLVE 9468 * - \ref SCIP_STAGE_PRESOLVED 9469 * - \ref SCIP_STAGE_INITSOLVE 9470 * - \ref SCIP_STAGE_SOLVING 9471 * - \ref SCIP_STAGE_SOLVED 9472 */ 9473 SCIP_Real SCIPgetVarAvgInferenceScore( 9474 SCIP* scip, /**< SCIP data structure */ 9475 SCIP_VAR* var /**< problem variable */ 9476 ) 9477 { 9478 SCIP_Real inferdown; 9479 SCIP_Real inferup; 9480 9481 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9482 9483 assert( var->scip == scip ); 9484 9485 inferdown = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9486 inferup = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9487 9488 return SCIPbranchGetScore(scip->set, var, inferdown, inferup); 9489 } 9490 9491 /** returns the variable's average inference score value only using inferences of the current run 9492 * 9493 * @return the variable's average inference score value only using inferences of the current run 9494 * 9495 * @pre This method can be called if @p scip is in one of the following stages: 9496 * - \ref SCIP_STAGE_INITPRESOLVE 9497 * - \ref SCIP_STAGE_PRESOLVING 9498 * - \ref SCIP_STAGE_EXITPRESOLVE 9499 * - \ref SCIP_STAGE_PRESOLVED 9500 * - \ref SCIP_STAGE_INITSOLVE 9501 * - \ref SCIP_STAGE_SOLVING 9502 * - \ref SCIP_STAGE_SOLVED 9503 */ 9504 SCIP_Real SCIPgetVarAvgInferenceScoreCurrentRun( 9505 SCIP* scip, /**< SCIP data structure */ 9506 SCIP_VAR* var /**< problem variable */ 9507 ) 9508 { 9509 SCIP_Real inferdown; 9510 SCIP_Real inferup; 9511 9512 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9513 9514 assert( var->scip == scip ); 9515 9516 inferdown = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9517 inferup = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9518 9519 return SCIPbranchGetScore(scip->set, var, inferdown, inferup); 9520 } 9521 9522 /** initializes the upwards and downwards pseudocosts, conflict scores, conflict lengths, inference scores, cutoff scores 9523 * of a variable to the given values 9524 * 9525 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 9526 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 9527 * 9528 * @pre This method can be called if @p scip is in one of the following stages: 9529 * - \ref SCIP_STAGE_TRANSFORMED 9530 * - \ref SCIP_STAGE_INITPRESOLVE 9531 * - \ref SCIP_STAGE_PRESOLVING 9532 * - \ref SCIP_STAGE_EXITPRESOLVE 9533 * - \ref SCIP_STAGE_PRESOLVED 9534 * - \ref SCIP_STAGE_INITSOLVE 9535 * - \ref SCIP_STAGE_SOLVING 9536 */ 9537 SCIP_RETCODE SCIPinitVarBranchStats( 9538 SCIP* scip, /**< SCIP data structure */ 9539 SCIP_VAR* var, /**< variable which should be initialized */ 9540 SCIP_Real downpscost, /**< value to which pseudocosts for downwards branching should be initialized */ 9541 SCIP_Real uppscost, /**< value to which pseudocosts for upwards branching should be initialized */ 9542 SCIP_Real downvsids, /**< value to which VSIDS score for downwards branching should be initialized */ 9543 SCIP_Real upvsids, /**< value to which VSIDS score for upwards branching should be initialized */ 9544 SCIP_Real downconflen, /**< value to which conflict length score for downwards branching should be initialized */ 9545 SCIP_Real upconflen, /**< value to which conflict length score for upwards branching should be initialized */ 9546 SCIP_Real downinfer, /**< value to which inference counter for downwards branching should be initialized */ 9547 SCIP_Real upinfer, /**< value to which inference counter for upwards branching should be initialized */ 9548 SCIP_Real downcutoff, /**< value to which cutoff counter for downwards branching should be initialized */ 9549 SCIP_Real upcutoff /**< value to which cutoff counter for upwards branching should be initialized */ 9550 ) 9551 { 9552 SCIP_CALL( SCIPcheckStage(scip, "SCIPinitVarBranchStats", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 9553 9554 assert(downpscost >= 0.0 && uppscost >= 0.0); 9555 assert(downvsids >= 0.0 && upvsids >= 0.0); 9556 assert(downconflen >= 0.0 && upconflen >= 0.0); 9557 assert(downinfer >= 0.0 && upinfer >= 0.0); 9558 assert(downcutoff >= 0.0 && upcutoff >= 0.0); 9559 9560 if( !SCIPisFeasZero(scip, downpscost) || !SCIPisFeasZero(scip, downvsids) 9561 || !SCIPisFeasZero(scip, downinfer) || !SCIPisFeasZero(scip, downcutoff) ) 9562 { 9563 SCIP_CALL( SCIPvarIncNBranchings(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, 1) ); 9564 SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, -1.0, downpscost, 1.0) ); 9565 SCIP_CALL( SCIPvarIncInferenceSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downinfer) ); 9566 SCIP_CALL( SCIPvarIncVSIDS(var, NULL, scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downvsids) ); 9567 SCIP_CALL( SCIPvarIncCutoffSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downcutoff) ); 9568 } 9569 9570 if( !SCIPisFeasZero(scip, downconflen) ) 9571 { 9572 SCIP_CALL( SCIPvarIncNActiveConflicts(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, SCIP_UNKNOWN, downconflen) ); 9573 } 9574 9575 if( !SCIPisFeasZero(scip, uppscost) || !SCIPisFeasZero(scip, upvsids) 9576 || !SCIPisFeasZero(scip, upinfer) || !SCIPisFeasZero(scip, upcutoff) ) 9577 { 9578 SCIP_CALL( SCIPvarIncNBranchings(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, 1) ); 9579 SCIP_CALL( SCIPvarUpdatePseudocost(var, scip->set, scip->stat, 1.0, uppscost, 1.0) ); 9580 SCIP_CALL( SCIPvarIncInferenceSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upinfer) ); 9581 SCIP_CALL( SCIPvarIncVSIDS(var, NULL, scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upvsids) ); 9582 SCIP_CALL( SCIPvarIncCutoffSum(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upcutoff) ); 9583 } 9584 9585 if( !SCIPisFeasZero(scip, upconflen) ) 9586 { 9587 SCIP_CALL( SCIPvarIncNActiveConflicts(var, NULL, NULL, scip->stat, SCIP_BRANCHDIR_UPWARDS, SCIP_UNKNOWN, upconflen) ); 9588 } 9589 9590 return SCIP_OKAY; 9591 } 9592 9593 /** initializes the upwards and downwards conflict scores, conflict lengths, inference scores, cutoff scores of a 9594 * variable w.r.t. a value by the given values (SCIP_VALUEHISTORY) 9595 * 9596 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 9597 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 9598 * 9599 * @pre This method can be called if @p scip is in one of the following stages: 9600 * - \ref SCIP_STAGE_TRANSFORMED 9601 * - \ref SCIP_STAGE_INITPRESOLVE 9602 * - \ref SCIP_STAGE_PRESOLVING 9603 * - \ref SCIP_STAGE_EXITPRESOLVE 9604 * - \ref SCIP_STAGE_PRESOLVED 9605 * - \ref SCIP_STAGE_INITSOLVE 9606 * - \ref SCIP_STAGE_SOLVING 9607 */ 9608 SCIP_RETCODE SCIPinitVarValueBranchStats( 9609 SCIP* scip, /**< SCIP data structure */ 9610 SCIP_VAR* var, /**< variable which should be initialized */ 9611 SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */ 9612 SCIP_Real downvsids, /**< value to which VSIDS score for downwards branching should be initialized */ 9613 SCIP_Real upvsids, /**< value to which VSIDS score for upwards branching should be initialized */ 9614 SCIP_Real downconflen, /**< value to which conflict length score for downwards branching should be initialized */ 9615 SCIP_Real upconflen, /**< value to which conflict length score for upwards branching should be initialized */ 9616 SCIP_Real downinfer, /**< value to which inference counter for downwards branching should be initialized */ 9617 SCIP_Real upinfer, /**< value to which inference counter for upwards branching should be initialized */ 9618 SCIP_Real downcutoff, /**< value to which cutoff counter for downwards branching should be initialized */ 9619 SCIP_Real upcutoff /**< value to which cutoff counter for upwards branching should be initialized */ 9620 ) 9621 { 9622 SCIP_CALL( SCIPcheckStage(scip, "SCIPinitVarValueBranchStats", FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 9623 9624 assert(downvsids >= 0.0 && upvsids >= 0.0); 9625 assert(downconflen >= 0.0 && upconflen >= 0.0); 9626 assert(downinfer >= 0.0 && upinfer >= 0.0); 9627 assert(downcutoff >= 0.0 && upcutoff >= 0.0); 9628 9629 if( !SCIPisFeasZero(scip, downvsids) || !SCIPisFeasZero(scip, downinfer) || !SCIPisFeasZero(scip, downcutoff) ) 9630 { 9631 SCIP_CALL( SCIPvarIncNBranchings(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, 1) ); 9632 SCIP_CALL( SCIPvarIncInferenceSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downinfer) ); 9633 SCIP_CALL( SCIPvarIncVSIDS(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downvsids) ); 9634 SCIP_CALL( SCIPvarIncCutoffSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downcutoff) ); 9635 } 9636 9637 if( !SCIPisFeasZero(scip, downconflen) ) 9638 { 9639 SCIP_CALL( SCIPvarIncNActiveConflicts(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_DOWNWARDS, value, downconflen) ); 9640 } 9641 9642 if( !SCIPisFeasZero(scip, upvsids) || !SCIPisFeasZero(scip, upinfer) || !SCIPisFeasZero(scip, upcutoff) ) 9643 { 9644 SCIP_CALL( SCIPvarIncNBranchings(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, 1) ); 9645 SCIP_CALL( SCIPvarIncInferenceSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upinfer) ); 9646 SCIP_CALL( SCIPvarIncVSIDS(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upvsids) ); 9647 SCIP_CALL( SCIPvarIncCutoffSum(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upcutoff) ); 9648 } 9649 9650 if( !SCIPisFeasZero(scip, upconflen) ) 9651 { 9652 SCIP_CALL( SCIPvarIncNActiveConflicts(var, SCIPblkmem(scip), scip->set, scip->stat, SCIP_BRANCHDIR_UPWARDS, value, upconflen) ); 9653 } 9654 9655 return SCIP_OKAY; 9656 } 9657 9658 /** returns the average number of cutoffs found after branching on the variable in given direction; 9659 * if branching on the variable in the given direction was yet evaluated, the average number of cutoffs 9660 * over all variables for branching in the given direction is returned 9661 * 9662 * @return the average number of cutoffs found after branching on the variable in given direction 9663 * 9664 * @pre This method can be called if @p scip is in one of the following stages: 9665 * - \ref SCIP_STAGE_INITPRESOLVE 9666 * - \ref SCIP_STAGE_PRESOLVING 9667 * - \ref SCIP_STAGE_EXITPRESOLVE 9668 * - \ref SCIP_STAGE_PRESOLVED 9669 * - \ref SCIP_STAGE_INITSOLVE 9670 * - \ref SCIP_STAGE_SOLVING 9671 * - \ref SCIP_STAGE_SOLVED 9672 */ 9673 SCIP_Real SCIPgetVarAvgCutoffs( 9674 SCIP* scip, /**< SCIP data structure */ 9675 SCIP_VAR* var, /**< problem variable */ 9676 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9677 ) 9678 { 9679 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffs", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9680 9681 assert( var->scip == scip ); 9682 9683 return SCIPvarGetAvgCutoffs(var, scip->stat, dir); 9684 } 9685 9686 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run; 9687 * if branching on the variable in the given direction was yet evaluated, the average number of cutoffs 9688 * over all variables for branching in the given direction is returned 9689 * 9690 * @return the average number of cutoffs found after branching on the variable in given direction in the current run 9691 * 9692 * @pre This method can be called if @p scip is in one of the following stages: 9693 * - \ref SCIP_STAGE_INITPRESOLVE 9694 * - \ref SCIP_STAGE_PRESOLVING 9695 * - \ref SCIP_STAGE_EXITPRESOLVE 9696 * - \ref SCIP_STAGE_PRESOLVED 9697 * - \ref SCIP_STAGE_INITSOLVE 9698 * - \ref SCIP_STAGE_SOLVING 9699 * - \ref SCIP_STAGE_SOLVED 9700 */ 9701 SCIP_Real SCIPgetVarAvgCutoffsCurrentRun( 9702 SCIP* scip, /**< SCIP data structure */ 9703 SCIP_VAR* var, /**< problem variable */ 9704 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */ 9705 ) 9706 { 9707 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffsCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9708 9709 assert( var->scip == scip ); 9710 9711 return SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, dir); 9712 } 9713 9714 /** returns the variable's average cutoff score value 9715 * 9716 * @return the variable's average cutoff score value 9717 * 9718 * @pre This method can be called if @p scip is in one of the following stages: 9719 * - \ref SCIP_STAGE_INITPRESOLVE 9720 * - \ref SCIP_STAGE_PRESOLVING 9721 * - \ref SCIP_STAGE_EXITPRESOLVE 9722 * - \ref SCIP_STAGE_PRESOLVED 9723 * - \ref SCIP_STAGE_INITSOLVE 9724 * - \ref SCIP_STAGE_SOLVING 9725 * - \ref SCIP_STAGE_SOLVED 9726 */ 9727 SCIP_Real SCIPgetVarAvgCutoffScore( 9728 SCIP* scip, /**< SCIP data structure */ 9729 SCIP_VAR* var /**< problem variable */ 9730 ) 9731 { 9732 SCIP_Real cutoffdown; 9733 SCIP_Real cutoffup; 9734 9735 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9736 9737 assert( var->scip == scip ); 9738 9739 cutoffdown = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9740 cutoffup = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9741 9742 return SCIPbranchGetScore(scip->set, var, cutoffdown, cutoffup); 9743 } 9744 9745 /** returns the variable's average cutoff score value, only using cutoffs of the current run 9746 * 9747 * @return the variable's average cutoff score value, only using cutoffs of the current run 9748 * 9749 * @pre This method can be called if @p scip is in one of the following stages: 9750 * - \ref SCIP_STAGE_INITPRESOLVE 9751 * - \ref SCIP_STAGE_PRESOLVING 9752 * - \ref SCIP_STAGE_EXITPRESOLVE 9753 * - \ref SCIP_STAGE_PRESOLVED 9754 * - \ref SCIP_STAGE_INITSOLVE 9755 * - \ref SCIP_STAGE_SOLVING 9756 * - \ref SCIP_STAGE_SOLVED 9757 */ 9758 SCIP_Real SCIPgetVarAvgCutoffScoreCurrentRun( 9759 SCIP* scip, /**< SCIP data structure */ 9760 SCIP_VAR* var /**< problem variable */ 9761 ) 9762 { 9763 SCIP_Real cutoffdown; 9764 SCIP_Real cutoffup; 9765 9766 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgCutoffScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9767 9768 assert( var->scip == scip ); 9769 9770 cutoffdown = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9771 cutoffup = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9772 9773 return SCIPbranchGetScore(scip->set, var, cutoffdown, cutoffup); 9774 } 9775 9776 /** returns the variable's average inference/cutoff score value, weighting the cutoffs of the variable with the given 9777 * factor 9778 * 9779 * @return the variable's average inference/cutoff score value 9780 * 9781 * @pre This method can be called if @p scip is in one of the following stages: 9782 * - \ref SCIP_STAGE_INITPRESOLVE 9783 * - \ref SCIP_STAGE_PRESOLVING 9784 * - \ref SCIP_STAGE_EXITPRESOLVE 9785 * - \ref SCIP_STAGE_PRESOLVED 9786 * - \ref SCIP_STAGE_INITSOLVE 9787 * - \ref SCIP_STAGE_SOLVING 9788 * - \ref SCIP_STAGE_SOLVED 9789 */ 9790 SCIP_Real SCIPgetVarAvgInferenceCutoffScore( 9791 SCIP* scip, /**< SCIP data structure */ 9792 SCIP_VAR* var, /**< problem variable */ 9793 SCIP_Real cutoffweight /**< factor to weigh average number of cutoffs in branching score */ 9794 ) 9795 { 9796 SCIP_Real avginferdown; 9797 SCIP_Real avginferup; 9798 SCIP_Real avginfer; 9799 SCIP_Real inferdown; 9800 SCIP_Real inferup; 9801 SCIP_Real cutoffdown; 9802 SCIP_Real cutoffup; 9803 9804 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceCutoffScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9805 9806 assert( var->scip == scip ); 9807 9808 avginferdown = SCIPhistoryGetAvgInferences(scip->stat->glbhistory, SCIP_BRANCHDIR_DOWNWARDS); 9809 avginferup = SCIPhistoryGetAvgInferences(scip->stat->glbhistory, SCIP_BRANCHDIR_UPWARDS); 9810 avginfer = (avginferdown + avginferup)/2.0; 9811 inferdown = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9812 inferup = SCIPvarGetAvgInferences(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9813 cutoffdown = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9814 cutoffup = SCIPvarGetAvgCutoffs(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9815 9816 return SCIPbranchGetScore(scip->set, var, 9817 inferdown + cutoffweight * avginfer * cutoffdown, inferup + cutoffweight * avginfer * cutoffup); 9818 } 9819 9820 /** returns the variable's average inference/cutoff score value, weighting the cutoffs of the variable with the given 9821 * factor, only using inferences and cutoffs of the current run 9822 * 9823 * @return the variable's average inference/cutoff score value, only using inferences and cutoffs of the current run 9824 * 9825 * @pre This method can be called if @p scip is in one of the following stages: 9826 * - \ref SCIP_STAGE_INITPRESOLVE 9827 * - \ref SCIP_STAGE_PRESOLVING 9828 * - \ref SCIP_STAGE_EXITPRESOLVE 9829 * - \ref SCIP_STAGE_PRESOLVED 9830 * - \ref SCIP_STAGE_INITSOLVE 9831 * - \ref SCIP_STAGE_SOLVING 9832 * - \ref SCIP_STAGE_SOLVED 9833 */ 9834 SCIP_Real SCIPgetVarAvgInferenceCutoffScoreCurrentRun( 9835 SCIP* scip, /**< SCIP data structure */ 9836 SCIP_VAR* var, /**< problem variable */ 9837 SCIP_Real cutoffweight /**< factor to weigh average number of cutoffs in branching score */ 9838 ) 9839 { 9840 SCIP_Real avginferdown; 9841 SCIP_Real avginferup; 9842 SCIP_Real avginfer; 9843 SCIP_Real inferdown; 9844 SCIP_Real inferup; 9845 SCIP_Real cutoffdown; 9846 SCIP_Real cutoffup; 9847 9848 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgInferenceCutoffScoreCurrentRun", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9849 9850 assert( var->scip == scip ); 9851 9852 avginferdown = SCIPhistoryGetAvgInferences(scip->stat->glbhistorycrun, SCIP_BRANCHDIR_DOWNWARDS); 9853 avginferup = SCIPhistoryGetAvgInferences(scip->stat->glbhistorycrun, SCIP_BRANCHDIR_UPWARDS); 9854 avginfer = (avginferdown + avginferup)/2.0; 9855 inferdown = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9856 inferup = SCIPvarGetAvgInferencesCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9857 cutoffdown = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_DOWNWARDS); 9858 cutoffup = SCIPvarGetAvgCutoffsCurrentRun(var, scip->stat, SCIP_BRANCHDIR_UPWARDS); 9859 9860 return SCIPbranchGetScore(scip->set, var, 9861 inferdown + cutoffweight * avginfer * cutoffdown, inferup + cutoffweight * avginfer * cutoffup); 9862 } 9863 9864 /** returns the variable's average GMI efficacy score value 9865 * 9866 * @return the variable's average GMI efficacy score value 9867 * 9868 * @pre This method can be called if @p scip is in one of the following stages: 9869 * - \ref SCIP_STAGE_INITPRESOLVE 9870 * - \ref SCIP_STAGE_PRESOLVING 9871 * - \ref SCIP_STAGE_EXITPRESOLVE 9872 * - \ref SCIP_STAGE_PRESOLVED 9873 * - \ref SCIP_STAGE_INITSOLVE 9874 * - \ref SCIP_STAGE_SOLVING 9875 * - \ref SCIP_STAGE_SOLVED 9876 */ 9877 SCIP_Real SCIPgetVarAvgGMIScore( 9878 SCIP* scip, /**< SCIP data structure */ 9879 SCIP_VAR* var /**< problem variable */ 9880 ) 9881 { 9882 9883 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarAvgGMIScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9884 9885 assert( var->scip == scip ); 9886 9887 return SCIPvarGetAvgGMIScore(var, scip->stat); 9888 } 9889 9890 /** sets the variable's average GMI efficacy score value 9891 * 9892 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 9893 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 9894 * 9895 * @pre This method can be called if @p scip is in one of the following stages: 9896 * - \ref SCIP_STAGE_INITPRESOLVE 9897 * - \ref SCIP_STAGE_PRESOLVING 9898 * - \ref SCIP_STAGE_EXITPRESOLVE 9899 * - \ref SCIP_STAGE_PRESOLVED 9900 * - \ref SCIP_STAGE_INITSOLVE 9901 * - \ref SCIP_STAGE_SOLVING 9902 * - \ref SCIP_STAGE_SOLVED 9903 */ 9904 SCIP_EXPORT 9905 SCIP_RETCODE SCIPincVarGMISumScore( 9906 SCIP* scip, /**< SCIP data structure */ 9907 SCIP_VAR* var, /**< problem variable */ 9908 SCIP_Real gmieff /**< Efficacy of last GMI cut generated from when var was basic /frac */ 9909 ) 9910 { 9911 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPincVarGMISumScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9912 9913 assert( var->scip == scip ); 9914 9915 SCIP_CALL( SCIPvarIncGMIeffSum(var, scip->stat, gmieff) ); 9916 9917 return SCIP_OKAY; 9918 } 9919 9920 /** returns the variable's last GMI efficacy score value 9921 * 9922 * @return the variable's last GMI efficacy score value 9923 * 9924 * @pre This method can be called if @p scip is in one of the following stages: 9925 * - \ref SCIP_STAGE_INITPRESOLVE 9926 * - \ref SCIP_STAGE_PRESOLVING 9927 * - \ref SCIP_STAGE_EXITPRESOLVE 9928 * - \ref SCIP_STAGE_PRESOLVED 9929 * - \ref SCIP_STAGE_INITSOLVE 9930 * - \ref SCIP_STAGE_SOLVING 9931 * - \ref SCIP_STAGE_SOLVED 9932 */ 9933 SCIP_Real SCIPgetVarLastGMIScore( 9934 SCIP* scip, /**< SCIP data structure */ 9935 SCIP_VAR* var /**< problem variable */ 9936 ) 9937 { 9938 9939 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetVarLastGMIScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9940 9941 assert( var->scip == scip ); 9942 9943 return SCIPvarGetLastGMIScore(var, scip->stat); 9944 } 9945 9946 /** sets the variable's last GMI efficacy score value 9947 * 9948 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 9949 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 9950 * 9951 * @pre This method can be called if @p scip is in one of the following stages: 9952 * - \ref SCIP_STAGE_INITPRESOLVE 9953 * - \ref SCIP_STAGE_PRESOLVING 9954 * - \ref SCIP_STAGE_EXITPRESOLVE 9955 * - \ref SCIP_STAGE_PRESOLVED 9956 * - \ref SCIP_STAGE_INITSOLVE 9957 * - \ref SCIP_STAGE_SOLVING 9958 * - \ref SCIP_STAGE_SOLVED 9959 */ 9960 SCIP_RETCODE SCIPsetVarLastGMIScore( 9961 SCIP* scip, /**< SCIP data structure */ 9962 SCIP_VAR* var, /**< problem variable */ 9963 SCIP_Real gmieff /**< efficacy of GMI cut from tableau row when variable is basic / frac */ 9964 ) 9965 { 9966 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPsetVarLastGMIScore", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 9967 9968 assert( var->scip == scip ); 9969 9970 SCIP_CALL( SCIPvarSetLastGMIScore(var, scip->stat, gmieff) ); 9971 9972 return SCIP_OKAY; 9973 } 9974 9975 /** outputs variable information to file stream via the message system 9976 * 9977 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 9978 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 9979 * 9980 * @pre This method can be called if @p scip is in one of the following stages: 9981 * - \ref SCIP_STAGE_PROBLEM 9982 * - \ref SCIP_STAGE_TRANSFORMING 9983 * - \ref SCIP_STAGE_TRANSFORMED 9984 * - \ref SCIP_STAGE_INITPRESOLVE 9985 * - \ref SCIP_STAGE_PRESOLVING 9986 * - \ref SCIP_STAGE_EXITPRESOLVE 9987 * - \ref SCIP_STAGE_PRESOLVED 9988 * - \ref SCIP_STAGE_INITSOLVE 9989 * - \ref SCIP_STAGE_SOLVING 9990 * - \ref SCIP_STAGE_SOLVED 9991 * - \ref SCIP_STAGE_EXITSOLVE 9992 * - \ref SCIP_STAGE_FREETRANS 9993 * 9994 * @note If the message handler is set to a NULL pointer nothing will be printed 9995 */ 9996 SCIP_RETCODE SCIPprintVar( 9997 SCIP* scip, /**< SCIP data structure */ 9998 SCIP_VAR* var, /**< problem variable */ 9999 FILE* file /**< output file (or NULL for standard output) */ 10000 ) 10001 { 10002 SCIP_CALL( SCIPcheckStage(scip, "SCIPprintVar", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 10003 10004 SCIP_CALL( SCIPvarPrint(var, scip->set, scip->messagehdlr, file) ); 10005 10006 return SCIP_OKAY; 10007 } 10008