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 sol.c 26 * @ingroup OTHER_CFILES 27 * @brief methods for storing primal CIP solutions 28 * @author Tobias Achterberg 29 */ 30 31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 32 33 #include "scip/clock.h" 34 #include "scip/cons.h" 35 #include "scip/lp.h" 36 #include "scip/misc.h" 37 #include "scip/nlp.h" 38 #include "scip/primal.h" 39 #include "scip/prob.h" 40 #include "scip/pub_lp.h" 41 #include "scip/pub_message.h" 42 #include "scip/pub_sol.h" 43 #include "scip/pub_var.h" 44 #include "scip/relax.h" 45 #include "scip/set.h" 46 #include "scip/sol.h" 47 #include "scip/stat.h" 48 #include "scip/struct_lp.h" 49 #include "scip/struct_prob.h" 50 #include "scip/struct_set.h" 51 #include "scip/struct_sol.h" 52 #include "scip/struct_stat.h" 53 #include "scip/struct_var.h" 54 #include "scip/tree.h" 55 #include "scip/var.h" 56 57 58 59 /** clears solution arrays of primal CIP solution */ 60 static 61 SCIP_RETCODE solClearArrays( 62 SCIP_SOL* sol /**< primal CIP solution */ 63 ) 64 { 65 assert(sol != NULL); 66 67 SCIP_CALL( SCIPboolarrayClear(sol->valid) ); 68 sol->hasinfval = FALSE; 69 70 return SCIP_OKAY; 71 } 72 73 /** sets value of variable in the solution's array */ 74 static 75 SCIP_RETCODE solSetArrayVal( 76 SCIP_SOL* sol, /**< primal CIP solution */ 77 SCIP_SET* set, /**< global SCIP settings */ 78 SCIP_VAR* var, /**< problem variable */ 79 SCIP_Real val /**< value to set variable to */ 80 ) 81 { 82 int idx; 83 84 assert(sol != NULL); 85 86 idx = SCIPvarGetIndex(var); 87 88 /* from now on, variable must not be deleted */ 89 SCIPvarMarkNotDeletable(var); 90 91 /* mark the variable valid */ 92 SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) ); 93 94 /* set the value in the solution array */ 95 SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, val) ); 96 97 /* store whether the solution has infinite values assigned to variables */ 98 if( val != SCIP_UNKNOWN ) /*lint !e777*/ 99 sol->hasinfval = (sol->hasinfval || SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val)); 100 101 return SCIP_OKAY; 102 } 103 104 /** increases value of variable in the solution's array */ 105 static 106 SCIP_RETCODE solIncArrayVal( 107 SCIP_SOL* sol, /**< primal CIP solution */ 108 SCIP_SET* set, /**< global SCIP settings */ 109 SCIP_VAR* var, /**< problem variable */ 110 SCIP_Real incval /**< increase of variable's solution value */ 111 ) 112 { 113 int idx; 114 115 assert(sol != NULL); 116 117 idx = SCIPvarGetIndex(var); 118 119 /* from now on, variable must not be deleted */ 120 SCIPvarMarkNotDeletable(var); 121 122 /* if the variable was not valid, mark it to be valid and set the value to the incval (it is 0.0 if not valid) */ 123 if( !SCIPboolarrayGetVal(sol->valid, idx) ) 124 { 125 /* mark the variable valid */ 126 SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) ); 127 128 /* set the value in the solution array */ 129 SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, incval) ); 130 } 131 else 132 { 133 /* increase the value in the solution array */ 134 SCIP_CALL( SCIPrealarrayIncVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, incval) ); 135 } 136 137 /* store whether the solution has infinite values assigned to variables */ 138 incval = SCIPrealarrayGetVal(sol->vals, idx); 139 if( incval != SCIP_UNKNOWN ) /*lint !e777*/ 140 sol->hasinfval = (sol->hasinfval || SCIPsetIsInfinity(set, incval) || SCIPsetIsInfinity(set, -incval)); 141 142 return SCIP_OKAY; 143 } 144 145 /** returns the value of the variable in the given solution */ 146 static 147 SCIP_Real solGetArrayVal( 148 SCIP_SOL* sol, /**< primal CIP solution */ 149 SCIP_VAR* var /**< problem variable */ 150 ) 151 { 152 int idx; 153 154 assert(sol != NULL); 155 156 idx = SCIPvarGetIndex(var); 157 158 /* check, if the variable's value is valid */ 159 if( SCIPboolarrayGetVal(sol->valid, idx) ) 160 { 161 return SCIPrealarrayGetVal(sol->vals, idx); 162 } 163 else 164 { 165 /* return the variable's value corresponding to the origin */ 166 switch( sol->solorigin ) 167 { 168 case SCIP_SOLORIGIN_ORIGINAL: 169 case SCIP_SOLORIGIN_ZERO: 170 return 0.0; 171 172 case SCIP_SOLORIGIN_LPSOL: 173 return SCIPvarGetLPSol(var); 174 175 case SCIP_SOLORIGIN_NLPSOL: 176 return SCIPvarGetNLPSol(var); 177 178 case SCIP_SOLORIGIN_RELAXSOL: 179 return SCIPvarGetRelaxSolTransVar(var); 180 181 case SCIP_SOLORIGIN_PSEUDOSOL: 182 return SCIPvarGetPseudoSol(var); 183 184 case SCIP_SOLORIGIN_PARTIAL: 185 case SCIP_SOLORIGIN_UNKNOWN: 186 return SCIP_UNKNOWN; 187 188 default: 189 SCIPerrorMessage("unknown solution origin <%d>\n", sol->solorigin); 190 SCIPABORT(); 191 return 0.0; /*lint !e527*/ 192 } 193 } 194 } 195 196 /** stores solution value of variable in solution's own array */ 197 static 198 SCIP_RETCODE solUnlinkVar( 199 SCIP_SOL* sol, /**< primal CIP solution */ 200 SCIP_SET* set, /**< global SCIP settings */ 201 SCIP_VAR* var /**< problem variable */ 202 ) 203 { 204 SCIP_Real solval; 205 206 assert(sol != NULL); 207 assert(var != NULL); 208 assert(SCIPvarIsTransformed(var)); 209 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); 210 211 /* if variable is already valid, nothing has to be done */ 212 if( SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var)) ) 213 return SCIP_OKAY; 214 215 SCIPsetDebugMsg(set, "unlinking solution value of variable <%s>\n", SCIPvarGetName(var)); 216 217 /* store the correct solution value into the solution array */ 218 switch( sol->solorigin ) 219 { 220 case SCIP_SOLORIGIN_ORIGINAL: 221 SCIPerrorMessage("cannot unlink solutions of original problem space\n"); 222 return SCIP_INVALIDDATA; 223 224 case SCIP_SOLORIGIN_ZERO: 225 return SCIP_OKAY; 226 227 case SCIP_SOLORIGIN_LPSOL: 228 solval = SCIPvarGetLPSol(var); 229 SCIP_CALL( solSetArrayVal(sol, set, var, solval) ); 230 return SCIP_OKAY; 231 232 case SCIP_SOLORIGIN_NLPSOL: 233 solval = SCIPvarGetNLPSol(var); 234 SCIP_CALL( solSetArrayVal(sol, set, var, solval) ); 235 return SCIP_OKAY; 236 237 case SCIP_SOLORIGIN_RELAXSOL: 238 solval = SCIPvarGetRelaxSolTransVar(var); 239 SCIP_CALL( solSetArrayVal(sol, set, var, solval) ); 240 return SCIP_OKAY; 241 242 case SCIP_SOLORIGIN_PSEUDOSOL: 243 solval = SCIPvarGetPseudoSol(var); 244 SCIP_CALL( solSetArrayVal(sol, set, var, solval) ); 245 return SCIP_OKAY; 246 247 case SCIP_SOLORIGIN_PARTIAL: 248 case SCIP_SOLORIGIN_UNKNOWN: 249 SCIP_CALL( solSetArrayVal(sol, set, var, SCIP_UNKNOWN) ); 250 return SCIP_OKAY; 251 252 default: 253 SCIPerrorMessage("unknown solution origin <%d>\n", sol->solorigin); 254 return SCIP_INVALIDDATA; 255 } 256 } 257 258 /** sets the solution time, nodenum, runnum, and depth stamp to the current values */ 259 static 260 void solStamp( 261 SCIP_SOL* sol, /**< primal CIP solution */ 262 SCIP_STAT* stat, /**< problem statistics data */ 263 SCIP_TREE* tree, /**< branch and bound tree, or NULL */ 264 SCIP_Bool checktime /**< should the time be updated? */ 265 ) 266 { 267 assert(sol != NULL); 268 assert(stat != NULL); 269 270 if( checktime ) 271 { 272 sol->time = SCIPclockGetTime(stat->solvingtime); 273 #ifndef NDEBUG 274 sol->lpcount = stat->lpcount; 275 #endif 276 } 277 else 278 sol->time = SCIPclockGetLastTime(stat->solvingtime); 279 sol->nodenum = stat->nnodes; 280 sol->runnum = stat->nruns; 281 if( tree == NULL ) 282 sol->depth = -1; 283 else 284 sol->depth = SCIPtreeGetCurrentDepth(tree); 285 } 286 287 /** creates primal CIP solution, initialized to zero */ 288 SCIP_RETCODE SCIPsolCreate( 289 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 290 BMS_BLKMEM* blkmem, /**< block memory */ 291 SCIP_SET* set, /**< global SCIP settings */ 292 SCIP_STAT* stat, /**< problem statistics data */ 293 SCIP_PRIMAL* primal, /**< primal data */ 294 SCIP_TREE* tree, /**< branch and bound tree */ 295 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 296 ) 297 { 298 assert(sol != NULL); 299 assert(blkmem != NULL); 300 assert(stat != NULL); 301 302 SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) ); 303 SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) ); 304 SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) ); 305 306 (*sol)->solorigin = SCIP_SOLORIGIN_ZERO; 307 (*sol)->obj = 0.0; 308 (*sol)->primalindex = -1; 309 (*sol)->index = stat->solindex; 310 (*sol)->hasinfval = FALSE; 311 SCIPsolResetViolations(*sol); 312 stat->solindex++; 313 solStamp(*sol, stat, tree, TRUE); 314 SCIPsolResetViolations(*sol); 315 316 /* set solution type and creator depending on whether a heuristic or NULL is passed */ 317 SCIPsolSetHeur(*sol, heur); 318 319 SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) ); 320 321 return SCIP_OKAY; 322 } 323 324 /** creates primal CIP solution in original problem space, initialized to the offset in the original problem */ 325 SCIP_RETCODE SCIPsolCreateOriginal( 326 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 327 BMS_BLKMEM* blkmem, /**< block memory */ 328 SCIP_SET* set, /**< global SCIP settings */ 329 SCIP_STAT* stat, /**< problem statistics data */ 330 SCIP_PROB* origprob, /**< original problem data */ 331 SCIP_PRIMAL* primal, /**< primal data */ 332 SCIP_TREE* tree, /**< branch and bound tree */ 333 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 334 ) 335 { 336 assert(sol != NULL); 337 assert(blkmem != NULL); 338 assert(stat != NULL); 339 340 SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) ); 341 SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) ); 342 SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) ); 343 (*sol)->solorigin = SCIP_SOLORIGIN_ORIGINAL; 344 (*sol)->obj = origprob->objoffset; 345 (*sol)->primalindex = -1; 346 (*sol)->index = stat->solindex; 347 (*sol)->hasinfval = FALSE; 348 stat->solindex++; 349 solStamp(*sol, stat, tree, TRUE); 350 351 /* set solution type and creator depending on whether a heuristic or NULL is passed */ 352 SCIPsolSetHeur(*sol, heur); 353 354 SCIPsolResetViolations(*sol); 355 356 SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) ); 357 358 return SCIP_OKAY; 359 } 360 361 /** creates a copy of a primal CIP solution */ 362 SCIP_RETCODE SCIPsolCopy( 363 SCIP_SOL** sol, /**< pointer to store the copy of the primal CIP solution */ 364 BMS_BLKMEM* blkmem, /**< block memory */ 365 SCIP_SET* set, /**< global SCIP settings */ 366 SCIP_STAT* stat, /**< problem statistics data */ 367 SCIP_PRIMAL* primal, /**< primal data */ 368 SCIP_SOL* sourcesol /**< primal CIP solution to copy */ 369 ) 370 { 371 assert(sol != NULL); 372 assert(sourcesol != NULL); 373 374 SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) ); 375 SCIP_CALL( SCIPrealarrayCopy(&(*sol)->vals, blkmem, sourcesol->vals) ); 376 SCIP_CALL( SCIPboolarrayCopy(&(*sol)->valid, blkmem, sourcesol->valid) ); 377 378 /* copy solution type and creator information */ 379 switch( sourcesol->type ) 380 { 381 case SCIP_SOLTYPE_UNKNOWN: 382 case SCIP_SOLTYPE_LPRELAX: 383 case SCIP_SOLTYPE_STRONGBRANCH: 384 case SCIP_SOLTYPE_PSEUDO: 385 (*sol)->type = sourcesol->type; 386 break; 387 case SCIP_SOLTYPE_HEUR: 388 SCIPsolSetHeur((*sol), SCIPsolGetHeur(sourcesol)); 389 break; 390 case SCIP_SOLTYPE_RELAX: 391 SCIPsolSetRelax((*sol), SCIPsolGetRelax(sourcesol)); 392 break; 393 default: 394 SCIPerrorMessage("Unknown source solution type %d!\n", sourcesol->type); 395 return SCIP_INVALIDDATA; 396 } 397 (*sol)->obj = sourcesol->obj; 398 (*sol)->primalindex = -1; 399 (*sol)->time = sourcesol->time; 400 #ifndef NDEBUG 401 (*sol)->lpcount = sourcesol->lpcount; 402 #endif 403 (*sol)->nodenum = sourcesol->nodenum; 404 (*sol)->solorigin = sourcesol->solorigin; 405 (*sol)->runnum = sourcesol->runnum; 406 (*sol)->depth = sourcesol->depth; 407 (*sol)->index = stat->solindex; 408 (*sol)->hasinfval = sourcesol->hasinfval; 409 stat->solindex++; 410 (*sol)->viol.absviolbounds = sourcesol->viol.absviolbounds; 411 (*sol)->viol.absviolcons = sourcesol->viol.absviolcons; 412 (*sol)->viol.absviolintegrality = sourcesol->viol.absviolintegrality; 413 (*sol)->viol.absviollprows = sourcesol->viol.absviollprows; 414 (*sol)->viol.relviolbounds = sourcesol->viol.relviolbounds; 415 (*sol)->viol.relviolcons = sourcesol->viol.relviolcons; 416 (*sol)->viol.relviollprows = sourcesol->viol.relviollprows; 417 418 SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) ); 419 420 return SCIP_OKAY; 421 } 422 423 /** transformes given original solution to the transformed space; a corresponding transformed solution has to be given 424 * which is copied into the existing solution and freed afterwards 425 */ 426 SCIP_RETCODE SCIPsolTransform( 427 SCIP_SOL* sol, /**< primal CIP solution to change, living in original space */ 428 SCIP_SOL** transsol, /**< pointer to corresponding transformed primal CIP solution */ 429 BMS_BLKMEM* blkmem, /**< block memory */ 430 SCIP_SET* set, /**< global SCIP settings */ 431 SCIP_PRIMAL* primal /**< primal data */ 432 ) 433 { /*lint --e{715}*/ 434 SCIP_REALARRAY* tmpvals; 435 SCIP_BOOLARRAY* tmpvalid; 436 SCIP_SOL* tsol; 437 438 assert(sol != NULL); 439 assert(transsol != NULL); 440 assert(set != NULL); 441 assert(SCIPsolIsOriginal(sol)); 442 assert(sol->primalindex > -1); 443 444 tsol = *transsol; 445 assert(tsol != NULL); 446 assert(!SCIPsolIsOriginal(tsol)); 447 448 /* switch vals and valid arrays; the exisiting solution gets the arrays of the transformed solution; 449 * the transformed one gets the original arrays, because they have to be freed anyway and freeing the transsol 450 * automatically frees its arrays 451 */ 452 tmpvals = sol->vals; 453 tmpvalid = sol->valid; 454 sol->vals = tsol->vals; 455 sol->valid = tsol->valid; 456 tsol->vals = tmpvals; 457 tsol->valid = tmpvalid; 458 459 /* copy solorigin and objective (should be the same, only to avoid numerical issues); 460 * we keep the other statistics of the original solution, since that was the first time that this solution as found 461 */ 462 sol->solorigin = tsol->solorigin; 463 sol->obj = tsol->obj; 464 465 SCIP_CALL( SCIPsolFree(transsol, blkmem, primal) ); 466 467 return SCIP_OKAY; 468 } 469 470 /** adjusts solution values of implicit integer variables in handed solution. Solution objective value is not 471 * deteriorated by this method. 472 */ 473 SCIP_RETCODE SCIPsolAdjustImplicitSolVals( 474 SCIP_SOL* sol, /**< primal CIP solution */ 475 SCIP_SET* set, /**< global SCIP settings */ 476 SCIP_STAT* stat, /**< problem statistics data */ 477 SCIP_PROB* prob, /**< either original or transformed problem, depending on sol origin */ 478 SCIP_TREE* tree, /**< branch and bound tree */ 479 SCIP_Bool uselprows /**< should LP row information be considered for none-objective variables */ 480 ) 481 { 482 SCIP_VAR** vars; 483 int nimplvars; 484 int nbinvars; 485 int nintvars; 486 int v; 487 488 assert(sol != NULL); 489 assert(prob != NULL); 490 491 /* get variable data */ 492 vars = SCIPprobGetVars(prob); 493 nbinvars = SCIPprobGetNBinVars(prob); 494 nintvars = SCIPprobGetNIntVars(prob); 495 nimplvars = SCIPprobGetNImplVars(prob); 496 497 if( nimplvars == 0 ) 498 return SCIP_OKAY; 499 500 /* calculate the last array position of implicit integer variables */ 501 nimplvars = nbinvars + nintvars + nimplvars; 502 503 /* loop over implicit integer variables and round them up or down */ 504 for( v = nbinvars + nintvars; v < nimplvars; ++v ) 505 { 506 SCIP_VAR* var; 507 SCIP_Real solval; 508 SCIP_Real obj; 509 SCIP_Real newsolval; 510 SCIP_Bool roundup; 511 SCIP_Bool rounddown; 512 int nuplocks; 513 int ndownlocks; 514 515 var = vars[v]; 516 517 assert( SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT ); 518 solval = SCIPsolGetVal(sol, set, stat, var); 519 520 /* we do not need to round integral solution values or those of variables which are not column variables */ 521 if( SCIPsetIsFeasIntegral(set, solval) || SCIPvarGetStatus(var) != SCIP_VARSTATUS_COLUMN ) 522 continue; 523 524 nuplocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL); 525 ndownlocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL); 526 obj = SCIPvarGetUnchangedObj(var); 527 528 roundup = FALSE; 529 rounddown = FALSE; 530 531 /* in case of a non-zero objective coefficient, there is only one possible rounding direction */ 532 if( SCIPsetIsFeasNegative(set, obj) ) 533 roundup = TRUE; 534 else if( SCIPsetIsFeasPositive(set, obj) ) 535 rounddown = TRUE; 536 else if( uselprows ) 537 { 538 /* determine rounding direction based on row violations */ 539 SCIP_COL* col; 540 SCIP_ROW** rows; 541 SCIP_Real* vals; 542 int nrows; 543 int r; 544 545 col = SCIPvarGetCol(var); 546 vals = SCIPcolGetVals(col); 547 rows = SCIPcolGetRows(col); 548 nrows = SCIPcolGetNNonz(col); 549 550 /* loop over rows and search for equations whose violation can be decreased by rounding */ 551 for( r = 0; r < nrows && !(roundup && rounddown); ++r ) 552 { 553 SCIP_ROW* row; 554 SCIP_Real activity; 555 SCIP_Real rhs; 556 SCIP_Real lhs; 557 558 row = rows[r]; 559 560 if( SCIProwIsLocal(row) || !SCIProwIsInLP(row) ) 561 continue; 562 563 rhs = SCIProwGetRhs(row); 564 lhs = SCIProwGetLhs(row); 565 566 if( SCIPsetIsInfinity(set, rhs) || SCIPsetIsInfinity(set, -lhs) ) 567 continue; 568 569 activity = SCIProwGetSolActivity(row, set, stat, sol); 570 if( SCIPsetIsFeasLE(set, activity, rhs) && SCIPsetIsFeasLE(set, lhs, activity) ) 571 continue; 572 573 assert(! SCIPsetIsZero(set, vals[r])); 574 if( (SCIPsetIsFeasGT(set, activity, rhs) && SCIPsetIsPositive(set, vals[r])) 575 || (SCIPsetIsFeasLT(set, activity, lhs) && SCIPsetIsNegative(set, vals[r])) ) 576 rounddown = TRUE; 577 else 578 roundup = TRUE; 579 } 580 } 581 582 /* in case of a tie, we select the rounding step based on the number of variable locks */ 583 if( roundup == rounddown ) 584 { 585 rounddown = ndownlocks <= nuplocks; 586 roundup = !rounddown; 587 } 588 589 /* round the variable up or down */ 590 if( roundup ) 591 { 592 newsolval = SCIPsetCeil(set, solval); 593 assert(SCIPsetIsFeasLE(set, newsolval, SCIPvarGetUbGlobal(var))); 594 } 595 else 596 { 597 assert( rounddown ); /* should be true because of the code above */ 598 newsolval = SCIPsetFloor(set, solval); 599 assert(SCIPsetIsFeasGE(set, newsolval, SCIPvarGetLbGlobal(var))); 600 } 601 602 SCIP_CALL( SCIPsolSetVal(sol, set, stat, tree, var, newsolval) ); 603 } 604 605 return SCIP_OKAY; 606 } 607 /** creates primal CIP solution, initialized to the current LP solution */ 608 SCIP_RETCODE SCIPsolCreateLPSol( 609 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 610 BMS_BLKMEM* blkmem, /**< block memory */ 611 SCIP_SET* set, /**< global SCIP settings */ 612 SCIP_STAT* stat, /**< problem statistics data */ 613 SCIP_PROB* prob, /**< transformed problem data */ 614 SCIP_PRIMAL* primal, /**< primal data */ 615 SCIP_TREE* tree, /**< branch and bound tree */ 616 SCIP_LP* lp, /**< current LP data */ 617 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 618 ) 619 { 620 assert(sol != NULL); 621 assert(lp != NULL); 622 assert(SCIPlpIsSolved(lp)); 623 624 SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) ); 625 SCIP_CALL( SCIPsolLinkLPSol(*sol, set, stat, prob, tree, lp) ); 626 627 return SCIP_OKAY; 628 } 629 630 /** creates primal CIP solution, initialized to the current NLP solution */ 631 SCIP_RETCODE SCIPsolCreateNLPSol( 632 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 633 BMS_BLKMEM* blkmem, /**< block memory */ 634 SCIP_SET* set, /**< global SCIP settings */ 635 SCIP_STAT* stat, /**< problem statistics data */ 636 SCIP_PRIMAL* primal, /**< primal data */ 637 SCIP_TREE* tree, /**< branch and bound tree */ 638 SCIP_NLP* nlp, /**< current NLP data */ 639 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 640 ) 641 { 642 assert(sol != NULL); 643 assert(nlp != NULL); 644 645 SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) ); 646 SCIP_CALL( SCIPsolLinkNLPSol(*sol, stat, tree, nlp) ); 647 648 return SCIP_OKAY; 649 } 650 651 /** creates primal CIP solution, initialized to the current relaxation solution */ 652 SCIP_RETCODE SCIPsolCreateRelaxSol( 653 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 654 BMS_BLKMEM* blkmem, /**< block memory */ 655 SCIP_SET* set, /**< global SCIP settings */ 656 SCIP_STAT* stat, /**< problem statistics data */ 657 SCIP_PRIMAL* primal, /**< primal data */ 658 SCIP_TREE* tree, /**< branch and bound tree */ 659 SCIP_RELAXATION* relaxation, /**< global relaxation data */ 660 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 661 ) 662 { 663 assert(sol != NULL); 664 assert(relaxation != NULL); 665 assert(SCIPrelaxationIsSolValid(relaxation)); 666 667 SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) ); 668 SCIP_CALL( SCIPsolLinkRelaxSol(*sol, set, stat, tree, relaxation) ); 669 670 /* update solution type and store relaxator as creator only if no heuristic is specified as creator */ 671 if( heur == NULL ) 672 SCIPsolSetRelax(*sol, SCIPrelaxationGetSolRelax(relaxation)); 673 674 return SCIP_OKAY; 675 } 676 677 /** creates primal CIP solution, initialized to the current pseudo solution */ 678 SCIP_RETCODE SCIPsolCreatePseudoSol( 679 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 680 BMS_BLKMEM* blkmem, /**< block memory */ 681 SCIP_SET* set, /**< global SCIP settings */ 682 SCIP_STAT* stat, /**< problem statistics data */ 683 SCIP_PROB* prob, /**< transformed problem data */ 684 SCIP_PRIMAL* primal, /**< primal data */ 685 SCIP_TREE* tree, /**< branch and bound tree, or NULL */ 686 SCIP_LP* lp, /**< current LP data */ 687 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 688 ) 689 { 690 assert(sol != NULL); 691 692 SCIP_CALL( SCIPsolCreate(sol, blkmem, set, stat, primal, tree, heur) ); 693 SCIP_CALL( SCIPsolLinkPseudoSol(*sol, set, stat, prob, tree, lp) ); 694 695 /* update solution type to pseudo solution */ 696 if( heur == NULL ) 697 SCIPsolSetPseudo(*sol); 698 699 return SCIP_OKAY; 700 } 701 702 /** creates primal CIP solution, initialized to the current solution */ 703 SCIP_RETCODE SCIPsolCreateCurrentSol( 704 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 705 BMS_BLKMEM* blkmem, /**< block memory */ 706 SCIP_SET* set, /**< global SCIP settings */ 707 SCIP_STAT* stat, /**< problem statistics data */ 708 SCIP_PROB* prob, /**< transformed problem data */ 709 SCIP_PRIMAL* primal, /**< primal data */ 710 SCIP_TREE* tree, /**< branch and bound tree */ 711 SCIP_LP* lp, /**< current LP data */ 712 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 713 ) 714 { 715 assert(tree != NULL); 716 717 if( SCIPtreeHasCurrentNodeLP(tree) ) 718 { 719 SCIP_CALL( SCIPsolCreateLPSol(sol, blkmem, set, stat, prob, primal, tree, lp, heur) ); 720 } 721 else 722 { 723 SCIP_CALL( SCIPsolCreatePseudoSol(sol, blkmem, set, stat, prob, primal, tree, lp, heur) ); 724 } 725 726 return SCIP_OKAY; 727 } 728 729 /** creates partial primal CIP solution, initialized to unknown values */ 730 SCIP_RETCODE SCIPsolCreatePartial( 731 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 732 BMS_BLKMEM* blkmem, /**< block memory */ 733 SCIP_SET* set, /**< global SCIP settings */ 734 SCIP_STAT* stat, /**< problem statistics data */ 735 SCIP_PRIMAL* primal, /**< primal data */ 736 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 737 ) 738 { 739 assert(sol != NULL); 740 assert(blkmem != NULL); 741 assert(set != NULL); 742 assert(stat != NULL); 743 assert(primal != NULL); 744 745 SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) ); 746 SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) ); 747 SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) ); 748 (*sol)->solorigin = SCIP_SOLORIGIN_PARTIAL; 749 (*sol)->obj = SCIP_UNKNOWN; 750 (*sol)->primalindex = -1; 751 (*sol)->index = stat->solindex; 752 (*sol)->hasinfval = FALSE; 753 stat->solindex++; 754 solStamp(*sol, stat, NULL, TRUE); 755 SCIPsolResetViolations(*sol); 756 757 /* set solution type and creator depending on whether a heuristic or NULL is passed */ 758 SCIPsolSetHeur(*sol, heur); 759 760 SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) ); 761 762 return SCIP_OKAY; 763 } 764 765 /** creates primal CIP solution, initialized to unknown values */ 766 SCIP_RETCODE SCIPsolCreateUnknown( 767 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 768 BMS_BLKMEM* blkmem, /**< block memory */ 769 SCIP_SET* set, /**< global SCIP settings */ 770 SCIP_STAT* stat, /**< problem statistics data */ 771 SCIP_PRIMAL* primal, /**< primal data */ 772 SCIP_TREE* tree, /**< branch and bound tree */ 773 SCIP_HEUR* heur /**< heuristic that found the solution (or NULL if it's from the tree) */ 774 ) 775 { 776 assert(sol != NULL); 777 assert(blkmem != NULL); 778 assert(stat != NULL); 779 780 SCIP_ALLOC( BMSallocBlockMemory(blkmem, sol) ); 781 SCIP_CALL( SCIPrealarrayCreate(&(*sol)->vals, blkmem) ); 782 SCIP_CALL( SCIPboolarrayCreate(&(*sol)->valid, blkmem) ); 783 (*sol)->solorigin = SCIP_SOLORIGIN_UNKNOWN; 784 (*sol)->obj = 0.0; 785 (*sol)->primalindex = -1; 786 (*sol)->index = stat->solindex; 787 (*sol)->hasinfval = FALSE; 788 stat->solindex++; 789 solStamp(*sol, stat, tree, TRUE); 790 SCIPsolResetViolations(*sol); 791 792 /* set solution type and creator depending on whether a heuristic or NULL is passed */ 793 SCIPsolSetHeur(*sol, heur); 794 795 SCIP_CALL( SCIPprimalSolCreated(primal, set, *sol) ); 796 797 return SCIP_OKAY; 798 } 799 800 /** frees primal CIP solution */ 801 SCIP_RETCODE SCIPsolFree( 802 SCIP_SOL** sol, /**< pointer to primal CIP solution */ 803 BMS_BLKMEM* blkmem, /**< block memory */ 804 SCIP_PRIMAL* primal /**< primal data */ 805 ) 806 { 807 assert(sol != NULL); 808 assert(*sol != NULL); 809 810 SCIPprimalSolFreed(primal, *sol); 811 812 SCIP_CALL( SCIPrealarrayFree(&(*sol)->vals) ); 813 SCIP_CALL( SCIPboolarrayFree(&(*sol)->valid) ); 814 BMSfreeBlockMemory(blkmem, sol); 815 816 return SCIP_OKAY; 817 } 818 819 /** copies current LP solution into CIP solution by linking */ 820 SCIP_RETCODE SCIPsolLinkLPSol( 821 SCIP_SOL* sol, /**< primal CIP solution */ 822 SCIP_SET* set, /**< global SCIP settings */ 823 SCIP_STAT* stat, /**< problem statistics data */ 824 SCIP_PROB* prob, /**< transformed problem data */ 825 SCIP_TREE* tree, /**< branch and bound tree */ 826 SCIP_LP* lp /**< current LP data */ 827 ) 828 { 829 assert(sol != NULL); 830 assert(stat != NULL); 831 assert(tree != NULL); 832 assert(lp != NULL); 833 assert(lp->solved); 834 assert(SCIPlpDiving(lp) || SCIPtreeProbing(tree) || !SCIPlpDivingObjChanged(lp)); 835 836 SCIPsetDebugMsg(set, "linking solution to LP\n"); 837 838 /* clear the old solution arrays */ 839 SCIP_CALL( solClearArrays(sol) ); 840 841 /* link solution to LP solution */ 842 if( SCIPlpDivingObjChanged(lp) ) 843 { 844 /* the objective value has to be calculated manually, because the LP's value is invalid; 845 * use objective values of variables, because columns objective values are changed to dive values 846 */ 847 sol->obj = SCIPlpGetLooseObjval(lp, set, prob); 848 if( !SCIPsetIsInfinity(set, -sol->obj) ) 849 { 850 SCIP_VAR* var; 851 SCIP_COL** cols; 852 int ncols; 853 int c; 854 855 cols = SCIPlpGetCols(lp); 856 ncols = SCIPlpGetNCols(lp); 857 for( c = 0; c < ncols; ++c ) 858 { 859 var = SCIPcolGetVar(cols[c]); 860 sol->obj += SCIPvarGetUnchangedObj(var) * cols[c]->primsol; 861 } 862 } 863 } 864 else 865 { 866 /* the objective value in the columns is correct, s.t. the LP's objective value is also correct */ 867 sol->obj = SCIPlpGetObjval(lp, set, prob); 868 } 869 sol->solorigin = SCIP_SOLORIGIN_LPSOL; 870 solStamp(sol, stat, tree, TRUE); 871 872 SCIPsetDebugMsg(set, " -> objective value: %g\n", sol->obj); 873 874 return SCIP_OKAY; 875 } 876 877 /** copies current NLP solution into CIP solution by linking */ 878 SCIP_RETCODE SCIPsolLinkNLPSol( 879 SCIP_SOL* sol, /**< primal CIP solution */ 880 SCIP_STAT* stat, /**< problem statistics data */ 881 SCIP_TREE* tree, /**< branch and bound tree */ 882 SCIP_NLP* nlp /**< current NLP data */ 883 ) 884 { 885 assert(sol != NULL); 886 assert(stat != NULL); 887 assert(tree != NULL); 888 assert(nlp != NULL); 889 assert(SCIPnlpHasSolution(nlp)); 890 891 SCIPstatDebugMsg(stat, "linking solution to NLP\n"); 892 893 /* clear the old solution arrays */ 894 SCIP_CALL( solClearArrays(sol) ); 895 896 /* get objective value of NLP solution */ 897 if( SCIPnlpIsDivingObjChanged(nlp) ) 898 { 899 /* the objective value has to be calculated manually, because the NLP's value is invalid */ 900 901 SCIP_VAR** vars; 902 int nvars; 903 int v; 904 905 sol->obj = 0.0; 906 907 vars = SCIPnlpGetVars(nlp); 908 nvars = SCIPnlpGetNVars(nlp); 909 for( v = 0; v < nvars; ++v ) 910 { 911 assert(SCIPvarIsActive(vars[v])); 912 sol->obj += SCIPvarGetUnchangedObj(vars[v]) * SCIPvarGetNLPSol(vars[v]); 913 } 914 } 915 else 916 { 917 sol->obj = SCIPnlpGetObjval(nlp); 918 } 919 920 sol->solorigin = SCIP_SOLORIGIN_NLPSOL; 921 solStamp(sol, stat, tree, TRUE); 922 923 SCIPstatDebugMsg(stat, " -> objective value: %g\n", sol->obj); 924 925 return SCIP_OKAY; 926 } 927 928 /** copies current relaxation solution into CIP solution by linking */ 929 SCIP_RETCODE SCIPsolLinkRelaxSol( 930 SCIP_SOL* sol, /**< primal CIP solution */ 931 SCIP_SET* set, /**< global SCIP settings */ 932 SCIP_STAT* stat, /**< problem statistics data */ 933 SCIP_TREE* tree, /**< branch and bound tree */ 934 SCIP_RELAXATION* relaxation /**< global relaxation data */ 935 ) 936 { /*lint --e{715}*/ 937 assert(sol != NULL); 938 assert(stat != NULL); 939 assert(tree != NULL); 940 assert(relaxation != NULL); 941 assert(SCIPrelaxationIsSolValid(relaxation)); 942 943 SCIPsetDebugMsg(set, "linking solution to relaxation\n"); 944 945 /* clear the old solution arrays */ 946 SCIP_CALL( solClearArrays(sol) ); 947 948 /* the objective value in the columns is correct, s.t. the LP's objective value is also correct */ 949 sol->obj = SCIPrelaxationGetSolObj(relaxation); 950 sol->solorigin = SCIP_SOLORIGIN_RELAXSOL; 951 solStamp(sol, stat, tree, TRUE); 952 953 SCIPsetDebugMsg(set, " -> objective value: %g\n", sol->obj); 954 955 return SCIP_OKAY; 956 } 957 958 /** copies current pseudo solution into CIP solution by linking */ 959 SCIP_RETCODE SCIPsolLinkPseudoSol( 960 SCIP_SOL* sol, /**< primal CIP solution */ 961 SCIP_SET* set, /**< global SCIP settings */ 962 SCIP_STAT* stat, /**< problem statistics data */ 963 SCIP_PROB* prob, /**< transformed problem data */ 964 SCIP_TREE* tree, /**< branch and bound tree, or NULL */ 965 SCIP_LP* lp /**< current LP data */ 966 ) 967 { 968 assert(sol != NULL); 969 assert(stat != NULL); 970 assert(tree != NULL); 971 972 SCIPsetDebugMsg(set, "linking solution to pseudo solution\n"); 973 974 /* clear the old solution arrays */ 975 SCIP_CALL( solClearArrays(sol) ); 976 977 /* link solution to pseudo solution */ 978 sol->obj = SCIPlpGetPseudoObjval(lp, set, prob); 979 sol->solorigin = SCIP_SOLORIGIN_PSEUDOSOL; 980 solStamp(sol, stat, tree, TRUE); 981 982 SCIPsetDebugMsg(set, " -> objective value: %g\n", sol->obj); 983 984 return SCIP_OKAY; 985 } 986 987 /** copies current solution (LP or pseudo solution) into CIP solution by linking */ 988 SCIP_RETCODE SCIPsolLinkCurrentSol( 989 SCIP_SOL* sol, /**< primal CIP solution */ 990 SCIP_SET* set, /**< global SCIP settings */ 991 SCIP_STAT* stat, /**< problem statistics data */ 992 SCIP_PROB* prob, /**< transformed problem data */ 993 SCIP_TREE* tree, /**< branch and bound tree */ 994 SCIP_LP* lp /**< current LP data */ 995 ) 996 { 997 assert(tree != NULL); 998 999 SCIPsetDebugMsg(set, "linking solution to current solution\n"); 1000 1001 if( SCIPtreeHasCurrentNodeLP(tree) && SCIPlpIsSolved(lp) ) 1002 { 1003 SCIP_CALL( SCIPsolLinkLPSol(sol, set, stat, prob, tree, lp) ); 1004 } 1005 else 1006 { 1007 SCIP_CALL( SCIPsolLinkPseudoSol(sol, set, stat, prob, tree, lp) ); 1008 } 1009 1010 return SCIP_OKAY; 1011 } 1012 1013 /** clears primal CIP solution */ 1014 SCIP_RETCODE SCIPsolClear( 1015 SCIP_SOL* sol, /**< primal CIP solution */ 1016 SCIP_STAT* stat, /**< problem statistics data */ 1017 SCIP_TREE* tree /**< branch and bound tree */ 1018 ) 1019 { 1020 assert(sol != NULL); 1021 1022 SCIP_CALL( solClearArrays(sol) ); 1023 sol->solorigin = SCIP_SOLORIGIN_ZERO; 1024 sol->obj = 0.0; 1025 solStamp(sol, stat, tree, TRUE); 1026 1027 return SCIP_OKAY; 1028 } 1029 1030 /** declares all entries in the primal CIP solution to be unknown */ 1031 SCIP_RETCODE SCIPsolSetUnknown( 1032 SCIP_SOL* sol, /**< primal CIP solution */ 1033 SCIP_STAT* stat, /**< problem statistics data */ 1034 SCIP_TREE* tree /**< branch and bound tree */ 1035 ) 1036 { 1037 assert(sol != NULL); 1038 1039 SCIP_CALL( solClearArrays(sol) ); 1040 sol->solorigin = SCIP_SOLORIGIN_UNKNOWN; 1041 sol->obj = 0.0; 1042 solStamp(sol, stat, tree, TRUE); 1043 1044 return SCIP_OKAY; 1045 } 1046 1047 /** stores solution values of variables in solution's own array */ 1048 SCIP_RETCODE SCIPsolUnlink( 1049 SCIP_SOL* sol, /**< primal CIP solution */ 1050 SCIP_SET* set, /**< global SCIP settings */ 1051 SCIP_PROB* prob /**< transformed problem data */ 1052 ) 1053 { 1054 int v; 1055 1056 assert(sol != NULL); 1057 assert(prob != NULL); 1058 assert(prob->nvars == 0 || prob->vars != NULL); 1059 1060 if( !SCIPsolIsOriginal(sol) && sol->solorigin != SCIP_SOLORIGIN_ZERO 1061 && sol->solorigin != SCIP_SOLORIGIN_UNKNOWN ) 1062 { 1063 SCIPsetDebugMsg(set, "completing solution %p\n", (void*)sol); 1064 1065 for( v = 0; v < prob->nvars; ++v ) 1066 { 1067 SCIP_CALL( solUnlinkVar(sol, set, prob->vars[v]) ); 1068 } 1069 1070 sol->solorigin = SCIP_SOLORIGIN_ZERO; 1071 } 1072 1073 return SCIP_OKAY; 1074 } 1075 1076 /** sets value of variable in primal CIP solution */ 1077 SCIP_RETCODE SCIPsolSetVal( 1078 SCIP_SOL* sol, /**< primal CIP solution */ 1079 SCIP_SET* set, /**< global SCIP settings */ 1080 SCIP_STAT* stat, /**< problem statistics data */ 1081 SCIP_TREE* tree, /**< branch and bound tree, or NULL */ 1082 SCIP_VAR* var, /**< variable to add to solution */ 1083 SCIP_Real val /**< solution value of variable */ 1084 ) 1085 { 1086 SCIP_Real oldval; 1087 1088 assert(sol != NULL); 1089 assert(stat != NULL); 1090 assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL 1091 || sol->solorigin == SCIP_SOLORIGIN_ZERO 1092 || sol->solorigin == SCIP_SOLORIGIN_PARTIAL 1093 || sol->solorigin == SCIP_SOLORIGIN_UNKNOWN 1094 || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns)); 1095 assert(var != NULL); 1096 assert(SCIPisFinite(val)); 1097 1098 SCIPsetDebugMsg(set, "setting value of <%s> in solution %p to %g\n", SCIPvarGetName(var), (void*)sol, val); 1099 1100 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */ 1101 switch( SCIPvarGetStatus(var) ) 1102 { 1103 case SCIP_VARSTATUS_ORIGINAL: 1104 if( SCIPsolIsOriginal(sol) ) 1105 { 1106 oldval = solGetArrayVal(sol, var); 1107 1108 if( val != oldval ) /*lint !e777*/ 1109 { 1110 SCIP_CALL( solSetArrayVal(sol, set, var, val) ); 1111 1112 /* update the objective value; we do not need to do this for invalid objectives or partial solutions */ 1113 if( sol->obj != SCIP_INVALID && !SCIPsolIsPartial(sol) ) /*lint !e777*/ 1114 { 1115 SCIP_Real obj; 1116 SCIP_Real oldobjcont; 1117 SCIP_Real newobjcont; 1118 1119 /* an unknown solution value does not count towards the objective */ 1120 obj = SCIPvarGetUnchangedObj(var); 1121 oldobjcont = (oldval == SCIP_UNKNOWN ? 0.0 : obj * oldval); /*lint !e777*/ 1122 newobjcont = (val == SCIP_UNKNOWN ? 0.0 : obj * val); /*lint !e777*/ 1123 1124 /* we want to use a safe invalid if the contribution exchange contradicts the infinity status of the objective value */ 1125 if( SCIPsetIsInfinity(set, sol->obj) ) 1126 { 1127 if( ( SCIPsetIsInfinity(set, oldobjcont) && !SCIPsetIsInfinity(set, newobjcont) ) 1128 || ( !SCIPsetIsInfinity(set, -oldobjcont) && SCIPsetIsInfinity(set, -newobjcont) ) ) 1129 sol->obj = SCIP_INVALID; 1130 } 1131 else if( SCIPsetIsInfinity(set, -sol->obj) ) 1132 { 1133 if( ( SCIPsetIsInfinity(set, -oldobjcont) && !SCIPsetIsInfinity(set, -newobjcont) ) 1134 || ( !SCIPsetIsInfinity(set, oldobjcont) && SCIPsetIsInfinity(set, newobjcont) ) ) 1135 sol->obj = SCIP_INVALID; 1136 } 1137 /* we want to use a clean infinity if the contribution exchange or the resulting objective hits the infinity bound */ 1138 else 1139 { 1140 if( !SCIPsetIsInfinity(set, MAX(ABS(oldobjcont), ABS(newobjcont))) ) 1141 { 1142 sol->obj -= oldobjcont; 1143 sol->obj += newobjcont; 1144 1145 if( SCIPsetIsInfinity(set, sol->obj) ) 1146 sol->obj = SCIPsetInfinity(set); 1147 else if( SCIPsetIsInfinity(set, -sol->obj) ) 1148 sol->obj = -SCIPsetInfinity(set); 1149 } 1150 else if( !SCIPsetIsInfinity(set, MAX(oldobjcont, -newobjcont)) ) 1151 sol->obj = SCIPsetInfinity(set); 1152 else if( !SCIPsetIsInfinity(set, MAX(-oldobjcont, newobjcont)) ) 1153 sol->obj = -SCIPsetInfinity(set); 1154 } 1155 } 1156 1157 solStamp(sol, stat, tree, FALSE); 1158 } 1159 return SCIP_OKAY; 1160 } 1161 else 1162 return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetTransVar(var), val); 1163 1164 case SCIP_VARSTATUS_LOOSE: 1165 case SCIP_VARSTATUS_COLUMN: 1166 assert(!SCIPsolIsOriginal(sol)); 1167 assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var)) 1168 || sol->lpcount == stat->lpcount); 1169 oldval = solGetArrayVal(sol, var); 1170 if( val != oldval ) /*lint !e777*/ 1171 { 1172 SCIP_CALL( solSetArrayVal(sol, set, var, val) ); 1173 1174 /* update the objective value; we do not need to do this for invalid objectives */ 1175 if( sol->obj != SCIP_INVALID ) /*lint !e777*/ 1176 { 1177 SCIP_Real obj; 1178 SCIP_Real oldobjcont; 1179 SCIP_Real newobjcont; 1180 1181 /* an unknown solution value does not count towards the objective */ 1182 obj = SCIPvarGetUnchangedObj(var); 1183 oldobjcont = (oldval == SCIP_UNKNOWN ? 0.0 : obj * oldval); /*lint !e777*/ 1184 newobjcont = (val == SCIP_UNKNOWN ? 0.0 : obj * val); /*lint !e777*/ 1185 1186 /* we want to use a safe invalid if the contribution exchange contradicts the infinity status of the objective value */ 1187 if( SCIPsetIsInfinity(set, sol->obj) ) 1188 { 1189 if( ( SCIPsetIsInfinity(set, oldobjcont) && !SCIPsetIsInfinity(set, newobjcont) ) 1190 || ( !SCIPsetIsInfinity(set, -oldobjcont) && SCIPsetIsInfinity(set, -newobjcont) ) ) 1191 sol->obj = SCIP_INVALID; 1192 } 1193 else if( SCIPsetIsInfinity(set, -sol->obj) ) 1194 { 1195 if( ( SCIPsetIsInfinity(set, -oldobjcont) && !SCIPsetIsInfinity(set, -newobjcont) ) 1196 || ( !SCIPsetIsInfinity(set, oldobjcont) && SCIPsetIsInfinity(set, newobjcont) ) ) 1197 sol->obj = SCIP_INVALID; 1198 } 1199 /* we want to use a clean infinity if the contribution exchange or the resulting objective hits the infinity bound */ 1200 else 1201 { 1202 if( !SCIPsetIsInfinity(set, MAX(ABS(oldobjcont), ABS(newobjcont))) ) 1203 { 1204 sol->obj -= oldobjcont; 1205 sol->obj += newobjcont; 1206 1207 if( SCIPsetIsInfinity(set, sol->obj) ) 1208 sol->obj = SCIPsetInfinity(set); 1209 else if( SCIPsetIsInfinity(set, -sol->obj) ) 1210 sol->obj = -SCIPsetInfinity(set); 1211 } 1212 else if( !SCIPsetIsInfinity(set, MAX(oldobjcont, -newobjcont)) ) 1213 sol->obj = SCIPsetInfinity(set); 1214 else if( !SCIPsetIsInfinity(set, MAX(-oldobjcont, newobjcont)) ) 1215 sol->obj = -SCIPsetInfinity(set); 1216 } 1217 } 1218 1219 solStamp(sol, stat, tree, FALSE); 1220 } 1221 return SCIP_OKAY; 1222 1223 case SCIP_VARSTATUS_FIXED: 1224 assert(!SCIPsolIsOriginal(sol)); 1225 oldval = SCIPvarGetLbGlobal(var); 1226 if( val != oldval ) /*lint !e777*/ 1227 { 1228 SCIPerrorMessage("cannot set solution value for variable <%s> fixed to %.15g to different value %.15g\n", 1229 SCIPvarGetName(var), oldval, val); 1230 return SCIP_INVALIDDATA; 1231 } 1232 return SCIP_OKAY; 1233 1234 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */ 1235 assert(!SCIPsetIsZero(set, SCIPvarGetAggrScalar(var))); 1236 assert(!SCIPsetIsInfinity(set, SCIPvarGetAggrConstant(var)) && !SCIPsetIsInfinity(set, -SCIPvarGetAggrConstant(var))); 1237 assert(!SCIPsetIsInfinity(set, SCIPvarGetAggrScalar(var)) && !SCIPsetIsInfinity(set, -SCIPvarGetAggrScalar(var))); 1238 1239 if( val == SCIP_UNKNOWN )/*lint !e777*/ 1240 return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), val); 1241 if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) ) 1242 return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), SCIPvarGetAggrScalar(var) > 0 ? val : -val); 1243 else 1244 return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), (val - SCIPvarGetAggrConstant(var))/SCIPvarGetAggrScalar(var)); 1245 1246 case SCIP_VARSTATUS_MULTAGGR: 1247 if ( SCIPvarGetMultaggrNVars(var) == 1 ) 1248 { 1249 SCIP_VAR** multaggrvars; 1250 SCIP_Real* multaggrscalars; 1251 SCIP_Real multaggrconstant; 1252 1253 multaggrvars = SCIPvarGetMultaggrVars(var); 1254 multaggrscalars = SCIPvarGetMultaggrScalars(var); 1255 multaggrconstant = SCIPvarGetMultaggrConstant(var); 1256 1257 if( SCIPsetIsInfinity(set, multaggrconstant) || SCIPsetIsInfinity(set, -multaggrconstant) ) 1258 { 1259 if( (SCIPsetIsInfinity(set, multaggrconstant) && !SCIPsetIsInfinity(set, val)) 1260 || (SCIPsetIsInfinity(set, -multaggrconstant) && !SCIPsetIsInfinity(set, -val)) ) 1261 { 1262 SCIPerrorMessage("cannot set solution value for variable <%s> fixed to %.15g to different value %.15g\n", 1263 SCIPvarGetName(var), multaggrconstant, val); 1264 return SCIP_INVALIDDATA; 1265 } 1266 return SCIP_OKAY; 1267 } 1268 else 1269 { 1270 if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) ) 1271 return SCIPsolSetVal(sol, set, stat, tree, multaggrvars[0], multaggrscalars[0] > 0 ? val : -val); 1272 else 1273 return SCIPsolSetVal(sol, set, stat, tree, multaggrvars[0], (val - multaggrconstant)/multaggrscalars[0]); 1274 } 1275 } 1276 SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n"); 1277 return SCIP_INVALIDDATA; 1278 1279 case SCIP_VARSTATUS_NEGATED: 1280 assert(!SCIPsetIsInfinity(set, SCIPvarGetNegationConstant(var)) && !SCIPsetIsInfinity(set, -SCIPvarGetNegationConstant(var))); 1281 1282 if( val == SCIP_UNKNOWN )/*lint !e777*/ 1283 return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), val); 1284 else if( SCIPsetIsInfinity(set, val) || SCIPsetIsInfinity(set, -val) ) 1285 return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), -val); 1286 else 1287 return SCIPsolSetVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), SCIPvarGetNegationConstant(var) - val); 1288 1289 default: 1290 SCIPerrorMessage("unknown variable status\n"); 1291 return SCIP_INVALIDDATA; 1292 } 1293 } 1294 1295 /** increases value of variable in primal CIP solution */ 1296 SCIP_RETCODE SCIPsolIncVal( 1297 SCIP_SOL* sol, /**< primal CIP solution */ 1298 SCIP_SET* set, /**< global SCIP settings */ 1299 SCIP_STAT* stat, /**< problem statistics data */ 1300 SCIP_TREE* tree, /**< branch and bound tree */ 1301 SCIP_VAR* var, /**< variable to increase solution value for */ 1302 SCIP_Real incval /**< increment for solution value of variable */ 1303 ) 1304 { 1305 SCIP_Real oldval; 1306 1307 assert(sol != NULL); 1308 assert(stat != NULL); 1309 assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL 1310 || sol->solorigin == SCIP_SOLORIGIN_ZERO 1311 || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns)); 1312 assert(var != NULL); 1313 assert(!SCIPsetIsInfinity(set, incval) && !SCIPsetIsInfinity(set, -incval)); 1314 1315 SCIPsetDebugMsg(set, "increasing value of <%s> in solution %p by %g\n", SCIPvarGetName(var), (void*)sol, incval); 1316 1317 if( incval == 0.0 ) 1318 return SCIP_OKAY; 1319 1320 assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var)) 1321 || sol->lpcount == stat->lpcount); 1322 1323 oldval = solGetArrayVal(sol, var); 1324 if( SCIPsetIsInfinity(set, oldval) || SCIPsetIsInfinity(set, -oldval) ) 1325 return SCIP_OKAY; 1326 1327 /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */ 1328 /* @todo: handle strange cases, such as sums that yield infinite values */ 1329 switch( SCIPvarGetStatus(var) ) 1330 { 1331 case SCIP_VARSTATUS_ORIGINAL: 1332 if( SCIPsolIsOriginal(sol) ) 1333 { 1334 SCIP_CALL( solIncArrayVal(sol, set, var, incval) ); 1335 sol->obj += SCIPvarGetUnchangedObj(var) * incval; 1336 solStamp(sol, stat, tree, FALSE); 1337 return SCIP_OKAY; 1338 } 1339 else 1340 return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetTransVar(var), incval); 1341 1342 case SCIP_VARSTATUS_LOOSE: 1343 case SCIP_VARSTATUS_COLUMN: 1344 assert(!SCIPsolIsOriginal(sol)); 1345 SCIP_CALL( solIncArrayVal(sol, set, var, incval) ); 1346 sol->obj += SCIPvarGetUnchangedObj(var) * incval; 1347 solStamp(sol, stat, tree, FALSE); 1348 return SCIP_OKAY; 1349 1350 case SCIP_VARSTATUS_FIXED: 1351 SCIPerrorMessage("cannot increase solution value for fixed variable\n"); 1352 return SCIP_INVALIDDATA; 1353 1354 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */ 1355 assert(!SCIPsetIsZero(set, SCIPvarGetAggrScalar(var))); 1356 return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetAggrVar(var), incval/SCIPvarGetAggrScalar(var)); 1357 1358 case SCIP_VARSTATUS_MULTAGGR: 1359 SCIPerrorMessage("cannot increase solution value for multiple aggregated variable\n"); 1360 return SCIP_INVALIDDATA; 1361 1362 case SCIP_VARSTATUS_NEGATED: 1363 return SCIPsolIncVal(sol, set, stat, tree, SCIPvarGetNegationVar(var), -incval); 1364 1365 default: 1366 SCIPerrorMessage("unknown variable status\n"); 1367 return SCIP_INVALIDDATA; 1368 } 1369 } 1370 1371 /** returns value of variable in primal CIP solution */ 1372 SCIP_Real SCIPsolGetVal( 1373 SCIP_SOL* sol, /**< primal CIP solution */ 1374 SCIP_SET* set, /**< global SCIP settings */ 1375 SCIP_STAT* stat, /**< problem statistics data */ 1376 SCIP_VAR* var /**< variable to get value for */ 1377 ) 1378 { 1379 SCIP_VAR** vars; 1380 SCIP_Real* scalars; 1381 SCIP_Real solval; 1382 SCIP_Real solvalsum; 1383 int nvars; 1384 int i; 1385 1386 assert(sol != NULL); 1387 assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL 1388 || sol->solorigin == SCIP_SOLORIGIN_ZERO 1389 || sol->solorigin == SCIP_SOLORIGIN_PARTIAL 1390 || sol->solorigin == SCIP_SOLORIGIN_UNKNOWN 1391 || (sol->nodenum == stat->nnodes && sol->runnum == stat->nruns)); 1392 assert(var != NULL); 1393 1394 /* if the value of a transformed variable in an original solution is requested, we need to project the variable back 1395 * to the original space, the opposite case is handled below 1396 */ 1397 if( SCIPsolIsOriginal(sol) && SCIPvarIsTransformed(var) ) 1398 { 1399 SCIP_RETCODE retcode; 1400 SCIP_VAR* origvar; 1401 SCIP_Real scalar; 1402 SCIP_Real constant; 1403 1404 /* we cannot get the value of a transformed variable for a solution that lives in the original problem space 1405 * -> get the corresponding original variable first 1406 */ 1407 origvar = var; 1408 scalar = 1.0; 1409 constant = 0.0; 1410 retcode = SCIPvarGetOrigvarSum(&origvar, &scalar, &constant); 1411 if ( retcode != SCIP_OKAY ) 1412 return SCIP_INVALID; 1413 if( origvar == NULL ) 1414 { 1415 /* the variable has no original counterpart: in the original solution, it has a value of zero */ 1416 return 0.0; 1417 } 1418 assert(!SCIPvarIsTransformed(origvar)); 1419 1420 solval = SCIPsolGetVal(sol, set, stat, origvar); 1421 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 1422 return SCIP_UNKNOWN; 1423 else 1424 return scalar * solval + constant; 1425 } 1426 1427 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */ 1428 switch( SCIPvarGetStatus(var) ) 1429 { 1430 case SCIP_VARSTATUS_ORIGINAL: 1431 if( SCIPsolIsOriginal(sol) ) 1432 return solGetArrayVal(sol, var); 1433 else 1434 return SCIPsolGetVal(sol, set, stat, SCIPvarGetTransVar(var)); 1435 1436 case SCIP_VARSTATUS_LOOSE: 1437 case SCIP_VARSTATUS_COLUMN: 1438 assert(!SCIPsolIsOriginal(sol)); 1439 assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var)) 1440 || sol->lpcount == stat->lpcount); 1441 return solGetArrayVal(sol, var); 1442 1443 case SCIP_VARSTATUS_FIXED: 1444 assert(!SCIPsolIsOriginal(sol)); 1445 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/ 1446 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/ 1447 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/ 1448 return SCIPvarGetLbGlobal(var); 1449 1450 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */ 1451 solval = SCIPsolGetVal(sol, set, stat, SCIPvarGetAggrVar(var)); 1452 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 1453 return SCIP_UNKNOWN; 1454 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) ) 1455 { 1456 if( SCIPvarGetAggrScalar(var) * solval > 0.0 ) 1457 return SCIPsetInfinity(set); 1458 if( SCIPvarGetAggrScalar(var) * solval < 0.0 ) 1459 return -SCIPsetInfinity(set); 1460 } 1461 return SCIPvarGetAggrScalar(var) * solval + SCIPvarGetAggrConstant(var); 1462 1463 case SCIP_VARSTATUS_MULTAGGR: 1464 nvars = SCIPvarGetMultaggrNVars(var); 1465 vars = SCIPvarGetMultaggrVars(var); 1466 scalars = SCIPvarGetMultaggrScalars(var); 1467 solvalsum = SCIPvarGetMultaggrConstant(var); 1468 for( i = 0; i < nvars; ++i ) 1469 { 1470 solval = SCIPsolGetVal(sol, set, stat, vars[i]); 1471 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 1472 return SCIP_UNKNOWN; 1473 if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) ) 1474 { 1475 if( scalars[i] * solval > 0.0 ) 1476 return SCIPsetInfinity(set); 1477 if( scalars[i] * solval < 0.0 ) 1478 return -SCIPsetInfinity(set); 1479 } 1480 solvalsum += scalars[i] * solval; 1481 } 1482 return solvalsum; 1483 1484 case SCIP_VARSTATUS_NEGATED: 1485 solval = SCIPsolGetVal(sol, set, stat, SCIPvarGetNegationVar(var)); 1486 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 1487 return SCIP_UNKNOWN; 1488 if( SCIPsetIsInfinity(set, solval) ) 1489 return -SCIPsetInfinity(set); 1490 if( SCIPsetIsInfinity(set, -solval) ) 1491 return SCIPsetInfinity(set); 1492 return SCIPvarGetNegationConstant(var) - solval; 1493 1494 default: 1495 SCIPerrorMessage("unknown variable status\n"); 1496 SCIPABORT(); 1497 return 0.0; /*lint !e527*/ 1498 } 1499 } 1500 1501 /** returns value of variable in primal ray represented by primal CIP solution */ 1502 SCIP_Real SCIPsolGetRayVal( 1503 SCIP_SOL* sol, /**< primal CIP solution, representing a primal ray */ 1504 SCIP_SET* set, /**< global SCIP settings */ 1505 SCIP_STAT* stat, /**< problem statistics data */ 1506 SCIP_VAR* var /**< variable to get value for */ 1507 ) 1508 { 1509 SCIP_VAR** vars; 1510 SCIP_Real* scalars; 1511 SCIP_Real solval; 1512 SCIP_Real solvalsum; 1513 int nvars; 1514 int i; 1515 1516 assert(sol != NULL); 1517 assert(sol->solorigin == SCIP_SOLORIGIN_ZERO); 1518 assert(var != NULL); 1519 1520 /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */ 1521 switch( SCIPvarGetStatus(var) ) 1522 { 1523 case SCIP_VARSTATUS_ORIGINAL: 1524 return SCIPsolGetRayVal(sol, set, stat, SCIPvarGetTransVar(var)); 1525 1526 case SCIP_VARSTATUS_LOOSE: 1527 case SCIP_VARSTATUS_COLUMN: 1528 return solGetArrayVal(sol, var); 1529 1530 case SCIP_VARSTATUS_FIXED: 1531 assert(!SCIPsolIsOriginal(sol)); 1532 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/ 1533 assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/ 1534 assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/ 1535 return 0.0; /* constants are ignored for computing the ray direction */ 1536 1537 case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */ 1538 solval = SCIPsolGetRayVal(sol, set, stat, SCIPvarGetAggrVar(var)); 1539 assert(solval != SCIP_UNKNOWN); /*lint !e777*/ 1540 assert(!SCIPsetIsInfinity(set, REALABS(solval))); 1541 return SCIPvarGetAggrScalar(var) * solval; /* constants are ignored for computing the ray direction */ 1542 1543 case SCIP_VARSTATUS_MULTAGGR: 1544 nvars = SCIPvarGetMultaggrNVars(var); 1545 vars = SCIPvarGetMultaggrVars(var); 1546 scalars = SCIPvarGetMultaggrScalars(var); 1547 solvalsum = 0.0; /* constants are ignored for computing the ray direction */ 1548 for( i = 0; i < nvars; ++i ) 1549 { 1550 solval = SCIPsolGetRayVal(sol, set, stat, vars[i]); 1551 assert(solval != SCIP_UNKNOWN ); /*lint !e777*/ 1552 assert(!SCIPsetIsInfinity(set, REALABS(solval))); 1553 solvalsum += scalars[i] * solval; 1554 } 1555 return solvalsum; 1556 1557 case SCIP_VARSTATUS_NEGATED: 1558 solval = SCIPsolGetRayVal(sol, set, stat, SCIPvarGetNegationVar(var)); 1559 assert(solval != SCIP_UNKNOWN); /*lint !e777*/ 1560 assert(!SCIPsetIsInfinity(set, REALABS(solval))); 1561 return -solval; /* constants are ignored for computing the ray direction */ 1562 1563 default: 1564 SCIPerrorMessage("unknown variable status\n"); 1565 SCIPABORT(); 1566 return 0.0; /*lint !e527*/ 1567 } 1568 } 1569 1570 /** gets objective value of primal CIP solution in transformed problem */ 1571 SCIP_Real SCIPsolGetObj( 1572 SCIP_SOL* sol, /**< primal CIP solution */ 1573 SCIP_SET* set, /**< global SCIP settings */ 1574 SCIP_PROB* transprob, /**< tranformed problem data */ 1575 SCIP_PROB* origprob /**< original problem data */ 1576 ) 1577 { 1578 assert(sol != NULL); 1579 1580 /* for original solutions, sol->obj contains the external objective value */ 1581 if( SCIPsolIsOriginal(sol) ) 1582 return SCIPprobInternObjval(transprob, origprob, set, sol->obj); 1583 else 1584 return sol->obj; 1585 } 1586 1587 /** updates primal solutions after a change in a variable's objective value */ 1588 void SCIPsolUpdateVarObj( 1589 SCIP_SOL* sol, /**< primal CIP solution */ 1590 SCIP_VAR* var, /**< problem variable */ 1591 SCIP_Real oldobj, /**< old objective value */ 1592 SCIP_Real newobj /**< new objective value */ 1593 ) 1594 { 1595 SCIP_Real solval; 1596 1597 assert(sol != NULL); 1598 assert(!SCIPsolIsOriginal(sol)); 1599 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 1600 1601 solval = solGetArrayVal(sol, var); 1602 if( solval != SCIP_UNKNOWN ) /*lint !e777*/ 1603 sol->obj += (newobj - oldobj) * solval; 1604 } 1605 1606 /* mark the given solution as partial solution */ 1607 SCIP_RETCODE SCIPsolMarkPartial( 1608 SCIP_SOL* sol, /**< primal CIP solution */ 1609 SCIP_SET* set, /**< global SCIP settings */ 1610 SCIP_STAT* stat, /**< problem statistics */ 1611 SCIP_VAR** vars, /**< problem variables */ 1612 int nvars /**< number of problem variables */ 1613 ) 1614 { 1615 SCIP_Real* vals; 1616 int v; 1617 1618 assert(sol != NULL); 1619 assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL); 1620 assert(nvars == 0 || vars != NULL); 1621 1622 if( nvars == 0 ) 1623 return SCIP_OKAY;; 1624 1625 SCIP_CALL( SCIPsetAllocBufferArray(set, &vals, nvars) ); 1626 1627 /* get values */ 1628 for( v = 0; v < nvars; v++ ) 1629 { 1630 assert(!SCIPvarIsTransformed(vars[v])); 1631 vals[v] = SCIPsolGetVal(sol, set, stat, vars[v]); 1632 } 1633 1634 /* change origin to partial */ 1635 sol->solorigin = SCIP_SOLORIGIN_PARTIAL; 1636 1637 /* set values */ 1638 for( v = 0; v < nvars; v++ ) 1639 { 1640 int idx = SCIPvarGetIndex(vars[v]); 1641 1642 if( vals[v] != SCIP_UNKNOWN ) /*lint !e777*/ 1643 { 1644 /* from now on, variable must not be deleted */ 1645 SCIPvarMarkNotDeletable(vars[v]); 1646 1647 /* mark the variable valid */ 1648 SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, TRUE) ); 1649 1650 /* set the value in the solution array */ 1651 SCIP_CALL( SCIPrealarraySetVal(sol->vals, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, vals[v]) ); 1652 } 1653 else 1654 { 1655 /* mark the variable invalid */ 1656 SCIP_CALL( SCIPboolarraySetVal(sol->valid, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, FALSE) ); 1657 } 1658 } 1659 1660 /* free buffer */ 1661 SCIPsetFreeBufferArray(set, &vals); 1662 1663 return SCIP_OKAY; 1664 } 1665 1666 /** checks solution for feasibility in original problem without adding it to the solution store 1667 * 1668 * We first check the variable bounds. Then we loop over all constraint handlers and constraints, checking each in the 1669 * order of their check priority. 1670 */ 1671 SCIP_RETCODE SCIPsolCheckOrig( 1672 SCIP_SOL* sol, /**< primal CIP solution */ 1673 SCIP_SET* set, /**< global SCIP settings */ 1674 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 1675 BMS_BLKMEM* blkmem, /**< block memory */ 1676 SCIP_STAT* stat, /**< problem statistics */ 1677 SCIP_PROB* prob, /**< transformed problem data */ 1678 SCIP_PRIMAL* primal, /**< primal data */ 1679 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */ 1680 SCIP_Bool completely, /**< Should all violations be checked if printreason is true? */ 1681 SCIP_Bool checkbounds, /**< Should the bounds of the variables be checked? */ 1682 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */ 1683 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */ 1684 SCIP_Bool checkmodifiable, /**< have modifiable constraint to be checked? */ 1685 SCIP_Bool* feasible /**< stores whether given solution is feasible */ 1686 ) 1687 { 1688 SCIP_RESULT result; 1689 #ifndef NDEBUG 1690 int oldpriority; 1691 #endif 1692 int v; 1693 int c; 1694 int h; 1695 1696 assert(sol != NULL); 1697 assert(set != NULL); 1698 assert(prob != NULL); 1699 assert(!prob->transformed); 1700 assert(feasible != NULL); 1701 1702 *feasible = TRUE; 1703 1704 SCIPsolResetViolations(sol); 1705 1706 if( !printreason ) 1707 completely = FALSE; 1708 1709 /* check bounds */ 1710 if( checkbounds ) 1711 { 1712 for( v = 0; v < prob->nvars; ++v ) 1713 { 1714 SCIP_VAR* var; 1715 SCIP_Real solval; 1716 SCIP_Real lb; 1717 SCIP_Real ub; 1718 1719 var = prob->vars[v]; 1720 solval = SCIPsolGetVal(sol, set, stat, var); 1721 1722 lb = SCIPvarGetLbOriginal(var); 1723 ub = SCIPvarGetUbOriginal(var); 1724 1725 if( SCIPprimalUpdateViolations(primal) ) 1726 { 1727 SCIPsolUpdateBoundViolation(sol, lb - solval, SCIPrelDiff(lb, solval)); 1728 SCIPsolUpdateBoundViolation(sol, solval - ub, SCIPrelDiff(solval, ub)); 1729 } 1730 1731 if( SCIPsetIsFeasLT(set, solval, lb) || SCIPsetIsFeasGT(set, solval, ub) ) 1732 { 1733 *feasible = FALSE; 1734 1735 if( printreason ) 1736 { 1737 SCIPmessagePrintInfo(messagehdlr, "solution violates original bounds of variable <%s> [%g,%g] solution value <%g>\n", 1738 SCIPvarGetName(var), lb, ub, solval); 1739 } 1740 1741 if( !completely ) 1742 return SCIP_OKAY; 1743 } 1744 } 1745 } 1746 1747 /* sort original constraint according to check priority */ 1748 SCIP_CALL( SCIPprobSortConssCheck(prob) ); 1749 1750 /* check original constraints 1751 * 1752 * in general modifiable constraints can not be checked, because the variables to fulfill them might be missing in 1753 * the original problem; however, if the solution comes from a heuristic during presolving, modifiable constraints 1754 * have to be checked; 1755 */ 1756 #ifndef NDEBUG 1757 oldpriority = INT_MAX; 1758 #endif 1759 h = 0; 1760 for( c = 0; c < prob->nconss; ++c ) 1761 { 1762 SCIP_CONS* cons; 1763 int priority; 1764 1765 cons = prob->origcheckconss[c]; 1766 assert( SCIPconsGetHdlr(cons) != NULL ); 1767 priority = SCIPconshdlrGetCheckPriority(SCIPconsGetHdlr(cons)); 1768 1769 #ifndef NDEBUG 1770 assert( priority <= oldpriority ); 1771 oldpriority = priority; 1772 #endif 1773 1774 /* check constraints handlers without constraints that have a check priority at least as high as current 1775 * constraint */ 1776 while( h < set->nconshdlrs && SCIPconshdlrGetCheckPriority(set->conshdlrs[h]) >= priority ) 1777 { 1778 if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) ) 1779 { 1780 SCIP_CALL( SCIPconshdlrCheck(set->conshdlrs[h], blkmem, set, stat, sol, 1781 checkintegrality, checklprows, printreason, completely, &result) ); 1782 1783 if( result != SCIP_FEASIBLE ) 1784 { 1785 *feasible = FALSE; 1786 1787 if( !completely ) 1788 return SCIP_OKAY; 1789 } 1790 } 1791 ++h; 1792 } 1793 1794 /* now check constraint */ 1795 if( SCIPconsIsChecked(cons) && (checkmodifiable || !SCIPconsIsModifiable(cons)) ) 1796 { 1797 /* check solution */ 1798 SCIP_CALL( SCIPconsCheck(cons, set, sol, checkintegrality, checklprows, printreason, &result) ); 1799 1800 if( result != SCIP_FEASIBLE ) 1801 { 1802 *feasible = FALSE; 1803 1804 if( !completely ) 1805 return SCIP_OKAY; 1806 } 1807 } 1808 } 1809 1810 /* one final loop over the remaining constraints handlers without constraints */ 1811 while( h < set->nconshdlrs ) 1812 { 1813 if( !SCIPconshdlrNeedsCons(set->conshdlrs[h]) ) 1814 { 1815 SCIP_CALL( SCIPconshdlrCheck(set->conshdlrs[h], blkmem, set, stat, sol, 1816 checkintegrality, checklprows, printreason, completely, &result) ); 1817 1818 if( result != SCIP_FEASIBLE ) 1819 { 1820 *feasible = FALSE; 1821 1822 if( !completely ) 1823 return SCIP_OKAY; 1824 } 1825 } 1826 ++h; 1827 } 1828 1829 return SCIP_OKAY; 1830 } 1831 1832 /** checks primal CIP solution for feasibility 1833 * 1834 * @note The difference between SCIPsolCheck() and SCIPcheckSolOrig() is that modifiable constraints are handled 1835 * differently. There might be some variables which do not have an original counter part (e.g. in 1836 * branch-and-price). Therefore, modifiable constraints can not be double-checked in the original space. 1837 */ 1838 SCIP_RETCODE SCIPsolCheck( 1839 SCIP_SOL* sol, /**< primal CIP solution */ 1840 SCIP_SET* set, /**< global SCIP settings */ 1841 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 1842 BMS_BLKMEM* blkmem, /**< block memory */ 1843 SCIP_STAT* stat, /**< problem statistics */ 1844 SCIP_PROB* prob, /**< transformed problem data */ 1845 SCIP_Bool printreason, /**< Should all reasons of violations be printed? */ 1846 SCIP_Bool completely, /**< Should all violations be checked? */ 1847 SCIP_Bool checkbounds, /**< Should the bounds of the variables be checked? */ 1848 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */ 1849 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */ 1850 SCIP_Bool* feasible /**< stores whether solution is feasible */ 1851 ) 1852 { 1853 SCIP_RESULT result; 1854 int h; 1855 1856 assert(sol != NULL); 1857 assert(!SCIPsolIsOriginal(sol)); 1858 assert(set != NULL); 1859 assert(prob != NULL); 1860 assert(feasible != NULL); 1861 1862 SCIPsetDebugMsg(set, "checking solution with objective value %g (nodenum=%" SCIP_LONGINT_FORMAT ", origin=%d)\n", 1863 sol->obj, sol->nodenum, sol->solorigin); 1864 1865 *feasible = TRUE; 1866 1867 SCIPsolResetViolations(sol); 1868 1869 if( !printreason ) 1870 completely = FALSE; 1871 1872 /* check whether the solution respects the global bounds of the variables */ 1873 if( checkbounds || sol->hasinfval ) 1874 { 1875 int v; 1876 1877 for( v = 0; v < prob->nvars && (*feasible || completely); ++v ) 1878 { 1879 SCIP_VAR* var; 1880 SCIP_Real solval; 1881 1882 var = prob->vars[v]; 1883 solval = SCIPsolGetVal(sol, set, stat, var); 1884 1885 if( solval != SCIP_UNKNOWN ) /*lint !e777*/ 1886 { 1887 SCIP_Real lb; 1888 SCIP_Real ub; 1889 1890 lb = SCIPvarGetLbGlobal(var); 1891 ub = SCIPvarGetUbGlobal(var); 1892 1893 /* if we have to check bound and one of the current bounds is violated */ 1894 if( checkbounds && ((!SCIPsetIsInfinity(set, -lb) && SCIPsetIsFeasLT(set, solval, lb)) 1895 || (!SCIPsetIsInfinity(set, ub) && SCIPsetIsFeasGT(set, solval, ub))) ) 1896 { 1897 *feasible = FALSE; 1898 1899 if( printreason ) 1900 { 1901 SCIPmessagePrintInfo(messagehdlr, "solution value %g violates bounds of <%s>[%g,%g] by %g\n", solval, SCIPvarGetName(var), 1902 SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), MAX(lb - solval, 0.0) + MAX(solval - ub, 0.0)); 1903 } 1904 #ifdef SCIP_DEBUG 1905 else 1906 { 1907 SCIPsetDebugMsgPrint(set, " -> solution value %g violates bounds of <%s>[%g,%g]\n", solval, SCIPvarGetName(var), 1908 SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)); 1909 } 1910 #endif 1911 } 1912 1913 /* check whether there are infinite variable values that lead to an objective value of +infinity */ 1914 if( *feasible && sol->hasinfval ) 1915 { 1916 *feasible = *feasible && (!SCIPsetIsInfinity(set, solval) || SCIPsetIsLE(set, SCIPvarGetUnchangedObj(var), 0.0) ); 1917 *feasible = *feasible && (!SCIPsetIsInfinity(set, -solval) || SCIPsetIsGE(set, SCIPvarGetUnchangedObj(var), 0.0) ); 1918 1919 if( ((SCIPsetIsInfinity(set, solval) && SCIPsetIsGT(set, SCIPvarGetUnchangedObj(var), 0.0)) || (SCIPsetIsInfinity(set, -solval) && SCIPsetIsLT(set, SCIPvarGetUnchangedObj(var), 0.0))) ) 1920 { 1921 if( printreason ) 1922 { 1923 SCIPmessagePrintInfo(messagehdlr, "infinite solution value %g for variable <%s> with obj %g implies objective value +infinity\n", 1924 solval, SCIPvarGetName(var), SCIPvarGetUnchangedObj(var)); 1925 } 1926 #ifdef SCIP_DEBUG 1927 else 1928 { 1929 SCIPsetDebugMsgPrint(set, "infinite solution value %g for variable <%s> with obj %g implies objective value +infinity\n", 1930 solval, SCIPvarGetName(var), SCIPvarGetUnchangedObj(var)); 1931 } 1932 #endif 1933 } 1934 } 1935 } 1936 } 1937 } 1938 1939 /* check whether the solution fulfills all constraints */ 1940 for( h = 0; h < set->nconshdlrs && (*feasible || completely); ++h ) 1941 { 1942 SCIP_CALL( SCIPconshdlrCheck(set->conshdlrs[h], blkmem, set, stat, sol, 1943 checkintegrality, checklprows, printreason, completely, &result) ); 1944 *feasible = *feasible && (result == SCIP_FEASIBLE); 1945 1946 #ifdef SCIP_DEBUG 1947 if( !(*feasible) ) 1948 { 1949 SCIPdebugPrintf(" -> infeasibility detected in constraint handler <%s>\n", 1950 SCIPconshdlrGetName(set->conshdlrs[h])); 1951 } 1952 #endif 1953 } 1954 1955 return SCIP_OKAY; 1956 } 1957 1958 /** try to round given solution */ 1959 SCIP_RETCODE SCIPsolRound( 1960 SCIP_SOL* sol, /**< primal solution */ 1961 SCIP_SET* set, /**< global SCIP settings */ 1962 SCIP_STAT* stat, /**< problem statistics data */ 1963 SCIP_PROB* prob, /**< transformed problem data */ 1964 SCIP_TREE* tree, /**< branch and bound tree */ 1965 SCIP_Bool* success /**< pointer to store whether rounding was successful */ 1966 ) 1967 { 1968 int nvars; 1969 int v; 1970 1971 assert(sol != NULL); 1972 assert(!SCIPsolIsOriginal(sol)); 1973 assert(prob != NULL); 1974 assert(prob->transformed); 1975 assert(success != NULL); 1976 1977 /* round all roundable fractional variables in the corresponding direction as long as no unroundable var was found */ 1978 nvars = prob->nbinvars + prob->nintvars; 1979 for( v = 0; v < nvars; ++v ) 1980 { 1981 SCIP_VAR* var; 1982 SCIP_Real solval; 1983 SCIP_Bool mayrounddown; 1984 SCIP_Bool mayroundup; 1985 1986 var = prob->vars[v]; 1987 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 1988 assert(sol->solorigin != SCIP_SOLORIGIN_LPSOL || SCIPboolarrayGetVal(sol->valid, SCIPvarGetIndex(var)) 1989 || sol->lpcount == stat->lpcount); 1990 solval = solGetArrayVal(sol, var); 1991 1992 /* solutions with unknown entries cannot be rounded */ 1993 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 1994 break; 1995 1996 /* if solution value is already integral with feastol, continue */ 1997 if( SCIPsetIsFeasIntegral(set, solval) ) 1998 continue; 1999 2000 /* get rounding possibilities */ 2001 mayrounddown = SCIPvarMayRoundDown(var); 2002 mayroundup = SCIPvarMayRoundUp(var); 2003 2004 /* choose rounding direction */ 2005 if( mayrounddown && mayroundup ) 2006 { 2007 /* we can round in both directions: round in objective function direction */ 2008 if( SCIPvarGetUnchangedObj(var) >= 0.0 ) 2009 solval = SCIPsetFeasFloor(set, solval); 2010 else 2011 solval = SCIPsetFeasCeil(set, solval); 2012 } 2013 else if( mayrounddown ) 2014 solval = SCIPsetFeasFloor(set, solval); 2015 else if( mayroundup ) 2016 solval = SCIPsetFeasCeil(set, solval); 2017 else 2018 break; 2019 2020 /* store new solution value */ 2021 SCIP_CALL( SCIPsolSetVal(sol, set, stat, tree, var, solval) ); 2022 } 2023 2024 /* check, if rounding was successful */ 2025 *success = (v == nvars); 2026 2027 return SCIP_OKAY; 2028 } 2029 2030 /** updates the solution value sums in variables by adding the value in the given solution */ 2031 void SCIPsolUpdateVarsum( 2032 SCIP_SOL* sol, /**< primal CIP solution */ 2033 SCIP_SET* set, /**< global SCIP settings */ 2034 SCIP_STAT* stat, /**< problem statistics data */ 2035 SCIP_PROB* prob, /**< transformed problem data */ 2036 SCIP_Real weight /**< weight of solution in weighted average */ 2037 ) 2038 { 2039 SCIP_Real solval; 2040 int v; 2041 2042 assert(sol != NULL); 2043 assert(!SCIPsolIsOriginal(sol)); 2044 assert(0.0 <= weight && weight <= 1.0); 2045 2046 for( v = 0; v < prob->nvars; ++v ) 2047 { 2048 assert(prob->vars[v] != NULL); 2049 solval = SCIPsolGetVal(sol, set, stat, prob->vars[v]); 2050 if( solval != SCIP_UNKNOWN ) /*lint !e777*/ 2051 { 2052 prob->vars[v]->primsolavg *= (1.0-weight); 2053 prob->vars[v]->primsolavg += weight*solval; 2054 } 2055 } 2056 } 2057 2058 /** retransforms solution to original problem space */ 2059 SCIP_RETCODE SCIPsolRetransform( 2060 SCIP_SOL* sol, /**< primal CIP solution */ 2061 SCIP_SET* set, /**< global SCIP settings */ 2062 SCIP_STAT* stat, /**< problem statistics data */ 2063 SCIP_PROB* origprob, /**< original problem */ 2064 SCIP_PROB* transprob, /**< transformed problem */ 2065 SCIP_Bool* hasinfval /**< pointer to store whether the solution has infinite values */ 2066 ) 2067 { 2068 SCIP_VAR** transvars; 2069 SCIP_VAR** vars; 2070 SCIP_VAR** activevars; 2071 SCIP_Real* solvals; 2072 SCIP_Real* activevals; 2073 SCIP_Real* transsolvals; 2074 SCIP_Real constant; 2075 int requiredsize; 2076 int ntransvars; 2077 int nactivevars; 2078 int nvars; 2079 int v; 2080 int i; 2081 2082 assert(sol != NULL); 2083 assert(sol->solorigin == SCIP_SOLORIGIN_ZERO); 2084 assert(origprob != NULL); 2085 assert(transprob != NULL); 2086 assert(hasinfval != NULL); 2087 assert(!origprob->transformed); 2088 assert(transprob->transformed); 2089 2090 *hasinfval = FALSE; 2091 2092 /* This method was a performance bottleneck when retransforming a solution during presolving, before flattening the 2093 * aggregation graph. In that case, calling SCIPsolGetVal() on the original variable consumed too much 2094 * time. Therefore, we now first compute the active representation of each original variable using 2095 * SCIPvarGetActiveRepresentatives(), which is much faster, and sum up the solution values of the active variables by 2096 * hand for each original variable. 2097 */ 2098 vars = origprob->vars; 2099 nvars = origprob->nvars; 2100 transvars = transprob->vars; 2101 ntransvars = transprob->nvars; 2102 2103 /* allocate temporary memory for getting the active representation of the original variables, buffering the solution 2104 * values of all active variables and storing the original solution values 2105 */ 2106 SCIP_CALL( SCIPsetAllocBufferArray(set, &transsolvals, ntransvars + 1) ); 2107 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, ntransvars + 1) ); 2108 SCIP_CALL( SCIPsetAllocBufferArray(set, &activevals, ntransvars + 1) ); 2109 SCIP_CALL( SCIPsetAllocBufferArray(set, &solvals, nvars) ); 2110 assert(transsolvals != NULL); /* for flexelint */ 2111 assert(solvals != NULL); /* for flexelint */ 2112 2113 /* get the solution values of all active variables */ 2114 for( v = 0; v < ntransvars; ++v ) 2115 { 2116 transsolvals[v] = SCIPsolGetVal(sol, set, stat, transvars[v]); 2117 } 2118 2119 /* get the solution in original problem variables */ 2120 for( v = 0; v < nvars; ++v ) 2121 { 2122 activevars[0] = vars[v]; 2123 activevals[0] = 1.0; 2124 nactivevars = 1; 2125 constant = 0.0; 2126 2127 /* get active representation of the original variable */ 2128 SCIP_CALL( SCIPvarGetActiveRepresentatives(set, activevars, activevals, &nactivevars, ntransvars + 1, &constant, 2129 &requiredsize, TRUE) ); 2130 assert(requiredsize <= ntransvars); 2131 2132 /* compute solution value of the original variable */ 2133 solvals[v] = constant; 2134 for( i = 0; i < nactivevars; ++i ) 2135 { 2136 assert(0 <= SCIPvarGetProbindex(activevars[i]) && SCIPvarGetProbindex(activevars[i]) < ntransvars); 2137 assert(!SCIPsetIsInfinity(set, -solvals[v]) || !SCIPsetIsInfinity(set, activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])])); 2138 assert(!SCIPsetIsInfinity(set, solvals[v]) || !SCIPsetIsInfinity(set, -activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])])); 2139 solvals[v] += activevals[i] * transsolvals[SCIPvarGetProbindex(activevars[i])]; 2140 } 2141 2142 if( SCIPsetIsInfinity(set, solvals[v]) ) 2143 { 2144 solvals[v] = SCIPsetInfinity(set); 2145 *hasinfval = TRUE; 2146 } 2147 else if( SCIPsetIsInfinity(set, -solvals[v]) ) 2148 { 2149 solvals[v] = -SCIPsetInfinity(set); 2150 *hasinfval = TRUE; 2151 } 2152 } 2153 2154 /* clear the solution and convert it into original space */ 2155 SCIP_CALL( solClearArrays(sol) ); 2156 sol->solorigin = SCIP_SOLORIGIN_ORIGINAL; 2157 sol->obj = origprob->objoffset; 2158 2159 /* reinsert the values of the original variables */ 2160 for( v = 0; v < nvars; ++v ) 2161 { 2162 assert(SCIPvarGetUnchangedObj(vars[v]) == SCIPvarGetObj(vars[v])); /*lint !e777*/ 2163 2164 if( solvals[v] != 0.0 ) 2165 { 2166 SCIP_CALL( solSetArrayVal(sol, set, vars[v], solvals[v]) ); 2167 if( solvals[v] != SCIP_UNKNOWN ) /*lint !e777*/ 2168 sol->obj += SCIPvarGetUnchangedObj(vars[v]) * solvals[v]; 2169 } 2170 } 2171 2172 /**@todo remember the variables without original counterpart (priced variables) in the solution */ 2173 2174 /* free temporary memory */ 2175 SCIPsetFreeBufferArray(set, &solvals); 2176 SCIPsetFreeBufferArray(set, &activevals); 2177 SCIPsetFreeBufferArray(set, &activevars); 2178 SCIPsetFreeBufferArray(set, &transsolvals); 2179 2180 return SCIP_OKAY; 2181 } 2182 2183 /** recomputes the objective value of an original solution, e.g., when transferring solutions 2184 * from the solution pool (objective coefficients might have changed in the meantime) 2185 */ 2186 void SCIPsolRecomputeObj( 2187 SCIP_SOL* sol, /**< primal CIP solution */ 2188 SCIP_SET* set, /**< global SCIP settings */ 2189 SCIP_STAT* stat, /**< problem statistics data */ 2190 SCIP_PROB* origprob /**< original problem */ 2191 ) 2192 { 2193 SCIP_VAR** vars; 2194 SCIP_Real solval; 2195 int nvars; 2196 int v; 2197 2198 assert(sol != NULL); 2199 assert(SCIPsolIsOriginal(sol)); 2200 assert(origprob != NULL); 2201 2202 vars = origprob->vars; 2203 nvars = origprob->nvars; 2204 2205 /* recompute the objective value */ 2206 sol->obj = SCIPprobGetObjoffset(origprob); 2207 for( v = 0; v < nvars; ++v ) 2208 { 2209 solval = SCIPsolGetVal(sol, set, stat, vars[v]); 2210 if( solval != 0.0 && solval != SCIP_UNKNOWN ) /*lint !e777*/ 2211 { 2212 sol->obj += SCIPvarGetUnchangedObj(vars[v]) * solval; 2213 } 2214 } 2215 2216 if( SCIPsetIsInfinity(set, -sol->obj) ) 2217 sol->obj = -SCIPsetInfinity(set); 2218 } 2219 2220 /** returns whether the given solutions are equal */ 2221 SCIP_Bool SCIPsolsAreEqual( 2222 SCIP_SOL* sol1, /**< first primal CIP solution */ 2223 SCIP_SOL* sol2, /**< second primal CIP solution */ 2224 SCIP_SET* set, /**< global SCIP settings */ 2225 SCIP_STAT* stat, /**< problem statistics data */ 2226 SCIP_PROB* origprob, /**< original problem */ 2227 SCIP_PROB* transprob /**< transformed problem after presolve, or NULL if both solution are 2228 * defined in the original problem space */ 2229 ) 2230 { 2231 SCIP_PROB* prob; 2232 SCIP_Bool infobjs; 2233 SCIP_Real obj1; 2234 SCIP_Real obj2; 2235 int v; 2236 2237 assert(sol1 != NULL); 2238 assert(sol2 != NULL); 2239 assert((SCIPsolIsOriginal(sol1) && SCIPsolIsOriginal(sol2)) || transprob != NULL); 2240 2241 /* if both solutions are original or both are transformed, take the objective values stored in the solutions */ 2242 if( SCIPsolIsOriginal(sol1) == SCIPsolIsOriginal(sol2) ) 2243 { 2244 obj1 = sol1->obj; 2245 obj2 = sol2->obj; 2246 } 2247 /* one solution is original and the other not, so we have to get for both the objective in the transformed problem */ 2248 else 2249 { 2250 obj1 = SCIPsolGetObj(sol1, set, transprob, origprob); 2251 obj2 = SCIPsolGetObj(sol2, set, transprob, origprob); 2252 } 2253 2254 /* solutions with different objective values cannot be the same; we consider two infinite objective values with the 2255 * same sign always to be different 2256 */ 2257 infobjs = (SCIPsetIsInfinity(set, obj1) && SCIPsetIsInfinity(set, obj2)) 2258 || (SCIPsetIsInfinity(set, -obj1) && SCIPsetIsInfinity(set, -obj2)); 2259 if( !infobjs && !SCIPsetIsEQ(set, obj1, obj2) ) 2260 return FALSE; 2261 2262 /* if one of the solutions is defined in the original space, the comparison has to be performed in the original 2263 * space 2264 */ 2265 prob = transprob; 2266 if( SCIPsolIsOriginal(sol1) || SCIPsolIsOriginal(sol2) ) 2267 prob = origprob; 2268 assert(prob != NULL); 2269 2270 /* compare each variable value */ 2271 for( v = 0; v < prob->nvars; ++v ) 2272 { 2273 SCIP_Real val1; 2274 SCIP_Real val2; 2275 2276 val1 = SCIPsolGetVal(sol1, set, stat, prob->vars[v]); 2277 val2 = SCIPsolGetVal(sol2, set, stat, prob->vars[v]); 2278 if( !SCIPsetIsEQ(set, val1, val2) ) 2279 return FALSE; 2280 } 2281 2282 return TRUE; 2283 } 2284 2285 /** outputs non-zero elements of solution to file stream */ 2286 SCIP_RETCODE SCIPsolPrint( 2287 SCIP_SOL* sol, /**< primal CIP solution */ 2288 SCIP_SET* set, /**< global SCIP settings */ 2289 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 2290 SCIP_STAT* stat, /**< problem statistics data */ 2291 SCIP_PROB* prob, /**< problem data (original or transformed) */ 2292 SCIP_PROB* transprob, /**< transformed problem data or NULL (to display priced variables) */ 2293 FILE* file, /**< output file (or NULL for standard output) */ 2294 SCIP_Bool mipstart, /**< should only discrete variables be printed? */ 2295 SCIP_Bool printzeros /**< should variables set to zero be printed? */ 2296 ) 2297 { 2298 SCIP_Real solval; 2299 int v; 2300 2301 assert(sol != NULL); 2302 assert(prob != NULL); 2303 assert(SCIPsolIsOriginal(sol) || prob->transformed || transprob != NULL); 2304 assert(!mipstart || !SCIPsolIsPartial(sol)); 2305 2306 /* display variables of problem data */ 2307 for( v = 0; v < prob->nfixedvars; ++v ) 2308 { 2309 assert(prob->fixedvars[v] != NULL); 2310 2311 /* skip non-discrete variables in a mip start */ 2312 if( mipstart && !SCIPvarIsIntegral(prob->fixedvars[v]) ) 2313 continue; 2314 2315 solval = SCIPsolGetVal(sol, set, stat, prob->fixedvars[v]); 2316 if( printzeros || mipstart 2317 || (sol->solorigin != SCIP_SOLORIGIN_PARTIAL && !SCIPsetIsZero(set, solval)) 2318 || (sol->solorigin == SCIP_SOLORIGIN_PARTIAL && solval != SCIP_UNKNOWN) ) /*lint !e777*/ 2319 { 2320 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->fixedvars[v])); 2321 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2322 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2323 else if( SCIPsetIsInfinity(set, solval) ) 2324 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2325 else if( SCIPsetIsInfinity(set, -solval) ) 2326 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2327 else 2328 SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval); 2329 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->fixedvars[v])); 2330 } 2331 } 2332 2333 for( v = 0; v < prob->nvars; ++v ) 2334 { 2335 assert(prob->vars[v] != NULL); 2336 2337 /* skip non-discrete variables in a mip start */ 2338 if( mipstart && !SCIPvarIsIntegral(prob->vars[v]) ) 2339 continue; 2340 2341 solval = SCIPsolGetVal(sol, set, stat, prob->vars[v]); 2342 if( printzeros || mipstart 2343 || (sol->solorigin != SCIP_SOLORIGIN_PARTIAL && !SCIPsetIsZero(set, solval)) 2344 || (sol->solorigin == SCIP_SOLORIGIN_PARTIAL && solval != SCIP_UNKNOWN) ) /*lint !e777*/ 2345 { 2346 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->vars[v])); 2347 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2348 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2349 else if( SCIPsetIsInfinity(set, solval) ) 2350 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2351 else if( SCIPsetIsInfinity(set, -solval) ) 2352 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2353 else 2354 SCIPmessageFPrintInfo(messagehdlr, file, " %20.15g", solval); 2355 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->vars[v])); 2356 } 2357 } 2358 2359 /* display additional priced variables (if given problem data is original problem); consider these variables only 2360 * if there is at least one active pricer, otherwise we might print variables that have been added by, e.g., the 2361 * dual sparsify presolver (see #2946) 2362 */ 2363 if( !prob->transformed && !SCIPsolIsOriginal(sol) && set->nactivepricers > 0 ) 2364 { 2365 assert(transprob != NULL); 2366 for( v = 0; v < transprob->nfixedvars; ++v ) 2367 { 2368 assert(transprob->fixedvars[v] != NULL); 2369 if( SCIPvarIsTransformedOrigvar(transprob->fixedvars[v]) ) 2370 continue; 2371 2372 /* skip non-discrete variables in a mip start */ 2373 if( mipstart && !SCIPvarIsIntegral(transprob->fixedvars[v]) ) 2374 continue; 2375 2376 solval = SCIPsolGetVal(sol, set, stat, transprob->fixedvars[v]); 2377 if( printzeros || mipstart || !SCIPsetIsZero(set, solval) ) 2378 { 2379 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->fixedvars[v])); 2380 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2381 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2382 else if( SCIPsetIsInfinity(set, solval) ) 2383 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2384 else if( SCIPsetIsInfinity(set, -solval) ) 2385 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2386 else 2387 SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval); 2388 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->fixedvars[v])); 2389 } 2390 } 2391 for( v = 0; v < transprob->nvars; ++v ) 2392 { 2393 assert(transprob->vars[v] != NULL); 2394 if( SCIPvarIsTransformedOrigvar(transprob->vars[v]) ) 2395 continue; 2396 2397 /* skip non-discrete variables in a mip start */ 2398 if( mipstart && !SCIPvarIsIntegral(transprob->vars[v]) ) 2399 continue; 2400 2401 solval = SCIPsolGetVal(sol, set, stat, transprob->vars[v]); 2402 if( printzeros || !SCIPsetIsZero(set, solval) ) 2403 { 2404 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->vars[v])); 2405 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2406 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2407 else if( SCIPsetIsInfinity(set, solval) ) 2408 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2409 else if( SCIPsetIsInfinity(set, -solval) ) 2410 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2411 else 2412 SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval); 2413 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->vars[v])); 2414 } 2415 } 2416 } 2417 2418 return SCIP_OKAY; 2419 } 2420 2421 /** outputs non-zero elements of solution representing a ray to file stream */ 2422 SCIP_RETCODE SCIPsolPrintRay( 2423 SCIP_SOL* sol, /**< primal CIP solution */ 2424 SCIP_SET* set, /**< global SCIP settings */ 2425 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 2426 SCIP_STAT* stat, /**< problem statistics data */ 2427 SCIP_PROB* prob, /**< problem data (original or transformed) */ 2428 SCIP_PROB* transprob, /**< transformed problem data or NULL (to display priced variables) */ 2429 FILE* file, /**< output file (or NULL for standard output) */ 2430 SCIP_Bool printzeros /**< should variables set to zero be printed? */ 2431 ) 2432 { 2433 SCIP_Real solval; 2434 int v; 2435 2436 assert(sol != NULL); 2437 assert(prob != NULL); 2438 assert(SCIPsolIsOriginal(sol) || prob->transformed || transprob != NULL); 2439 2440 /* display variables of problem data */ 2441 for( v = 0; v < prob->nfixedvars; ++v ) 2442 { 2443 assert(prob->fixedvars[v] != NULL); 2444 solval = SCIPsolGetRayVal(sol, set, stat, prob->fixedvars[v]); 2445 if( printzeros || !SCIPsetIsZero(set, solval) ) 2446 { 2447 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->fixedvars[v])); 2448 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2449 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2450 else if( SCIPsetIsInfinity(set, solval) ) 2451 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2452 else if( SCIPsetIsInfinity(set, -solval) ) 2453 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2454 else 2455 SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval); 2456 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->fixedvars[v])); 2457 } 2458 } 2459 for( v = 0; v < prob->nvars; ++v ) 2460 { 2461 assert(prob->vars[v] != NULL); 2462 solval = SCIPsolGetRayVal(sol, set, stat, prob->vars[v]); 2463 if( printzeros || !SCIPsetIsZero(set, solval) ) 2464 { 2465 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(prob->vars[v])); 2466 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2467 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2468 else if( SCIPsetIsInfinity(set, solval) ) 2469 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2470 else if( SCIPsetIsInfinity(set, -solval) ) 2471 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2472 else 2473 SCIPmessageFPrintInfo(messagehdlr, file, " %20.15g", solval); 2474 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(prob->vars[v])); 2475 } 2476 } 2477 2478 /* display additional priced variables (if given problem data is original problem) */ 2479 if( !prob->transformed && !SCIPsolIsOriginal(sol) ) 2480 { 2481 assert(transprob != NULL); 2482 for( v = 0; v < transprob->nfixedvars; ++v ) 2483 { 2484 assert(transprob->fixedvars[v] != NULL); 2485 if( SCIPvarIsTransformedOrigvar(transprob->fixedvars[v]) ) 2486 continue; 2487 2488 solval = SCIPsolGetRayVal(sol, set, stat, transprob->fixedvars[v]); 2489 if( printzeros || !SCIPsetIsZero(set, solval) ) 2490 { 2491 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->fixedvars[v])); 2492 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2493 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2494 else if( SCIPsetIsInfinity(set, solval) ) 2495 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2496 else if( SCIPsetIsInfinity(set, -solval) ) 2497 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2498 else 2499 SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval); 2500 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->fixedvars[v])); 2501 } 2502 } 2503 for( v = 0; v < transprob->nvars; ++v ) 2504 { 2505 assert(transprob->vars[v] != NULL); 2506 if( SCIPvarIsTransformedOrigvar(transprob->vars[v]) ) 2507 continue; 2508 2509 solval = SCIPsolGetRayVal(sol, set, stat, transprob->vars[v]); 2510 if( printzeros || !SCIPsetIsZero(set, solval) ) 2511 { 2512 SCIPmessageFPrintInfo(messagehdlr, file, "%-32s", SCIPvarGetName(transprob->vars[v])); 2513 if( solval == SCIP_UNKNOWN ) /*lint !e777*/ 2514 SCIPmessageFPrintInfo(messagehdlr, file, " unknown"); 2515 else if( SCIPsetIsInfinity(set, solval) ) 2516 SCIPmessageFPrintInfo(messagehdlr, file, " +infinity"); 2517 else if( SCIPsetIsInfinity(set, -solval) ) 2518 SCIPmessageFPrintInfo(messagehdlr, file, " -infinity"); 2519 else 2520 SCIPmessageFPrintInfo(messagehdlr, file, " % 20.15g", solval); 2521 SCIPmessageFPrintInfo(messagehdlr, file, " \t(obj:%.15g)\n", SCIPvarGetUnchangedObj(transprob->vars[v])); 2522 } 2523 } 2524 } 2525 2526 return SCIP_OKAY; 2527 } 2528 2529 /* 2530 * methods for accumulated numerical violations of a solution 2531 */ 2532 2533 /** reset violations of a solution */ 2534 void SCIPsolResetViolations( 2535 SCIP_SOL* sol /**< primal CIP solution */ 2536 ) 2537 { 2538 assert(sol != NULL); 2539 2540 sol->viol.absviolbounds = 0.0; 2541 sol->viol.relviolbounds = 0.0; 2542 sol->viol.absviolintegrality = 0.0; 2543 sol->viol.absviollprows = 0.0; 2544 sol->viol.relviollprows = 0.0; 2545 sol->viol.absviolcons = 0.0; 2546 sol->viol.relviolcons = 0.0; 2547 } 2548 2549 /** update integrality violation of a solution */ 2550 void SCIPsolUpdateIntegralityViolation( 2551 SCIP_SOL* sol, /**< primal CIP solution */ 2552 SCIP_Real absviolintegrality /**< absolute violation of integrality */ 2553 ) 2554 { 2555 assert(sol != NULL); 2556 2557 sol->viol.absviolintegrality = MAX(sol->viol.absviolintegrality, absviolintegrality); 2558 } 2559 2560 /** update bound violation of a solution */ 2561 void SCIPsolUpdateBoundViolation( 2562 SCIP_SOL* sol, /**< primal CIP solution */ 2563 SCIP_Real absviolbounds, /**< absolute violation of bounds */ 2564 SCIP_Real relviolbounds /**< relative violation of bounds */ 2565 ) 2566 { 2567 assert(sol != NULL); 2568 2569 sol->viol.absviolbounds = MAX(sol->viol.absviolbounds, absviolbounds); 2570 sol->viol.relviolbounds = MAX(sol->viol.relviolbounds, relviolbounds); 2571 } 2572 2573 /** update LP row violation of a solution */ 2574 void SCIPsolUpdateLPRowViolation( 2575 SCIP_SOL* sol, /**< primal CIP solution */ 2576 SCIP_Real absviollprows, /**< absolute violation of LP rows */ 2577 SCIP_Real relviollprows /**< relative violation of LP rows */ 2578 ) 2579 { 2580 assert(sol != NULL); 2581 2582 sol->viol.absviollprows = MAX(sol->viol.absviollprows, absviollprows); 2583 sol->viol.relviollprows = MAX(sol->viol.relviollprows, relviollprows); 2584 } 2585 2586 /** update constraint violation of a solution */ 2587 void SCIPsolUpdateConsViolation( 2588 SCIP_SOL* sol, /**< primal CIP solution */ 2589 SCIP_Real absviolcons, /**< absolute violation of constraint */ 2590 SCIP_Real relviolcons /**< relative violation of constraint */ 2591 ) 2592 { 2593 assert(sol != NULL); 2594 2595 sol->viol.absviolcons = MAX(sol->viol.absviolcons, absviolcons); 2596 sol->viol.relviolcons = MAX(sol->viol.relviolcons, relviolcons); 2597 } 2598 2599 /** update violation of a constraint that is represented in the LP */ 2600 void SCIPsolUpdateLPConsViolation( 2601 SCIP_SOL* sol, /**< primal CIP solution */ 2602 SCIP_Real absviol, /**< absolute violation of constraint */ 2603 SCIP_Real relviol /**< relative violation of constraint */ 2604 ) 2605 { 2606 assert(sol != NULL); 2607 2608 SCIPsolUpdateConsViolation(sol, absviol, relviol); 2609 SCIPsolUpdateLPRowViolation(sol, absviol, relviol); 2610 } 2611 2612 /** get maximum absolute bound violation of solution */ 2613 SCIP_Real SCIPsolGetAbsBoundViolation( 2614 SCIP_SOL* sol /**< primal CIP solution */ 2615 ) 2616 { 2617 assert(sol != NULL); 2618 2619 return sol->viol.absviolbounds; 2620 } 2621 2622 /** get maximum relative bound violation of solution */ 2623 SCIP_Real SCIPsolGetRelBoundViolation( 2624 SCIP_SOL* sol /**< primal CIP solution */ 2625 ) 2626 { 2627 assert(sol != NULL); 2628 2629 return sol->viol.relviolbounds; 2630 } 2631 2632 /** get maximum absolute integrality violation of solution */ 2633 SCIP_Real SCIPsolGetAbsIntegralityViolation( 2634 SCIP_SOL* sol /**< primal CIP solution */ 2635 ) 2636 { 2637 assert(sol != NULL); 2638 2639 return sol->viol.absviolintegrality; 2640 } 2641 2642 /** get maximum absolute LP row violation of solution */ 2643 SCIP_Real SCIPsolGetAbsLPRowViolation( 2644 SCIP_SOL* sol /**< primal CIP solution */ 2645 ) 2646 { 2647 assert(sol != NULL); 2648 2649 return sol->viol.absviollprows; 2650 } 2651 2652 /** get maximum relative LP row violation of solution */ 2653 SCIP_Real SCIPsolGetRelLPRowViolation( 2654 SCIP_SOL* sol /**< primal CIP solution */ 2655 ) 2656 { 2657 assert(sol != NULL); 2658 2659 return sol->viol.relviollprows; 2660 } 2661 2662 /** get maximum absolute constraint violation of solution */ 2663 SCIP_Real SCIPsolGetAbsConsViolation( 2664 SCIP_SOL* sol /**< primal CIP solution */ 2665 ) 2666 { 2667 assert(sol != NULL); 2668 2669 return sol->viol.absviolcons; 2670 } 2671 2672 /** get maximum relative constraint violation of solution */ 2673 SCIP_Real SCIPsolGetRelConsViolation( 2674 SCIP_SOL* sol /**< primal CIP solution */ 2675 ) 2676 { 2677 assert(sol != NULL); 2678 2679 return sol->viol.relviolcons; 2680 } 2681 2682 /* 2683 * simple functions implemented as defines 2684 */ 2685 2686 /* In debug mode, the following methods are implemented as function calls to ensure 2687 * type validity. 2688 * In optimized mode, the methods are implemented as defines to improve performance. 2689 * However, we want to have them in the library anyways, so we have to undef the defines. 2690 */ 2691 2692 #undef SCIPsolGetOrigin 2693 #undef SCIPsolIsOriginal 2694 #undef SCIPsolGetOrigObj 2695 #undef SCIPsolGetTime 2696 #undef SCIPsolGetNodenum 2697 #undef SCIPsolGetRunnum 2698 #undef SCIPsolGetDepth 2699 #undef SCIPsolGetHeur 2700 #undef SCIPsolGetRelax 2701 #undef SCIPsolOrigAddObjval 2702 #undef SCIPsolGetPrimalIndex 2703 #undef SCIPsolSetPrimalIndex 2704 #undef SCIPsolGetIndex 2705 #undef SCIPsolGetType 2706 #undef SCIPsolSetLPRelaxation 2707 #undef SCIPsolSetStrongbranching 2708 #undef SCIPsolSetPseudo 2709 2710 /** gets origin of solution */ 2711 SCIP_SOLORIGIN SCIPsolGetOrigin( 2712 SCIP_SOL* sol /**< primal CIP solution */ 2713 ) 2714 { 2715 assert(sol != NULL); 2716 2717 return sol->solorigin; 2718 } 2719 2720 /** returns whether the given solution is defined on original variables */ 2721 SCIP_Bool SCIPsolIsOriginal( 2722 SCIP_SOL* sol /**< primal CIP solution */ 2723 ) 2724 { 2725 assert(sol != NULL); 2726 2727 return (sol->solorigin == SCIP_SOLORIGIN_ORIGINAL || sol->solorigin == SCIP_SOLORIGIN_PARTIAL); 2728 } 2729 2730 /** returns whether the given solution is defined on original variables and containes unknown solution values */ 2731 SCIP_Bool SCIPsolIsPartial( 2732 SCIP_SOL* sol /**< primal CIP solution */ 2733 ) 2734 { 2735 assert(sol != NULL); 2736 2737 return (sol->solorigin == SCIP_SOLORIGIN_PARTIAL); 2738 } 2739 2740 /** gets objective value of primal CIP solution which lives in the original problem space */ 2741 SCIP_Real SCIPsolGetOrigObj( 2742 SCIP_SOL* sol /**< primal CIP solution */ 2743 ) 2744 { 2745 assert(sol != NULL); 2746 assert(SCIPsolIsOriginal(sol)); 2747 2748 return sol->obj; 2749 } 2750 2751 /** adds value to the objective value of a given original primal CIP solution */ 2752 void SCIPsolOrigAddObjval( 2753 SCIP_SOL* sol, /**< primal CIP solution */ 2754 SCIP_Real addval /**< offset value to add */ 2755 ) 2756 { 2757 assert(sol != NULL); 2758 assert(sol->solorigin == SCIP_SOLORIGIN_ORIGINAL); 2759 2760 sol->obj += addval; 2761 } 2762 2763 /** gets clock time, when this solution was found */ 2764 SCIP_Real SCIPsolGetTime( 2765 SCIP_SOL* sol /**< primal CIP solution */ 2766 ) 2767 { 2768 assert(sol != NULL); 2769 2770 return sol->time; 2771 } 2772 2773 /** gets branch and bound run number, where this solution was found */ 2774 int SCIPsolGetRunnum( 2775 SCIP_SOL* sol /**< primal CIP solution */ 2776 ) 2777 { 2778 assert(sol != NULL); 2779 2780 return sol->runnum; 2781 } 2782 2783 /** gets node number, where this solution was found */ 2784 SCIP_Longint SCIPsolGetNodenum( 2785 SCIP_SOL* sol /**< primal CIP solution */ 2786 ) 2787 { 2788 assert(sol != NULL); 2789 2790 return sol->nodenum; 2791 } 2792 2793 /** gets node's depth, where this solution was found */ 2794 int SCIPsolGetDepth( 2795 SCIP_SOL* sol /**< primal CIP solution */ 2796 ) 2797 { 2798 assert(sol != NULL); 2799 2800 return sol->depth; 2801 } 2802 2803 /** gets heuristic, that found this solution or NULL if solution has type different than SCIP_SOLTYPE_HEUR */ 2804 SCIP_HEUR* SCIPsolGetHeur( 2805 SCIP_SOL* sol /**< primal CIP solution */ 2806 ) 2807 { 2808 assert(sol != NULL); 2809 2810 return sol->type == SCIP_SOLTYPE_HEUR ? sol->creator.heur : NULL; 2811 } 2812 2813 /** gets current position of solution in array of existing solutions of primal data */ 2814 int SCIPsolGetPrimalIndex( 2815 SCIP_SOL* sol /**< primal CIP solution */ 2816 ) 2817 { 2818 assert(sol != NULL); 2819 2820 return sol->primalindex; 2821 } 2822 2823 /** sets current position of solution in array of existing solutions of primal data */ 2824 void SCIPsolSetPrimalIndex( 2825 SCIP_SOL* sol, /**< primal CIP solution */ 2826 int primalindex /**< new primal index of solution */ 2827 ) 2828 { 2829 assert(sol != NULL); 2830 2831 sol->primalindex = primalindex; 2832 } 2833 2834 /** returns unique index of given solution */ 2835 int SCIPsolGetIndex( 2836 SCIP_SOL* sol /**< primal CIP solution */ 2837 ) 2838 { 2839 assert(sol != NULL); 2840 2841 return sol->index; 2842 } 2843 2844 /** informs the solution that it now belongs to the given primal heuristic. For convenience and backwards compatibility, 2845 * the method accepts NULL as input for \p heur, in which case the solution type is set to SCIP_SOLTYPE_LPRELAX. 2846 * 2847 * @note Relaxation handlers should use SCIPsolSetRelax() instead. 2848 */ 2849 void SCIPsolSetHeur( 2850 SCIP_SOL* sol, /**< primal CIP solution */ 2851 SCIP_HEUR* heur /**< primal heuristic that found the solution, or NULL for LP solutions */ 2852 ) 2853 { 2854 assert(sol != NULL); 2855 2856 if( heur == NULL ) 2857 SCIPsolSetLPRelaxation(sol); 2858 else 2859 { 2860 sol->type = SCIP_SOLTYPE_HEUR; 2861 sol->creator.heur = heur; 2862 } 2863 } 2864 2865 /** gets information if solution was found by the LP, a primal heuristic, or a custom relaxator */ 2866 SCIP_SOLTYPE SCIPsolGetType( 2867 SCIP_SOL* sol /**< primal CIP solution */ 2868 ) 2869 { 2870 assert(sol != NULL); 2871 2872 return sol->type; 2873 } 2874 2875 /** gets relaxation handler that found this solution, or NULL if solution has different type than SCIP_SOLTYPE_RELAX */ 2876 SCIP_RELAX* SCIPsolGetRelax( 2877 SCIP_SOL* sol /**< primal CIP solution */ 2878 ) 2879 { 2880 assert(sol != NULL); 2881 2882 return sol->type == SCIP_SOLTYPE_RELAX ? sol->creator.relax : NULL; 2883 } 2884 2885 /** informs the solution that it now belongs to the given relaxation handler */ 2886 void SCIPsolSetRelax( 2887 SCIP_SOL* sol, /**< primal CIP solution */ 2888 SCIP_RELAX* relax /**< relaxator that found the solution */ 2889 ) 2890 { 2891 assert(sol != NULL); 2892 assert(relax != NULL); 2893 2894 sol->type = SCIP_SOLTYPE_RELAX; 2895 sol->creator.relax = relax; 2896 } 2897 2898 /** informs the solution that it is an LP relaxation solution */ 2899 void SCIPsolSetLPRelaxation( 2900 SCIP_SOL* sol /**< primal CIP solution */ 2901 ) 2902 { 2903 assert(sol != NULL); 2904 2905 sol->type = SCIP_SOLTYPE_LPRELAX; 2906 } 2907 2908 /** informs the solution that it is a solution found during strong branching */ 2909 void SCIPsolSetStrongbranching( 2910 SCIP_SOL* sol /**< primal CIP solution */ 2911 ) 2912 { 2913 assert(sol != NULL); 2914 2915 sol->type = SCIP_SOLTYPE_STRONGBRANCH; 2916 } 2917 2918 /** informs the solution that it originates from a pseudo solution */ 2919 void SCIPsolSetPseudo( 2920 SCIP_SOL* sol /**< primal CIP solution */ 2921 ) 2922 { 2923 assert(sol != NULL); 2924 2925 sol->type = SCIP_SOLTYPE_PSEUDO; 2926 } 2927 2928