1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the program and library */ 4 /* SCIP --- Solving Constraint Integer Programs */ 5 /* */ 6 /* Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB) */ 7 /* */ 8 /* Licensed under the Apache License, Version 2.0 (the "License"); */ 9 /* you may not use this file except in compliance with the License. */ 10 /* You may obtain a copy of the License at */ 11 /* */ 12 /* http://www.apache.org/licenses/LICENSE-2.0 */ 13 /* */ 14 /* Unless required by applicable law or agreed to in writing, software */ 15 /* distributed under the License is distributed on an "AS IS" BASIS, */ 16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ 17 /* See the License for the specific language governing permissions and */ 18 /* limitations under the License. */ 19 /* */ 20 /* You should have received a copy of the Apache-2.0 license */ 21 /* along with SCIP; see the file LICENSE. If not visit scipopt.org. */ 22 /* */ 23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 24 25 /**@file scip_cut.c 26 * @ingroup OTHER_CFILES 27 * @brief public methods for cuts and aggregation rows 28 * @author Tobias Achterberg 29 * @author Timo Berthold 30 * @author Gerald Gamrath 31 * @author Leona Gottwald 32 * @author Stefan Heinz 33 * @author Gregor Hendel 34 * @author Thorsten Koch 35 * @author Alexander Martin 36 * @author Marc Pfetsch 37 * @author Michael Winkler 38 * @author Kati Wolter 39 * 40 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE 41 */ 42 43 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 44 45 #include "scip/cutpool.h" 46 #include "scip/debug.h" 47 #include "scip/lp.h" 48 #include "scip/prob.h" 49 #include "scip/pub_cutpool.h" 50 #include "scip/pub_lp.h" 51 #include "scip/pub_message.h" 52 #include "scip/scip_conflict.h" 53 #include "scip/scip_cut.h" 54 #include "scip/scip_numerics.h" 55 #include "scip/scip_tree.h" 56 #include "scip/sepastore.h" 57 #include "scip/set.h" 58 #include "scip/solve.h" 59 #include "scip/struct_lp.h" 60 #include "scip/struct_mem.h" 61 #include "scip/struct_scip.h" 62 #include "scip/struct_set.h" 63 #include "scip/tree.h" 64 65 /** returns row's cutoff distance in the direction of the given primal solution 66 * 67 * @return the cutoff distance of the cut with respect to the LP solution in the direction of the given primal solution 68 * 69 * @pre This method can be called if @p scip is in one of the following stages: 70 * - \ref SCIP_STAGE_SOLVING 71 */ 72 SCIP_Real SCIPgetCutLPSolCutoffDistance( 73 SCIP* scip, /**< SCIP data structure */ 74 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */ 75 SCIP_ROW* cut /**< separated cut */ 76 ) 77 { 78 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetCutLPSolCutoffDistance", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 79 80 assert(sol != NULL); 81 82 return SCIProwGetLPSolCutoffDistance(cut, scip->set, scip->stat, sol, scip->lp); 83 } 84 85 /** returns efficacy of the cut with respect to the given primal solution or the current LP solution: 86 * e = -feasibility/norm 87 * 88 * @return the efficacy of the cut with respect to the given primal solution or the current LP solution: 89 * e = -feasibility/norm 90 * 91 * @pre This method can be called if @p scip is in one of the following stages: 92 * - \ref SCIP_STAGE_SOLVING 93 */ 94 SCIP_Real SCIPgetCutEfficacy( 95 SCIP* scip, /**< SCIP data structure */ 96 SCIP_SOL* sol, /**< primal CIP solution, or NULL for current LP solution */ 97 SCIP_ROW* cut /**< separated cut */ 98 ) 99 { 100 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetCutEfficacy", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 101 102 if( sol == NULL ) 103 return SCIProwGetLPEfficacy(cut, scip->set, scip->stat, scip->lp); 104 else 105 return SCIProwGetSolEfficacy(cut, scip->set, scip->stat, sol); 106 } 107 108 /** returns whether the cut's efficacy with respect to the given primal solution or the current LP solution is greater 109 * than the minimal cut efficacy 110 * 111 * @return TRUE if the cut's efficacy with respect to the given primal solution or the current LP solution is greater 112 * than the minimal cut efficacy, otherwise FALSE 113 * 114 * @pre This method can be called if @p scip is in one of the following stages: 115 * - \ref SCIP_STAGE_SOLVING 116 */ 117 SCIP_Bool SCIPisCutEfficacious( 118 SCIP* scip, /**< SCIP data structure */ 119 SCIP_SOL* sol, /**< primal CIP solution, or NULL for current LP solution */ 120 SCIP_ROW* cut /**< separated cut */ 121 ) 122 { 123 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisCutEfficacious", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 124 125 if( sol == NULL ) 126 return SCIProwIsLPEfficacious(cut, scip->set, scip->stat, scip->lp, (SCIPtreeGetCurrentDepth(scip->tree) == 0)); 127 else 128 return SCIProwIsSolEfficacious(cut, scip->set, scip->stat, sol, (SCIPtreeGetCurrentDepth(scip->tree) == 0)); 129 } 130 131 /** checks, if the given cut's efficacy is larger than the minimal cut efficacy 132 * 133 * @return TRUE if the given cut's efficacy is larger than the minimal cut efficacy, otherwise FALSE 134 */ 135 SCIP_Bool SCIPisEfficacious( 136 SCIP* scip, /**< SCIP data structure */ 137 SCIP_Real efficacy /**< efficacy of the cut */ 138 ) 139 { 140 assert(scip != NULL); 141 142 return SCIPsetIsEfficacious(scip->set, (SCIPtreeGetCurrentDepth(scip->tree) == 0), efficacy); 143 } 144 145 /** calculates the efficacy norm of the given vector, which depends on the "separating/efficacynorm" parameter 146 * 147 * @return the efficacy norm of the given vector, which depends on the "separating/efficacynorm" parameter 148 */ 149 SCIP_Real SCIPgetVectorEfficacyNorm( 150 SCIP* scip, /**< SCIP data structure */ 151 SCIP_Real* vals, /**< array of values */ 152 int nvals /**< number of values */ 153 ) 154 { 155 SCIP_Real norm; 156 int i; 157 158 assert(scip != NULL); 159 assert(scip->set != NULL); 160 161 norm = 0.0; 162 switch( scip->set->sepa_efficacynorm ) 163 { 164 case 'e': 165 for( i = 0; i < nvals; ++i ) 166 norm += SQR(vals[i]); 167 norm = SQRT(norm); 168 break; 169 case 'm': 170 for( i = 0; i < nvals; ++i ) 171 { 172 SCIP_Real absval; 173 174 absval = REALABS(vals[i]); 175 norm = MAX(norm, absval); 176 } 177 break; 178 case 's': 179 for( i = 0; i < nvals; ++i ) 180 norm += REALABS(vals[i]); 181 break; 182 case 'd': 183 for( i = 0; i < nvals; ++i ) 184 { 185 if( !SCIPisZero(scip, vals[i]) ) 186 { 187 norm = 1.0; 188 break; 189 } 190 } 191 break; 192 default: 193 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", scip->set->sepa_efficacynorm); 194 assert(FALSE); /*lint !e506*/ 195 } 196 197 return norm; 198 } 199 200 /** indicates whether a cut is applicable, i.e., will modify the LP when applied 201 * 202 * @pre This method can be called if @p scip is in one of the following stages: 203 * - \ref SCIP_STAGE_SOLVING 204 * 205 * @return whether the cut is modifiable, not a bound change, or a bound change that changes bounds by at least epsilon 206 */ 207 SCIP_Bool SCIPisCutApplicable( 208 SCIP* scip, /**< SCIP data structure */ 209 SCIP_ROW* cut /**< separated cut */ 210 ) 211 { 212 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisCutApplicable", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 213 214 return SCIPsepastoreIsCutApplicable(scip->set, cut); 215 } 216 217 /** adds cut to separation storage 218 * 219 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 220 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 221 * 222 * @pre This method can be called if @p scip is in one of the following stages: 223 * - \ref SCIP_STAGE_SOLVING 224 * 225 * @deprecated Please use SCIPaddRow() instead, or, if the row is a global cut, add it only to the global cutpool. 226 */ 227 SCIP_DEPRECATED 228 SCIP_RETCODE SCIPaddCut( 229 SCIP* scip, /**< SCIP data structure */ 230 SCIP_SOL* sol, /**< primal solution that was separated, or NULL for LP solution */ 231 SCIP_ROW* cut, /**< separated cut */ 232 SCIP_Bool forcecut, /**< should the cut be forced to enter the LP? */ 233 SCIP_Bool* infeasible /**< pointer to store whether cut has been detected to be infeasible for local bounds */ 234 ) 235 { 236 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddCut", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 237 238 SCIP_UNUSED(sol); 239 240 return SCIPaddRow(scip, cut, forcecut, infeasible); 241 } 242 243 /** adds row to separation storage 244 * 245 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 246 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 247 * 248 * @pre This method can be called if @p scip is in one of the following stages: 249 * - \ref SCIP_STAGE_SOLVING 250 */ 251 SCIP_RETCODE SCIPaddRow( 252 SCIP* scip, /**< SCIP data structure */ 253 SCIP_ROW* row, /**< row */ 254 SCIP_Bool forcecut, /**< should the row be forced to enter the LP? */ 255 SCIP_Bool* infeasible /**< pointer to store whether row has been detected to be infeasible for local bounds */ 256 ) 257 { 258 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddRow", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 259 260 assert(SCIPtreeGetCurrentNode(scip->tree) != NULL); 261 262 SCIP_CALL( SCIPsepastoreAddCut(scip->sepastore, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, 263 scip->eventfilter, scip->lp, row, forcecut, (SCIPtreeGetCurrentDepth(scip->tree) == 0), infeasible) ); 264 265 /* possibly run conflict analysis */ 266 if ( *infeasible && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && SCIPisConflictAnalysisApplicable(scip) ) 267 { 268 SCIP_Real act; 269 SCIP_VAR* var; 270 SCIP_Real val; 271 int ncols; 272 int j; 273 274 /* initialize conflict analysis */ 275 SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) ); 276 277 if ( ! SCIPisInfinity(scip, -row->lhs) ) 278 { 279 act = SCIProwGetMaxActivity(row, scip->set, scip->stat); 280 if ( SCIPisLT(scip, act, row->lhs) ) 281 { 282 ncols = SCIProwGetNNonz(row); 283 for (j = 0; j < ncols; ++j) 284 { 285 val = row->vals[j]; 286 if ( ! SCIPisZero(scip, val) ) 287 { 288 var = SCIPcolGetVar(row->cols[j]); 289 assert( var != NULL ); 290 291 if ( val > 0.0 ) 292 { 293 SCIP_CALL( SCIPaddConflictUb(scip, var, NULL) ); 294 } 295 else 296 { 297 SCIP_CALL( SCIPaddConflictLb(scip, var, NULL) ); 298 } 299 } 300 } 301 } 302 } 303 else if ( ! SCIPisInfinity(scip, row->rhs) ) 304 { 305 act = SCIProwGetMinActivity(row, scip->set, scip->stat); 306 if ( SCIPisGT(scip, act, row->rhs) ) 307 { 308 ncols = SCIProwGetNNonz(row); 309 for (j = 0; j < ncols; ++j) 310 { 311 val = row->vals[j]; 312 if ( ! SCIPisZero(scip, val) ) 313 { 314 var = SCIPcolGetVar(row->cols[j]); 315 assert( var != NULL ); 316 317 if ( val > 0.0 ) 318 { 319 SCIP_CALL( SCIPaddConflictLb(scip, var, NULL) ); 320 } 321 else 322 { 323 SCIP_CALL( SCIPaddConflictUb(scip, var, NULL) ); 324 } 325 } 326 } 327 } 328 } 329 330 /* analyze the conflict */ 331 SCIP_CALL( SCIPanalyzeConflict(scip, SCIPgetDepth(scip), NULL) ); 332 } 333 334 return SCIP_OKAY; 335 } 336 337 /** checks if cut is already existing in global cutpool 338 * 339 * @return TRUE is returned if the cut is not already existing in the global cutpool, FALSE otherwise 340 * 341 * @pre This method can be called if @p scip is in one of the following stages: 342 * - \ref SCIP_STAGE_SOLVING 343 */ 344 SCIP_Bool SCIPisCutNew( 345 SCIP* scip, /**< SCIP data structure */ 346 SCIP_ROW* row /**< cutting plane to add */ 347 ) 348 { 349 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisCutNew", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 350 351 return SCIPcutpoolIsCutNew(scip->cutpool, scip->set, row); 352 } 353 354 /** if not already existing, adds row to global cut pool 355 * 356 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 357 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 358 * 359 * @pre This method can be called if @p scip is in one of the following stages: 360 * - \ref SCIP_STAGE_SOLVING 361 */ 362 SCIP_RETCODE SCIPaddPoolCut( 363 SCIP* scip, /**< SCIP data structure */ 364 SCIP_ROW* row /**< row to remove */ 365 ) 366 { 367 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddPoolCut", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 368 369 SCIP_CALL( SCIPcutpoolAddRow(scip->cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) ); 370 371 return SCIP_OKAY; 372 } 373 374 /** removes the row from the global cut pool 375 * 376 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 377 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 378 * 379 * @pre This method can be called if @p scip is in one of the following stages: 380 * - \ref SCIP_STAGE_SOLVING 381 */ 382 SCIP_RETCODE SCIPdelPoolCut( 383 SCIP* scip, /**< SCIP data structure */ 384 SCIP_ROW* row /**< cutting plane to add */ 385 ) 386 { 387 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelPoolCut", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 388 389 SCIP_CALL( SCIPcutpoolDelRow(scip->cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) ); 390 391 return SCIP_OKAY; 392 } 393 394 /** gets current cuts in the global cut pool 395 * 396 * @return the current cuts in the global cut pool 397 * 398 * @pre This method can be called if @p scip is in one of the following stages: 399 * - \ref SCIP_STAGE_SOLVING 400 * - \ref SCIP_STAGE_SOLVED 401 * - \ref SCIP_STAGE_EXITSOLVE 402 */ 403 SCIP_CUT** SCIPgetPoolCuts( 404 SCIP* scip /**< SCIP data structure */ 405 ) 406 { 407 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetPoolCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 408 409 return SCIPcutpoolGetCuts(scip->cutpool); 410 } 411 412 /** gets current number of rows in the global cut pool 413 * 414 * @return the current number of rows in the global cut pool 415 * 416 * @pre This method can be called if @p scip is in one of the following stages: 417 * - \ref SCIP_STAGE_SOLVING 418 * - \ref SCIP_STAGE_SOLVED 419 * - \ref SCIP_STAGE_EXITSOLVE 420 */ 421 int SCIPgetNPoolCuts( 422 SCIP* scip /**< SCIP data structure */ 423 ) 424 { 425 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNPoolCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 426 427 return SCIPcutpoolGetNCuts(scip->cutpool); 428 } 429 430 /** gets the global cut pool used by SCIP 431 * 432 * @return the global cut pool used by SCIP 433 * 434 * @pre This method can be called if @p scip is in one of the following stages: 435 * - \ref SCIP_STAGE_SOLVING 436 * - \ref SCIP_STAGE_SOLVED 437 * - \ref SCIP_STAGE_EXITSOLVE 438 */ 439 SCIP_CUTPOOL* SCIPgetGlobalCutpool( 440 SCIP* scip /**< SCIP data structure */ 441 ) 442 { 443 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetGlobalCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 444 445 return scip->cutpool; 446 } 447 448 /** creates a cut pool 449 * 450 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 451 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 452 * 453 * @pre This method can be called if @p scip is in one of the following stages: 454 * - \ref SCIP_STAGE_TRANSFORMING 455 * - \ref SCIP_STAGE_TRANSFORMED 456 * - \ref SCIP_STAGE_INITPRESOLVE 457 * - \ref SCIP_STAGE_PRESOLVING 458 * - \ref SCIP_STAGE_EXITPRESOLVE 459 * - \ref SCIP_STAGE_PRESOLVED 460 * - \ref SCIP_STAGE_INITSOLVE 461 * - \ref SCIP_STAGE_SOLVING 462 */ 463 SCIP_RETCODE SCIPcreateCutpool( 464 SCIP* scip, /**< SCIP data structure */ 465 SCIP_CUTPOOL** cutpool, /**< pointer to store cut pool */ 466 int agelimit /**< maximum age a cut can reach before it is deleted from the pool */ 467 ) 468 { 469 SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateCutpool", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 470 471 SCIP_CALL( SCIPcutpoolCreate(cutpool, scip->mem->probmem, scip->set, agelimit, FALSE) ); 472 473 return SCIP_OKAY; 474 } 475 476 /** frees a cut pool 477 * 478 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 479 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 480 * 481 * @pre This method can be called if @p scip is in one of the following stages: 482 * - \ref SCIP_STAGE_TRANSFORMING 483 * - \ref SCIP_STAGE_TRANSFORMED 484 * - \ref SCIP_STAGE_INITPRESOLVE 485 * - \ref SCIP_STAGE_PRESOLVING 486 * - \ref SCIP_STAGE_EXITPRESOLVE 487 * - \ref SCIP_STAGE_PRESOLVED 488 * - \ref SCIP_STAGE_INITSOLVE 489 * - \ref SCIP_STAGE_SOLVING 490 * - \ref SCIP_STAGE_SOLVED 491 * - \ref SCIP_STAGE_EXITSOLVE 492 * - \ref SCIP_STAGE_FREETRANS 493 */ 494 SCIP_RETCODE SCIPfreeCutpool( 495 SCIP* scip, /**< SCIP data structure */ 496 SCIP_CUTPOOL** cutpool /**< pointer to store cut pool */ 497 ) 498 { 499 SCIP_CALL( SCIPcheckStage(scip, "SCIPfreeCutpool", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 500 501 SCIP_CALL( SCIPcutpoolFree(cutpool, scip->mem->probmem, scip->set, scip->lp) ); 502 503 return SCIP_OKAY; 504 } 505 506 /** if not already existing, adds row to a cut pool and captures it 507 * 508 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 509 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 510 * 511 * @pre This method can be called if @p scip is in one of the following stages: 512 * - \ref SCIP_STAGE_INITSOLVE 513 * - \ref SCIP_STAGE_SOLVING 514 */ 515 SCIP_RETCODE SCIPaddRowCutpool( 516 SCIP* scip, /**< SCIP data structure */ 517 SCIP_CUTPOOL* cutpool, /**< cut pool */ 518 SCIP_ROW* row /**< cutting plane to add */ 519 ) 520 { 521 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddRowCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 522 523 SCIP_CALL( SCIPcutpoolAddRow(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) ); 524 525 return SCIP_OKAY; 526 } 527 528 /** adds row to a cut pool and captures it; doesn't check for multiple cuts 529 * 530 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 531 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 532 * 533 * @pre This method can be called if @p scip is in one of the following stages: 534 * - \ref SCIP_STAGE_INITSOLVE 535 * - \ref SCIP_STAGE_SOLVING 536 */ 537 SCIP_RETCODE SCIPaddNewRowCutpool( 538 SCIP* scip, /**< SCIP data structure */ 539 SCIP_CUTPOOL* cutpool, /**< cut pool */ 540 SCIP_ROW* row /**< cutting plane to add */ 541 ) 542 { 543 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddNewRowCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 544 545 SCIP_CALL( SCIPcutpoolAddNewRow(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) ); 546 547 return SCIP_OKAY; 548 } 549 550 /** removes the LP row from a cut pool 551 * 552 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 553 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 554 * 555 * @pre This method can be called if @p scip is in one of the following stages: 556 * - \ref SCIP_STAGE_INITSOLVE 557 * - \ref SCIP_STAGE_SOLVING 558 * - \ref SCIP_STAGE_SOLVED 559 */ 560 SCIP_RETCODE SCIPdelRowCutpool( 561 SCIP* scip, /**< SCIP data structure */ 562 SCIP_CUTPOOL* cutpool, /**< cut pool */ 563 SCIP_ROW* row /**< row to remove */ 564 ) 565 { 566 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelRowCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 567 568 SCIP_CALL( SCIPcutpoolDelRow(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) ); 569 570 return SCIP_OKAY; 571 } 572 573 /** separates cuts from a cut pool 574 * 575 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 576 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 577 * 578 * @pre This method can be called if @p scip is in one of the following stages: 579 * - \ref SCIP_STAGE_SOLVING 580 */ 581 SCIP_RETCODE SCIPseparateCutpool( 582 SCIP* scip, /**< SCIP data structure */ 583 SCIP_CUTPOOL* cutpool, /**< cut pool */ 584 SCIP_RESULT* result /**< pointer to store the result of the separation call */ 585 ) 586 { 587 SCIP_CALL( SCIPcheckStage(scip, "SCIPseparateCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 588 589 assert(SCIPtreeGetCurrentNode(scip->tree) != NULL); 590 591 if( !SCIPtreeHasCurrentNodeLP(scip->tree) ) 592 { 593 SCIPerrorMessage("cannot add cuts, because node LP is not processed\n"); 594 return SCIP_INVALIDCALL; 595 } 596 597 SCIP_CALL( SCIPcutpoolSeparate(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, scip->eventfilter, 598 scip->lp, scip->sepastore, NULL, FALSE, (SCIPtreeGetCurrentDepth(scip->tree) == 0), result) ); 599 600 return SCIP_OKAY; 601 } 602 603 /** separates cuts w.r.t. given solution from a cut pool 604 * 605 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 606 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 607 * 608 * @pre This method can be called if @p scip is in one of the following stages: 609 * - \ref SCIP_STAGE_SOLVING 610 */ 611 SCIP_RETCODE SCIPseparateSolCutpool( 612 SCIP* scip, /**< SCIP data structure */ 613 SCIP_CUTPOOL* cutpool, /**< cut pool */ 614 SCIP_SOL* sol, /**< solution to be separated */ 615 SCIP_Bool pretendroot, /**< should the cut separators be called as if we are at the root node? */ 616 SCIP_RESULT* result /**< pointer to store the result of the separation call */ 617 ) 618 { 619 SCIP_CALL( SCIPcheckStage(scip, "SCIPseparateSolCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 620 621 assert(SCIPtreeGetCurrentNode(scip->tree) != NULL); 622 623 if( !SCIPtreeHasCurrentNodeLP(scip->tree) ) 624 { 625 SCIPerrorMessage("cannot add cuts, because node LP is not processed\n"); 626 return SCIP_INVALIDCALL; 627 } 628 629 SCIP_CALL( SCIPcutpoolSeparate(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, scip->eventfilter, 630 scip->lp, scip->sepastore, sol, FALSE, pretendroot, result) ); 631 632 return SCIP_OKAY; 633 } 634 635 /** if not already existing, adds row to delayed global cut pool 636 * 637 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 638 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 639 * 640 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING 641 */ 642 SCIP_RETCODE SCIPaddDelayedPoolCut( 643 SCIP* scip, /**< SCIP data structure */ 644 SCIP_ROW* row /**< cutting plane to add */ 645 ) 646 { 647 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddDelayedPoolCut", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 648 649 SCIP_CALL( SCIPcutpoolAddRow(scip->delayedcutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) ); 650 651 return SCIP_OKAY; 652 } 653 654 /** removes the row from the delayed global cut pool 655 * 656 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 657 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 658 * 659 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING 660 */ 661 SCIP_RETCODE SCIPdelDelayedPoolCut( 662 SCIP* scip, /**< SCIP data structure */ 663 SCIP_ROW* row /**< cutting plane to add */ 664 ) 665 { 666 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelDelayedPoolCut", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 667 668 SCIP_CALL( SCIPcutpoolDelRow(scip->delayedcutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) ); 669 670 return SCIP_OKAY; 671 } 672 673 /** gets current cuts in the delayed global cut pool 674 * 675 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 676 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 677 * 678 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING 679 */ 680 SCIP_CUT** SCIPgetDelayedPoolCuts( 681 SCIP* scip /**< SCIP data structure */ 682 ) 683 { 684 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetDelayedPoolCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 685 686 return SCIPcutpoolGetCuts(scip->delayedcutpool); 687 } 688 689 /** gets current number of rows in the delayed global cut pool 690 * 691 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 692 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 693 * 694 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING 695 */ 696 int SCIPgetNDelayedPoolCuts( 697 SCIP* scip /**< SCIP data structure */ 698 ) 699 { 700 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNDelayedPoolCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 701 702 return SCIPcutpoolGetNCuts(scip->delayedcutpool); 703 } 704 705 /** gets the delayed global cut pool used by SCIP 706 * 707 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 708 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 709 * 710 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING 711 */ 712 SCIP_CUTPOOL* SCIPgetDelayedGlobalCutpool( 713 SCIP* scip /**< SCIP data structure */ 714 ) 715 { 716 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetDelayedGlobalCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) ); 717 718 return scip->delayedcutpool; 719 } 720 721 /** separates the given primal solution or the current LP solution by calling the separators and constraint handlers' 722 * separation methods; 723 * the generated cuts are stored in the separation storage and can be accessed with the methods SCIPgetCuts() and 724 * SCIPgetNCuts(); 725 * after evaluating the cuts, you have to call SCIPclearCuts() in order to remove the cuts from the 726 * separation storage; 727 * it is possible to call SCIPseparateSol() multiple times with different solutions and evaluate the found cuts 728 * afterwards 729 * 730 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 731 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 732 * 733 * @pre This method can be called if @p scip is in one of the following stages: 734 * - \ref SCIP_STAGE_SOLVING 735 */ 736 SCIP_RETCODE SCIPseparateSol( 737 SCIP* scip, /**< SCIP data structure */ 738 SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */ 739 SCIP_Bool pretendroot, /**< should the cut separators be called as if we are at the root node? */ 740 SCIP_Bool allowlocal, /**< should the separator be asked to separate local cuts */ 741 SCIP_Bool onlydelayed, /**< should only separators be called that were delayed in the previous round? */ 742 SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */ 743 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */ 744 ) 745 { 746 int actdepth; 747 748 SCIP_CALL( SCIPcheckStage(scip, "SCIPseparateSol", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 749 750 /* get current depth */ 751 actdepth = (pretendroot ? 0 : SCIPtreeGetCurrentDepth(scip->tree)); 752 753 /* apply separation round */ 754 SCIP_CALL( SCIPseparationRound(scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat, scip->eventqueue, 755 scip->eventfilter, scip->transprob, scip->primal, scip->tree, scip->lp, scip->sepastore, 756 sol, actdepth, allowlocal, onlydelayed, delayed, cutoff) ); 757 758 return SCIP_OKAY; 759 } 760 761 /** gets the array of cuts currently stored in the separation storage 762 * 763 * @return the array of cuts currently stored in the separation storage 764 * 765 * @pre This method can be called if @p scip is in one of the following stages: 766 * - \ref SCIP_STAGE_PRESOLVED 767 * - \ref SCIP_STAGE_SOLVING 768 * - \ref SCIP_STAGE_SOLVED 769 */ 770 SCIP_ROW** SCIPgetCuts( 771 SCIP* scip /**< SCIP data structure */ 772 ) 773 { 774 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 775 776 return SCIPsepastoreGetCuts(scip->sepastore); 777 } 778 779 /** get current number of cuts in the separation storage 780 * 781 * @return the current number of cuts in the separation storage 782 * 783 * @pre This method can be called if @p scip is in one of the following stages: 784 * - \ref SCIP_STAGE_PRESOLVED 785 * - \ref SCIP_STAGE_SOLVING 786 * - \ref SCIP_STAGE_SOLVED 787 */ 788 int SCIPgetNCuts( 789 SCIP* scip /**< SCIP data structure */ 790 ) 791 { 792 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE) ); 793 794 return SCIPsepastoreGetNCuts(scip->sepastore); 795 } 796 797 /** clears the separation storage 798 * 799 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 800 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 801 * 802 * @pre This method can be called if @p scip is in one of the following stages: 803 * - \ref SCIP_STAGE_SOLVING 804 */ 805 SCIP_RETCODE SCIPclearCuts( 806 SCIP* scip /**< SCIP data structure */ 807 ) 808 { 809 SCIP_CALL( SCIPcheckStage(scip, "SCIPclearCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 810 811 SCIP_CALL( SCIPsepastoreClearCuts(scip->sepastore, scip->mem->probmem, scip->set, scip->eventqueue, scip->eventfilter, scip->lp) ); 812 813 return SCIP_OKAY; 814 } 815 816 /** removes cuts that are inefficacious w.r.t. the current LP solution from separation storage without adding the cuts to the LP 817 * 818 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 819 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 820 * 821 * @pre This method can be called if @p scip is in one of the following stages: 822 * - \ref SCIP_STAGE_SOLVING 823 */ 824 SCIP_RETCODE SCIPremoveInefficaciousCuts( 825 SCIP* scip /**< SCIP data structure */ 826 ) 827 { 828 SCIP_Bool isroot = FALSE; 829 830 SCIP_CALL( SCIPcheckStage(scip, "SCIPremoveInefficaciousCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) ); 831 832 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 ) 833 isroot = TRUE; 834 835 SCIP_CALL( SCIPsepastoreRemoveInefficaciousCuts(scip->sepastore, scip->mem->probmem, scip->set, scip->stat, 836 scip->eventqueue, scip->eventfilter, scip->lp, isroot, SCIP_EFFICIACYCHOICE_LP) ); 837 838 return SCIP_OKAY; 839 } 840