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