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_general.c 26 * @ingroup OTHER_CFILES 27 * @brief general public methods 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 "blockmemshell/memory.h" 46 #include "lpi/lpi.h" 47 #include "scip/exprinterpret.h" 48 #include "scip/clock.h" 49 #include "scip/debug.h" 50 #include "scip/dialog.h" 51 #include "scip/interrupt.h" 52 #include "scip/mem.h" 53 #include "scip/message_default.h" 54 #include "scip/nlp.h" 55 #include "scip/pub_message.h" 56 #include "scip/retcode.h" 57 #include "scip/scipbuildflags.h" 58 #include "scip/scipcoreplugins.h" 59 #include "scip/scip_general.h" 60 #include "scip/scipgithash.h" 61 #include "scip/scip_mem.h" 62 #include "scip/scip_message.h" 63 #include "scip/scip_numerics.h" 64 #include "scip/scip_prob.h" 65 #include "scip/scip_solvingstats.h" 66 #include "scip/set.h" 67 #include "scip/solve.h" 68 #include "scip/struct_mem.h" 69 #include "scip/struct_primal.h" 70 #include "scip/struct_prob.h" 71 #include "scip/struct_scip.h" 72 #include "scip/struct_set.h" 73 #include "scip/struct_stat.h" 74 #include "scip/syncstore.h" 75 #include "scip/lapack_calls.h" 76 77 #include <string.h> 78 #if defined(_WIN32) || defined(_WIN64) 79 #else 80 #include <strings.h> /*lint --e{766}*/ 81 #endif 82 83 #ifdef SCIP_WITH_ZLIB 84 #include <zlib.h> 85 #endif 86 87 /* In debug mode, the following methods are implemented as function calls to ensure 88 * type validity. 89 * In optimized mode, the methods are implemented as defines to improve performance. 90 * However, we want to have them in the library anyways, so we have to undef the defines. 91 */ 92 93 #undef SCIPgetStage 94 #undef SCIPhasPerformedPresolve 95 #undef SCIPisStopped 96 97 /** returns complete SCIP version number in the format "major . minor tech" 98 * 99 * @return complete SCIP version 100 */ 101 SCIP_Real SCIPversion( 102 void 103 ) 104 { 105 return SCIP_VERSION_MAJOR + SCIP_VERSION_MINOR/100.0; /*lint !e835*/ 106 } 107 108 /** returns SCIP major version 109 * 110 * @return major SCIP version 111 */ 112 int SCIPmajorVersion( 113 void 114 ) 115 { 116 return SCIP_VERSION_MAJOR; 117 } 118 119 /** returns SCIP minor version 120 * 121 * @return minor SCIP version 122 */ 123 int SCIPminorVersion( 124 void 125 ) 126 { 127 return SCIP_VERSION_MINOR; 128 } 129 130 /** returns SCIP technical version 131 * 132 * @return technical SCIP version 133 */ 134 int SCIPtechVersion( 135 void 136 ) 137 { 138 return SCIP_VERSION_PATCH; 139 } 140 141 /** returns SCIP sub version number 142 * 143 * @return subversion SCIP version 144 */ 145 int SCIPsubversion( 146 void 147 ) 148 { 149 return SCIP_SUBVERSION; 150 } 151 152 /** prints a version information line to a file stream via the message handler system 153 * 154 * @note If the message handler is set to a NULL pointer nothing will be printed 155 */ 156 void SCIPprintVersion( 157 SCIP* scip, /**< SCIP data structure */ 158 FILE* file /**< output file (or NULL for standard output) */ 159 ) 160 { 161 assert( scip != NULL ); 162 163 SCIPmessageFPrintInfo(scip->messagehdlr, file, "SCIP version %d.%d.%d", 164 SCIPmajorVersion(), SCIPminorVersion(), SCIPtechVersion()); 165 #if SCIP_SUBVERSION > 0 166 SCIPmessageFPrintInfo(scip->messagehdlr, file, ".%d", SCIPsubversion()); 167 #endif 168 169 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [precision: %d byte]", (int)sizeof(SCIP_Real)); 170 171 #ifndef BMS_NOBLOCKMEM 172 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [memory: block]"); 173 #else 174 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [memory: standard]"); 175 #endif 176 #ifndef NDEBUG 177 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [mode: debug]"); 178 #else 179 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [mode: optimized]"); 180 #endif 181 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [LP solver: %s]", SCIPlpiGetSolverName()); 182 SCIPmessageFPrintInfo(scip->messagehdlr, file, " [GitHash: %s]", SCIPgetGitHash()); 183 SCIPmessageFPrintInfo(scip->messagehdlr, file, "\n"); 184 SCIPmessageFPrintInfo(scip->messagehdlr, file, "%s\n", SCIP_COPYRIGHT); 185 } 186 187 /** prints detailed information on the compile-time flags 188 * 189 * @note If the message handler is set to a NULL pointer nothing will be printed 190 */ 191 void SCIPprintBuildOptions( 192 SCIP* scip, /**< SCIP data structure */ 193 FILE* file /**< output file (or NULL for standard output) */ 194 ) 195 { 196 assert( scip != NULL ); 197 198 /* compiler */ 199 SCIPmessageFPrintInfo(scip->messagehdlr, file, "Compiler: "); 200 #if defined(__INTEL_COMPILER) 201 SCIPmessageFPrintInfo(scip->messagehdlr, file, "Intel %d\n", __INTEL_COMPILER); 202 #elif defined(__clang__) 203 SCIPmessageFPrintInfo(scip->messagehdlr, file, "clang %d.%d.%d\n", __clang_major__, __clang_minor__, __clang_patchlevel__); 204 #elif defined(_MSC_VER) 205 SCIPmessageFPrintInfo(scip->messagehdlr, file, "microsoft visual c %d\n", _MSC_FULL_VER); 206 #elif defined(__GNUC__) 207 #if defined(__GNUC_PATCHLEVEL__) 208 SCIPmessageFPrintInfo(scip->messagehdlr, file, "gcc %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); 209 #else 210 SCIPmessageFPrintInfo(scip->messagehdlr, file, "gcc %d.%d\n", __GNUC__, __GNUC_MINOR__); 211 #endif 212 #else 213 SCIPmessageFPrintInfo(scip->messagehdlr, file, "unknown\n"); 214 #endif 215 216 /* build flags */ 217 SCIPmessageFPrintInfo(scip->messagehdlr, file, "\nBuild options:\n%s", SCIPgetBuildFlags()); 218 } 219 220 /** prints error message for the given SCIP_RETCODE via the error prints method */ 221 void SCIPprintError( 222 SCIP_RETCODE retcode /**< SCIP return code causing the error */ 223 ) 224 { 225 SCIPmessagePrintError("SCIP Error (%d): ", retcode); 226 SCIPretcodePrintError(retcode); 227 SCIPmessagePrintError("\n"); 228 } 229 230 /* 231 * general SCIP methods 232 */ 233 234 /** internal method to create SCIP */ 235 static 236 SCIP_RETCODE doScipCreate( 237 SCIP** scip /**< pointer to SCIP data structure */ 238 ) 239 { 240 assert(scip != NULL); 241 242 SCIP_ALLOC( BMSallocMemory(scip) ); 243 244 /* all members are initialized to NULL */ 245 BMSclearMemory(*scip); 246 247 /* create a default message handler */ 248 SCIP_CALL( SCIPcreateMessagehdlrDefault(&(*scip)->messagehdlr, TRUE, NULL, FALSE) ); 249 250 SCIP_CALL( SCIPmemCreate(&(*scip)->mem) ); 251 SCIP_CALL( SCIPsetCreate(&(*scip)->set, (*scip)->messagehdlr, (*scip)->mem->setmem, *scip) ); 252 SCIP_CALL( SCIPinterruptCreate(&(*scip)->interrupt) ); 253 SCIP_CALL( SCIPdialoghdlrCreate((*scip)->set, &(*scip)->dialoghdlr) ); 254 SCIP_CALL( SCIPclockCreate(&(*scip)->totaltime, SCIP_CLOCKTYPE_DEFAULT) ); 255 SCIP_CALL( SCIPsyncstoreCreate( &(*scip)->syncstore ) ); 256 257 /* include additional core functionality */ 258 SCIP_CALL( SCIPincludeCorePlugins(*scip) ); 259 260 SCIPclockStart((*scip)->totaltime, (*scip)->set); 261 262 SCIP_CALL( SCIPnlpInclude((*scip)->set, SCIPblkmem(*scip)) ); 263 264 if( strcmp(SCIPlpiGetSolverName(), "NONE") != 0 ) 265 { 266 SCIP_CALL( SCIPsetIncludeExternalCode((*scip)->set, SCIPlpiGetSolverName(), SCIPlpiGetSolverDesc()) ); 267 } 268 if( strcmp(SCIPexprintGetName(), "NONE") != 0 ) 269 { 270 SCIP_CALL( SCIPsetIncludeExternalCode((*scip)->set, SCIPexprintGetName(), SCIPexprintGetDesc()) ); 271 } 272 273 #ifdef SCIP_WITH_ZLIB 274 SCIP_CALL( SCIPsetIncludeExternalCode((*scip)->set, "ZLIB " ZLIB_VERSION, "General purpose compression library by J. Gailly and M. Adler (zlib.net)") ); 275 #endif 276 277 #ifdef SCIP_WITH_LAPACK 278 { 279 char name[SCIP_MAXSTRLEN]; 280 int major; 281 int minor; 282 int patch; 283 284 SCIPlapackVersion(&major, &minor, &patch); 285 SCIPsnprintf(name, SCIP_MAXSTRLEN, "LAPACK %d.%d.%d", major, minor, patch); 286 287 SCIP_CALL( SCIPsetIncludeExternalCode((*scip)->set, name, "General Linear Algebra PACKage (http://www.netlib.org/lapack/)") ); 288 } 289 #endif 290 291 return SCIP_OKAY; 292 } 293 294 /** creates and initializes SCIP data structures 295 * 296 * @note The SCIP default message handler is installed. Use the method SCIPsetMessagehdlr() to install your own 297 * message handler or SCIPsetMessagehdlrLogfile() and SCIPsetMessagehdlrQuiet() to write into a log 298 * file and turn off/on the display output, respectively. 299 * 300 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 301 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 302 * 303 * @post After calling this method \SCIP reached the solving stage \ref SCIP_STAGE_INIT 304 * 305 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages. 306 */ 307 SCIP_RETCODE SCIPcreate( 308 SCIP** scip /**< pointer to SCIP data structure */ 309 ) 310 { 311 assert(scip != NULL); 312 313 SCIP_CALL_FINALLY( doScipCreate(scip), (void)SCIPfree(scip) ); 314 315 return SCIP_OKAY; 316 } 317 318 /** frees SCIP data structures 319 * 320 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 321 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 322 * 323 * @pre This method can be called if @p scip is in one of the following stages: 324 * - \ref SCIP_STAGE_INIT 325 * - \ref SCIP_STAGE_PROBLEM 326 * - \ref SCIP_STAGE_TRANSFORMED 327 * - \ref SCIP_STAGE_INITPRESOLVE 328 * - \ref SCIP_STAGE_PRESOLVING 329 * - \ref SCIP_STAGE_PRESOLVED 330 * - \ref SCIP_STAGE_EXITPRESOLVE 331 * - \ref SCIP_STAGE_SOLVING 332 * - \ref SCIP_STAGE_SOLVED 333 * - \ref SCIP_STAGE_FREE 334 * 335 * @post After calling this method \SCIP reached the solving stage \ref SCIP_STAGE_FREE 336 * 337 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages. 338 */ 339 SCIP_RETCODE SCIPfree( 340 SCIP** scip /**< pointer to SCIP data structure */ 341 ) 342 { 343 assert(scip != NULL); 344 if( *scip == NULL ) 345 return SCIP_OKAY; 346 347 SCIP_CALL( SCIPcheckStage(*scip, "SCIPfree", TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE) ); 348 349 SCIP_CALL( SCIPfreeProb(*scip) ); 350 assert((*scip)->set->stage == SCIP_STAGE_INIT); 351 352 /* switch stage to FREE */ 353 (*scip)->set->stage = SCIP_STAGE_FREE; 354 355 SCIP_CALL( SCIPsyncstoreRelease(&(*scip)->syncstore) ); 356 SCIP_CALL( SCIPsetFree(&(*scip)->set, (*scip)->mem->setmem) ); 357 SCIP_CALL( SCIPdialoghdlrFree(*scip, &(*scip)->dialoghdlr) ); 358 SCIPclockFree(&(*scip)->totaltime); 359 SCIPinterruptFree(&(*scip)->interrupt); 360 SCIP_CALL( SCIPmemFree(&(*scip)->mem) ); 361 362 /* release message handler */ 363 SCIP_CALL( SCIPmessagehdlrRelease(&(*scip)->messagehdlr) ); 364 365 BMSfreeMemory(scip); 366 367 return SCIP_OKAY; 368 } 369 370 #undef SCIPgetStage 371 #undef SCIPhasPerformedPresolve 372 #undef SCIPisStopped 373 374 /** returns current stage of SCIP 375 * 376 * @return the current SCIP stage 377 * 378 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages. 379 */ 380 SCIP_STAGE SCIPgetStage( 381 SCIP* scip /**< SCIP data structure */ 382 ) 383 { 384 assert(scip != NULL); 385 assert(scip->set != NULL); 386 387 return scip->set->stage; 388 } 389 390 /** outputs SCIP stage and solution status if applicable via the message handler 391 * 392 * @note If the message handler is set to a NULL pointer nothing will be printed 393 * 394 * @note If limits have been changed between the solution and the call to this function, the status is recomputed and 395 * thus may to correspond to the original status. 396 * 397 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 398 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 399 * 400 * See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages. 401 */ 402 SCIP_RETCODE SCIPprintStage( 403 SCIP* scip, /**< SCIP data structure */ 404 FILE* file /**< output file (or NULL for standard output) */ 405 ) 406 { 407 SCIP_CALL( SCIPcheckStage(scip, "SCIPprintStage", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) ); 408 409 switch( scip->set->stage ) 410 { 411 case SCIP_STAGE_INIT: 412 SCIPmessageFPrintInfo(scip->messagehdlr, file, "initialization"); 413 break; 414 case SCIP_STAGE_PROBLEM: 415 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem creation / modification"); 416 break; 417 case SCIP_STAGE_TRANSFORMING: 418 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem transformation"); 419 break; 420 case SCIP_STAGE_TRANSFORMED: 421 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem transformed"); 422 break; 423 case SCIP_STAGE_INITPRESOLVE: 424 SCIPmessageFPrintInfo(scip->messagehdlr, file, "presolving is being initialized"); 425 break; 426 case SCIP_STAGE_PRESOLVING: 427 if( SCIPsolveIsStopped(scip->set, scip->stat, TRUE) ) 428 { 429 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving was interrupted ["); 430 SCIP_CALL( SCIPprintStatus(scip, file) ); 431 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]"); 432 } 433 else 434 SCIPmessageFPrintInfo(scip->messagehdlr, file, "presolving process is running"); 435 break; 436 case SCIP_STAGE_EXITPRESOLVE: 437 SCIPmessageFPrintInfo(scip->messagehdlr, file, "presolving is being exited"); 438 break; 439 case SCIP_STAGE_PRESOLVED: 440 if( SCIPsolveIsStopped(scip->set, scip->stat, TRUE) ) 441 { 442 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving was interrupted ["); 443 SCIP_CALL( SCIPprintStatus(scip, file) ); 444 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]"); 445 } 446 else 447 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem is presolved"); 448 break; 449 case SCIP_STAGE_INITSOLVE: 450 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving process initialization"); 451 break; 452 case SCIP_STAGE_SOLVING: 453 if( SCIPsolveIsStopped(scip->set, scip->stat, TRUE) ) 454 { 455 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving was interrupted ["); 456 SCIP_CALL( SCIPprintStatus(scip, file) ); 457 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]"); 458 } 459 else 460 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving process is running"); 461 break; 462 case SCIP_STAGE_SOLVED: 463 SCIPmessageFPrintInfo(scip->messagehdlr, file, "problem is solved ["); 464 SCIP_CALL( SCIPprintStatus(scip, file) ); 465 SCIPmessageFPrintInfo(scip->messagehdlr, file, "]"); 466 467 /* We output that the objective limit has been reached if no solution respecting the objective limit has been 468 * found (nlimsolsfound == 0) and the primal bound is finite. Note that it still might be that the original 469 * problem is infeasible, even without the objective limit, i.e., we cannot be sure that we actually reached the 470 * objective limit. */ 471 if( scip->primal->nlimsolsfound == 0 && !SCIPisInfinity(scip, (SCIP_Real)SCIPgetObjsense(scip) * SCIPgetPrimalbound(scip)) ) 472 SCIPmessageFPrintInfo(scip->messagehdlr, file, " (objective limit reached)"); 473 474 break; 475 case SCIP_STAGE_EXITSOLVE: 476 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solving process deinitialization"); 477 break; 478 case SCIP_STAGE_FREETRANS: 479 SCIPmessageFPrintInfo(scip->messagehdlr, file, "freeing transformed problem"); 480 break; 481 case SCIP_STAGE_FREE: 482 SCIPmessageFPrintInfo(scip->messagehdlr, file, "freeing SCIP"); 483 break; 484 default: 485 SCIPerrorMessage("invalid SCIP stage <%d>\n", scip->set->stage); 486 return SCIP_INVALIDDATA; 487 } 488 489 return SCIP_OKAY; 490 } 491 492 /** gets solution status 493 * 494 * @return SCIP solution status 495 * 496 * See \ref SCIP_Status "SCIP_STATUS" for a complete list of all possible solving status. 497 */ 498 SCIP_STATUS SCIPgetStatus( 499 SCIP* scip /**< SCIP data structure */ 500 ) 501 { 502 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetStatus", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) ); 503 504 if( scip->set->stage == SCIP_STAGE_INIT || scip->set->stage == SCIP_STAGE_FREE ) 505 return SCIP_STATUS_UNKNOWN; 506 else 507 { 508 assert(scip->stat != NULL); 509 510 return scip->stat->status; 511 } 512 } 513 514 /** outputs solution status 515 * 516 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref 517 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes. 518 * 519 * See \ref SCIP_Status "SCIP_STATUS" for a complete list of all possible solving status. 520 */ 521 SCIP_RETCODE SCIPprintStatus( 522 SCIP* scip, /**< SCIP data structure */ 523 FILE* file /**< output file (or NULL for standard output) */ 524 ) 525 { 526 SCIP_CALL( SCIPcheckStage(scip, "SCIPprintStatus", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) ); 527 528 switch( SCIPgetStatus(scip) ) 529 { 530 case SCIP_STATUS_UNKNOWN: 531 SCIPmessageFPrintInfo(scip->messagehdlr, file, "unknown"); 532 break; 533 case SCIP_STATUS_USERINTERRUPT: 534 SCIPmessageFPrintInfo(scip->messagehdlr, file, "user interrupt"); 535 break; 536 case SCIP_STATUS_NODELIMIT: 537 SCIPmessageFPrintInfo(scip->messagehdlr, file, "node limit reached"); 538 break; 539 case SCIP_STATUS_TOTALNODELIMIT: 540 SCIPmessageFPrintInfo(scip->messagehdlr, file, "total node limit reached"); 541 break; 542 case SCIP_STATUS_STALLNODELIMIT: 543 SCIPmessageFPrintInfo(scip->messagehdlr, file, "stall node limit reached"); 544 break; 545 case SCIP_STATUS_TIMELIMIT: 546 SCIPmessageFPrintInfo(scip->messagehdlr, file, "time limit reached"); 547 break; 548 case SCIP_STATUS_MEMLIMIT: 549 SCIPmessageFPrintInfo(scip->messagehdlr, file, "memory limit reached"); 550 break; 551 case SCIP_STATUS_GAPLIMIT: 552 SCIPmessageFPrintInfo(scip->messagehdlr, file, "gap limit reached"); 553 break; 554 case SCIP_STATUS_SOLLIMIT: 555 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solution limit reached"); 556 break; 557 case SCIP_STATUS_BESTSOLLIMIT: 558 SCIPmessageFPrintInfo(scip->messagehdlr, file, "solution improvement limit reached"); 559 break; 560 case SCIP_STATUS_RESTARTLIMIT: 561 SCIPmessageFPrintInfo(scip->messagehdlr, file, "restart limit reached"); 562 break; 563 case SCIP_STATUS_OPTIMAL: 564 SCIPmessageFPrintInfo(scip->messagehdlr, file, "optimal solution found"); 565 break; 566 case SCIP_STATUS_INFEASIBLE: 567 SCIPmessageFPrintInfo(scip->messagehdlr, file, "infeasible"); 568 break; 569 case SCIP_STATUS_UNBOUNDED: 570 SCIPmessageFPrintInfo(scip->messagehdlr, file, "unbounded"); 571 break; 572 case SCIP_STATUS_INFORUNBD: 573 SCIPmessageFPrintInfo(scip->messagehdlr, file, "infeasible or unbounded"); 574 break; 575 case SCIP_STATUS_TERMINATE: 576 SCIPmessageFPrintInfo(scip->messagehdlr, file, "termination signal received"); 577 break; 578 default: 579 SCIPerrorMessage("invalid status code <%d>\n", SCIPgetStatus(scip)); 580 return SCIP_INVALIDDATA; 581 } 582 583 return SCIP_OKAY; 584 } 585 586 /** returns whether the current stage belongs to the transformed problem space 587 * 588 * @return Returns TRUE if the \SCIP instance is transformed, otherwise FALSE 589 */ 590 SCIP_Bool SCIPisTransformed( 591 SCIP* scip /**< SCIP data structure */ 592 ) 593 { 594 assert(scip != NULL); 595 596 return ((int)scip->set->stage >= (int)SCIP_STAGE_TRANSFORMING); 597 } 598 599 /** returns whether the solution process should be probably correct 600 * 601 * @note This feature is not supported yet! 602 * 603 * @return Returns TRUE if \SCIP is exact solving mode, otherwise FALSE 604 */ 605 SCIP_Bool SCIPisExactSolve( 606 SCIP* scip /**< SCIP data structure */ 607 ) 608 { 609 assert(scip != NULL); 610 assert(scip->set != NULL); 611 612 return (scip->set->misc_exactsolve); 613 } 614 615 /** returns whether the presolving process would be finished given no more presolving reductions are found in this 616 * presolving round 617 * 618 * Checks whether the number of presolving rounds is not exceeded and the presolving reductions found in the current 619 * presolving round suffice to trigger another presolving round. 620 * 621 * @note if subsequent presolvers find more reductions, presolving might continue even if the method returns FALSE 622 * @note does not check whether infeasibility or unboundedness was already detected in presolving (which would result 623 * in presolving being stopped although the method returns TRUE) 624 * 625 * @return Returns TRUE if presolving is finished if no further reductions are detected 626 */ 627 SCIP_Bool SCIPisPresolveFinished( 628 SCIP* scip /**< SCIP data structure */ 629 ) 630 { 631 int maxnrounds; 632 SCIP_Bool finished; 633 634 assert(scip != NULL); 635 assert(scip->stat != NULL); 636 assert(scip->transprob != NULL); 637 638 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisPresolveFinished", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 639 640 /* get maximum number of presolving rounds */ 641 maxnrounds = scip->set->presol_maxrounds; 642 if( maxnrounds == -1 ) 643 maxnrounds = INT_MAX; 644 645 /* don't abort, if enough changes were applied to the variables */ 646 finished = (scip->transprob->nvars == 0 647 || (scip->stat->npresolfixedvars - scip->stat->lastnpresolfixedvars 648 + scip->stat->npresolaggrvars - scip->stat->lastnpresolaggrvars 649 + scip->stat->npresolchgvartypes - scip->stat->lastnpresolchgvartypes 650 + (scip->stat->npresolchgbds - scip->stat->lastnpresolchgbds)/10.0 651 + (scip->stat->npresoladdholes - scip->stat->lastnpresoladdholes)/10.0 652 <= scip->set->presol_abortfac * scip->transprob->nvars)); /*lint !e653*/ 653 654 /* don't abort, if enough changes were applied to the constraints */ 655 finished = finished 656 && (scip->transprob->nconss == 0 657 || (scip->stat->npresoldelconss - scip->stat->lastnpresoldelconss 658 + scip->stat->npresoladdconss - scip->stat->lastnpresoladdconss 659 + scip->stat->npresolupgdconss - scip->stat->lastnpresolupgdconss 660 + scip->stat->npresolchgsides - scip->stat->lastnpresolchgsides 661 <= scip->set->presol_abortfac * scip->transprob->nconss)); 662 663 /* don't abort, if enough changes were applied to the coefficients (assume a 1% density of non-zero elements) */ 664 finished = finished 665 && (scip->transprob->nvars == 0 || scip->transprob->nconss == 0 666 || (scip->stat->npresolchgcoefs - scip->stat->lastnpresolchgcoefs 667 <= scip->set->presol_abortfac * 0.01 * scip->transprob->nvars * scip->transprob->nconss)); 668 669 #ifdef SCIP_DISABLED_CODE 670 /* since 2005, we do not take cliques and implications into account when deciding whether to stop presolving */ 671 /* don't abort, if enough new implications or cliques were found (assume 100 implications per variable) */ 672 finished = finished 673 && (scip->stat->nimplications - scip->stat->lastnpresolimplications 674 <= scip->set->presol_abortfac * 100 * scip->transprob->nbinvars) 675 && (SCIPcliquetableGetNCliques(scip->cliquetable) - scip->stat->lastnpresolcliques 676 <= scip->set->presol_abortfac * scip->transprob->nbinvars); 677 #endif 678 679 /* abort if maximal number of presolving rounds is reached */ 680 finished = finished || (scip->stat->npresolrounds + 1 >= maxnrounds); 681 682 return finished; 683 } 684 685 /** returns whether SCIP has performed presolving during the last solve 686 * 687 * @return Returns TRUE if presolving was performed during the last solve 688 */ 689 SCIP_Bool SCIPhasPerformedPresolve( 690 SCIP* scip /**< SCIP data structure */ 691 ) 692 { 693 assert(scip != NULL); 694 assert(scip->stat != NULL); 695 696 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPhasPerformedPresolve", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 697 698 return scip->stat->performpresol; 699 } 700 701 /** returns whether the user pressed CTRL-C to interrupt the solving process 702 * 703 * @return Returns TRUE if Ctrl-C was pressed, otherwise FALSE. 704 */ /*lint -e715*/ 705 SCIP_Bool SCIPpressedCtrlC( 706 SCIP* scip /**< SCIP data structure */ 707 ) 708 { 709 return SCIPinterrupted(); 710 } 711 712 /** returns whether the solving process should be / was stopped before proving optimality; 713 * if the solving process should be / was stopped, the status returned by SCIPgetStatus() yields 714 * the reason for the premature abort 715 * 716 * @return Returns TRUE if solving process is stopped/interrupted, otherwise FALSE. 717 */ 718 SCIP_Bool SCIPisStopped( 719 SCIP* scip /**< SCIP data structure */ 720 ) 721 { 722 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPisStopped", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) ); 723 724 return SCIPsolveIsStopped(scip->set, scip->stat, FALSE); 725 } 726 727 /** includes information about an external code linked into the SCIP library */ 728 SCIP_RETCODE SCIPincludeExternalCodeInformation( 729 SCIP* scip, /**< SCIP data structure */ 730 const char* name, /**< name of external code */ 731 const char* description /**< description of external code, or NULL */ 732 ) 733 { 734 assert(scip != NULL); 735 assert(name != NULL); 736 737 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeExternalCodeInformation", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 738 739 SCIP_CALL( SCIPsetIncludeExternalCode(scip->set, name, description) ); 740 741 return SCIP_OKAY; 742 } 743 744 /** returns an array of names of currently included external codes */ 745 char** SCIPgetExternalCodeNames( 746 SCIP* scip /**< SCIP data structure */ 747 ) 748 { 749 assert(scip != NULL); 750 assert(scip->set != NULL); 751 752 return scip->set->extcodenames; 753 } 754 755 /** returns an array of the descriptions of currently included external codes 756 * 757 * @note some descriptions may be NULL 758 */ 759 char** SCIPgetExternalCodeDescriptions( 760 SCIP* scip /**< SCIP data structure */ 761 ) 762 { 763 assert(scip != NULL); 764 assert(scip->set != NULL); 765 766 return scip->set->extcodedescs; 767 } 768 769 /** returns the number of currently included information on external codes */ 770 int SCIPgetNExternalCodes( 771 SCIP* scip /**< SCIP data structure */ 772 ) 773 { 774 assert(scip != NULL); 775 assert(scip->set != NULL); 776 777 return scip->set->nextcodes; 778 } 779 780 /** prints information on external libraries to a file stream via the message handler system 781 * 782 * @note If the message handler is set to a NULL pointer nothing will be printed 783 */ 784 void SCIPprintExternalCodes( 785 SCIP* scip, /**< SCIP data structure */ 786 FILE* file /**< output file (or NULL for standard output) */ 787 ) 788 { 789 int i; 790 791 SCIPmessageFPrintInfo(scip->messagehdlr, file, "External libraries: "); 792 if( scip->set->nextcodes == 0 ) 793 { 794 SCIPinfoMessage(scip, file, "none\n"); 795 return; 796 } 797 SCIPinfoMessage(scip, file, "\n"); 798 799 for( i = 0; i < scip->set->nextcodes; ++i ) 800 { 801 SCIPinfoMessage(scip, file, " %-20s %s\n", scip->set->extcodenames[i], scip->set->extcodedescs[i] != NULL ? scip->set->extcodedescs[i] : ""); 802 } 803 } 804