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